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
29struct 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
49static 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
81bool 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 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 min_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
137void sequence_definition::read_fields(TABLE *table)
138{
139 my_bitmap_map *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
158void sequence_definition::store_fields(TABLE *table)
159{
160 my_bitmap_map *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 createing a sequence.
180
181 RETURN VALUES
182 false Success
183 true Failure
184*/
185
186bool 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
207 for (field_no= 0; (field= it++); field_no++)
208 {
209 Field_definition *field_def= &sequence_structure[field_no];
210 if (my_strcasecmp(system_charset_info, field_def->field_name,
211 field->field_name.str) ||
212 field->flags != field_def->flags ||
213 field->type_handler() != field_def->type_handler)
214 {
215 reason= field->field_name.str;
216 goto err;
217 }
218 }
219 DBUG_RETURN(FALSE);
220
221err:
222 my_error(ER_SEQUENCE_INVALID_TABLE_STRUCTURE, MYF(0),
223 lex->select_lex.table_list.first->db.str,
224 lex->select_lex.table_list.first->table_name.str, reason);
225 DBUG_RETURN(TRUE);
226}
227
228
229/*
230 Create the fields for a SEQUENCE TABLE
231
232 RETURN VALUES
233 false Success
234 true Failure (out of memory)
235*/
236
237bool prepare_sequence_fields(THD *thd, List<Create_field> *fields)
238{
239 Field_definition *field_info;
240 DBUG_ENTER("prepare_sequence_fields");
241
242 for (field_info= sequence_structure; field_info->field_name ; field_info++)
243 {
244 Create_field *new_field;
245 LEX_CSTRING field_name= {field_info->field_name,
246 strlen(field_info->field_name)};
247
248 if (unlikely(!(new_field= new Create_field())))
249 DBUG_RETURN(TRUE); /* purify inspected */
250
251 new_field->field_name= field_name;
252 new_field->set_handler(field_info->type_handler);
253 new_field->length= field_info->length;
254 new_field->char_length= field_info->length;
255 new_field->comment= field_info->comment;
256 new_field->flags= field_info->flags;
257 if (unlikely(fields->push_back(new_field)))
258 DBUG_RETURN(TRUE); /* purify inspected */
259 }
260 DBUG_RETURN(FALSE);
261}
262
263/*
264 Initialize the sequence table record as part of CREATE SEQUENCE
265
266 Store one row with sequence information.
267
268 RETURN VALUES
269 false Success
270 true Failure. Error reported.
271
272 NOTES
273 This function is called as part of CREATE SEQUENCE. When called
274 there are now active transactions and no open tables.
275 There is also a MDL lock on the table.
276*/
277
278bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *org_table_list)
279{
280 int error;
281 TABLE *table;
282 Reprepare_observer *save_reprepare_observer;
283 sequence_definition *seq= lex->create_info.seq_create_info;
284 bool temporary_table= org_table_list->table != 0;
285 Open_tables_backup open_tables_backup;
286 Query_tables_list query_tables_list_backup;
287 TABLE_LIST table_list; // For sequence table
288 DBUG_ENTER("sequence_insert");
289
290 /*
291 seq is 0 if sequence was created with CREATE TABLE instead of
292 CREATE SEQUENCE
293 */
294 if (!seq)
295 {
296 if (!(seq= new (thd->mem_root) sequence_definition))
297 DBUG_RETURN(TRUE);
298 }
299
300 /* If not temporary table */
301 if (!temporary_table)
302 {
303 /*
304 The following code works like open_system_tables_for_read() and
305 close_system_tables()
306 The idea is:
307 - Copy the table_list object for the sequence that was created
308 - Backup the current state of open tables and create a new
309 environment for open tables without any tables opened
310 - open the newly sequence table for write
311 This is safe as the sequence table has a mdl lock thanks to the
312 create sequence statement that is calling this function
313 */
314
315 table_list.init_one_table(&org_table_list->db,
316 &org_table_list->table_name,
317 NULL, TL_WRITE_DEFAULT);
318 table_list.updating= 1;
319 table_list.open_strategy= TABLE_LIST::OPEN_IF_EXISTS;
320 table_list.open_type= OT_BASE_ONLY;
321
322 DBUG_ASSERT(!thd->locked_tables_mode ||
323 (thd->variables.option_bits & OPTION_TABLE_LOCK));
324 lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
325 thd->reset_n_backup_open_tables_state(&open_tables_backup);
326
327 /*
328 The FOR CREATE flag is needed to ensure that ha_open() doesn't try to
329 read the not yet existing row in the sequence table
330 */
331 thd->open_options|= HA_OPEN_FOR_CREATE;
332 /*
333 We have to reset the reprepare observer to be able to open the
334 table under prepared statements.
335 */
336 save_reprepare_observer= thd->m_reprepare_observer;
337 thd->m_reprepare_observer= 0;
338 lex->sql_command= SQLCOM_CREATE_SEQUENCE;
339 error= open_and_lock_tables(thd, &table_list, FALSE,
340 MYSQL_LOCK_IGNORE_TIMEOUT |
341 MYSQL_OPEN_HAS_MDL_LOCK);
342 thd->open_options&= ~HA_OPEN_FOR_CREATE;
343 thd->m_reprepare_observer= save_reprepare_observer;
344 if (unlikely(error))
345 {
346 lex->restore_backup_query_tables_list(&query_tables_list_backup);
347 thd->restore_backup_open_tables_state(&open_tables_backup);
348 DBUG_RETURN(error);
349 }
350 table= table_list.table;
351 }
352 else
353 table= org_table_list->table;
354
355 seq->reserved_until= seq->start;
356 error= seq->write_initial_sequence(table);
357
358 trans_commit_stmt(thd);
359 trans_commit_implicit(thd);
360
361 if (!temporary_table)
362 {
363 close_thread_tables(thd);
364 lex->restore_backup_query_tables_list(&query_tables_list_backup);
365 thd->restore_backup_open_tables_state(&open_tables_backup);
366
367 /* OPTION_TABLE_LOCK was reset in trans_commit_implicit */
368 if (thd->locked_tables_mode)
369 thd->variables.option_bits|= OPTION_TABLE_LOCK;
370 }
371 DBUG_RETURN(error);
372}
373
374
375/* Create a SQUENCE object */
376
377SEQUENCE::SEQUENCE() :all_values_used(0), initialized(SEQ_UNINTIALIZED)
378{
379 mysql_rwlock_init(key_LOCK_SEQUENCE, &mutex);
380}
381
382SEQUENCE::~SEQUENCE()
383{
384 mysql_rwlock_destroy(&mutex);
385}
386
387/*
388 The following functions is to ensure that we when reserve new values
389 trough sequence object sequence we have only one writer at at time.
390 A sequence table can have many readers (trough normal SELECT's).
391
392 We mark that we have a write lock in the table object so that
393 ha_sequence::ha_write() can check if we have a lock. If already locked, then
394 ha_write() knows that we are running a sequence operation. If not, then
395 ha_write() knows that it's an INSERT.
396*/
397
398void SEQUENCE::write_lock(TABLE *table)
399{
400 DBUG_ASSERT(((ha_sequence*) table->file)->is_locked() == 0);
401 mysql_rwlock_wrlock(&mutex);
402 ((ha_sequence*) table->file)->write_lock();
403}
404void SEQUENCE::write_unlock(TABLE *table)
405{
406 ((ha_sequence*) table->file)->unlock();
407 mysql_rwlock_unlock(&mutex);
408}
409void SEQUENCE::read_lock(TABLE *table)
410{
411 if (!((ha_sequence*) table->file)->is_locked())
412 mysql_rwlock_rdlock(&mutex);
413}
414void SEQUENCE::read_unlock(TABLE *table)
415{
416 if (!((ha_sequence*) table->file)->is_locked())
417 mysql_rwlock_unlock(&mutex);
418}
419
420/**
421 Read values from the sequence tables to table_share->sequence.
422 This is called from ha_open() when the table is not yet locked
423*/
424
425int SEQUENCE::read_initial_values(TABLE *table)
426{
427 int error= 0;
428 enum thr_lock_type save_lock_type;
429 MDL_request mdl_request; // Empty constructor!
430 DBUG_ENTER("SEQUENCE::read_initial_values");
431
432 if (likely(initialized != SEQ_UNINTIALIZED))
433 DBUG_RETURN(0);
434 write_lock(table);
435 if (likely(initialized == SEQ_UNINTIALIZED))
436 {
437 MYSQL_LOCK *lock;
438 bool mdl_lock_used= 0;
439 THD *thd= table->in_use;
440 bool has_active_transaction= !thd->transaction.stmt.is_empty();
441 /*
442 There is already a mdl_ticket for this table. However, for list_fields
443 the MDL lock is of type MDL_SHARED_HIGH_PRIO which is not usable
444 for doing a able lock. Get a proper read lock to solve this.
445 */
446 if (table->mdl_ticket == 0)
447 {
448 MDL_request_list mdl_requests;
449 mdl_lock_used= 1;
450 /*
451 This happens if first request is SHOW CREATE TABLE or LIST FIELDS
452 where we don't have a mdl lock on the table
453 */
454
455 mdl_request.init(MDL_key::TABLE,
456 table->s->db.str,
457 table->s->table_name.str,
458 MDL_SHARED_READ, MDL_EXPLICIT);
459 mdl_requests.push_front(&mdl_request);
460 if (thd->mdl_context.acquire_locks(&mdl_requests,
461 thd->variables.lock_wait_timeout))
462 {
463 write_unlock(table);
464 DBUG_RETURN(HA_ERR_LOCK_WAIT_TIMEOUT);
465 }
466 }
467 save_lock_type= table->reginfo.lock_type;
468 table->reginfo.lock_type= TL_READ;
469 if (!(lock= mysql_lock_tables(thd, &table, 1,
470 MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY)))
471 {
472 if (mdl_lock_used)
473 thd->mdl_context.release_lock(mdl_request.ticket);
474 write_unlock(table);
475 DBUG_RETURN(HA_ERR_LOCK_WAIT_TIMEOUT);
476 }
477 DBUG_ASSERT(table->reginfo.lock_type == TL_READ);
478 if (likely(!(error= read_stored_values(table))))
479 initialized= SEQ_READY_TO_USE;
480 mysql_unlock_tables(thd, lock);
481 if (mdl_lock_used)
482 thd->mdl_context.release_lock(mdl_request.ticket);
483
484 /* Reset value to default */
485 table->reginfo.lock_type= save_lock_type;
486 /*
487 Doing mysql_lock_tables() may have started a read only transaction.
488 If that happend, it's better that we commit it now, as a lot of
489 code assumes that there is no active stmt transaction directly after
490 open_tables()
491 */
492 if (!has_active_transaction && !thd->transaction.stmt.is_empty())
493 trans_commit_stmt(thd);
494 }
495 write_unlock(table);
496 DBUG_RETURN(error);
497}
498
499
500/*
501 Do the actiual reading of data from sequence table and
502 update values in the sequence object.
503
504 Called once from when table is opened
505*/
506
507int SEQUENCE::read_stored_values(TABLE *table)
508{
509 int error;
510 my_bitmap_map *save_read_set;
511 DBUG_ENTER("SEQUENCE::read_stored_values");
512
513 save_read_set= tmp_use_all_columns(table, table->read_set);
514 error= table->file->ha_read_first_row(table->record[0], MAX_KEY);
515 tmp_restore_column_map(table->read_set, save_read_set);
516
517 if (unlikely(error))
518 {
519 table->file->print_error(error, MYF(0));
520 DBUG_RETURN(error);
521 }
522 read_fields(table);
523 adjust_values(reserved_until);
524
525 all_values_used= 0;
526 DBUG_RETURN(0);
527}
528
529
530/*
531 Adjust values after reading a the stored state
532*/
533
534void sequence_definition::adjust_values(longlong next_value)
535{
536 next_free_value= next_value;
537 if (!(real_increment= increment))
538 {
539 longlong offset= 0;
540 longlong off, to_add;
541 /* Use auto_increment_increment and auto_increment_offset */
542
543 if ((real_increment= global_system_variables.auto_increment_increment)
544 != 1)
545 offset= global_system_variables.auto_increment_offset;
546
547 /*
548 Ensure that next_free_value has the right offset, so that we
549 can generate a serie by just adding real_increment.
550 */
551 off= next_free_value % real_increment;
552 if (off < 0)
553 off+= real_increment;
554 to_add= (real_increment + offset - off) % real_increment;
555
556 /*
557 Check if add will make next_free_value bigger than max_value,
558 taken into account that next_free_value or max_value addition
559 may overflow
560 */
561 if (next_free_value > max_value - to_add ||
562 next_free_value + to_add > max_value)
563 next_free_value= max_value+1;
564 else
565 {
566 next_free_value+= to_add;
567 DBUG_ASSERT(next_free_value % real_increment == offset);
568 }
569 }
570}
571
572
573/**
574 Write initial sequence information for CREATE and ALTER to sequence table
575*/
576
577int sequence_definition::write_initial_sequence(TABLE *table)
578{
579 int error;
580 THD *thd= table->in_use;
581 MY_BITMAP *save_write_set;
582
583 store_fields(table);
584 /* Store the sequence values in table share */
585 table->s->sequence->copy(this);
586 /*
587 Sequence values will be replicated as a statement
588 like 'create sequence'. So disable binary log temporarily
589 */
590 tmp_disable_binlog(thd);
591 save_write_set= table->write_set;
592 table->write_set= &table->s->all_set;
593 table->s->sequence->initialized= SEQUENCE::SEQ_IN_PREPARE;
594 error= table->file->ha_write_row(table->record[0]);
595 table->s->sequence->initialized= SEQUENCE::SEQ_UNINTIALIZED;
596 reenable_binlog(thd);
597 table->write_set= save_write_set;
598 if (unlikely(error))
599 table->file->print_error(error, MYF(0));
600 else
601 {
602 /*
603 Sequence structure is up to date and table has one row,
604 sequence is now usable
605 */
606 table->s->sequence->initialized= SEQUENCE::SEQ_READY_TO_USE;
607 }
608 return error;
609}
610
611
612/**
613 Store current sequence values into the sequence table
614*/
615
616int sequence_definition::write(TABLE *table, bool all_fields)
617{
618 int error;
619 MY_BITMAP *save_rpl_write_set, *save_write_set, *save_read_set;
620 DBUG_ASSERT(((ha_sequence*) table->file)->is_locked());
621
622 save_rpl_write_set= table->rpl_write_set;
623 if (likely(!all_fields))
624 {
625 /* Only write next_value and round to binary log */
626 table->rpl_write_set= &table->def_rpl_write_set;
627 bitmap_clear_all(table->rpl_write_set);
628 bitmap_set_bit(table->rpl_write_set, NEXT_FIELD_NO);
629 bitmap_set_bit(table->rpl_write_set, ROUND_FIELD_NO);
630 }
631 else
632 table->rpl_write_set= &table->s->all_set;
633
634 /* Update table */
635 save_write_set= table->write_set;
636 save_read_set= table->read_set;
637 table->read_set= table->write_set= &table->s->all_set;
638 table->file->column_bitmaps_signal();
639 store_fields(table);
640 if (unlikely((error= table->file->ha_write_row(table->record[0]))))
641 table->file->print_error(error, MYF(0));
642 table->rpl_write_set= save_rpl_write_set;
643 table->read_set= save_read_set;
644 table->write_set= save_write_set;
645 table->file->column_bitmaps_signal();
646 return error;
647}
648
649
650/**
651 Get next value for sequence
652
653 @param in table Sequence table
654 @param in second_round
655 1 if recursive call (out of values once)
656 @param out error Set this to <> 0 in case of error
657 push_warning_printf(WARN_LEVEL_WARN) has been called
658
659
660 @retval 0 Next number or error. Check error variable
661 # Next sequence number
662
663 NOTES:
664 Return next_free_value and increment next_free_value to next allowed
665 value or reserved_value if out of range
666 if next_free_value >= reserved_value reserve a new range by writing
667 a record to the sequence table.
668
669 The state of the variables:
670 next_free_value contains next value to use. It may be
671 bigger than max_value or less than min_value if end of sequence.
672 reserved_until contains the last value written to the file. All
673 values up to this one can be used.
674 If next_free_value >= reserved_until we have to reserve new
675 values from the sequence.
676*/
677
678longlong SEQUENCE::next_value(TABLE *table, bool second_round, int *error)
679{
680 longlong res_value, org_reserved_until, add_to;
681 bool out_of_values;
682 DBUG_ENTER("SEQUENCE::next_value");
683
684 *error= 0;
685 if (!second_round)
686 write_lock(table);
687
688 res_value= next_free_value;
689 next_free_value= increment_value(next_free_value);
690
691 if ((real_increment > 0 && res_value < reserved_until) ||
692 (real_increment < 0 && res_value > reserved_until))
693 {
694 write_unlock(table);
695 DBUG_RETURN(res_value);
696 }
697
698 if (all_values_used)
699 goto err;
700
701 org_reserved_until= reserved_until;
702
703 /*
704 Out of cached values, reserve 'cache' new ones
705 The cache value is checked on insert so the following can't
706 overflow
707 */
708 add_to= cache ? real_increment * cache : real_increment;
709 out_of_values= 0;
710
711 if (real_increment > 0)
712 {
713 if (reserved_until + add_to > max_value ||
714 reserved_until > max_value - add_to)
715 {
716 reserved_until= max_value + 1;
717 out_of_values= res_value >= reserved_until;
718 }
719 else
720 reserved_until+= add_to;
721 }
722 else
723 {
724 if (reserved_until + add_to < min_value ||
725 reserved_until < min_value - add_to)
726 {
727 reserved_until= min_value - 1;
728 out_of_values= res_value <= reserved_until;
729 }
730 else
731 reserved_until+= add_to;
732 }
733 if (out_of_values)
734 {
735 if (!cycle || second_round)
736 goto err;
737 round++;
738 reserved_until= real_increment >0 ? min_value : max_value;
739 adjust_values(reserved_until); // Fix next_free_value
740 /*
741 We have to do everything again to ensure that the given range was
742 not empty, which could happen if increment == 0
743 */
744 DBUG_RETURN(next_value(table, 1, error));
745 }
746
747 if (unlikely((*error= write(table, 0))))
748 {
749 reserved_until= org_reserved_until;
750 next_free_value= res_value;
751 }
752
753 write_unlock(table);
754 DBUG_RETURN(res_value);
755
756err:
757 write_unlock(table);
758 my_error(ER_SEQUENCE_RUN_OUT, MYF(0), table->s->db.str,
759 table->s->table_name.str);
760 *error= ER_SEQUENCE_RUN_OUT;
761 all_values_used= 1;
762 DBUG_RETURN(0);
763}
764
765
766/*
767 The following functions is to detect if a table has been dropped
768 and re-created since last call to PREVIOUS VALUE.
769
770 This is needed as we don't delete dropped sequences from THD->sequence
771 for DROP TABLE.
772*/
773
774bool SEQUENCE_LAST_VALUE::check_version(TABLE *table)
775{
776 DBUG_ASSERT(table->s->tabledef_version.length == MY_UUID_SIZE);
777 return memcmp(table->s->tabledef_version.str, table_version,
778 MY_UUID_SIZE) != 0;
779}
780
781void SEQUENCE_LAST_VALUE::set_version(TABLE *table)
782{
783 memcpy(table_version, table->s->tabledef_version.str, MY_UUID_SIZE);
784}
785
786/**
787 Set the next value for sequence
788
789 @param in table Sequence table
790 @param in next_val Next free value
791 @param in next_round Round for 'next_value' (in case of cycles)
792 @param in is_used 1 if next_val is already used
793
794 @retval 0 ok, value adjusted
795 -1 value was less than current value
796 1 error when storing value
797
798 @comment
799 A new value is set only if "nextval,next_round" is less than
800 "next_free_value,round". This is needed as in replication
801 setvalue() calls may come out to the slave out-of-order.
802 Storing only the highest value ensures that sequence object will always
803 contain the highest used value when the slave is promoted to a master.
804*/
805
806int SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round,
807 bool is_used)
808{
809 int error= -1;
810 bool needs_to_be_stored= 0;
811 longlong org_reserved_until= reserved_until;
812 longlong org_next_free_value= next_free_value;
813 ulonglong org_round= round;
814 DBUG_ENTER("SEQUENCE::set_value");
815
816 write_lock(table);
817 if (is_used)
818 next_val= increment_value(next_val);
819
820 if (round > next_round)
821 goto end; // error = -1
822 if (round == next_round)
823 {
824 if (real_increment > 0 ?
825 next_val < next_free_value :
826 next_val > next_free_value)
827 goto end; // error = -1
828 if (next_val == next_free_value)
829 {
830 error= 0;
831 goto end;
832 }
833 }
834 else if (cycle == 0)
835 {
836 // round < next_round && no cycles, which is impossible
837 my_error(ER_SEQUENCE_RUN_OUT, MYF(0), table->s->db.str,
838 table->s->table_name.str);
839 error= 1;
840 goto end;
841 }
842 else
843 needs_to_be_stored= 1;
844
845 round= next_round;
846 adjust_values(next_val);
847 if ((real_increment > 0 ?
848 next_free_value > reserved_until :
849 next_free_value < reserved_until) ||
850 needs_to_be_stored)
851 {
852 reserved_until= next_free_value;
853 if (write(table, 0))
854 {
855 reserved_until= org_reserved_until;
856 next_free_value= org_next_free_value;
857 round= org_round;
858 error= 1;
859 goto end;
860 }
861 }
862 error= 0;
863
864end:
865 write_unlock(table);
866 DBUG_RETURN(error);
867}
868
869
870bool Sql_cmd_alter_sequence::execute(THD *thd)
871{
872 int error= 0;
873 int trapped_errors= 0;
874 LEX *lex= thd->lex;
875 TABLE_LIST *first_table= lex->query_tables;
876 TABLE *table;
877 sequence_definition *new_seq= lex->create_info.seq_create_info;
878 SEQUENCE *seq;
879 No_such_table_error_handler no_such_table_handler;
880 DBUG_ENTER("Sql_cmd_alter_sequence::execute");
881
882 if (check_access(thd, ALTER_ACL, first_table->db.str,
883 &first_table->grant.privilege,
884 &first_table->grant.m_internal,
885 0, 0))
886 DBUG_RETURN(TRUE); /* purecov: inspected */
887
888 if (check_grant(thd, ALTER_ACL, first_table, FALSE, 1, FALSE))
889 DBUG_RETURN(TRUE); /* purecov: inspected */
890
891 if (if_exists())
892 thd->push_internal_handler(&no_such_table_handler);
893 error= open_and_lock_tables(thd, first_table, FALSE, 0);
894 if (if_exists())
895 {
896 trapped_errors= no_such_table_handler.safely_trapped_errors();
897 thd->pop_internal_handler();
898 }
899 if (unlikely(error))
900 {
901 if (trapped_errors)
902 {
903 StringBuffer<FN_REFLEN> tbl_name;
904 tbl_name.append(&first_table->db);
905 tbl_name.append('.');
906 tbl_name.append(&first_table->table_name);
907 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
908 ER_UNKNOWN_SEQUENCES,
909 ER_THD(thd, ER_UNKNOWN_SEQUENCES),
910 tbl_name.c_ptr_safe());
911 my_ok(thd);
912 DBUG_RETURN(FALSE);
913 }
914 DBUG_RETURN(TRUE);
915 }
916
917 table= first_table->table;
918 seq= table->s->sequence;
919 new_seq->reserved_until= seq->reserved_until;
920
921 /* Copy from old sequence those fields that the user didn't specified */
922 if (!(new_seq->used_fields & seq_field_used_increment))
923 new_seq->increment= seq->increment;
924 if (!(new_seq->used_fields & seq_field_used_min_value))
925 new_seq->min_value= seq->min_value;
926 if (!(new_seq->used_fields & seq_field_used_max_value))
927 new_seq->max_value= seq->max_value;
928 if (!(new_seq->used_fields & seq_field_used_start))
929 new_seq->start= seq->start;
930 if (!(new_seq->used_fields & seq_field_used_cache))
931 new_seq->cache= seq->cache;
932 if (!(new_seq->used_fields & seq_field_used_cycle))
933 new_seq->cycle= seq->cycle;
934
935 /* If we should restart from a new value */
936 if (new_seq->used_fields & seq_field_used_restart)
937 {
938 if (!(new_seq->used_fields & seq_field_used_restart_value))
939 new_seq->restart= new_seq->start;
940 new_seq->reserved_until= new_seq->restart;
941 }
942
943 /* Let check_and_adjust think all fields are used */
944 new_seq->used_fields= ~0;
945 if (new_seq->check_and_adjust(0))
946 {
947 my_error(ER_SEQUENCE_INVALID_DATA, MYF(0),
948 first_table->db.str,
949 first_table->table_name.str);
950 error= 1;
951 goto end;
952 }
953
954 table->s->sequence->write_lock(table);
955 if (likely(!(error= new_seq->write(table, 1))))
956 {
957 /* Store the sequence values in table share */
958 table->s->sequence->copy(new_seq);
959 }
960 else
961 table->file->print_error(error, MYF(0));
962 table->s->sequence->write_unlock(table);
963 if (trans_commit_stmt(thd))
964 error= 1;
965 if (trans_commit_implicit(thd))
966 error= 1;
967 if (likely(!error))
968 error= write_bin_log(thd, 1, thd->query(), thd->query_length());
969 if (likely(!error))
970 my_ok(thd);
971
972end:
973 DBUG_RETURN(error);
974}
975