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