yielding
yielding

Reputation: 77

parsing SQL CREATE statement using ANTLR4: no viable alternative at input 'conflict'

I'm newbie ANTLR user and trying to parse the following sql create statement. (I dropped some unimportant part of both SQL and grammar)

CREATE TABLE Account (_id integer primary key, conflict integer default 1);

and the grammar is like this: (You can compile this grammar with copy&paste)

grammar CreateTable;

tableList : (createTableStmt)* ;

createTableStmt : CREATE TABLE tableName LP columnDefs (COMMA tableConstraints)? RP SEMICOLON ;

columnDefs      : columnDef (COMMA columnDef)* ;
columnDef       : columnName typeName? columnConstraint* ;
typeName        : sqliteType (LP SIGNED_NUMBER (COMMA SIGNED_NUMBER)? RP)?  ;
sqliteType      : intType | textType | ID ;
intType         : 'INTEGER'|'LONG';
textType        : TEXT ; 

columnConstraint
    : (CONSTRAINT name)? PRIMARY KEY conflictClause?
    | (CONSTRAINT name)? UNIQUE conflictClause?
    | (CONSTRAINT name)? DEFAULT SIGNED_NUMBER
    ;

tableConstraints
    : tableConstraint (COMMA tableConstraint)* ;

tableConstraint
    : (CONSTRAINT name)? (PRIMARY KEY|UNIQUE) LP indexedColumns RP conflictClause? ;

conflictClause  : ON CONFLICT REPLACE ;
indexedColumns  : indexedColumn (COMMA indexedColumn)* ;
indexedColumn   : columnName;
columnName      : name ;
tableName       : name ;
name            : ID | '\"' ID '\"' | STRING_LITERAL ;

SIGNED_NUMBER   : (PLUS|MINUS)? NUMERIC_LITERAL ;
NUMERIC_LITERAL : DIGIT+ ;
STRING_LITERAL  : '\'' (~'\'')* '\'' ;

LP              : '(' ;
RP              : ')' ;
COMMA           : ',' ;
SEMICOLON       : ';' ;
PLUS            : '+' ;
MINUS           : '-' ;

CONFLICT        : C O N F L I C T ; 
CONSTRAINT      : C O N S T R A I N T ; 
CREATE          : C R E A T E ; 
DEFAULT         : D E F A U L T;
KEY             : K E Y ; 
ON              : O N;
PRIMARY         : P R I M A R Y ; 
REPLACE         : R E P L A C E;
TABLE           : T A B L E ; 
TEXT            : T E X T;
UNIQUE          : U N I Q U E ; 

WS              : [ \t\r\n\f]+ -> channel(HIDDEN);
ID              : LETTER (LETTER|DIGIT)*;
fragment LETTER : [a-zA-Z_];
fragment DIGIT  : [0-9] ;
NL              : '\r'? '\n' ;

fragment A:('a'|'A'); fragment B:('b'|'B'); fragment C:('c'|'C'); 
fragment D:('d'|'D'); fragment E:('e'|'E'); fragment F:('f'|'F'); 
fragment G:('g'|'G'); fragment I:('i'|'I'); fragment K:('k'|'K'); 
fragment L:('l'|'L'); fragment M:('m'|'M'); fragment N:('n'|'N'); 
fragment O:('o'|'O'); fragment P:('p'|'P'); fragment Q:('q'|'Q'); 
fragment R:('r'|'R'); fragment S:('s'|'S'); fragment T:('t'|'T'); 
fragment U:('u'|'U'); fragment X:('x'|'X');

By the way, the above SQL statement I should parse uses reserved word 'conflict' as column name. If I change column name 'conflict' with other name like 'conflict1' everything is okay.

Where should I change to parse above SQL statement?

The parse trees look like this.

wrong case correct case

Thanks

Upvotes: 0

Views: 1141

Answers (1)

Ken Homer
Ken Homer

Reputation: 141

You are defining the input "conflict" as a separate token CONFLICT. So if it is also a valid table name and column name, this should work:

name            : ID | '\"' ID '\"' | STRING_LITERAL | CONFLICT

Upvotes: 1

Related Questions