grammar: Fix parsing of exotic column data types

This fixes two issues with unusual but valid data types for columns:

1) When having a data type that consists of more than one word these
wouldn't be separated anymore after parsing. This is fixed now. Example:
CREATE TABLE test(a long int);
would have become
CREATE TABLE test(a longint);

2) Some keywords are allowed to be used as data types. Parsing these
tables would have failed entire prior to this. This is fixed, too.
Example:
CREATE TABLE test(a no);
would fail.
This commit is contained in:
Martin Kleusberg
2017-01-14 14:46:04 +01:00
parent 09b679252e
commit 64fdd78105
3 changed files with 82 additions and 11 deletions

View File

@@ -1242,6 +1242,34 @@ void Sqlite3Parser::columndef() {
}
{
switch ( LA(1)) {
case ABORT:
case ACTION:
case ASC:
case CASCADE:
case CAST:
case CONFLICT:
case CURRENT_TIME:
case CURRENT_DATE:
case CURRENT_TIMESTAMP:
case DEFERRED:
case DESC:
case END:
case FAIL:
case GLOB:
case KEY:
case LIKE:
case IGNORE:
case INITIALLY:
case IMMEDIATE:
case NO:
case MATCH:
case RAISE:
case REGEXP:
case REPLACE:
case RESTRICT:
case ROLLBACK:
case TEMPORARY:
case TEMP:
case ID:
case QUOTEDID:
case QUOTEDLITERAL:
@@ -2495,16 +2523,58 @@ void Sqlite3Parser::type_name() {
{ // ( ... )+
int _cnt117=0;
for (;;) {
if ((_tokenSet_1.member(LA(1)))) {
switch ( LA(1)) {
case ID:
case QUOTEDID:
case QUOTEDLITERAL:
case STRINGLITERAL:
{
name();
if (inputState->guessing==0) {
astFactory->addASTChild( currentAST, returnAST );
}
break;
}
else {
case ABORT:
case ACTION:
case ASC:
case CASCADE:
case CAST:
case CONFLICT:
case CURRENT_TIME:
case CURRENT_DATE:
case CURRENT_TIMESTAMP:
case DEFERRED:
case DESC:
case END:
case FAIL:
case GLOB:
case KEY:
case LIKE:
case IGNORE:
case INITIALLY:
case IMMEDIATE:
case NO:
case MATCH:
case RAISE:
case REGEXP:
case REPLACE:
case RESTRICT:
case ROLLBACK:
case TEMPORARY:
case TEMP:
{
keywordastablename();
if (inputState->guessing==0) {
astFactory->addASTChild( currentAST, returnAST );
}
break;
}
default:
{
if ( _cnt117>=1 ) { goto _loop117; } else {throw ANTLR_USE_NAMESPACE(antlr)NoViableAltException(LT(1), getFilename());}
}
}
_cnt117++;
}
_loop117:;

View File

@@ -348,7 +348,7 @@ name : ID | QUOTEDID | QUOTEDLITERAL | STRINGLITERAL;
type_name
:
(name)+
(name | keywordastablename)+
(LPAREN signednumber (COMMA signednumber)? RPAREN)?
{#type_name = #([TYPE_NAME, "TYPE_NAME"], #type_name);}
;

View File

@@ -429,15 +429,16 @@ QString identifier(antlr::RefAST ident)
QString concatTextAST(antlr::RefAST t, bool withspace = false)
{
// When this is called for a KEYWORDASTABLENAME token, we must take the child's content to get the actual value
// instead of 'KEYWORDASTABLENAME' as a string. The same applies for KEYWORDASCOLUMNNAME tokens.
if(t != antlr::nullAST && (t->getType() == sqlite3TokenTypes::KEYWORDASTABLENAME || t->getType() == sqlite3TokenTypes::KEYWORDASCOLUMNNAME))
return concatTextAST(t->getFirstChild());
QStringList stext;
while(t != antlr::nullAST)
{
stext.append(t->getText().c_str());
// When this is called for a KEYWORDASTABLENAME token, we must take the child's content to get the actual value
// instead of 'KEYWORDASTABLENAME' as a string. The same applies for KEYWORDASCOLUMNNAME tokens.
if(t != antlr::nullAST && (t->getType() == sqlite3TokenTypes::KEYWORDASTABLENAME || t->getType() == sqlite3TokenTypes::KEYWORDASCOLUMNNAME))
stext.append(t->getFirstChild()->getText().c_str());
else
stext.append(t->getText().c_str());
t = t->getNextSibling();
}
return stext.join(withspace ? " " : "");
@@ -707,7 +708,7 @@ void CreateTableWalker::parsecolumn(Table& table, antlr::RefAST c)
c = c->getNextSibling(); //type?
if(c != antlr::nullAST && c->getType() == sqlite3TokenTypes::TYPE_NAME)
{
type = concatTextAST(c->getFirstChild());
type = concatTextAST(c->getFirstChild(), true);
c = c->getNextSibling();
}