mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
SQL: 0.3 per column versioning syntax, .frm, optimized updates and tests
This commit is contained in:
committed by
Aleksey Midenkov
parent
2db17e6624
commit
a9a56b2355
@@ -2033,3 +2033,86 @@ Sys_end INT GENERATED ALWAYS AS ROW END,
|
|||||||
PERIOD FOR SYSTEM_TIME (Sys_start, Sys_end)
|
PERIOD FOR SYSTEM_TIME (Sys_start, Sys_end)
|
||||||
) WITH SYSTEM VERSIONING;
|
) WITH SYSTEM VERSIONING;
|
||||||
ERROR HY000: System end field must be of type TIMESTAMP
|
ERROR HY000: System end field must be of type TIMESTAMP
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT WITH SYSTEM VERSIONING,
|
||||||
|
B INT
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`A` int(11) DEFAULT NULL,
|
||||||
|
`B` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING,
|
||||||
|
`sys_trx_start` timestamp(6) NULL GENERATED AS ROW START,
|
||||||
|
`sys_trx_end` timestamp(6) NULL GENERATED AS ROW END,
|
||||||
|
PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT WITH SYSTEM VERSIONING,
|
||||||
|
B INT
|
||||||
|
) WITH SYSTEM VERSIONING;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`A` int(11) DEFAULT NULL,
|
||||||
|
`B` int(11) DEFAULT NULL,
|
||||||
|
`sys_trx_start` timestamp(6) NULL GENERATED AS ROW START,
|
||||||
|
`sys_trx_end` timestamp(6) NULL GENERATED AS ROW END,
|
||||||
|
PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT,
|
||||||
|
B INT WITHOUT SYSTEM VERSIONING
|
||||||
|
);
|
||||||
|
ERROR HY000: Every field specified unversioned in versioned table
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT,
|
||||||
|
B INT WITHOUT SYSTEM VERSIONING
|
||||||
|
) WITH SYSTEM VERSIONING;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`A` int(11) DEFAULT NULL,
|
||||||
|
`B` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING,
|
||||||
|
`sys_trx_start` timestamp(6) NULL GENERATED AS ROW START,
|
||||||
|
`sys_trx_end` timestamp(6) NULL GENERATED AS ROW END,
|
||||||
|
PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT WITH SYSTEM VERSIONING,
|
||||||
|
B INT WITHOUT SYSTEM VERSIONING
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`A` int(11) DEFAULT NULL,
|
||||||
|
`B` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING,
|
||||||
|
`sys_trx_start` timestamp(6) NULL GENERATED AS ROW START,
|
||||||
|
`sys_trx_end` timestamp(6) NULL GENERATED AS ROW END,
|
||||||
|
PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT WITH SYSTEM VERSIONING,
|
||||||
|
B INT WITHOUT SYSTEM VERSIONING
|
||||||
|
) WITH SYSTEM VERSIONING;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`A` int(11) DEFAULT NULL,
|
||||||
|
`B` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING,
|
||||||
|
`sys_trx_start` timestamp(6) NULL GENERATED AS ROW START,
|
||||||
|
`sys_trx_end` timestamp(6) NULL GENERATED AS ROW END,
|
||||||
|
PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT WITHOUT SYSTEM VERSIONING
|
||||||
|
);
|
||||||
|
ERROR HY000: Every field specified unversioned in versioned table
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT WITHOUT SYSTEM VERSIONING
|
||||||
|
) WITH SYSTEM VERSIONING;
|
||||||
|
ERROR HY000: Every field specified unversioned in versioned table
|
||||||
|
@@ -1227,3 +1227,35 @@ No A B C D
|
|||||||
2 1 1 1 1
|
2 1 1 1 1
|
||||||
3 1 1 1 1
|
3 1 1 1 1
|
||||||
drop procedure verify_vtq;
|
drop procedure verify_vtq;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
name VARCHAR(128) WITH SYSTEM VERSIONING,
|
||||||
|
salary BIGINT
|
||||||
|
);
|
||||||
|
INSERT INTO t1 VALUES (1, "Jeremy", 3000);
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
name VARCHAR(128) WITH SYSTEM VERSIONING,
|
||||||
|
salary BIGINT
|
||||||
|
);
|
||||||
|
INSERT INTO t2 VALUES (1, "Jeremy", 4000);
|
||||||
|
SELECT sys_trx_start INTO @tmp1 FROM t1;
|
||||||
|
SELECT sys_trx_start INTO @tmp2 FROM t2;
|
||||||
|
UPDATE t1, t2 SET t1.name="Jerry", t2.name="Jerry" WHERE t1.id=t2.id AND t1.name="Jeremy";
|
||||||
|
SELECT @tmp1 < sys_trx_start, name FROM t1;
|
||||||
|
@tmp1 < sys_trx_start name
|
||||||
|
1 Jerry
|
||||||
|
SELECT @tmp2 < sys_trx_start, name FROM t2;
|
||||||
|
@tmp2 < sys_trx_start name
|
||||||
|
1 Jerry
|
||||||
|
SELECT sys_trx_start INTO @tmp1 FROM t1;
|
||||||
|
SELECT sys_trx_start INTO @tmp2 FROM t2;
|
||||||
|
UPDATE t1, t2 SET t1.salary=2500, t2.salary=2500 WHERE t1.id=t2.id AND t1.name="Jerry";
|
||||||
|
SELECT @tmp1 = sys_trx_start, salary FROM t1;
|
||||||
|
@tmp1 = sys_trx_start salary
|
||||||
|
1 2500
|
||||||
|
SELECT @tmp2 = sys_trx_start, salary FROM t2;
|
||||||
|
@tmp2 = sys_trx_start salary
|
||||||
|
1 2500
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
@@ -845,3 +845,20 @@ No A B C D
|
|||||||
1 1 1 1 1
|
1 1 1 1 1
|
||||||
2 1 1 1 1
|
2 1 1 1 1
|
||||||
drop procedure verify_vtq;
|
drop procedure verify_vtq;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
A INT,
|
||||||
|
B INT WITHOUT SYSTEM VERSIONING
|
||||||
|
) WITH SYSTEM VERSIONING;
|
||||||
|
INSERT INTO t1 VALUES(1, 1, 1);
|
||||||
|
SELECT sys_trx_start INTO @tmp1 FROM t1;
|
||||||
|
UPDATE t1 SET A=11, B=11 WHERE id=1;
|
||||||
|
SELECT @tmp1 < sys_trx_start, A, B FROM t1;
|
||||||
|
@tmp1 < sys_trx_start A B
|
||||||
|
1 11 11
|
||||||
|
SELECT sys_trx_start INTO @tmp1 FROM t1;
|
||||||
|
UPDATE t1 SET B=1 WHERE id=1;
|
||||||
|
SELECT @tmp1 = sys_trx_start, B FROM t1;
|
||||||
|
@tmp1 = sys_trx_start B
|
||||||
|
1 1
|
||||||
|
DROP TABLE t1;
|
||||||
|
@@ -1887,3 +1887,54 @@ create table t1 (
|
|||||||
Sys_end INT GENERATED ALWAYS AS ROW END,
|
Sys_end INT GENERATED ALWAYS AS ROW END,
|
||||||
PERIOD FOR SYSTEM_TIME (Sys_start, Sys_end)
|
PERIOD FOR SYSTEM_TIME (Sys_start, Sys_end)
|
||||||
) WITH SYSTEM VERSIONING;
|
) WITH SYSTEM VERSIONING;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT WITH SYSTEM VERSIONING,
|
||||||
|
B INT
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT WITH SYSTEM VERSIONING,
|
||||||
|
B INT
|
||||||
|
) WITH SYSTEM VERSIONING;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--error ER_NO_VERSIONED_FIELDS_IN_VERSIONED_TABLE
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT,
|
||||||
|
B INT WITHOUT SYSTEM VERSIONING
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT,
|
||||||
|
B INT WITHOUT SYSTEM VERSIONING
|
||||||
|
) WITH SYSTEM VERSIONING;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT WITH SYSTEM VERSIONING,
|
||||||
|
B INT WITHOUT SYSTEM VERSIONING
|
||||||
|
);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT WITH SYSTEM VERSIONING,
|
||||||
|
B INT WITHOUT SYSTEM VERSIONING
|
||||||
|
) WITH SYSTEM VERSIONING;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--error ER_NO_VERSIONED_FIELDS_IN_VERSIONED_TABLE
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT WITHOUT SYSTEM VERSIONING
|
||||||
|
);
|
||||||
|
|
||||||
|
--error ER_NO_VERSIONED_FIELDS_IN_VERSIONED_TABLE
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
A INT WITHOUT SYSTEM VERSIONING
|
||||||
|
) WITH SYSTEM VERSIONING;
|
||||||
|
@@ -1119,3 +1119,32 @@ delimiter ;~~
|
|||||||
|
|
||||||
call verify_vtq;
|
call verify_vtq;
|
||||||
drop procedure verify_vtq;
|
drop procedure verify_vtq;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
name VARCHAR(128) WITH SYSTEM VERSIONING,
|
||||||
|
salary BIGINT
|
||||||
|
);
|
||||||
|
INSERT INTO t1 VALUES (1, "Jeremy", 3000);
|
||||||
|
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
name VARCHAR(128) WITH SYSTEM VERSIONING,
|
||||||
|
salary BIGINT
|
||||||
|
);
|
||||||
|
INSERT INTO t2 VALUES (1, "Jeremy", 4000);
|
||||||
|
|
||||||
|
SELECT sys_trx_start INTO @tmp1 FROM t1;
|
||||||
|
SELECT sys_trx_start INTO @tmp2 FROM t2;
|
||||||
|
UPDATE t1, t2 SET t1.name="Jerry", t2.name="Jerry" WHERE t1.id=t2.id AND t1.name="Jeremy";
|
||||||
|
SELECT @tmp1 < sys_trx_start, name FROM t1;
|
||||||
|
SELECT @tmp2 < sys_trx_start, name FROM t2;
|
||||||
|
|
||||||
|
SELECT sys_trx_start INTO @tmp1 FROM t1;
|
||||||
|
SELECT sys_trx_start INTO @tmp2 FROM t2;
|
||||||
|
UPDATE t1, t2 SET t1.salary=2500, t2.salary=2500 WHERE t1.id=t2.id AND t1.name="Jerry";
|
||||||
|
SELECT @tmp1 = sys_trx_start, salary FROM t1;
|
||||||
|
SELECT @tmp2 = sys_trx_start, salary FROM t2;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
@@ -726,3 +726,21 @@ delimiter ;~~
|
|||||||
|
|
||||||
call verify_vtq;
|
call verify_vtq;
|
||||||
drop procedure verify_vtq;
|
drop procedure verify_vtq;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
id BIGINT PRIMARY KEY,
|
||||||
|
A INT,
|
||||||
|
B INT WITHOUT SYSTEM VERSIONING
|
||||||
|
) WITH SYSTEM VERSIONING;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES(1, 1, 1);
|
||||||
|
|
||||||
|
SELECT sys_trx_start INTO @tmp1 FROM t1;
|
||||||
|
UPDATE t1 SET A=11, B=11 WHERE id=1;
|
||||||
|
SELECT @tmp1 < sys_trx_start, A, B FROM t1;
|
||||||
|
|
||||||
|
SELECT sys_trx_start INTO @tmp1 FROM t1;
|
||||||
|
UPDATE t1 SET B=1 WHERE id=1;
|
||||||
|
SELECT @tmp1 = sys_trx_start, B FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
14
sql/field.h
14
sql/field.h
@@ -3872,6 +3872,13 @@ class Column_definition: public Sql_alloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
enum enum_column_versioning
|
||||||
|
{
|
||||||
|
VERSIONING_NOT_SET,
|
||||||
|
WITH_VERSIONING,
|
||||||
|
WITHOUT_VERSIONING
|
||||||
|
};
|
||||||
|
|
||||||
const char *field_name;
|
const char *field_name;
|
||||||
LEX_STRING comment; // Comment for field
|
LEX_STRING comment; // Comment for field
|
||||||
Item *on_update; // ON UPDATE NOW()
|
Item *on_update; // ON UPDATE NOW()
|
||||||
@@ -3907,6 +3914,8 @@ public:
|
|||||||
*default_value, // Default value
|
*default_value, // Default value
|
||||||
*check_constraint; // Check constraint
|
*check_constraint; // Check constraint
|
||||||
|
|
||||||
|
enum_column_versioning versioning;
|
||||||
|
|
||||||
Column_definition():
|
Column_definition():
|
||||||
comment(null_lex_str),
|
comment(null_lex_str),
|
||||||
on_update(NULL), sql_type(MYSQL_TYPE_NULL), length(0), decimals(0),
|
on_update(NULL), sql_type(MYSQL_TYPE_NULL), length(0), decimals(0),
|
||||||
@@ -3914,7 +3923,8 @@ public:
|
|||||||
interval(0), charset(&my_charset_bin),
|
interval(0), charset(&my_charset_bin),
|
||||||
srid(0), geom_type(Field::GEOM_GEOMETRY),
|
srid(0), geom_type(Field::GEOM_GEOMETRY),
|
||||||
option_list(NULL), pack_flag(0),
|
option_list(NULL), pack_flag(0),
|
||||||
vcol_info(0), default_value(0), check_constraint(0)
|
vcol_info(0), default_value(0), check_constraint(0),
|
||||||
|
versioning(VERSIONING_NOT_SET)
|
||||||
{
|
{
|
||||||
interval_list.empty();
|
interval_list.empty();
|
||||||
}
|
}
|
||||||
@@ -4276,6 +4286,7 @@ bool check_expression(Virtual_column_info *vcol, const char *name,
|
|||||||
|
|
||||||
#define FIELDFLAG_TREAT_BIT_AS_CHAR 4096U /* use Field_bit_as_char */
|
#define FIELDFLAG_TREAT_BIT_AS_CHAR 4096U /* use Field_bit_as_char */
|
||||||
#define FIELDFLAG_LONG_DECIMAL 8192U
|
#define FIELDFLAG_LONG_DECIMAL 8192U
|
||||||
|
#define FIELDFLAG_WITHOUT_SYSTEM_VERSIONING 8192U
|
||||||
#define FIELDFLAG_NO_DEFAULT 16384U /* sql */
|
#define FIELDFLAG_NO_DEFAULT 16384U /* sql */
|
||||||
#define FIELDFLAG_MAYBE_NULL 32768U // sql
|
#define FIELDFLAG_MAYBE_NULL 32768U // sql
|
||||||
#define FIELDFLAG_HEX_ESCAPE 0x10000U
|
#define FIELDFLAG_HEX_ESCAPE 0x10000U
|
||||||
@@ -4302,5 +4313,6 @@ bool check_expression(Virtual_column_info *vcol, const char *name,
|
|||||||
#define f_no_default(x) ((x) & FIELDFLAG_NO_DEFAULT)
|
#define f_no_default(x) ((x) & FIELDFLAG_NO_DEFAULT)
|
||||||
#define f_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR)
|
#define f_bit_as_char(x) ((x) & FIELDFLAG_TREAT_BIT_AS_CHAR)
|
||||||
#define f_is_hex_escape(x) ((x) & FIELDFLAG_HEX_ESCAPE)
|
#define f_is_hex_escape(x) ((x) & FIELDFLAG_HEX_ESCAPE)
|
||||||
|
#define f_without_system_versioning(x) ((x) & FIELDFLAG_WITHOUT_SYSTEM_VERSIONING)
|
||||||
|
|
||||||
#endif /* FIELD_INCLUDED */
|
#endif /* FIELD_INCLUDED */
|
||||||
|
123
sql/handler.cc
123
sql/handler.cc
@@ -6582,12 +6582,35 @@ static bool create_sys_trx_field_if_missing(THD *thd, const char *field_name,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool System_versioning_info::add_implicit_fields(THD *thd,
|
bool System_versioning_info::add_versioning_info(THD *thd,
|
||||||
Alter_info *alter_info)
|
Alter_info *alter_info)
|
||||||
{
|
{
|
||||||
if (!declared_system_versioning)
|
DBUG_ASSERT(versioned());
|
||||||
|
|
||||||
|
if (!declared_system_versioning && !has_versioned_fields)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
bool without_system_versioning_by_default= !declared_system_versioning;
|
||||||
|
List_iterator<Create_field> it(alter_info->create_list);
|
||||||
|
while (Create_field *f= it++)
|
||||||
|
{
|
||||||
|
const char *name= f->field_name;
|
||||||
|
size_t len= strlen(name);
|
||||||
|
if (generated_as_row.start &&
|
||||||
|
!strncmp(name, generated_as_row.start->c_ptr(), len))
|
||||||
|
continue;
|
||||||
|
if (generated_as_row.end &&
|
||||||
|
!strncmp(name, generated_as_row.end->c_ptr(), len))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (f->versioning == Column_definition::VERSIONING_NOT_SET &&
|
||||||
|
without_system_versioning_by_default)
|
||||||
|
f->flags|= WITHOUT_SYSTEM_VERSIONING_FLAG;
|
||||||
|
|
||||||
|
else if (f->versioning == Column_definition::WITHOUT_VERSIONING)
|
||||||
|
f->flags|= WITHOUT_SYSTEM_VERSIONING_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
// If user specified some of these he must specify the others too. Do nothing.
|
// If user specified some of these he must specify the others too. Do nothing.
|
||||||
if (generated_as_row.start || generated_as_row.end ||
|
if (generated_as_row.start || generated_as_row.end ||
|
||||||
period_for_system_time.start || period_for_system_time.end)
|
period_for_system_time.start || period_for_system_time.end)
|
||||||
@@ -6602,3 +6625,99 @@ bool System_versioning_info::add_implicit_fields(THD *thd,
|
|||||||
create_string(thd->mem_root, &period_for_system_time.end,
|
create_string(thd->mem_root, &period_for_system_time.end,
|
||||||
"sys_trx_end");
|
"sys_trx_end");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool System_versioning_info::check(THD *thd, Alter_info *alter_info)
|
||||||
|
{
|
||||||
|
if (!versioned())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (add_versioning_info(thd, alter_info))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bool r= false;
|
||||||
|
|
||||||
|
{
|
||||||
|
int not_set= 0;
|
||||||
|
int with= 0;
|
||||||
|
List_iterator<Create_field> it(alter_info->create_list);
|
||||||
|
while (const Create_field *f= it++)
|
||||||
|
{
|
||||||
|
const char *name= f->field_name;
|
||||||
|
size_t len= strlen(name);
|
||||||
|
if (generated_as_row.start &&
|
||||||
|
!strncmp(name, generated_as_row.start->c_ptr(), len))
|
||||||
|
continue;
|
||||||
|
if (generated_as_row.end &&
|
||||||
|
!strncmp(name, generated_as_row.end->c_ptr(), len))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (f->versioning == Column_definition::VERSIONING_NOT_SET)
|
||||||
|
not_set++;
|
||||||
|
else if (f->versioning == Column_definition::WITH_VERSIONING)
|
||||||
|
with++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool table_with_system_versioning=
|
||||||
|
declared_system_versioning || generated_as_row.start ||
|
||||||
|
generated_as_row.end || period_for_system_time.start ||
|
||||||
|
period_for_system_time.end;
|
||||||
|
|
||||||
|
if ((table_with_system_versioning && not_set == 0 && with == 0) ||
|
||||||
|
(!table_with_system_versioning && with == 0))
|
||||||
|
{
|
||||||
|
r= true;
|
||||||
|
my_error(ER_NO_VERSIONED_FIELDS_IN_VERSIONED_TABLE, MYF(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!declared_system_versioning && !has_versioned_fields)
|
||||||
|
{
|
||||||
|
r= true;
|
||||||
|
my_error(ER_MISSING_WITH_SYSTEM_VERSIONING, MYF(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!generated_as_row.start)
|
||||||
|
{
|
||||||
|
r= true;
|
||||||
|
my_error(ER_SYS_START_NOT_SPECIFIED, MYF(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!generated_as_row.end)
|
||||||
|
{
|
||||||
|
r= true;
|
||||||
|
my_error(ER_SYS_END_NOT_SPECIFIED, MYF(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!period_for_system_time.start || !period_for_system_time.end)
|
||||||
|
{
|
||||||
|
r= true;
|
||||||
|
my_error(ER_MISSING_PERIOD_FOR_SYSTEM_TIME, MYF(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!r)
|
||||||
|
{
|
||||||
|
if (my_strcasecmp(system_charset_info, generated_as_row.start->c_ptr(),
|
||||||
|
period_for_system_time.start->c_ptr()))
|
||||||
|
{
|
||||||
|
r= true;
|
||||||
|
my_error(ER_PERIOD_FOR_SYSTEM_TIME_CONTAINS_WRONG_START_COLUMN, MYF(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my_strcasecmp(system_charset_info, generated_as_row.end->c_ptr(),
|
||||||
|
period_for_system_time.end->c_ptr()))
|
||||||
|
{
|
||||||
|
r= true;
|
||||||
|
my_error(ER_PERIOD_FOR_SYSTEM_TIME_CONTAINS_WRONG_END_COLUMN, MYF(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r; // false means no error
|
||||||
|
}
|
||||||
|
|
||||||
|
bool System_versioning_info::versioned() const
|
||||||
|
{
|
||||||
|
return has_versioned_fields || has_unversioned_fields ||
|
||||||
|
declared_system_versioning || period_for_system_time.start ||
|
||||||
|
period_for_system_time.end || generated_as_row.start ||
|
||||||
|
generated_as_row.end;
|
||||||
|
}
|
||||||
|
@@ -1671,6 +1671,14 @@ struct Schema_specification_st
|
|||||||
|
|
||||||
struct System_versioning_info
|
struct System_versioning_info
|
||||||
{
|
{
|
||||||
|
System_versioning_info() :
|
||||||
|
period_for_system_time({NULL, NULL}),
|
||||||
|
generated_as_row({NULL, NULL}),
|
||||||
|
declared_system_versioning(false),
|
||||||
|
has_versioned_fields(false),
|
||||||
|
has_unversioned_fields(false)
|
||||||
|
{}
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
String *start, *end;
|
String *start, *end;
|
||||||
@@ -1693,13 +1701,28 @@ struct System_versioning_info
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true on failure */
|
/** Returns true on failure */
|
||||||
bool add_implicit_fields(THD *thd, Alter_info *alter_info);
|
bool add_versioning_info(THD *thd, Alter_info *alter_info);
|
||||||
|
|
||||||
|
/** Returns true on failure */
|
||||||
|
bool check(THD *thd, Alter_info *alter_info);
|
||||||
|
|
||||||
|
/** Returns true if table is versioned */
|
||||||
|
bool versioned() const;
|
||||||
|
|
||||||
/** User has added 'WITH SYSTEM VERSIONING' to table definition */
|
/** User has added 'WITH SYSTEM VERSIONING' to table definition */
|
||||||
bool declared_system_versioning;
|
bool declared_system_versioning : 1;
|
||||||
|
|
||||||
/** Table described by this structure have enabled system versioning */
|
/**
|
||||||
bool versioned;
|
At least one field was specified 'WITH SYSTEM VERSIONING'. Useful for
|
||||||
|
error handling.
|
||||||
|
*/
|
||||||
|
bool has_versioned_fields : 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
At least one field was specified 'WITHOUT SYSTEM VERSIONING'. Useful for
|
||||||
|
error handling.
|
||||||
|
*/
|
||||||
|
bool has_unversioned_fields : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1791,7 +1814,7 @@ struct Table_scope_and_contents_source_st
|
|||||||
|
|
||||||
bool versioned() const
|
bool versioned() const
|
||||||
{
|
{
|
||||||
return system_versioning_info.versioned;
|
return system_versioning_info.versioned();
|
||||||
}
|
}
|
||||||
const System_versioning_info *get_system_versioning_info() const
|
const System_versioning_info *get_system_versioning_info() const
|
||||||
{
|
{
|
||||||
|
@@ -703,6 +703,7 @@ static SYMBOL symbols[] = {
|
|||||||
{ "WHILE", SYM(WHILE_SYM)},
|
{ "WHILE", SYM(WHILE_SYM)},
|
||||||
{ "WINDOW", SYM(WINDOW_SYM)},
|
{ "WINDOW", SYM(WINDOW_SYM)},
|
||||||
{ "WITH", SYM(WITH)},
|
{ "WITH", SYM(WITH)},
|
||||||
|
{ "WITHOUT", SYM(WITHOUT)},
|
||||||
{ "WORK", SYM(WORK_SYM)},
|
{ "WORK", SYM(WORK_SYM)},
|
||||||
{ "WRAPPER", SYM(WRAPPER_SYM)},
|
{ "WRAPPER", SYM(WRAPPER_SYM)},
|
||||||
{ "WRITE", SYM(WRITE_SYM)},
|
{ "WRITE", SYM(WRITE_SYM)},
|
||||||
|
@@ -7537,3 +7537,6 @@ ER_SYS_START_FIELD_MUST_BE_BIGINT
|
|||||||
|
|
||||||
ER_SYS_END_FIELD_MUST_BE_BIGINT
|
ER_SYS_END_FIELD_MUST_BE_BIGINT
|
||||||
eng "System end field must be of type BIGINT UNSIGNED"
|
eng "System end field must be of type BIGINT UNSIGNED"
|
||||||
|
|
||||||
|
ER_NO_VERSIONED_FIELDS_IN_VERSIONED_TABLE
|
||||||
|
eng "Every field specified unversioned in versioned table"
|
||||||
|
@@ -5533,6 +5533,8 @@ class multi_update :public select_result_interceptor
|
|||||||
// For System Versioning (may need to insert new fields to a table).
|
// For System Versioning (may need to insert new fields to a table).
|
||||||
ha_rows updated_sys_ver;
|
ha_rows updated_sys_ver;
|
||||||
|
|
||||||
|
bool has_vers_fields;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
multi_update(THD *thd_arg, TABLE_LIST *ut, List<TABLE_LIST> *leaves_list,
|
multi_update(THD *thd_arg, TABLE_LIST *ut, List<TABLE_LIST> *leaves_list,
|
||||||
List<Item> *fields, List<Item> *values,
|
List<Item> *fields, List<Item> *values,
|
||||||
|
@@ -138,7 +138,6 @@ static void sql_kill_user(THD *thd, LEX_USER *user, killed_state state);
|
|||||||
static bool lock_tables_precheck(THD *thd, TABLE_LIST *tables);
|
static bool lock_tables_precheck(THD *thd, TABLE_LIST *tables);
|
||||||
static bool execute_show_status(THD *, TABLE_LIST *);
|
static bool execute_show_status(THD *, TABLE_LIST *);
|
||||||
static bool check_rename_table(THD *, TABLE_LIST *, TABLE_LIST *);
|
static bool check_rename_table(THD *, TABLE_LIST *, TABLE_LIST *);
|
||||||
static bool check_system_versioning(Table_scope_and_contents_source_st *);
|
|
||||||
|
|
||||||
const char *any_db="*any*"; // Special symbol for check_access
|
const char *any_db="*any*"; // Special symbol for check_access
|
||||||
|
|
||||||
@@ -3856,11 +3855,7 @@ mysql_execute_command(THD *thd)
|
|||||||
goto end_with_restore_list;
|
goto end_with_restore_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (System_versioning_info *info= create_info.get_system_versioning_info())
|
if (create_info.system_versioning_info.check(thd, &alter_info))
|
||||||
if (info->add_implicit_fields(thd, &alter_info))
|
|
||||||
goto end_with_restore_list;
|
|
||||||
|
|
||||||
if (check_system_versioning(&create_info))
|
|
||||||
goto end_with_restore_list;
|
goto end_with_restore_list;
|
||||||
|
|
||||||
/* Check privileges */
|
/* Check privileges */
|
||||||
@@ -7326,66 +7321,6 @@ bool check_fk_parent_table_access(THD *thd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Checks related to system versioning
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static bool check_system_versioning(Table_scope_and_contents_source_st *create_info)
|
|
||||||
{
|
|
||||||
const System_versioning_info *versioning_info = &create_info->system_versioning_info;
|
|
||||||
|
|
||||||
if (!versioning_info->versioned)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool r = false;
|
|
||||||
|
|
||||||
if (!versioning_info->declared_system_versioning)
|
|
||||||
{
|
|
||||||
r = true;
|
|
||||||
my_error(ER_MISSING_WITH_SYSTEM_VERSIONING, MYF(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!versioning_info->generated_as_row.start)
|
|
||||||
{
|
|
||||||
r = true;
|
|
||||||
my_error(ER_SYS_START_NOT_SPECIFIED, MYF(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!versioning_info->generated_as_row.end)
|
|
||||||
{
|
|
||||||
r = true;
|
|
||||||
my_error(ER_SYS_END_NOT_SPECIFIED, MYF(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!versioning_info->period_for_system_time.start || !versioning_info->period_for_system_time.end)
|
|
||||||
{
|
|
||||||
r = true;
|
|
||||||
my_error(ER_MISSING_PERIOD_FOR_SYSTEM_TIME, MYF(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!r)
|
|
||||||
{
|
|
||||||
if (my_strcasecmp(system_charset_info,
|
|
||||||
versioning_info->generated_as_row.start->c_ptr(),
|
|
||||||
versioning_info->period_for_system_time.start->c_ptr()))
|
|
||||||
{
|
|
||||||
r = true;
|
|
||||||
my_error(ER_PERIOD_FOR_SYSTEM_TIME_CONTAINS_WRONG_START_COLUMN, MYF(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (my_strcasecmp(system_charset_info,
|
|
||||||
versioning_info->generated_as_row.end->c_ptr(),
|
|
||||||
versioning_info->period_for_system_time.end->c_ptr()))
|
|
||||||
{
|
|
||||||
r = true;
|
|
||||||
my_error(ER_PERIOD_FOR_SYSTEM_TIME_CONTAINS_WRONG_END_COLUMN, MYF(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r; // false means no error
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Check stack size; Send error if there isn't enough stack to continue
|
Check stack size; Send error if there isn't enough stack to continue
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@@ -2133,6 +2133,11 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
|
|||||||
packet->append(STRING_WITH_LEN(" GENERATED AS ROW END"));
|
packet->append(STRING_WITH_LEN(" GENERATED AS ROW END"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (field->is_versioning_disabled())
|
||||||
|
{
|
||||||
|
packet->append(STRING_WITH_LEN(" WITHOUT SYSTEM VERSIONING"));
|
||||||
|
}
|
||||||
|
|
||||||
if (!limited_mysql_mode &&
|
if (!limited_mysql_mode &&
|
||||||
print_on_update_clause(field, &def_value, false))
|
print_on_update_clause(field, &def_value, false))
|
||||||
{
|
{
|
||||||
|
@@ -2989,6 +2989,8 @@ bool Column_definition::prepare_create_field(uint *blob_columns,
|
|||||||
pack_flag|= FIELDFLAG_MAYBE_NULL;
|
pack_flag|= FIELDFLAG_MAYBE_NULL;
|
||||||
if (flags & NO_DEFAULT_VALUE_FLAG)
|
if (flags & NO_DEFAULT_VALUE_FLAG)
|
||||||
pack_flag|= FIELDFLAG_NO_DEFAULT;
|
pack_flag|= FIELDFLAG_NO_DEFAULT;
|
||||||
|
if (flags & WITHOUT_SYSTEM_VERSIONING_FLAG)
|
||||||
|
pack_flag|= FIELDFLAG_WITHOUT_SYSTEM_VERSIONING;
|
||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -155,6 +155,17 @@ static bool check_fields(THD *thd, List<Item> &items)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool check_has_vers_fields(List<Item> &items)
|
||||||
|
{
|
||||||
|
List_iterator<Item> it(items);
|
||||||
|
while (Item *item= it++)
|
||||||
|
{
|
||||||
|
if (Item_field *item_field= item->field_for_view_update())
|
||||||
|
if (!(item_field->field->flags & WITHOUT_SYSTEM_VERSIONING_FLAG))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Re-read record if more columns are needed for error message.
|
Re-read record if more columns are needed for error message.
|
||||||
@@ -355,6 +366,7 @@ int mysql_update(THD *thd,
|
|||||||
{
|
{
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
bool has_vers_fields= check_has_vers_fields(fields);
|
||||||
if (check_key_in_view(thd, table_list))
|
if (check_key_in_view(thd, table_list))
|
||||||
{
|
{
|
||||||
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
|
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
|
||||||
@@ -763,7 +775,7 @@ int mysql_update(THD *thd,
|
|||||||
TRG_EVENT_UPDATE))
|
TRG_EVENT_UPDATE))
|
||||||
break; /* purecov: inspected */
|
break; /* purecov: inspected */
|
||||||
|
|
||||||
if (table->versioned_by_sql())
|
if (has_vers_fields && table->versioned_by_sql())
|
||||||
table->vers_update_fields();
|
table->vers_update_fields();
|
||||||
|
|
||||||
found++;
|
found++;
|
||||||
@@ -835,7 +847,7 @@ int mysql_update(THD *thd,
|
|||||||
{
|
{
|
||||||
updated++;
|
updated++;
|
||||||
|
|
||||||
if (table->versioned())
|
if (has_vers_fields && table->versioned())
|
||||||
{
|
{
|
||||||
if (table->versioned_by_sql())
|
if (table->versioned_by_sql())
|
||||||
{
|
{
|
||||||
@@ -1671,6 +1683,7 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
|
|||||||
transactional_tables(0), ignore(ignore_arg), error_handled(0), prepared(0),
|
transactional_tables(0), ignore(ignore_arg), error_handled(0), prepared(0),
|
||||||
updated_sys_ver(0)
|
updated_sys_ver(0)
|
||||||
{
|
{
|
||||||
|
has_vers_fields= check_has_vers_fields(*field_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2176,7 +2189,7 @@ int multi_update::send_data(List<Item> ¬_used_values)
|
|||||||
if (table->default_field && table->update_default_fields(1, ignore))
|
if (table->default_field && table->update_default_fields(1, ignore))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
if (table->versioned_by_sql())
|
if (has_vers_fields && table->versioned_by_sql())
|
||||||
table->vers_update_fields();
|
table->vers_update_fields();
|
||||||
|
|
||||||
if ((error= cur_table->view_check_option(thd, ignore)) !=
|
if ((error= cur_table->view_check_option(thd, ignore)) !=
|
||||||
@@ -2226,7 +2239,7 @@ int multi_update::send_data(List<Item> ¬_used_values)
|
|||||||
error= 0;
|
error= 0;
|
||||||
updated--;
|
updated--;
|
||||||
}
|
}
|
||||||
else if (table->versioned())
|
else if (has_vers_fields && table->versioned())
|
||||||
{
|
{
|
||||||
if (table->versioned_by_sql())
|
if (table->versioned_by_sql())
|
||||||
{
|
{
|
||||||
@@ -2511,7 +2524,7 @@ int multi_update::do_updates()
|
|||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (table->versioned_by_sql())
|
if (has_vers_fields && table->versioned_by_sql())
|
||||||
table->vers_update_fields();
|
table->vers_update_fields();
|
||||||
|
|
||||||
if ((local_error=table->file->ha_update_row(table->record[1],
|
if ((local_error=table->file->ha_update_row(table->record[1],
|
||||||
@@ -2529,7 +2542,7 @@ int multi_update::do_updates()
|
|||||||
{
|
{
|
||||||
updated++;
|
updated++;
|
||||||
|
|
||||||
if (table->versioned())
|
if (has_vers_fields && table->versioned())
|
||||||
{
|
{
|
||||||
if (table->versioned_by_sql())
|
if (table->versioned_by_sql())
|
||||||
{
|
{
|
||||||
|
@@ -1572,6 +1572,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
%token WINDOW_SYM
|
%token WINDOW_SYM
|
||||||
%token WHILE_SYM
|
%token WHILE_SYM
|
||||||
%token WITH /* SQL-2003-R */
|
%token WITH /* SQL-2003-R */
|
||||||
|
%token WITHOUT /* SQL-2003-R */
|
||||||
%token WITH_CUBE_SYM /* INTERNAL */
|
%token WITH_CUBE_SYM /* INTERNAL */
|
||||||
%token WITH_ROLLUP_SYM /* INTERNAL */
|
%token WITH_ROLLUP_SYM /* INTERNAL */
|
||||||
%token WORK_SYM /* SQL-2003-N */
|
%token WORK_SYM /* SQL-2003-N */
|
||||||
@@ -5852,7 +5853,7 @@ create_table_option:
|
|||||||
{
|
{
|
||||||
System_versioning_info &info= Lex->vers_get_info();
|
System_versioning_info &info= Lex->vers_get_info();
|
||||||
info.declared_system_versioning= true;
|
info.declared_system_versioning= true;
|
||||||
info.versioned= true;
|
Lex->create_info.options|= HA_VERSIONED_TABLE;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -6064,7 +6065,6 @@ period_for_system_time:
|
|||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
info.set_period_for_system_time($4, $6);
|
info.set_period_for_system_time($4, $6);
|
||||||
info.versioned= true;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -6165,7 +6165,6 @@ field_def:
|
|||||||
| opt_generated_always AS ROW_SYM start_or_end
|
| opt_generated_always AS ROW_SYM start_or_end
|
||||||
{
|
{
|
||||||
System_versioning_info &info= Lex->vers_get_info();
|
System_versioning_info &info= Lex->vers_get_info();
|
||||||
info.versioned= true;
|
|
||||||
String *field_name= new (thd->mem_root)
|
String *field_name= new (thd->mem_root)
|
||||||
String((const char*)Lex->last_field->field_name, system_charset_info);
|
String((const char*)Lex->last_field->field_name, system_charset_info);
|
||||||
if (!field_name)
|
if (!field_name)
|
||||||
@@ -6667,6 +6666,16 @@ serial_attribute:
|
|||||||
new (thd->mem_root)
|
new (thd->mem_root)
|
||||||
engine_option_value($1, &Lex->last_field->option_list, &Lex->option_list_last);
|
engine_option_value($1, &Lex->last_field->option_list, &Lex->option_list_last);
|
||||||
}
|
}
|
||||||
|
| WITH SYSTEM VERSIONING
|
||||||
|
{
|
||||||
|
Lex->last_field->versioning = Column_definition::WITH_VERSIONING;
|
||||||
|
Lex->create_info.system_versioning_info.has_versioned_fields= true;
|
||||||
|
}
|
||||||
|
| WITHOUT SYSTEM VERSIONING
|
||||||
|
{
|
||||||
|
Lex->last_field->versioning = Column_definition::WITHOUT_VERSIONING;
|
||||||
|
Lex->create_info.system_versioning_info.has_unversioned_fields= true;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2017,6 +2017,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
|
|||||||
if (f_no_default(pack_flag))
|
if (f_no_default(pack_flag))
|
||||||
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
|
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
|
||||||
|
|
||||||
|
if (f_without_system_versioning(pack_flag))
|
||||||
|
reg_field->flags|= WITHOUT_SYSTEM_VERSIONING_FLAG;
|
||||||
|
|
||||||
if (reg_field->unireg_check == Field::NEXT_NUMBER)
|
if (reg_field->unireg_check == Field::NEXT_NUMBER)
|
||||||
share->found_next_number_field= field_ptr;
|
share->found_next_number_field= field_ptr;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user