1 /*
2    Copyright (c) 2017, MariaDB Corporation, Alibaba Corporation
3    Copyrgiht (c) 2020, MariaDB Corporation.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; version 2 of the License.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
17 */
18 
19 #include "mariadb.h"
20 #include "sql_class.h"
21 #include "sql_list.h"
22 #include "sql_sequence.h"
23 #include "ha_sequence.h"
24 #include "sql_base.h"
25 #include "sql_table.h"                          // write_bin_log
26 #include "transaction.h"
27 #include "lock.h"
28 #include "sql_acl.h"
29 
30 struct Field_definition
31 {
32   const char *field_name;
33   uint length;
34   const Type_handler *type_handler;
35   LEX_CSTRING comment;
36   ulong flags;
37 };
38 
39 /*
40   Structure for all SEQUENCE tables
41 
42   Note that the first field is named "next_val" to all us to have
43   NEXTVAL a reserved word that will on access be changed to
44   NEXTVAL(sequence_table). For this to work, the table can't have
45   a column named NEXTVAL.
46 */
47 
48 #define FL (NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG)
49 
50 static Field_definition sequence_structure[]=
51 {
52   {"next_not_cached_value", 21, &type_handler_slonglong,
53    {STRING_WITH_LEN("")}, FL},
54   {"minimum_value", 21, &type_handler_slonglong, {STRING_WITH_LEN("")}, FL},
55   {"maximum_value", 21, &type_handler_slonglong, {STRING_WITH_LEN("")}, FL},
56   {"start_value", 21, &type_handler_slonglong, {STRING_WITH_LEN("start value when sequences is created or value if RESTART is used")},  FL},
57   {"increment", 21, &type_handler_slonglong,
58    {STRING_WITH_LEN("increment value")}, FL},
59   {"cache_size", 21, &type_handler_ulonglong, {STRING_WITH_LEN("")},
60    FL | UNSIGNED_FLAG},
61   {"cycle_option", 1, &type_handler_utiny, {STRING_WITH_LEN("0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed")},
62    FL | UNSIGNED_FLAG },
63   {"cycle_count", 21, &type_handler_slonglong,
64    {STRING_WITH_LEN("How many cycles have been done")}, FL},
65   {NULL, 0, &type_handler_slonglong, {STRING_WITH_LEN("")}, 0}
66 };
67 
68 #undef FL
69 
70 
71 #define MAX_AUTO_INCREMENT_VALUE 65535
72 
73 /*
74   Check whether sequence values are valid.
75   Sets default values for fields that are not used, according to Oracle spec.
76 
77   RETURN VALUES
78      false      valid
79      true       invalid
80 */
81 
check_and_adjust(bool set_reserved_until)82 bool sequence_definition::check_and_adjust(bool set_reserved_until)
83 {
84   longlong max_increment;
85   DBUG_ENTER("sequence_definition::check");
86 
87   if (!(real_increment= increment))
88     real_increment= global_system_variables.auto_increment_increment;
89 
90   /*
91     If min_value is not set, set it to LONGLONG_MIN or 1, depending on
92     real_increment
93   */
94   if (!(used_fields & seq_field_used_min_value))
95     min_value= real_increment < 0 ? LONGLONG_MIN+1 : 1;
96 
97   /*
98     If max_value is not set, set it to LONGLONG_MAX or -1, depending on
99     real_increment
100   */
101   if (!(used_fields & seq_field_used_max_value))
102     max_value= real_increment < 0 ? -1 : LONGLONG_MAX-1;
103 
104   if (!(used_fields & seq_field_used_start))
105   {
106     /* Use min_value or max_value for start depending on real_increment */
107     start= real_increment < 0 ? max_value : min_value;
108   }
109 
110   if (set_reserved_until)
111     reserved_until= start;
112 
113   adjust_values(reserved_until);
114 
115   /* To ensure that cache * real_increment will never overflow */
116   max_increment= (real_increment ?
117                   llabs(real_increment) :
118                   MAX_AUTO_INCREMENT_VALUE);
119 
120   if (max_value >= start &&
121       max_value > min_value &&
122       start >= min_value &&
123       max_value != LONGLONG_MAX &&
124       min_value != LONGLONG_MIN &&
125       cache < (LONGLONG_MAX - max_increment) / max_increment &&
126       ((real_increment > 0 && reserved_until >= min_value) ||
127        (real_increment < 0 && reserved_until <= max_value)))
128     DBUG_RETURN(FALSE);
129 
130   DBUG_RETURN(TRUE);                           // Error
131 }
132 
133 
134 /*
135   Read sequence values from a table
136 */
137 
read_fields(TABLE * table)138 void sequence_definition::read_fields(TABLE *table)
139 {
140   MY_BITMAP *old_map= dbug_tmp_use_all_columns(table, &table->read_set);
141   reserved_until= table->field[0]->val_int();
142   min_value=      table->field[1]->val_int();
143   max_value=      table->field[2]->val_int();
144   start=          table->field[3]->val_int();
145   increment=      table->field[4]->val_int();
146   cache=          table->field[5]->val_int();
147   cycle=          table->field[6]->val_int();
148   round=          table->field[7]->val_int();
149   dbug_tmp_restore_column_map(&table->read_set, old_map);
150   used_fields= ~(uint) 0;
151   print_dbug();
152 }
153 
154 
155 /*
156   Store sequence into a table row
157 */
158 
store_fields(TABLE * table)159 void sequence_definition::store_fields(TABLE *table)
160 {
161   MY_BITMAP *old_map= dbug_tmp_use_all_columns(table, &table->write_set);
162 
163   /* zero possible delete markers & null bits */
164   memcpy(table->record[0], table->s->default_values, table->s->null_bytes);
165   table->field[0]->store(reserved_until, 0);
166   table->field[1]->store(min_value, 0);
167   table->field[2]->store(max_value, 0);
168   table->field[3]->store(start, 0);
169   table->field[4]->store(increment, 0);
170   table->field[5]->store(cache, 0);
171   table->field[6]->store((longlong) cycle != 0, 0);
172   table->field[7]->store((longlong) round, 1);
173 
174   dbug_tmp_restore_column_map(&table->write_set, old_map);
175   print_dbug();
176 }
177 
178 
179 /*
180   Check the sequence fields through seq_fields when creating a sequence.
181 
182   RETURN VALUES
183     false       Success
184     true        Failure
185 */
186 
check_sequence_fields(LEX * lex,List<Create_field> * fields)187 bool check_sequence_fields(LEX *lex, List<Create_field> *fields)
188 {
189   Create_field *field;
190   List_iterator_fast<Create_field> it(*fields);
191   uint field_count;
192   uint field_no;
193   const char *reason;
194   DBUG_ENTER("check_sequence_fields");
195 
196   field_count= fields->elements;
197   if (field_count != array_elements(sequence_structure)-1)
198   {
199     reason= "Wrong number of columns";
200     goto err;
201   }
202   if (lex->alter_info.key_list.elements > 0)
203   {
204     reason= "Sequence tables cannot have any keys";
205     goto err;
206   }
207   if (lex->alter_info.check_constraint_list.elements > 0)
208   {
209     reason= "Sequence tables cannot have any constraints";
210     goto err;
211   }
212   if (lex->alter_info.flags & ALTER_ORDER)
213   {
214     reason= "ORDER BY";
215     goto err;
216   }
217 
218   for (field_no= 0; (field= it++); field_no++)
219   {
220     Field_definition *field_def= &sequence_structure[field_no];
221     if (my_strcasecmp(system_charset_info, field_def->field_name,
222                       field->field_name.str) ||
223         field->flags != field_def->flags ||
224         field->type_handler() != field_def->type_handler ||
225         field->check_constraint || field->vcol_info)
226     {
227       reason= field->field_name.str;
228       goto err;
229     }
230   }
231   DBUG_RETURN(FALSE);
232 
233 err:
234   my_error(ER_SEQUENCE_INVALID_TABLE_STRUCTURE, MYF(0),
235            lex->first_select_lex()->table_list.first->db.str,
236            lex->first_select_lex()->table_list.first->table_name.str, reason);
237   DBUG_RETURN(TRUE);
238 }
239 
240 
241 /*
242   Create the fields for a SEQUENCE TABLE
243 
244   RETURN VALUES
245     false       Success
246     true        Failure (out of memory)
247 */
248 
prepare_sequence_fields(THD * thd,List<Create_field> * fields)249 bool prepare_sequence_fields(THD *thd, List<Create_field> *fields)
250 {
251   Field_definition *field_info;
252   DBUG_ENTER("prepare_sequence_fields");
253 
254   for (field_info= sequence_structure; field_info->field_name ; field_info++)
255   {
256     Create_field *new_field;
257     LEX_CSTRING field_name= {field_info->field_name,
258                              strlen(field_info->field_name)};
259 
260     if (unlikely(!(new_field= new Create_field())))
261       DBUG_RETURN(TRUE); /* purify inspected */
262 
263     new_field->field_name=  field_name;
264     new_field->set_handler(field_info->type_handler);
265     new_field->length=      field_info->length;
266     new_field->char_length= field_info->length;
267     new_field->comment=     field_info->comment;
268     new_field->flags=       field_info->flags;
269     if (unlikely(fields->push_back(new_field)))
270       DBUG_RETURN(TRUE); /* purify inspected */
271   }
272   DBUG_RETURN(FALSE);
273 }
274 
275 /*
276   Initialize the sequence table record as part of CREATE SEQUENCE
277 
278   Store one row with sequence information.
279 
280   RETURN VALUES
281     false       Success
282     true        Failure. Error reported.
283 
284   NOTES
285     This function is called as part of CREATE SEQUENCE. When called
286     there are now active transactions and no open tables.
287     There is also a MDL lock on the table.
288 */
289 
sequence_insert(THD * thd,LEX * lex,TABLE_LIST * org_table_list)290 bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *org_table_list)
291 {
292   int error;
293   TABLE *table;
294   Reprepare_observer *save_reprepare_observer;
295   sequence_definition *seq= lex->create_info.seq_create_info;
296   bool temporary_table= org_table_list->table != 0;
297   Open_tables_backup open_tables_backup;
298   Query_tables_list query_tables_list_backup;
299   TABLE_LIST table_list;                        // For sequence table
300   DBUG_ENTER("sequence_insert");
301 
302   /*
303     seq is 0 if sequence was created with CREATE TABLE instead of
304     CREATE SEQUENCE
305   */
306   if (!seq)
307   {
308     if (!(seq= new (thd->mem_root) sequence_definition))
309       DBUG_RETURN(TRUE);
310   }
311 
312   /* If not temporary table */
313   if (!temporary_table)
314   {
315     /*
316       The following code works like open_system_tables_for_read()
317       The idea is:
318       - Copy the table_list object for the sequence that was created
319       - Backup the current state of open tables and create a new
320         environment for open tables without any tables opened
321      - open the newly sequence table for write
322      This is safe as the sequence table has a mdl lock thanks to the
323      create sequence statement that is calling this function
324     */
325 
326     table_list.init_one_table(&org_table_list->db,
327                               &org_table_list->table_name,
328                               NULL, TL_WRITE_DEFAULT);
329     table_list.updating=  1;
330     table_list.open_strategy= TABLE_LIST::OPEN_IF_EXISTS;
331     table_list.open_type= OT_BASE_ONLY;
332 
333     DBUG_ASSERT(!thd->locked_tables_mode ||
334                 (thd->variables.option_bits & OPTION_TABLE_LOCK));
335     lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
336     thd->reset_n_backup_open_tables_state(&open_tables_backup);
337 
338     /*
339       The FOR CREATE flag is needed to ensure that ha_open() doesn't try to
340       read the not yet existing row in the sequence table
341     */
342     thd->open_options|= HA_OPEN_FOR_CREATE;
343     /*
344       We have to reset the reprepare observer to be able to open the
345       table under prepared statements.
346     */
347     save_reprepare_observer= thd->m_reprepare_observer;
348     thd->m_reprepare_observer= 0;
349     lex->sql_command= SQLCOM_CREATE_SEQUENCE;
350     error= open_and_lock_tables(thd, &table_list, FALSE,
351                                 MYSQL_LOCK_IGNORE_TIMEOUT |
352                                 MYSQL_OPEN_HAS_MDL_LOCK);
353     thd->open_options&= ~HA_OPEN_FOR_CREATE;
354     thd->m_reprepare_observer= save_reprepare_observer;
355     if (unlikely(error))
356     {
357       lex->restore_backup_query_tables_list(&query_tables_list_backup);
358       thd->restore_backup_open_tables_state(&open_tables_backup);
359       DBUG_RETURN(error);
360     }
361     table= table_list.table;
362   }
363   else
364     table= org_table_list->table;
365 
366   seq->reserved_until= seq->start;
367   error= seq->write_initial_sequence(table);
368   {
369     uint save_unsafe_rollback_flags=
370       thd->transaction->stmt.m_unsafe_rollback_flags;
371     if (trans_commit_stmt(thd))
372       error= 1;
373     thd->transaction->stmt.m_unsafe_rollback_flags=
374       save_unsafe_rollback_flags;
375   }
376   if (trans_commit_implicit(thd))
377     error= 1;
378 
379   if (!temporary_table)
380   {
381     close_thread_tables(thd);
382     lex->restore_backup_query_tables_list(&query_tables_list_backup);
383     thd->restore_backup_open_tables_state(&open_tables_backup);
384 
385     /* OPTION_TABLE_LOCK was reset in trans_commit_implicit */
386     if (thd->locked_tables_mode)
387       thd->variables.option_bits|= OPTION_TABLE_LOCK;
388   }
389   DBUG_RETURN(error);
390 }
391 
392 
393 /* Create a SQUENCE object */
394 
SEQUENCE()395 SEQUENCE::SEQUENCE() :all_values_used(0), initialized(SEQ_UNINTIALIZED)
396 {
397   mysql_rwlock_init(key_LOCK_SEQUENCE, &mutex);
398 }
399 
~SEQUENCE()400 SEQUENCE::~SEQUENCE()
401 {
402   mysql_rwlock_destroy(&mutex);
403 }
404 
405 /*
406   The following functions is to ensure that we when reserve new values
407   trough sequence object sequence we have only one writer at at time.
408   A sequence table can have many readers (trough normal SELECT's).
409 
410   We mark that we have a write lock in the table object so that
411   ha_sequence::ha_write() can check if we have a lock. If already locked, then
412   ha_write() knows that we are running a sequence operation. If not, then
413   ha_write() knows that it's an INSERT.
414 */
415 
write_lock(TABLE * table)416 void SEQUENCE::write_lock(TABLE *table)
417 {
418   DBUG_ASSERT(((ha_sequence*) table->file)->is_locked() == 0);
419   mysql_rwlock_wrlock(&mutex);
420   ((ha_sequence*) table->file)->write_lock();
421 }
write_unlock(TABLE * table)422 void SEQUENCE::write_unlock(TABLE *table)
423 {
424   ((ha_sequence*) table->file)->unlock();
425   mysql_rwlock_unlock(&mutex);
426 }
read_lock(TABLE * table)427 void SEQUENCE::read_lock(TABLE *table)
428 {
429   if (!((ha_sequence*) table->file)->is_locked())
430     mysql_rwlock_rdlock(&mutex);
431 }
read_unlock(TABLE * table)432 void SEQUENCE::read_unlock(TABLE *table)
433 {
434   if (!((ha_sequence*) table->file)->is_locked())
435     mysql_rwlock_unlock(&mutex);
436 }
437 
438 /**
439    Read values from the sequence tables to table_share->sequence.
440    This is called from ha_open() when the table is not yet locked
441 */
442 
read_initial_values(TABLE * table)443 int SEQUENCE::read_initial_values(TABLE *table)
444 {
445   int error= 0;
446   enum thr_lock_type save_lock_type;
447   MDL_request mdl_request;                      // Empty constructor!
448   DBUG_ENTER("SEQUENCE::read_initial_values");
449 
450   if (likely(initialized != SEQ_UNINTIALIZED))
451     DBUG_RETURN(0);
452   write_lock(table);
453   if (likely(initialized == SEQ_UNINTIALIZED))
454   {
455     MYSQL_LOCK *lock;
456     bool mdl_lock_used= 0;
457     THD *thd= table->in_use;
458     bool has_active_transaction= !thd->transaction->stmt.is_empty();
459     /*
460       There is already a mdl_ticket for this table. However, for list_fields
461       the MDL lock is of type MDL_SHARED_HIGH_PRIO which is not usable
462       for doing a table lock. Get a proper read lock to solve this.
463     */
464     if (table->mdl_ticket == 0)
465     {
466       MDL_request_list mdl_requests;
467       mdl_lock_used= 1;
468       /*
469         This happens if first request is SHOW CREATE TABLE or LIST FIELDS
470         where we don't have a mdl lock on the table
471       */
472 
473       MDL_REQUEST_INIT(&mdl_request, MDL_key::TABLE, table->s->db.str,
474                        table->s->table_name.str, MDL_SHARED_READ,
475                        MDL_EXPLICIT);
476       mdl_requests.push_front(&mdl_request);
477       if (thd->mdl_context.acquire_locks(&mdl_requests,
478                                          thd->variables.lock_wait_timeout))
479       {
480         write_unlock(table);
481         DBUG_RETURN(HA_ERR_LOCK_WAIT_TIMEOUT);
482       }
483     }
484     save_lock_type= table->reginfo.lock_type;
485     table->reginfo.lock_type= TL_READ;
486     if (!(lock= mysql_lock_tables(thd, &table, 1,
487                                   MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY)))
488     {
489       if (mdl_lock_used)
490         thd->mdl_context.release_lock(mdl_request.ticket);
491       write_unlock(table);
492 
493       if (!has_active_transaction && !thd->transaction->stmt.is_empty() &&
494           !thd->in_sub_stmt)
495         trans_commit_stmt(thd);
496       DBUG_RETURN(HA_ERR_LOCK_WAIT_TIMEOUT);
497     }
498     DBUG_ASSERT(table->reginfo.lock_type == TL_READ);
499     if (likely(!(error= read_stored_values(table))))
500       initialized= SEQ_READY_TO_USE;
501     mysql_unlock_tables(thd, lock);
502     if (mdl_lock_used)
503       thd->mdl_context.release_lock(mdl_request.ticket);
504 
505     /* Reset value to default */
506     table->reginfo.lock_type= save_lock_type;
507     /*
508       Doing mysql_lock_tables() may have started a read only transaction.
509       If that happend, it's better that we commit it now, as a lot of
510       code assumes that there is no active stmt transaction directly after
511       open_tables().
512       But we also don't want to commit the stmt transaction while in a
513       substatement, see MDEV-15977.
514     */
515     if (!has_active_transaction && !thd->transaction->stmt.is_empty() &&
516         !thd->in_sub_stmt)
517       trans_commit_stmt(thd);
518   }
519   write_unlock(table);
520   DBUG_RETURN(error);
521 }
522 
523 
524 /*
525   Do the actiual reading of data from sequence table and
526   update values in the sequence object.
527 
528   Called once from when table is opened
529 */
530 
read_stored_values(TABLE * table)531 int SEQUENCE::read_stored_values(TABLE *table)
532 {
533   int error;
534   DBUG_ENTER("SEQUENCE::read_stored_values");
535 
536   MY_BITMAP *save_read_set= tmp_use_all_columns(table, &table->read_set);
537   error= table->file->ha_read_first_row(table->record[0], MAX_KEY);
538   tmp_restore_column_map(&table->read_set, save_read_set);
539 
540   if (unlikely(error))
541   {
542     table->file->print_error(error, MYF(0));
543     DBUG_RETURN(error);
544   }
545   read_fields(table);
546   adjust_values(reserved_until);
547 
548   all_values_used= 0;
549   DBUG_RETURN(0);
550 }
551 
552 
553 /*
554   Adjust values after reading a the stored state
555 */
556 
adjust_values(longlong next_value)557 void sequence_definition::adjust_values(longlong next_value)
558 {
559   next_free_value= next_value;
560   if (!(real_increment= increment))
561   {
562     longlong offset= 0;
563     longlong off, to_add;
564     /* Use auto_increment_increment and auto_increment_offset */
565 
566     if ((real_increment= global_system_variables.auto_increment_increment)
567         != 1)
568       offset= (global_system_variables.auto_increment_offset %
569                global_system_variables.auto_increment_increment);
570 
571     /*
572       Ensure that next_free_value has the right offset, so that we
573       can generate a serie by just adding real_increment.
574     */
575     off= next_free_value % real_increment;
576     if (off < 0)
577       off+= real_increment;
578     to_add= (real_increment + offset - off) % real_increment;
579 
580     /*
581       Check if add will make next_free_value bigger than max_value,
582       taken into account that next_free_value or max_value addition
583       may overflow
584     */
585     if (next_free_value > max_value - to_add ||
586         next_free_value + to_add > max_value)
587       next_free_value= max_value+1;
588     else
589     {
590       next_free_value+= to_add;
591       DBUG_ASSERT(llabs(next_free_value % real_increment) == offset);
592     }
593   }
594 }
595 
596 
597 /**
598    Write initial sequence information for CREATE and ALTER to sequence table
599 */
600 
write_initial_sequence(TABLE * table)601 int sequence_definition::write_initial_sequence(TABLE *table)
602 {
603   int error;
604   MY_BITMAP *save_write_set;
605 
606   store_fields(table);
607   /* Store the sequence values in table share */
608   table->s->sequence->copy(this);
609   /*
610     Sequence values will be replicated as a statement
611     like 'create sequence'. So disable row logging for this table & statement
612   */
613   table->file->row_logging= table->file->row_logging_init= 0;
614   save_write_set= table->write_set;
615   table->write_set= &table->s->all_set;
616   table->s->sequence->initialized= SEQUENCE::SEQ_IN_PREPARE;
617   error= table->file->ha_write_row(table->record[0]);
618   table->s->sequence->initialized= SEQUENCE::SEQ_UNINTIALIZED;
619   table->write_set= save_write_set;
620   if (unlikely(error))
621     table->file->print_error(error, MYF(0));
622   else
623   {
624     /*
625       Sequence structure is up to date and table has one row,
626       sequence is now usable
627     */
628     table->s->sequence->initialized= SEQUENCE::SEQ_READY_TO_USE;
629   }
630   return error;
631 }
632 
633 
634 /**
635    Store current sequence values into the sequence table
636 */
637 
write(TABLE * table,bool all_fields)638 int sequence_definition::write(TABLE *table, bool all_fields)
639 {
640   int error;
641   MY_BITMAP *save_rpl_write_set, *save_write_set, *save_read_set;
642   DBUG_ASSERT(((ha_sequence*) table->file)->is_locked());
643 
644   save_rpl_write_set= table->rpl_write_set;
645   if (likely(!all_fields))
646   {
647     /* Only write next_value and round to binary log */
648     table->rpl_write_set= &table->def_rpl_write_set;
649     bitmap_clear_all(table->rpl_write_set);
650     bitmap_set_bit(table->rpl_write_set, NEXT_FIELD_NO);
651     bitmap_set_bit(table->rpl_write_set, ROUND_FIELD_NO);
652   }
653   else
654     table->rpl_write_set= &table->s->all_set;
655 
656   /* Update table */
657   save_write_set= table->write_set;
658   save_read_set=  table->read_set;
659   table->read_set= table->write_set= &table->s->all_set;
660   table->file->column_bitmaps_signal();
661   store_fields(table);
662   if (unlikely((error= table->file->ha_write_row(table->record[0]))))
663     table->file->print_error(error, MYF(0));
664   table->rpl_write_set= save_rpl_write_set;
665   table->read_set=  save_read_set;
666   table->write_set= save_write_set;
667   table->file->column_bitmaps_signal();
668   return error;
669 }
670 
671 
672 /**
673    Get next value for sequence
674 
675    @param in   table  Sequence table
676    @param in   second_round
677                       1 if recursive call (out of values once)
678    @param out  error  Set this to <> 0 in case of error
679                       push_warning_printf(WARN_LEVEL_WARN) has been called
680 
681 
682    @retval     0      Next number or error. Check error variable
683                #      Next sequence number
684 
685    NOTES:
686      Return next_free_value and increment next_free_value to next allowed
687      value or reserved_value if out of range
688      if next_free_value >= reserved_value reserve a new range by writing
689      a record to the sequence table.
690 
691   The state of the variables:
692     next_free_value contains next value to use. It may be
693     bigger than max_value or less than min_value if end of sequence.
694     reserved_until contains the last value written to the file. All
695     values up to this one can be used.
696     If next_free_value >= reserved_until we have to reserve new
697     values from the sequence.
698 */
699 
next_value(TABLE * table,bool second_round,int * error)700 longlong SEQUENCE::next_value(TABLE *table, bool second_round, int *error)
701 {
702   longlong res_value, org_reserved_until, add_to;
703   bool out_of_values;
704   DBUG_ENTER("SEQUENCE::next_value");
705 
706   *error= 0;
707   if (!second_round)
708     write_lock(table);
709 
710   res_value= next_free_value;
711   next_free_value= increment_value(next_free_value);
712 
713   if ((real_increment > 0 && res_value < reserved_until) ||
714       (real_increment < 0 && res_value > reserved_until))
715   {
716     write_unlock(table);
717     DBUG_RETURN(res_value);
718   }
719 
720   if (all_values_used)
721     goto err;
722 
723   org_reserved_until= reserved_until;
724 
725   /*
726     Out of cached values, reserve 'cache' new ones
727     The cache value is checked on insert so the following can't
728     overflow
729   */
730   add_to= cache ? real_increment * cache : real_increment;
731   out_of_values= 0;
732 
733   if (real_increment > 0)
734   {
735     if (reserved_until > max_value - add_to ||
736         reserved_until + add_to > max_value)
737     {
738       reserved_until= max_value + 1;
739       out_of_values= res_value >= reserved_until;
740     }
741     else
742       reserved_until+= add_to;
743   }
744   else
745   {
746     if (reserved_until + add_to < min_value ||
747         reserved_until < min_value - add_to)
748     {
749       reserved_until= min_value - 1;
750       out_of_values= res_value <= reserved_until;
751     }
752     else
753       reserved_until+= add_to;
754   }
755   if (out_of_values)
756   {
757     if (!cycle || second_round)
758       goto err;
759     round++;
760     reserved_until= real_increment >0 ? min_value : max_value;
761     adjust_values(reserved_until);              // Fix next_free_value
762     /*
763       We have to do everything again to ensure that the given range was
764       not empty, which could happen if increment == 0
765     */
766     DBUG_RETURN(next_value(table, 1, error));
767   }
768 
769   if (unlikely((*error= write(table, 0))))
770   {
771     reserved_until= org_reserved_until;
772     next_free_value= res_value;
773   }
774 
775   write_unlock(table);
776   DBUG_RETURN(res_value);
777 
778 err:
779   write_unlock(table);
780   my_error(ER_SEQUENCE_RUN_OUT, MYF(0), table->s->db.str,
781            table->s->table_name.str);
782   *error= ER_SEQUENCE_RUN_OUT;
783   all_values_used= 1;
784   DBUG_RETURN(0);
785 }
786 
787 
788 /*
789    The following functions is to detect if a table has been dropped
790    and re-created since last call to PREVIOUS VALUE.
791 
792    This is needed as we don't delete dropped sequences from THD->sequence
793    for DROP TABLE.
794 */
795 
check_version(TABLE * table)796 bool SEQUENCE_LAST_VALUE::check_version(TABLE *table)
797 {
798   DBUG_ASSERT(table->s->tabledef_version.length == MY_UUID_SIZE);
799   return memcmp(table->s->tabledef_version.str, table_version,
800                 MY_UUID_SIZE) != 0;
801 }
802 
set_version(TABLE * table)803 void SEQUENCE_LAST_VALUE::set_version(TABLE *table)
804 {
805   memcpy(table_version, table->s->tabledef_version.str, MY_UUID_SIZE);
806 }
807 
808 /**
809    Set the next value for sequence
810 
811    @param in   table       Sequence table
812    @param in   next_val    Next free value
813    @param in   next_round  Round for 'next_value' (in case of cycles)
814    @param in   is_used     1 if next_val is already used
815 
816    @retval     0      ok, value adjusted
817                -1     value was less than current value
818                1      error when storing value
819 
820    @comment
821    A new value is set only if "nextval,next_round" is less than
822    "next_free_value,round". This is needed as in replication
823    setvalue() calls may come out to the slave out-of-order.
824    Storing only the highest value ensures that sequence object will always
825    contain the highest used value when the slave is promoted to a master.
826 */
827 
set_value(TABLE * table,longlong next_val,ulonglong next_round,bool is_used)828 int SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round,
829                          bool is_used)
830 {
831   int error= -1;
832   bool needs_to_be_stored= 0;
833   longlong org_reserved_until=  reserved_until;
834   longlong org_next_free_value= next_free_value;
835   ulonglong org_round= round;
836   DBUG_ENTER("SEQUENCE::set_value");
837 
838   write_lock(table);
839   if (is_used)
840     next_val= increment_value(next_val);
841 
842   if (round > next_round)
843     goto end;                                   // error = -1
844   if (round == next_round)
845   {
846     if (real_increment > 0  ?
847         next_val < next_free_value :
848         next_val > next_free_value)
849       goto end;                                 // error = -1
850     if (next_val == next_free_value)
851     {
852       error= 0;
853       goto end;
854     }
855   }
856   else if (cycle == 0)
857   {
858     // round < next_round && no cycles, which is impossible
859     my_error(ER_SEQUENCE_RUN_OUT, MYF(0), table->s->db.str,
860              table->s->table_name.str);
861     error= 1;
862     goto end;
863   }
864   else
865     needs_to_be_stored= 1;
866 
867   round= next_round;
868   adjust_values(next_val);
869   if ((real_increment > 0 ?
870        next_free_value > reserved_until :
871        next_free_value < reserved_until) ||
872       needs_to_be_stored)
873   {
874     reserved_until= next_free_value;
875     if (write(table, 0))
876     {
877       reserved_until=  org_reserved_until;
878       next_free_value= org_next_free_value;
879       round= org_round;
880       error= 1;
881       goto end;
882     }
883   }
884   error= 0;
885 
886 end:
887   write_unlock(table);
888   DBUG_RETURN(error);
889 }
890 
891 
execute(THD * thd)892 bool Sql_cmd_alter_sequence::execute(THD *thd)
893 {
894   int error= 0;
895   int trapped_errors= 0;
896   LEX *lex= thd->lex;
897   TABLE_LIST *first_table= lex->query_tables;
898   TABLE *table;
899   sequence_definition *new_seq= lex->create_info.seq_create_info;
900   SEQUENCE *seq;
901   No_such_table_error_handler no_such_table_handler;
902   DBUG_ENTER("Sql_cmd_alter_sequence::execute");
903 
904   if (check_access(thd, ALTER_ACL, first_table->db.str,
905                    &first_table->grant.privilege,
906                    &first_table->grant.m_internal,
907                    0, 0))
908     DBUG_RETURN(TRUE);                  /* purecov: inspected */
909 
910   if (check_grant(thd, ALTER_ACL, first_table, FALSE, 1, FALSE))
911     DBUG_RETURN(TRUE);                  /* purecov: inspected */
912 
913 #ifdef WITH_WSREP
914   if (WSREP_ON && WSREP(thd) &&
915       wsrep_to_isolation_begin(thd, first_table->db.str,
916 	                       first_table->table_name.str,
917 		               first_table))
918     DBUG_RETURN(TRUE);
919 #endif /* WITH_WSREP */
920   if (if_exists())
921     thd->push_internal_handler(&no_such_table_handler);
922   error= open_and_lock_tables(thd, first_table, FALSE, 0);
923   if (if_exists())
924   {
925     trapped_errors= no_such_table_handler.safely_trapped_errors();
926     thd->pop_internal_handler();
927   }
928   if (unlikely(error))
929   {
930     if (trapped_errors)
931     {
932       StringBuffer<FN_REFLEN> tbl_name;
933       tbl_name.append(&first_table->db);
934       tbl_name.append('.');
935       tbl_name.append(&first_table->table_name);
936       push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
937                           ER_UNKNOWN_SEQUENCES,
938                           ER_THD(thd, ER_UNKNOWN_SEQUENCES),
939                           tbl_name.c_ptr_safe());
940       my_ok(thd);
941       DBUG_RETURN(FALSE);
942     }
943     DBUG_RETURN(TRUE);
944   }
945 
946   table= first_table->table;
947   seq= table->s->sequence;
948 
949   seq->write_lock(table);
950   new_seq->reserved_until= seq->reserved_until;
951 
952   /* Copy from old sequence those fields that the user didn't specified */
953   if (!(new_seq->used_fields & seq_field_used_increment))
954     new_seq->increment= seq->increment;
955   if (!(new_seq->used_fields & seq_field_used_min_value))
956     new_seq->min_value= seq->min_value;
957   if (!(new_seq->used_fields & seq_field_used_max_value))
958     new_seq->max_value= seq->max_value;
959   if (!(new_seq->used_fields & seq_field_used_start))
960     new_seq->start=          seq->start;
961   if (!(new_seq->used_fields & seq_field_used_cache))
962     new_seq->cache= seq->cache;
963   if (!(new_seq->used_fields & seq_field_used_cycle))
964     new_seq->cycle= seq->cycle;
965 
966   /* If we should restart from a new value */
967   if (new_seq->used_fields & seq_field_used_restart)
968   {
969     if (!(new_seq->used_fields & seq_field_used_restart_value))
970       new_seq->restart=      new_seq->start;
971     new_seq->reserved_until= new_seq->restart;
972   }
973 
974   /* Let check_and_adjust think all fields are used */
975   new_seq->used_fields= ~0;
976   if (new_seq->check_and_adjust(0))
977   {
978     my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
979              first_table->db.str,
980              first_table->table_name.str);
981     error= 1;
982     seq->write_unlock(table);
983     goto end;
984   }
985 
986   if (likely(!(error= new_seq->write(table, 1))))
987   {
988     /* Store the sequence values in table share */
989     seq->copy(new_seq);
990   }
991   else
992     table->file->print_error(error, MYF(0));
993   seq->write_unlock(table);
994   if (trans_commit_stmt(thd))
995     error= 1;
996   if (trans_commit_implicit(thd))
997     error= 1;
998   if (likely(!error))
999     error= write_bin_log(thd, 1, thd->query(), thd->query_length());
1000   if (likely(!error))
1001     my_ok(thd);
1002 
1003 end:
1004   DBUG_RETURN(error);
1005 }
1006