MDEV-23908: Implement SELECT ... OFFSET ... FETCH ...
This commit implements the standard SQL extension OFFSET start { ROW | ROWS } [FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } { ONLY | WITH TIES }] To achieve this a reserved keyword OFFSET is introduced. The general logic for WITH TIES implies: 1. The number of rows a query returns is no longer known during optimize phase. Adjust optimizations to no longer consider this. 2. During end_send make use of an "order Cached_item"to compare if the ORDER BY columns changed. Keep returning rows until there is a change. This happens only after we reached the row limit. 3. Within end_send_group, the order by clause was eliminated. It is still possible to keep the optimization of using end_send_group for producing the final result set.
This commit is contained in:
parent
2d595319bf
commit
299b935320
1312
mysql-test/main/fetch_first.result
Normal file
1312
mysql-test/main/fetch_first.result
Normal file
File diff suppressed because it is too large
Load Diff
1008
mysql-test/main/fetch_first.test
Normal file
1008
mysql-test/main/fetch_first.test
Normal file
File diff suppressed because it is too large
Load Diff
@ -29,7 +29,7 @@ Warning 1280 Name 'TzId' ignored for PRIMARY key.
|
||||
CREATE TABLE time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions';
|
||||
Warnings:
|
||||
Warning 1280 Name 'TzIdTranTime' ignored for PRIMARY key.
|
||||
CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
|
||||
CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, `Offset` int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
|
||||
Warnings:
|
||||
Warning 1280 Name 'TzIdTrTId' ignored for PRIMARY key.
|
||||
CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
|
||||
|
@ -42,7 +42,7 @@ CREATE TABLE help_keyword ( help_keyword_id int unsigned not null, name varchar(
|
||||
CREATE TABLE time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names';
|
||||
CREATE TABLE time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones';
|
||||
CREATE TABLE time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions';
|
||||
CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
|
||||
CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, `Offset` int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
|
||||
CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
|
||||
|
||||
# Run the mysql_fix_privilege_tables.sql using "mysql --force"
|
||||
|
@ -29,7 +29,7 @@ Warning 1280 Name 'TzId' ignored for PRIMARY key.
|
||||
CREATE TABLE time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions';
|
||||
Warnings:
|
||||
Warning 1280 Name 'TzIdTranTime' ignored for PRIMARY key.
|
||||
CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
|
||||
CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, `Offset` int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
|
||||
Warnings:
|
||||
Warning 1280 Name 'TzIdTrTId' ignored for PRIMARY key.
|
||||
CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
|
||||
|
@ -42,7 +42,7 @@ CREATE TABLE help_keyword ( help_keyword_id int unsigned not null, name char(64)
|
||||
CREATE TABLE time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names';
|
||||
CREATE TABLE time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones';
|
||||
CREATE TABLE time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions';
|
||||
CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
|
||||
CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, `Offset` int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
|
||||
CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
|
||||
CREATE TABLE proc ( db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum('CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA' ) DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob DEFAULT '' NOT NULL, returns char(64) DEFAULT '' NOT NULL, body longblob DEFAULT '' NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' ) DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, PRIMARY KEY (db,name,type) ) engine=MyISAM character set utf8 comment='Stored Procedures';
|
||||
CREATE TABLE procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
|
||||
|
@ -14,7 +14,7 @@ CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null,
|
||||
CREATE TABLE IF NOT EXISTS time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names';
|
||||
CREATE TABLE IF NOT EXISTS time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones';
|
||||
CREATE TABLE IF NOT EXISTS time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions';
|
||||
CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
|
||||
CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, `Offset` int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
|
||||
CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
|
||||
CREATE TABLE IF NOT EXISTS proc ( db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum('CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA' ) DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns char(64) DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' ) DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, PRIMARY KEY (db,name,type) ) engine=MyISAM character set utf8 comment='Stored Procedures';
|
||||
CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
|
||||
|
@ -37,7 +37,7 @@ CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null,
|
||||
CREATE TABLE IF NOT EXISTS time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names';
|
||||
CREATE TABLE IF NOT EXISTS time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones';
|
||||
CREATE TABLE IF NOT EXISTS time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions';
|
||||
CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
|
||||
CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, `Offset` int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
|
||||
CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
|
||||
CREATE TABLE IF NOT EXISTS proc ( db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum('CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA' ) DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns char(64) DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' ) DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, PRIMARY KEY (db,name,type) ) engine=MyISAM character set utf8 comment='Stored Procedures';
|
||||
CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
|
||||
|
@ -144,7 +144,7 @@ CREATE TABLE IF NOT EXISTS time_zone ( Time_zone_id int unsigned NOT NULL auto
|
||||
CREATE TABLE IF NOT EXISTS time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY /*TzIdTranTime*/ (Time_zone_id, Transition_time) ) engine=Aria transactional=1 CHARACTER SET utf8 comment='Time zone transitions';
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY /*TzIdTrTId*/ (Time_zone_id, Transition_type_id) ) engine=Aria transactional=1 CHARACTER SET utf8 comment='Time zone transition types';
|
||||
CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, `Offset` int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY /*TzIdTrTId*/ (Time_zone_id, Transition_type_id) ) engine=Aria transactional=1 CHARACTER SET utf8 comment='Time zone transition types';
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY /*TranTime*/ (Transition_time) ) engine=Aria transactional=1 CHARACTER SET utf8 comment='Leap seconds information for time zones';
|
||||
|
File diff suppressed because one or more lines are too long
@ -7983,3 +7983,5 @@ ER_JSON_TABLE_SCALAR_EXPECTED
|
||||
eng "Can't store an array or an object in the scalar column '%s' of JSON_TABLE '%s'."
|
||||
ER_JSON_TABLE_MULTIPLE_MATCHES
|
||||
eng "Can't store multiple matches of the path in the column '%s' of JSON_TABLE '%s'."
|
||||
ER_WITH_TIES_NEEDS_ORDER
|
||||
eng "FETCH ... WITH TIES requires ORDER BY clause to be present"
|
||||
|
@ -3776,13 +3776,34 @@ void st_select_lex::print_limit(THD *thd,
|
||||
if (limit_params.explicit_limit &&
|
||||
limit_params.select_limit)
|
||||
{
|
||||
str->append(STRING_WITH_LEN(" limit "));
|
||||
if (limit_params.offset_limit)
|
||||
/*
|
||||
[OFFSET n]
|
||||
FETCH FIRST n ROWS WITH TIES
|
||||
|
||||
For FETCH FIRST n ROWS ONLY we fall back to the "limit" specification
|
||||
as it's identical.
|
||||
*/
|
||||
if (limit_params.with_ties)
|
||||
{
|
||||
limit_params.offset_limit->print(str, query_type);
|
||||
str->append(',');
|
||||
if (limit_params.offset_limit)
|
||||
{
|
||||
str->append(STRING_WITH_LEN(" offset "));
|
||||
limit_params.offset_limit->print(str, query_type);
|
||||
}
|
||||
str->append(STRING_WITH_LEN(" fetch first "));
|
||||
limit_params.select_limit->print(str, query_type);
|
||||
str->append(STRING_WITH_LEN(" rows with ties"));
|
||||
}
|
||||
else
|
||||
{
|
||||
str->append(STRING_WITH_LEN(" limit "));
|
||||
if (limit_params.offset_limit)
|
||||
{
|
||||
limit_params.offset_limit->print(str, query_type);
|
||||
str->append(',');
|
||||
}
|
||||
limit_params.select_limit->print(str, query_type);
|
||||
}
|
||||
limit_params.select_limit->print(str, query_type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4195,7 +4216,7 @@ void st_select_lex_unit::set_limit(st_select_lex *sl)
|
||||
{
|
||||
DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare());
|
||||
|
||||
lim.set_limit(sl->get_limit(), sl->get_offset());
|
||||
lim.set_limit(sl->get_limit(), sl->get_offset(), sl->limit_params.with_ties);
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,20 +23,23 @@
|
||||
class Select_limit_counters
|
||||
{
|
||||
ha_rows select_limit_cnt, offset_limit_cnt;
|
||||
bool with_ties;
|
||||
|
||||
public:
|
||||
Select_limit_counters():
|
||||
select_limit_cnt(0), offset_limit_cnt(0)
|
||||
select_limit_cnt(0), offset_limit_cnt(0), with_ties(false)
|
||||
{};
|
||||
Select_limit_counters(Select_limit_counters &orig):
|
||||
Select_limit_counters(const Select_limit_counters &orig):
|
||||
select_limit_cnt(orig.select_limit_cnt),
|
||||
offset_limit_cnt(orig.offset_limit_cnt)
|
||||
offset_limit_cnt(orig.offset_limit_cnt),
|
||||
with_ties(orig.with_ties)
|
||||
{};
|
||||
|
||||
void set_limit(ha_rows limit, ha_rows offset)
|
||||
void set_limit(ha_rows limit, ha_rows offset, bool with_ties_arg)
|
||||
{
|
||||
offset_limit_cnt= offset;
|
||||
select_limit_cnt= limit;
|
||||
with_ties= with_ties_arg;
|
||||
/*
|
||||
Guard against an overflow condition, where limit + offset exceede
|
||||
ha_rows value range. This case covers unreasonably large parameter
|
||||
@ -53,6 +56,7 @@ class Select_limit_counters
|
||||
{
|
||||
offset_limit_cnt= 0;
|
||||
select_limit_cnt= 1;
|
||||
with_ties= false;
|
||||
}
|
||||
|
||||
bool is_unlimited() const
|
||||
@ -67,7 +71,7 @@ class Select_limit_counters
|
||||
|
||||
/* Reset the limit entirely. */
|
||||
void clear()
|
||||
{ select_limit_cnt= HA_POS_ERROR; offset_limit_cnt= 0; }
|
||||
{ select_limit_cnt= HA_POS_ERROR; offset_limit_cnt= 0; with_ties= false;}
|
||||
|
||||
bool check_offset(ha_rows sent) const
|
||||
{
|
||||
@ -79,6 +83,8 @@ class Select_limit_counters
|
||||
{ return select_limit_cnt; }
|
||||
ha_rows get_offset_limit() const
|
||||
{ return offset_limit_cnt; }
|
||||
bool is_with_ties() const
|
||||
{ return with_ties; }
|
||||
};
|
||||
|
||||
#endif // INCLUDES_MARIADB_SQL_LIMIT_H
|
||||
|
@ -260,7 +260,8 @@ static TABLE *get_sort_by_table(ORDER *a,ORDER *b,List<TABLE_LIST> &tables,
|
||||
static void calc_group_buffer(JOIN *join, ORDER *group);
|
||||
static bool make_group_fields(JOIN *main_join, JOIN *curr_join);
|
||||
static bool alloc_group_fields(JOIN *join, ORDER *group);
|
||||
static bool alloc_order_fields(JOIN *join, ORDER *group);
|
||||
static bool alloc_order_fields(JOIN *join, ORDER *group,
|
||||
uint max_number_of_elements);
|
||||
// Create list for using with tempory table
|
||||
static bool change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
|
||||
List<Item> &new_list1,
|
||||
@ -1393,9 +1394,23 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
|
||||
|
||||
if (order)
|
||||
{
|
||||
bool real_order= FALSE;
|
||||
ORDER *ord;
|
||||
for (ord= order; ord; ord= ord->next)
|
||||
bool requires_sorting= FALSE;
|
||||
/*
|
||||
WITH TIES forces the results to be sorted, even if it's not sanely
|
||||
sortable.
|
||||
*/
|
||||
if (select_lex->limit_params.with_ties)
|
||||
requires_sorting= true;
|
||||
|
||||
/*
|
||||
Go through each ORDER BY item and perform the following:
|
||||
1. Detect if none of the items contain meaningful data, which means we
|
||||
can drop the sorting altogether.
|
||||
2. Split any columns with aggregation functions or window functions into
|
||||
their base components and store them as separate fields.
|
||||
(see split_sum_func) for more details.
|
||||
*/
|
||||
for (ORDER *ord= order; ord; ord= ord->next)
|
||||
{
|
||||
Item *item= *ord->item;
|
||||
/*
|
||||
@ -1404,7 +1419,7 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
|
||||
zero length NOT NULL string functions there.
|
||||
Such tuples don't contain any data to sort.
|
||||
*/
|
||||
if (!real_order &&
|
||||
if (!requires_sorting &&
|
||||
/* Not a zero length NOT NULL field */
|
||||
((item->type() != Item::FIELD_ITEM ||
|
||||
((Item_field *) item)->field->maybe_null() ||
|
||||
@ -1414,15 +1429,26 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
|
||||
item->maybe_null ||
|
||||
item->result_type() != STRING_RESULT ||
|
||||
item->max_length)))
|
||||
real_order= TRUE;
|
||||
requires_sorting= TRUE;
|
||||
|
||||
if ((item->with_sum_func() && item->type() != Item::SUM_FUNC_ITEM) ||
|
||||
item->with_window_func)
|
||||
item->split_sum_func(thd, ref_ptrs, all_fields, SPLIT_SUM_SELECT);
|
||||
}
|
||||
if (!real_order)
|
||||
/* Drop the ORDER BY clause if none of the columns contain any data that
|
||||
can produce a meaningful sorted set. */
|
||||
if (!requires_sorting)
|
||||
order= NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The current select does not have an ORDER BY */
|
||||
if (select_lex->limit_params.with_ties)
|
||||
{
|
||||
my_error(ER_WITH_TIES_NEEDS_ORDER, MYF(0));
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
}
|
||||
|
||||
if (having && having->with_sum_func())
|
||||
having->split_sum_func2(thd, ref_ptrs, all_fields,
|
||||
@ -2615,6 +2641,19 @@ int JOIN::optimize_stage2()
|
||||
if (!order && org_order)
|
||||
skip_sort_order= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
For FETCH ... WITH TIES save how many items order by had, after we've
|
||||
removed constant items that have no relevance on the final sorting.
|
||||
*/
|
||||
if (unit->lim.is_with_ties())
|
||||
{
|
||||
DBUG_ASSERT(with_ties_order_count == 0);
|
||||
for (ORDER *it= order; it; it= it->next)
|
||||
with_ties_order_count+= 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check if we can optimize away GROUP BY/DISTINCT.
|
||||
We can do that if there are no aggregate functions, the
|
||||
@ -2802,7 +2841,7 @@ int JOIN::optimize_stage2()
|
||||
if (test_if_subpart(group_list, order) ||
|
||||
(!group_list && tmp_table_param.sum_func_count))
|
||||
{
|
||||
order=0;
|
||||
order= 0;
|
||||
if (is_indexed_agg_distinct(this, NULL))
|
||||
sort_and_group= 0;
|
||||
}
|
||||
@ -3738,6 +3777,9 @@ bool JOIN::make_aggr_tables_info()
|
||||
sort_tab->filesort->limit=
|
||||
(has_group_by || (join_tab + top_join_tab_count > curr_tab + 1)) ?
|
||||
select_limit : unit->lim.get_select_limit();
|
||||
|
||||
if (unit->lim.is_with_ties())
|
||||
sort_tab->filesort->limit= HA_POS_ERROR;
|
||||
}
|
||||
if (!only_const_tables() &&
|
||||
!join_tab[const_tables].filesort &&
|
||||
@ -3774,6 +3816,18 @@ bool JOIN::make_aggr_tables_info()
|
||||
if (select_lex->custom_agg_func_used())
|
||||
status_var_increment(thd->status_var.feature_custom_aggregate_functions);
|
||||
|
||||
/*
|
||||
Allocate Cached_items of ORDER BY for FETCH FIRST .. WITH TIES.
|
||||
The order list might have been modified prior to this, but we are
|
||||
only interested in the initial order by columns, after all const
|
||||
elements are removed.
|
||||
*/
|
||||
if (unit->lim.is_with_ties())
|
||||
{
|
||||
if (alloc_order_fields(this, order, with_ties_order_count))
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
fields= curr_fields_list;
|
||||
// Reset before execution
|
||||
set_items_ref_array(items0);
|
||||
@ -21982,6 +22036,19 @@ end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
|
||||
DBUG_RETURN(NESTED_LOOP_ERROR);
|
||||
DBUG_RETURN(NESTED_LOOP_OK);
|
||||
}
|
||||
|
||||
if (join->send_records >= join->unit->lim.get_select_limit() &&
|
||||
join->unit->lim.is_with_ties())
|
||||
{
|
||||
/*
|
||||
Stop sending rows if the order fields corresponding to WITH TIES
|
||||
have changed.
|
||||
*/
|
||||
int idx= test_if_item_cache_changed(join->order_fields);
|
||||
if (idx >= 0)
|
||||
join->do_send_rows= false;
|
||||
}
|
||||
|
||||
if (join->do_send_rows)
|
||||
{
|
||||
int error;
|
||||
@ -21998,27 +22065,36 @@ end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
|
||||
}
|
||||
|
||||
++join->send_records;
|
||||
if (join->send_records >= join->unit->lim.get_select_limit() &&
|
||||
!join->do_send_rows)
|
||||
if (join->send_records >= join->unit->lim.get_select_limit())
|
||||
{
|
||||
/*
|
||||
If we have used Priority Queue for optimizing order by with limit,
|
||||
then stop here, there are no more records to consume.
|
||||
When this optimization is used, end_send is called on the next
|
||||
join_tab.
|
||||
*/
|
||||
if (join->order &&
|
||||
join->select_options & OPTION_FOUND_ROWS &&
|
||||
join_tab > join->join_tab &&
|
||||
(join_tab - 1)->filesort && (join_tab - 1)->filesort->using_pq)
|
||||
if (!join->do_send_rows)
|
||||
{
|
||||
DBUG_PRINT("info", ("filesort NESTED_LOOP_QUERY_LIMIT"));
|
||||
DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT);
|
||||
/*
|
||||
If we have used Priority Queue for optimizing order by with limit,
|
||||
then stop here, there are no more records to consume.
|
||||
When this optimization is used, end_send is called on the next
|
||||
join_tab.
|
||||
*/
|
||||
if (join->order &&
|
||||
join->select_options & OPTION_FOUND_ROWS &&
|
||||
join_tab > join->join_tab &&
|
||||
(join_tab - 1)->filesort && (join_tab - 1)->filesort->using_pq)
|
||||
{
|
||||
DBUG_PRINT("info", ("filesort NESTED_LOOP_QUERY_LIMIT"));
|
||||
DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT);
|
||||
}
|
||||
DBUG_RETURN(NESTED_LOOP_OK);
|
||||
}
|
||||
|
||||
/* For WITH TIES we keep sending rows until a group has changed. */
|
||||
if (join->unit->lim.is_with_ties())
|
||||
{
|
||||
/* Prepare the order_fields comparison for with ties. */
|
||||
if (join->send_records == join->unit->lim.get_select_limit())
|
||||
(void) test_if_group_changed(join->order_fields);
|
||||
/* One more loop, to check if the next row matches with_ties or not. */
|
||||
DBUG_RETURN(NESTED_LOOP_OK);
|
||||
}
|
||||
}
|
||||
if (join->send_records >= join->unit->lim.get_select_limit() &&
|
||||
join->do_send_rows)
|
||||
{
|
||||
if (join->select_options & OPTION_FOUND_ROWS)
|
||||
{
|
||||
JOIN_TAB *jt=join->join_tab;
|
||||
@ -22095,6 +22171,7 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
|
||||
{
|
||||
if (join->procedure)
|
||||
join->procedure->end_group();
|
||||
/* Test if there was a group change. */
|
||||
if (idx < (int) join->send_group_parts)
|
||||
{
|
||||
int error=0;
|
||||
@ -22113,6 +22190,7 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset all sum functions on group change. */
|
||||
if (!join->first_record)
|
||||
{
|
||||
List_iterator_fast<Item> it(*join->fields);
|
||||
@ -22152,21 +22230,27 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
|
||||
DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
|
||||
if (end_of_records)
|
||||
DBUG_RETURN(NESTED_LOOP_OK);
|
||||
if (join->send_records >= join->unit->lim.get_select_limit() &&
|
||||
join->do_send_rows)
|
||||
{
|
||||
if (!(join->select_options & OPTION_FOUND_ROWS))
|
||||
DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT); // Abort nicely
|
||||
join->do_send_rows=0;
|
||||
join->unit->lim.set_unlimited();
|
||||
if (join->send_records >= join->unit->lim.get_select_limit() &&
|
||||
join->do_send_rows)
|
||||
{
|
||||
/* WITH TIES can be computed during end_send_group if
|
||||
the order by is a subset of group by and we had an index
|
||||
available to compute group by order directly. */
|
||||
if (!join->unit->lim.is_with_ties() ||
|
||||
idx < (int)join->with_ties_order_count)
|
||||
{
|
||||
if (!(join->select_options & OPTION_FOUND_ROWS))
|
||||
DBUG_RETURN(NESTED_LOOP_QUERY_LIMIT); // Abort nicely
|
||||
join->do_send_rows= 0;
|
||||
join->unit->lim.set_unlimited();
|
||||
}
|
||||
}
|
||||
else if (join->send_records >= join->fetch_limit)
|
||||
{
|
||||
/*
|
||||
There is a server side cursor and all rows
|
||||
for this fetch request are sent.
|
||||
*/
|
||||
/*
|
||||
|
||||
Preventing code duplication. When finished with the group reset
|
||||
the group functions and copy_fields. We fall through. bug #11904
|
||||
*/
|
||||
@ -25221,6 +25305,19 @@ make_group_fields(JOIN *main_join, JOIN *curr_join)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static bool
|
||||
fill_cached_item_list(THD *thd, List<Cached_item> *list, ORDER *order,
|
||||
uint max_number_of_elements = UINT_MAX)
|
||||
{
|
||||
for (; order && max_number_of_elements ;
|
||||
order= order->next, max_number_of_elements--)
|
||||
{
|
||||
Cached_item *tmp= new_Cached_item(thd, *order->item, true);
|
||||
if (!tmp || list->push_front(tmp))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
Get a list of buffers for saving last group.
|
||||
@ -25229,21 +25326,20 @@ make_group_fields(JOIN *main_join, JOIN *curr_join)
|
||||
*/
|
||||
|
||||
static bool
|
||||
alloc_group_fields(JOIN *join,ORDER *group)
|
||||
alloc_group_fields(JOIN *join, ORDER *group)
|
||||
{
|
||||
if (group)
|
||||
{
|
||||
for (; group ; group=group->next)
|
||||
{
|
||||
Cached_item *tmp=new_Cached_item(join->thd, *group->item, TRUE);
|
||||
if (!tmp || join->group_fields.push_front(tmp))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (fill_cached_item_list(join->thd, &join->group_fields, group))
|
||||
return true;
|
||||
join->sort_and_group=1; /* Mark for do_select */
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
alloc_order_fields(JOIN *join, ORDER *order, uint max_number_of_elements)
|
||||
{
|
||||
return fill_cached_item_list(join->thd, &join->order_fields, order,
|
||||
max_number_of_elements);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -1177,6 +1177,16 @@ public:
|
||||
uint top_join_tab_count;
|
||||
uint aggr_tables; ///< Number of post-join tmp tables
|
||||
uint send_group_parts;
|
||||
/*
|
||||
This represents the number of items in ORDER BY *after* removing
|
||||
all const items. This is computed before other optimizations take place,
|
||||
such as removal of ORDER BY when it is a prefix of GROUP BY, for example:
|
||||
GROUP BY a, b ORDER BY a
|
||||
|
||||
This is used when deciding to send rows, by examining the correct number
|
||||
of items in the group_fields list when ORDER BY was previously eliminated.
|
||||
*/
|
||||
uint with_ties_order_count;
|
||||
/*
|
||||
True if the query has GROUP BY.
|
||||
(that is, if group_by != NULL. when DISTINCT is converted into GROUP BY, it
|
||||
@ -1306,6 +1316,10 @@ public:
|
||||
*/
|
||||
double join_record_count;
|
||||
List<Item> *fields;
|
||||
|
||||
/* Used only for FETCH ... WITH TIES to identify peers. */
|
||||
List<Cached_item> order_fields;
|
||||
/* Used during GROUP BY operations to identify when a group has changed. */
|
||||
List<Cached_item> group_fields, group_fields_cache;
|
||||
THD *thd;
|
||||
Item_sum **sum_funcs, ***sum_funcs_end;
|
||||
@ -1609,6 +1623,8 @@ public:
|
||||
sjm_lookup_tables= 0;
|
||||
sjm_scan_tables= 0;
|
||||
is_orig_degenerated= false;
|
||||
|
||||
with_ties_order_count= 0;
|
||||
}
|
||||
|
||||
/* True if the plan guarantees that it will be returned zero or one row */
|
||||
|
@ -347,7 +347,7 @@ static_assert(sizeof(YYSTYPE) == sizeof(void*)*2+8, "%union size check");
|
||||
bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
||||
%}
|
||||
|
||||
%pure-parser /* We have threads */
|
||||
%define api.pure /* We have threads */
|
||||
%parse-param { THD *thd }
|
||||
%lex-param { THD *thd }
|
||||
/*
|
||||
@ -1625,6 +1625,7 @@ End SQL_MODE_ORACLE_SPECIFIC */
|
||||
opt_lock_wait_timeout_new
|
||||
|
||||
%type <select_limit> opt_limit_clause limit_clause limit_options
|
||||
fetch_first_clause
|
||||
|
||||
%type <order_limit_lock>
|
||||
query_expression_tail
|
||||
@ -1731,6 +1732,7 @@ End SQL_MODE_ORACLE_SPECIFIC */
|
||||
|
||||
%type <num> view_algorithm view_check_option
|
||||
%type <view_suid> view_suid opt_view_suid
|
||||
%type <num> only_or_with_ties
|
||||
|
||||
%type <plsql_cursor_attr> plsql_cursor_attr
|
||||
%type <sp_suid> sp_suid
|
||||
@ -12484,8 +12486,77 @@ limit_clause:
|
||||
$$.clear();
|
||||
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
|
||||
}
|
||||
| fetch_first_clause
|
||||
{
|
||||
$$= $1;
|
||||
if (!$$.select_limit ||
|
||||
!$$.select_limit->basic_const_item() ||
|
||||
$$.select_limit->val_int() > 0)
|
||||
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT);
|
||||
}
|
||||
;
|
||||
|
||||
fetch_first_clause:
|
||||
FETCH_SYM first_or_next row_or_rows only_or_with_ties
|
||||
{
|
||||
Item *one= new (thd->mem_root) Item_int(thd, (int32) 1);
|
||||
if (unlikely(one == NULL))
|
||||
MYSQL_YYABORT;
|
||||
$$.select_limit= one;
|
||||
$$.offset_limit= 0;
|
||||
$$.explicit_limit= true;
|
||||
$$.with_ties= $4;
|
||||
}
|
||||
| OFFSET_SYM limit_option
|
||||
FETCH_SYM first_or_next row_or_rows only_or_with_ties
|
||||
{
|
||||
Item *one= new (thd->mem_root) Item_int(thd, (int32) 1);
|
||||
if (unlikely(one == NULL))
|
||||
MYSQL_YYABORT;
|
||||
$$.select_limit= one;
|
||||
$$.offset_limit= $2;
|
||||
$$.explicit_limit= true;
|
||||
$$.with_ties= $6;
|
||||
}
|
||||
| FETCH_SYM first_or_next limit_option row_or_rows only_or_with_ties
|
||||
{
|
||||
$$.select_limit= $3;
|
||||
$$.offset_limit= 0;
|
||||
$$.explicit_limit= true;
|
||||
$$.with_ties= $5;
|
||||
}
|
||||
| OFFSET_SYM limit_option
|
||||
FETCH_SYM first_or_next limit_option row_or_rows only_or_with_ties
|
||||
{
|
||||
$$.select_limit= $5;
|
||||
$$.offset_limit= $2;
|
||||
$$.explicit_limit= true;
|
||||
$$.with_ties= $7;
|
||||
}
|
||||
| OFFSET_SYM limit_option
|
||||
{
|
||||
$$.select_limit= 0;
|
||||
$$.offset_limit= $2;
|
||||
$$.explicit_limit= true;
|
||||
$$.with_ties= false;
|
||||
}
|
||||
;
|
||||
|
||||
first_or_next:
|
||||
FIRST_SYM
|
||||
| NEXT_SYM
|
||||
;
|
||||
row_or_rows:
|
||||
ROW_SYM
|
||||
| ROWS_SYM
|
||||
;
|
||||
|
||||
only_or_with_ties:
|
||||
ONLY_SYM { $$= 0; }
|
||||
| WITH TIES_SYM { $$= 1; }
|
||||
;
|
||||
|
||||
|
||||
opt_global_limit_clause:
|
||||
opt_limit_clause
|
||||
{
|
||||
@ -12497,20 +12568,23 @@ limit_options:
|
||||
limit_option
|
||||
{
|
||||
$$.select_limit= $1;
|
||||
$$.offset_limit= 0;
|
||||
$$.explicit_limit= 1;
|
||||
$$.offset_limit= NULL;
|
||||
$$.explicit_limit= true;
|
||||
$$.with_ties= false;
|
||||
}
|
||||
| limit_option ',' limit_option
|
||||
{
|
||||
$$.select_limit= $3;
|
||||
$$.offset_limit= $1;
|
||||
$$.explicit_limit= 1;
|
||||
$$.explicit_limit= true;
|
||||
$$.with_ties= false;
|
||||
}
|
||||
| limit_option OFFSET_SYM limit_option
|
||||
{
|
||||
$$.select_limit= $1;
|
||||
$$.offset_limit= $3;
|
||||
$$.explicit_limit= 1;
|
||||
$$.explicit_limit= true;
|
||||
$$.with_ties= false;
|
||||
}
|
||||
;
|
||||
|
||||
@ -12633,6 +12707,7 @@ opt_procedure_or_into:
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
order_or_limit:
|
||||
order_clause opt_limit_clause
|
||||
{
|
||||
@ -15554,6 +15629,7 @@ keyword_sysvar_name:
|
||||
| WINDOW_SYM
|
||||
| EXCEPTION_ORACLE_SYM
|
||||
| IGNORED_SYM
|
||||
| OFFSET_SYM
|
||||
;
|
||||
|
||||
keyword_set_usual_case:
|
||||
@ -15569,6 +15645,7 @@ keyword_set_usual_case:
|
||||
| WINDOW_SYM
|
||||
| EXCEPTION_ORACLE_SYM
|
||||
| IGNORED_SYM
|
||||
| OFFSET_SYM
|
||||
;
|
||||
|
||||
non_reserved_keyword_udt:
|
||||
@ -15579,6 +15656,7 @@ non_reserved_keyword_udt:
|
||||
| keyword_sp_block_section
|
||||
| keyword_sysvar_type
|
||||
| keyword_sp_var_and_label
|
||||
| OFFSET_SYM
|
||||
;
|
||||
|
||||
/*
|
||||
@ -15965,7 +16043,6 @@ keyword_sp_var_and_label:
|
||||
| NONE_SYM
|
||||
| NOTFOUND_SYM
|
||||
| OF_SYM
|
||||
| OFFSET_SYM
|
||||
| OLD_PASSWORD_SYM
|
||||
| ONE_SYM
|
||||
| ONLINE_SYM
|
||||
|
@ -826,11 +826,13 @@ class Lex_select_limit
|
||||
public:
|
||||
/* explicit LIMIT clause was used */
|
||||
bool explicit_limit;
|
||||
bool with_ties;
|
||||
Item *select_limit, *offset_limit;
|
||||
|
||||
void clear()
|
||||
{
|
||||
explicit_limit= FALSE; // No explicit limit given by user
|
||||
with_ties= FALSE; // No use of WITH TIES operator
|
||||
select_limit= NULL; // denotes the default limit = HA_POS_ERROR
|
||||
offset_limit= NULL; // denotes the default offset = 0
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ END//
|
||||
CREATE PROCEDURE test.dbf_header(in fname VARCHAR(1024)) DETERMINISTIC
|
||||
BEGIN
|
||||
DECLARE content BLOB;
|
||||
DECLARE offset INT;
|
||||
DECLARE `offset` INT;
|
||||
DECLARE fieldno INT;
|
||||
SELECT '--------';
|
||||
SELECT LOAD_FILE(fname) INTO content;
|
||||
@ -45,11 +45,11 @@ SELECT CONV(HEX(REVERSE(SUBSTRING(content,9,2))),16,10) AS FirstRecPos;
|
||||
SELECT CONV(HEX(REVERSE(SUBSTRING(content,11,2))),16,10) AS RecLength;
|
||||
SELECT HEX(REVERSE(SUBSTRING(content,29,2))) AS TableFlags;
|
||||
SELECT HEX(REVERSE(SUBSTRING(content,30,1))) AS CodePageMark;
|
||||
SET offset=33;
|
||||
SET `offset`=33;
|
||||
SET fieldno=0;
|
||||
WHILE SUBSTR(content, offset, 1) <> 0x0D AND offset + 32 < LENGTH(content) DO
|
||||
CALL dbf_field(fieldno, SUBSTRING(content, offset, 32));
|
||||
SET offset=offset + 32;
|
||||
WHILE SUBSTR(content, `offset`, 1) <> 0x0D AND `offset` + 32 < LENGTH(content) DO
|
||||
CALL dbf_field(fieldno, SUBSTRING(content, `offset`, 32));
|
||||
SET `offset`=`offset` + 32;
|
||||
SET fieldno=fieldno + 1;
|
||||
END WHILE;
|
||||
SELECT '--------';
|
||||
|
@ -34,7 +34,7 @@ END//
|
||||
CREATE PROCEDURE test.dbf_header(in fname VARCHAR(1024)) DETERMINISTIC
|
||||
BEGIN
|
||||
DECLARE content BLOB;
|
||||
DECLARE offset INT;
|
||||
DECLARE `offset` INT;
|
||||
DECLARE fieldno INT;
|
||||
SELECT '--------';
|
||||
SELECT LOAD_FILE(fname) INTO content;
|
||||
@ -45,11 +45,11 @@ BEGIN
|
||||
SELECT CONV(HEX(REVERSE(SUBSTRING(content,11,2))),16,10) AS RecLength;
|
||||
SELECT HEX(REVERSE(SUBSTRING(content,29,2))) AS TableFlags;
|
||||
SELECT HEX(REVERSE(SUBSTRING(content,30,1))) AS CodePageMark;
|
||||
SET offset=33;
|
||||
SET `offset`=33;
|
||||
SET fieldno=0;
|
||||
WHILE SUBSTR(content, offset, 1) <> 0x0D AND offset + 32 < LENGTH(content) DO
|
||||
CALL dbf_field(fieldno, SUBSTRING(content, offset, 32));
|
||||
SET offset=offset + 32;
|
||||
WHILE SUBSTR(content, `offset`, 1) <> 0x0D AND `offset` + 32 < LENGTH(content) DO
|
||||
CALL dbf_field(fieldno, SUBSTRING(content, `offset`, 32));
|
||||
SET `offset`=`offset` + 32;
|
||||
SET fieldno=fieldno + 1;
|
||||
END WHILE;
|
||||
SELECT '--------';
|
||||
|
Loading…
x
Reference in New Issue
Block a user