MXS-1584 Correctly classify "SELECT NEXT VALUE FOR seq"
This commit is contained in:
@ -156,12 +156,15 @@ static thread_local struct
|
|||||||
sqlite3* pDb; // Thread specific database handle.
|
sqlite3* pDb; // Thread specific database handle.
|
||||||
qc_sql_mode_t sql_mode; // What sql_mode is used.
|
qc_sql_mode_t sql_mode; // What sql_mode is used.
|
||||||
QcSqliteInfo* pInfo; // The information for the current statement being classified.
|
QcSqliteInfo* pInfo; // The information for the current statement being classified.
|
||||||
|
uint64_t version; // Encoded version number
|
||||||
uint32_t version_major;
|
uint32_t version_major;
|
||||||
uint32_t version_minor;
|
uint32_t version_minor;
|
||||||
uint32_t version_patch;
|
uint32_t version_patch;
|
||||||
QC_NAME_MAPPING* pFunction_name_mappings; // How function names should be mapped.
|
QC_NAME_MAPPING* pFunction_name_mappings; // How function names should be mapped.
|
||||||
} this_thread;
|
} this_thread;
|
||||||
|
|
||||||
|
const uint64_t VERSION_103 = 10 * 10000 + 3 * 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HELPERS
|
* HELPERS
|
||||||
*/
|
*/
|
||||||
@ -492,7 +495,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool must_check_sequence_related_functions() const
|
bool must_check_sequence_related_functions() const
|
||||||
{
|
{
|
||||||
return (m_sql_mode == QC_SQL_MODE_ORACLE) || (this_unit.parse_as == QC_PARSE_AS_103);
|
return
|
||||||
|
(m_sql_mode == QC_SQL_MODE_ORACLE) ||
|
||||||
|
(this_unit.parse_as == QC_PARSE_AS_103) ||
|
||||||
|
(this_thread.version >= VERSION_103);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -530,7 +536,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rv && (this_unit.parse_as == QC_PARSE_AS_103))
|
if (!rv && ((this_unit.parse_as == QC_PARSE_AS_103) || (this_thread.version >= VERSION_103)))
|
||||||
{
|
{
|
||||||
if ((strcasecmp(zFunc_name, "lastval") == 0) ||
|
if ((strcasecmp(zFunc_name, "lastval") == 0) ||
|
||||||
(strcasecmp(zFunc_name, "nextval") == 0))
|
(strcasecmp(zFunc_name, "nextval") == 0))
|
||||||
@ -4942,6 +4948,7 @@ static void qc_sqlite_set_server_version(uint64_t version)
|
|||||||
uint32_t minor = (version - major * 10000) / 100;
|
uint32_t minor = (version - major * 10000) / 100;
|
||||||
uint32_t patch = version - major * 10000 - minor * 100;
|
uint32_t patch = version - major * 10000 - minor * 100;
|
||||||
|
|
||||||
|
this_thread.version = version;
|
||||||
this_thread.version_major = major;
|
this_thread.version_major = major;
|
||||||
this_thread.version_minor = minor;
|
this_thread.version_minor = minor;
|
||||||
this_thread.version_patch = patch;
|
this_thread.version_patch = patch;
|
||||||
@ -4951,10 +4958,7 @@ static void qc_sqlite_get_server_version(uint64_t* pVersion)
|
|||||||
{
|
{
|
||||||
QC_TRACE();
|
QC_TRACE();
|
||||||
|
|
||||||
*pVersion =
|
*pVersion = this_thread.version;
|
||||||
this_thread.version_major * 10000 +
|
|
||||||
this_thread.version_minor * 100 +
|
|
||||||
this_thread.version_patch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -623,7 +623,7 @@ columnid(A) ::= nm(X). {
|
|||||||
/*KEY*/
|
/*KEY*/
|
||||||
/*LIKE_KW*/
|
/*LIKE_KW*/
|
||||||
MASTER /*MATCH*/ MERGE
|
MASTER /*MATCH*/ MERGE
|
||||||
NAMES
|
NAMES NEXT
|
||||||
NO
|
NO
|
||||||
OF OFFSET OPEN
|
OF OFFSET OPEN
|
||||||
QUICK
|
QUICK
|
||||||
@ -1207,6 +1207,14 @@ selcollist(A) ::= sclp(P) nm(X) DOT STAR(Y). {
|
|||||||
A = sqlite3ExprListAppend(pParse,P, pDot);
|
A = sqlite3ExprListAppend(pParse,P, pDot);
|
||||||
}
|
}
|
||||||
%ifdef MAXSCALE
|
%ifdef MAXSCALE
|
||||||
|
selcollist(A) ::= sclp(P) NEXT VALUE FOR nm(X) as(Y). {
|
||||||
|
Expr* pSeq = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
|
||||||
|
ExprList* pArgs = sqlite3ExprListAppend(pParse, NULL, pSeq);
|
||||||
|
Token nextval = { "nextval", 7 };
|
||||||
|
Expr* pFunc = sqlite3ExprFunction(pParse, pArgs, &nextval);
|
||||||
|
if( Y.n>0 ) sqlite3ExprListSetName(pParse, A, &Y, 1);
|
||||||
|
A = sqlite3ExprListAppend(pParse, P, pFunc);
|
||||||
|
}
|
||||||
selcollist(A) ::= sclp(P) DEFAULT LP nm RP as. {
|
selcollist(A) ::= sclp(P) DEFAULT LP nm RP as. {
|
||||||
A = P;
|
A = P;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -269,7 +269,11 @@ static Keyword aKeywordTable[] = {
|
|||||||
{ "FLUSH", "TK_FLUSH", ALWAYS },
|
{ "FLUSH", "TK_FLUSH", ALWAYS },
|
||||||
{ "FOLLOWING", "TK_FOLLOWING", ALWAYS },
|
{ "FOLLOWING", "TK_FOLLOWING", ALWAYS },
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MAXSCALE
|
||||||
|
{ "FOR", "TK_FOR", ALWAYS },
|
||||||
|
#else
|
||||||
{ "FOR", "TK_FOR", TRIGGER },
|
{ "FOR", "TK_FOR", TRIGGER },
|
||||||
|
#endif
|
||||||
#ifdef MAXSCALE
|
#ifdef MAXSCALE
|
||||||
{ "FORCE", "TK_FORCE", ALWAYS },
|
{ "FORCE", "TK_FORCE", ALWAYS },
|
||||||
#endif
|
#endif
|
||||||
@ -342,6 +346,9 @@ static Keyword aKeywordTable[] = {
|
|||||||
{ "NAMES", "TK_NAMES", ALWAYS },
|
{ "NAMES", "TK_NAMES", ALWAYS },
|
||||||
#endif
|
#endif
|
||||||
{ "NATURAL", "TK_JOIN_KW", ALWAYS },
|
{ "NATURAL", "TK_JOIN_KW", ALWAYS },
|
||||||
|
#ifdef MAXSCALE
|
||||||
|
{ "NEXT", "TK_NEXT", ALWAYS },
|
||||||
|
#endif
|
||||||
{ "NO", "TK_NO", FKEY },
|
{ "NO", "TK_NO", FKEY },
|
||||||
{ "NOT", "TK_NOT", ALWAYS },
|
{ "NOT", "TK_NOT", ALWAYS },
|
||||||
{ "NOTNULL", "TK_NOTNULL", ALWAYS },
|
{ "NOTNULL", "TK_NOTNULL", ALWAYS },
|
||||||
|
|||||||
@ -32,7 +32,9 @@ if (BUILD_QC_MYSQLEMBEDDED)
|
|||||||
|
|
||||||
add_test(TestQC_Crash_qcsqlite crash_qc_sqlite)
|
add_test(TestQC_Crash_qcsqlite crash_qc_sqlite)
|
||||||
|
|
||||||
add_test(TestQC_MySQLEmbedded classify qc_mysqlembedded ${CMAKE_CURRENT_SOURCE_DIR}/input.sql ${CMAKE_CURRENT_SOURCE_DIR}/expected.sql)
|
# TestQC_MySQLEmbedded excluded, classify is now solely used for verifying the
|
||||||
|
# functionality of qc_sqlite.
|
||||||
|
#add_test(TestQC_MySQLEmbedded classify qc_mysqlembedded ${CMAKE_CURRENT_SOURCE_DIR}/input.sql ${CMAKE_CURRENT_SOURCE_DIR}/expected.sql)
|
||||||
add_test(TestQC_SqLite classify qc_sqlite ${CMAKE_CURRENT_SOURCE_DIR}/input.sql ${CMAKE_CURRENT_SOURCE_DIR}/expected.sql)
|
add_test(TestQC_SqLite classify qc_sqlite ${CMAKE_CURRENT_SOURCE_DIR}/input.sql ${CMAKE_CURRENT_SOURCE_DIR}/expected.sql)
|
||||||
|
|
||||||
add_test(TestQC_CompareCreate compare -v 2 ${CMAKE_CURRENT_SOURCE_DIR}/create.test)
|
add_test(TestQC_CompareCreate compare -v 2 ${CMAKE_CURRENT_SOURCE_DIR}/create.test)
|
||||||
|
|||||||
@ -317,6 +317,11 @@ int main(int argc, char** argv)
|
|||||||
qc_process_init(QC_INIT_BOTH) &&
|
qc_process_init(QC_INIT_BOTH) &&
|
||||||
qc_thread_init(QC_INIT_BOTH))
|
qc_thread_init(QC_INIT_BOTH))
|
||||||
{
|
{
|
||||||
|
// Version encoded as MariaDB encodes the version, i.e.:
|
||||||
|
// version = major * 10000 + minor * 100 + patch
|
||||||
|
uint64_t version = 10 * 10000 + 3 * 100;
|
||||||
|
|
||||||
|
qc_set_server_version(version);
|
||||||
rc = run(input_name, expected_name);
|
rc = run(input_name, expected_name);
|
||||||
qc_process_end(QC_INIT_BOTH);
|
qc_process_end(QC_INIT_BOTH);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,3 +16,6 @@ QUERY_TYPE_READ|QUERY_TYPE_MASTER_READ
|
|||||||
QUERY_TYPE_READ|QUERY_TYPE_MASTER_READ
|
QUERY_TYPE_READ|QUERY_TYPE_MASTER_READ
|
||||||
QUERY_TYPE_READ|QUERY_TYPE_MASTER_READ
|
QUERY_TYPE_READ|QUERY_TYPE_MASTER_READ
|
||||||
QUERY_TYPE_READ|QUERY_TYPE_SYSVAR_READ
|
QUERY_TYPE_READ|QUERY_TYPE_SYSVAR_READ
|
||||||
|
QUERY_TYPE_READ|QUERY_TYPE_WRITE
|
||||||
|
QUERY_TYPE_READ|QUERY_TYPE_WRITE
|
||||||
|
QUERY_TYPE_READ|QUERY_TYPE_WRITE
|
||||||
|
|||||||
@ -16,3 +16,6 @@ select last_insert_id();
|
|||||||
select @@last_insert_id;
|
select @@last_insert_id;
|
||||||
select @@identity;
|
select @@identity;
|
||||||
select if(@@hostname='box02','prod_mariadb02','n');
|
select if(@@hostname='box02','prod_mariadb02','n');
|
||||||
|
select next value for seq1;
|
||||||
|
select nextval(seq1);
|
||||||
|
select seq1.nextval;
|
||||||
|
|||||||
Reference in New Issue
Block a user