1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-08-01 06:46:55 +03:00

MCOL-1384 Parser accepts quotes with qualified dbobject identifiers.

This commit is contained in:
Roman Nozdrin
2018-01-24 09:40:44 +03:00
parent f1b05a7c09
commit b9f2b55484
4 changed files with 149 additions and 46 deletions

View File

@ -9,6 +9,10 @@ ADD_CUSTOM_COMMAND(
DEPENDS ddl.y ddl.l DEPENDS ddl.y ddl.l
) )
# Parser puts extra info to stderr.
INCLUDE(../../check_compiler_flag.cmake)
MY_CHECK_AND_SET_COMPILER_FLAG("-DYYDEBUG" DEBUG)
########### next target ############### ########### next target ###############
set(ddlpackage_LIB_SRCS set(ddlpackage_LIB_SRCS

View File

@ -18,6 +18,7 @@
/* $Id: ddl.l 9341 2013-03-27 14:10:35Z chao $ */ /* $Id: ddl.l 9341 2013-03-27 14:10:35Z chao $ */
%{ %{
#include <string.h>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <stdio.h> #include <stdio.h>
@ -31,10 +32,11 @@
#endif #endif
using namespace ddlpackage; using namespace ddlpackage;
typedef enum { NOOP, STRIP_QUOTES, STRIP_QUOTES_FQ } copy_action_t;
int lineno = 1; int lineno = 1;
void ddlerror(struct pass_to_bison* x, char const *s); void ddlerror(struct pass_to_bison* x, char const *s);
static char* scanner_copy(char *str, yyscan_t yyscanner); static char* scanner_copy(char *str, yyscan_t yyscanner, copy_action_t action = NOOP );
%} %}
@ -54,6 +56,10 @@ horiz_space [ \t\f]
newline [\n\r] newline [\n\r]
non_newline [^\n\r] non_newline [^\n\r]
quote '
double_quote \"
grave_accent `
comment ("--"{non_newline}*) comment ("--"{non_newline}*)
self [,()\[\].;\:\+\-\*\/\%\^\<\>\=] self [,()\[\].;\:\+\-\*\/\%\^\<\>\=]
whitespace ({space}+|{comment}) whitespace ({space}+|{comment})
@ -62,6 +68,12 @@ digit [0-9]
ident_start [A-Za-z\200-\377_] ident_start [A-Za-z\200-\377_]
ident_cont [A-Za-z\200-\377_0-9\$] ident_cont [A-Za-z\200-\377_0-9\$]
identifier {ident_start}{ident_cont}* identifier {ident_start}{ident_cont}*
/* fully qualified names regexes */
fq_identifier {identifier}\.{identifier}
identifier_quoted {grave_accent}{identifier}{grave_accent}
identifier_double_quoted {double_quote}{identifier}{double_quote}
fq_quoted ({identifier_quoted}|{identifier})\.({identifier_quoted}|{identifier})
fq_double_quoted ({identifier_double_quoted}|{identifier})\.({identifier_double_quoted}|{identifier})
integer [-+]?{digit}+ integer [-+]?{digit}+
decimal ([-+]?({digit}*\.{digit}+)|({digit}+\.{digit}*)) decimal ([-+]?({digit}*\.{digit}+)|({digit}+\.{digit}*))
@ -69,11 +81,16 @@ real ({integer}|{decimal})[Ee][-+]?{digit}+
realfail1 ({integer}|{decimal})[Ee] realfail1 ({integer}|{decimal})[Ee]
realfail2 ({integer}|{decimal})[Ee][-+] realfail2 ({integer}|{decimal})[Ee][-+]
quote '
grave_accent `
%% %%
{identifier_quoted} { ddlget_lval(yyscanner)->str = scanner_copy( ddlget_text(yyscanner), yyscanner, STRIP_QUOTES ); return IDENT; }
{identifier_double_quoted} { ddlget_lval(yyscanner)->str = scanner_copy( ddlget_text(yyscanner), yyscanner, STRIP_QUOTES ); return IDENT; }
{fq_identifier} { ddlget_lval(yyscanner)->str = scanner_copy(ddlget_text(yyscanner), yyscanner); return FQ_IDENT; }
{fq_quoted} { ddlget_lval(yyscanner)->str = scanner_copy(ddlget_text(yyscanner), yyscanner, STRIP_QUOTES_FQ); return FQ_IDENT; }
{fq_double_quoted} { ddlget_lval(yyscanner)->str = scanner_copy(ddlget_text(yyscanner), yyscanner, STRIP_QUOTES_FQ); return FQ_IDENT; }
ACTION {return ACTION;} ACTION {return ACTION;}
ADD {return ADD;} ADD {return ADD;}
ALTER {return ALTER;} ALTER {return ALTER;}
@ -198,6 +215,11 @@ using namespace ddlpackage;
*/ */
void scanner_init(const char* str, yyscan_t yyscanner) void scanner_init(const char* str, yyscan_t yyscanner)
{ {
#ifdef YYDEBUG
extern int ddldebug;
ddldebug = 1;
#endif
size_t slen = strlen(str); size_t slen = strlen(str);
scan_data* pScanData = (scan_data*)ddlget_extra(yyscanner); scan_data* pScanData = (scan_data*)ddlget_extra(yyscanner);
@ -246,10 +268,72 @@ void scanner_finish(yyscan_t yyscanner)
pScanData->valbuf.clear(); pScanData->valbuf.clear();
} }
char* scanner_copy (char *str, yyscan_t yyscanner) char* scanner_copy (char *str, yyscan_t yyscanner, copy_action_t action)
{ {
char* nv = strdup(str); char* result;
if(nv) char* nv = strdup(str);
((scan_data*)ddlget_extra(yyscanner))->valbuf.push_back(nv); result = nv;
return nv;
// free strduped memory later to prevent possible memory leak
if(nv)
((scan_data*)ddlget_extra(yyscanner))->valbuf.push_back(nv);
if(action == STRIP_QUOTES)
{
nv[strlen(str) - 1] = '\0';
result = nv + 1;
}
else if (action == STRIP_QUOTES_FQ)
{
bool move_left = false;
bool move_right = false;
char* left = nv;
char* tmp_first = nv;
// MCOL-1384 Loop through all comas in this quoted fq id
// looking for $quote_sign.$quote_sign sequence.
char* fq_delimiter;
int tmp_pos = 0;
while((fq_delimiter = strchr(tmp_first, '.')) != NULL)
{
if( (*(fq_delimiter -1) == '`' && *(fq_delimiter + 1) == '`') ||
(*(fq_delimiter -1) == '"' && *(fq_delimiter + 1) == '"') )
{
tmp_pos += fq_delimiter - tmp_first;
break;
}
tmp_first = fq_delimiter;
}
char* fq_delimiter_orig = str + tmp_pos;
char* right = fq_delimiter + 1;
char* right_orig = fq_delimiter_orig + 1;
// MCOL-1384 Strip quotes from the left part.
if(*left == '"' || *left == '`')
{
result = left + 1;
*(fq_delimiter - 1) = '.';
move_left = true;
}
else
{
fq_delimiter += 1;
}
int right_length = strlen(right);
// MCOL-1384 Strip quotes from the right part.
if(*right == '`' || *right == '"')
{
right += 1; right_orig += 1;
right_length -= 2;
move_right = true;
*(fq_delimiter + right_length) = '\0';
}
if(move_left || move_right)
{
strncpy(fq_delimiter, right_orig, right_length);
}
}
return result;
} }

View File

@ -48,6 +48,7 @@
*/ */
%{ %{
#include "string.h"
#include "sqlparser.h" #include "sqlparser.h"
#ifdef _MSC_VER #ifdef _MSC_VER
@ -121,7 +122,7 @@ REFERENCES RENAME RESTRICT SET SMALLINT TABLE TEXT TIME TINYBLOB TINYTEXT
TINYINT TO UNIQUE UNSIGNED UPDATE USER SESSION_USER SYSTEM_USER VARCHAR VARBINARY TINYINT TO UNIQUE UNSIGNED UPDATE USER SESSION_USER SYSTEM_USER VARCHAR VARBINARY
VARYING WITH ZONE DOUBLE IDB_FLOAT REAL CHARSET IDB_IF EXISTS CHANGE TRUNCATE VARYING WITH ZONE DOUBLE IDB_FLOAT REAL CHARSET IDB_IF EXISTS CHANGE TRUNCATE
%token <str> IDENT FCONST SCONST CP_SEARCH_CONDITION_TEXT ICONST DATE %token <str> FQ_IDENT IDENT FCONST SCONST CP_SEARCH_CONDITION_TEXT ICONST DATE
/* Notes: /* Notes:
* 1. "ata" stands for alter_table_action * 1. "ata" stands for alter_table_action
@ -611,7 +612,19 @@ table_name:
; ;
qualified_name: qualified_name:
IDENT '.' IDENT {$$ = new QualifiedName($1, $3);} FQ_IDENT {
char* delimeterPosition = strchr(const_cast<char*>($1), '.');
if( delimeterPosition )
{
*delimeterPosition = '\0';
char* schemaName = const_cast<char*>($1);
char* tableName = delimeterPosition + 1;
$$ = new QualifiedName(schemaName, tableName);
*delimeterPosition = '.';
}
else
$$ = new QualifiedName($1);
}
| IDENT { | IDENT {
if (x->fDBSchema.size()) if (x->fDBSchema.size())
$$ = new QualifiedName((char*)x->fDBSchema.c_str(), $1); $$ = new QualifiedName((char*)x->fDBSchema.c_str(), $1);

View File

@ -2039,51 +2039,53 @@ int ha_calpont_impl_delete_table_(const char *db, const char *name, cal_connecti
int ha_calpont_impl_rename_table_(const char* from, const char* to, cal_connection_info& ci) int ha_calpont_impl_rename_table_(const char* from, const char* to, cal_connection_info& ci)
{ {
THD *thd = current_thd; THD* thd = current_thd;
string emsg; string emsg;
ostringstream stmt1; pair<string, string> fromPair;
pair<string, string> fromPair; pair<string, string> toPair;
pair<string, string> toPair; string stmt;
string stmt;
//this is replcated DDL, treat it just like SSO //this is replcated DDL, treat it just like SSO
if (thd->slave_thread) if (thd->slave_thread)
return 0; return 0;
//@bug 5660. Error out REAL DDL/DML on slave node. //@bug 5660. Error out REAL DDL/DML on slave node.
// When the statement gets here, it's NOT SSO or RESTRICT // When the statement gets here, it's NOT SSO or RESTRICT
if (ci.isSlaveNode) if (ci.isSlaveNode)
{ {
string emsg = logging::IDBErrorInfo::instance()->errorMsg(ERR_DML_DDL_SLAVE); string emsg = logging::IDBErrorInfo::instance()->errorMsg(ERR_DML_DDL_SLAVE);
setError(current_thd, ER_CHECK_NOT_IMPLEMENTED, emsg); setError(current_thd, ER_CHECK_NOT_IMPLEMENTED, emsg);
return 1; return 1;
} }
fromPair = parseTableName(from); fromPair = parseTableName(from);
toPair = parseTableName(to); toPair = parseTableName(to);
if (fromPair.first != toPair.first) if (fromPair.first != toPair.first)
{ {
thd->get_stmt_da()->set_overwrite_status(true); thd->get_stmt_da()->set_overwrite_status(true);
thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED, "Both tables must be in the same database to use RENAME TABLE"); thd->raise_error_printf(ER_CHECK_NOT_IMPLEMENTED, "Both tables must be in the same database to use RENAME TABLE");
return -1; return -1;
} }
stmt1 << "alter table " << fromPair.second << " rename to " << toPair.second << ";"; // This explicitely shields both db objects with quotes that the lexer strips down later.
stmt = "alter table `" + fromPair.second + "` rename to `" + toPair.second + "`;";
string db;
stmt = stmt1.str(); if ( thd->db )
string db; db = thd->db;
if ( fromPair.first.length() !=0 ) else if ( fromPair.first.length() != 0 )
db = fromPair.first; db = fromPair.first;
else if ( thd->db ) else
db = thd->db; db = toPair.first;
int rc = ProcessDDLStatement(stmt, db, "", tid2sid(thd->thread_id), emsg); int rc = ProcessDDLStatement(stmt, db, "", tid2sid(thd->thread_id), emsg);
if (rc != 0)
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999, emsg.c_str());
return rc; if (rc != 0)
push_warning(thd, Sql_condition::WARN_LEVEL_ERROR, 9999, emsg.c_str());
return rc;
} }