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