summaryrefslogtreecommitdiff
path: root/sql/sql_sequence.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_sequence.h')
-rw-r--r--sql/sql_sequence.h152
1 files changed, 127 insertions, 25 deletions
diff --git a/sql/sql_sequence.h b/sql/sql_sequence.h
index 29c589e67cd..4b3f102509b 100644
--- a/sql/sql_sequence.h
+++ b/sql/sql_sequence.h
@@ -25,12 +25,35 @@
#define seq_field_used_cycle 32
#define seq_field_used_restart 64
#define seq_field_used_restart_value 128
+#define seq_field_used_as 256
+#define seq_field_specified_min_value 512
+#define seq_field_specified_max_value 1024
/* Field position in sequence table for some fields we refer to directly */
#define NEXT_FIELD_NO 0
#define MIN_VALUE_FIELD_NO 1
#define ROUND_FIELD_NO 7
+#include "mysql_com.h"
+#include "sql_type_int.h"
+
+class Create_field;
+class Type_handler;
+
+struct Sequence_field_definition
+{
+ const char *field_name;
+ uint length;
+ const Type_handler *type_handler;
+ LEX_CSTRING comment;
+ ulong flags;
+};
+
+struct Sequence_row_definition
+{
+ Sequence_field_definition fields[9];
+};
+
/**
sequence_definition is used when defining a sequence as part of create
*/
@@ -39,33 +62,56 @@ class sequence_definition :public Sql_alloc
{
public:
sequence_definition():
- min_value(1), max_value(LONGLONG_MAX-1), start(1), increment(1),
- cache(1000), round(0), restart(0), cycle(0), used_fields(0)
+ min_value_from_parser(1, false),
+ max_value_from_parser(LONGLONG_MAX-1, false), start_from_parser(1, false),
+ increment(1), cache(1000), round(0), restart_from_parser(0, false),
+ cycle(0), used_fields(0),
+ /*
+ We use value type and is_unsigned instead of a handler because
+ Type_handler is incomplete, which we cannot initialise here with
+ &type_handler_slonglong.
+ */
+ value_type(MYSQL_TYPE_LONGLONG), is_unsigned(false)
{}
longlong reserved_until;
longlong min_value;
longlong max_value;
longlong start;
+ Longlong_hybrid min_value_from_parser;
+ Longlong_hybrid max_value_from_parser;
+ Longlong_hybrid start_from_parser;
longlong increment;
longlong cache;
ulonglong round;
longlong restart; // alter sequence restart value
+ Longlong_hybrid restart_from_parser;
bool cycle;
uint used_fields; // Which fields where used in CREATE
+ enum_field_types value_type; // value type of the sequence
+ bool is_unsigned;
- bool check_and_adjust(bool set_reserved_until);
+ Type_handler const *value_type_handler();
+ /* max value for the value type, e.g. 32767 for smallint. */
+ longlong value_type_max();
+ /* min value for the value type, e.g. -32768 for smallint. */
+ longlong value_type_min();
+ bool check_and_adjust(THD *thd, bool set_reserved_until);
void store_fields(TABLE *table);
void read_fields(TABLE *table);
int write_initial_sequence(TABLE *table);
int write(TABLE *table, bool all_fields);
/* This must be called after sequence data has been updated */
void adjust_values(longlong next_value);
+ longlong truncate_value(const Longlong_hybrid& original);
inline void print_dbug()
{
DBUG_PRINT("sequence", ("reserved: %lld start: %lld increment: %lld min_value: %lld max_value: %lld cache: %lld round: %lld",
reserved_until, start, increment, min_value,
max_value, cache, round));
}
+ static bool is_allowed_value_type(enum_field_types type);
+ bool prepare_sequence_fields(List<Create_field> *fields, bool alter);
+
protected:
/*
The following values are the values from sequence_definition
@@ -107,31 +153,90 @@ public:
longlong next_value(TABLE *table, bool second_round, int *error);
int set_value(TABLE *table, longlong next_value, ulonglong round_arg,
bool is_used);
- longlong increment_value(longlong value)
+
+ bool all_values_used;
+ seq_init initialized;
+
+private:
+ /**
+ Check that a value is within a relevant bound
+
+ If increasing sequence, check that the value is lower than an
+ upper bound, otherwise check that the value is higher than a lower
+ bound.
+
+ @param in value The value to check
+ @param in upper The upper bound
+ @param in lower The lower bound
+ @param in increasing Which bound to check
+
+ @retval true The value is within the bound.
+ false The value is out of the bound.
+ */
+ bool within_bound(const longlong value, const longlong upper,
+ const longlong lower, bool increasing)
+ {
+ return
+ (is_unsigned && increasing && (ulonglong) value < (ulonglong) upper) ||
+ (is_unsigned && !increasing && (ulonglong) value > (ulonglong) lower) ||
+ (!is_unsigned && increasing && value < upper) ||
+ (!is_unsigned && !increasing && value > lower);
+ }
+
+ /**
+ Increment a value, subject to truncation
+
+ Truncating to the nearer value between max_value + 1 and min_value
+ - 1
+
+ @param in value The original value
+ @param in increment The increment to add to the value
+
+ @return The value after increment and possible truncation
+ */
+ longlong increment_value(longlong value, const longlong increment)
{
- if (real_increment > 0)
+ if (is_unsigned)
{
- if (value > max_value - real_increment ||
- value + real_increment > max_value)
- value= max_value + 1;
+ if (increment > 0)
+ {
+ if (/* in case value + increment overflows */
+ (ulonglong) value >
+ (ulonglong) max_value - (ulonglong) increment ||
+ /* in case max_value - increment underflows */
+ (ulonglong) value + (ulonglong) increment >
+ (ulonglong) max_value)
+ value= max_value + 1;
+ else
+ value+= increment;
+ }
else
- value+= real_increment;
- }
- else
- {
- if (value + real_increment < min_value ||
- value < min_value - real_increment)
- value= min_value - 1;
+ {
+ if ((ulonglong) value - (ulonglong) (-increment) <
+ (ulonglong) min_value ||
+ (ulonglong) value <
+ (ulonglong) min_value + (ulonglong) (-increment))
+ value= min_value - 1;
+ else
+ value+= increment;
+ }
+ } else
+ if (increment > 0)
+ {
+ if (value > max_value - increment || value + increment > max_value)
+ value= max_value + 1;
+ else
+ value+= increment;
+ }
else
- value+= real_increment;
- }
+ {
+ if (value + increment < min_value || value < min_value - increment)
+ value= min_value - 1;
+ else
+ value+= increment;
+ }
return value;
}
-
- bool all_values_used;
- seq_init initialized;
-
-private:
mysql_rwlock_t mutex;
};
@@ -159,9 +264,6 @@ public:
uchar table_version[MY_UUID_SIZE];
};
-
-class Create_field;
-extern bool prepare_sequence_fields(THD *thd, List<Create_field> *fields);
extern bool check_sequence_fields(LEX *lex, List<Create_field> *fields);
extern bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list);
#endif /* SQL_SEQUENCE_INCLUDED */