You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/kexi/kexidb/parser/sqlparser.y

1369 lines
24 KiB

/* This file is part of the KDE project
Copyright (C) 2004 Lucijan Busch <lucijan@kde.org>
Copyright (C) 2004, 2006 Jaroslaw Staniek <js@iidea.pl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
%token UMINUS
%token SQL_TYPE
%token SQL_ABS
%token ACOS
%token AMPERSAND
%token SQL_ABSOLUTE
%token ADA
%token ADD
%token ADD_DAYS
%token ADD_HOURS
%token ADD_MINUTES
%token ADD_MONTHS
%token ADD_SECONDS
%token ADD_YEARS
%token ALL
%token ALLOCATE
%token ALTER
%token AND
%token ANY
%token ARE
%token AS
%token ASIN
%token ASC
%token ASCII
%token ASSERTION
%token ATAN
%token ATAN2
%token AUTHORIZATION
%token AUTO_INCREMENT
%token AVG
%token BEFORE
%token SQL_BEGIN
%token BETWEEN
%token BIGINT
%token BINARY
%token BIT
%token BIT_LENGTH
%token BITWISE_SHIFT_LEFT
%token BITWISE_SHIFT_RIGHT
%token BREAK
%token BY
%token CASCADE
%token CASCADED
%token CASE
%token CAST
%token CATALOG
%token CEILING
%token CENTER
%token SQL_CHAR
%token CHAR_LENGTH
%token CHARACTER_STRING_LITERAL
%token CHECK
%token CLOSE
%token COALESCE
%token COBOL
%token COLLATE
%token COLLATION
%token COLUMN
%token COMMIT
%token COMPUTE
%token CONCAT
%token CONCATENATION /* || */
%token CONNECT
%token CONNECTION
%token CONSTRAINT
%token CONSTRAINTS
%token CONTINUE
%token CONVERT
%token CORRESPONDING
%token COS
%token COT
%token COUNT
%token CREATE
%token CURDATE
%token CURRENT
%token CURRENT_DATE
%token CURRENT_TIME
%token CURRENT_TIMESTAMP
%token CURTIME
%token CURSOR
%token DATABASE
%token SQL_DATE
%token DATE_FORMAT
%token DATE_REMAINDER
%token DATE_VALUE
%token DAY
%token DAYOFMONTH
%token DAYOFWEEK
%token DAYOFYEAR
%token DAYS_BETWEEN
%token DEALLOCATE
%token DEC
%token DECLARE
%token DEFAULT
%token DEFERRABLE
%token DEFERRED
%token SQL_DELETE
%token DESC
%token DESCRIBE
%token DESCRIPTOR
%token DIAGNOSTICS
%token DICTIONARY
%token DIRECTORY
%token DISCONNECT
%token DISPLACEMENT
%token DISTINCT
%token DOMAIN_TOKEN
%token SQL_DOUBLE
%token DOUBLE_QUOTED_STRING
%token DROP
%token ELSE
%token END
%token END_EXEC
%token EQUAL
%token ESCAPE
%token EXCEPT
%token SQL_EXCEPTION
%token EXEC
%token EXECUTE
%token EXISTS
%token EXP
%token EXPONENT
%token EXTERNAL
%token EXTRACT
%token SQL_FALSE
%token FETCH
%token FIRST
%token SQL_FLOAT
%token FLOOR
%token FN
%token FOR
%token FOREIGN
%token FORTRAN
%token FOUND
%token FOUR_DIGITS
%token FROM
%token FULL
%token GET
%token GLOBAL
%token GO
%token GOTO
%token GRANT
%token GREATER_OR_EQUAL
//%token GREATER_THAN
//conflict %token GROUP
%token HAVING
%token HOUR
%token HOURS_BETWEEN
%token IDENTITY
%token IFNULL
%token SQL_IGNORE
%token IMMEDIATE
%token SQL_IN
%token INCLUDE
%token INDEX
%token INDICATOR
%token INITIALLY
%token INNER
%token INPUT
%token INSENSITIVE
%token INSERT
%token INTEGER
%token INTERSECT
%token INTERVAL
%token INTO
%token IS
%token ISOLATION
%token JOIN
%token JUSTIFY
%token KEY
%token LANGUAGE
%token LAST
%token LCASE
%token LEFT
%token LENGTH
%token LESS_OR_EQUAL
//%token LESS_THAN
%token LEVEL
%token LIKE
%token LINE_WIDTH
%token LOCAL
%token LOCATE
%token LOG
%token SQL_LONG
%token LOWER
%token LTRIM
%token LTRIP
%token MATCH
%token SQL_MAX
%token MICROSOFT
%token SQL_MIN
%token MINUS
%token MINUTE
%token MINUTES_BETWEEN
%token MOD
%token MODIFY
%token MODULE
%token MONTH
%token MONTHS_BETWEEN
%token MUMPS
%token NAMES
%token NATIONAL
%token NCHAR
%token NEXT
%token NODUP
%token NONE
%token NOT
%token NOT_EQUAL //<>
%token NOT_EQUAL2 //!=
%token NOW
%token SQL_NULL
%token SQL_IS
%token SQL_IS_NULL /*helper */
%token SQL_IS_NOT_NULL /*helper */
%token NULLIF
%token NUMERIC
%token OCTET_LENGTH
%token ODBC
%token OF
%token SQL_OFF
%token SQL_ON
%token ONLY
%token OPEN
%token OPTION
%token OR
%token ORDER
%token OUTER
%token OUTPUT
%token OVERLAPS
%token PAGE
%token PARTIAL
%token SQL_PASCAL
%token PERSISTENT
%token CQL_PI
%token PLI
%token POSITION
%token PRECISION
%token PREPARE
%token PRESERVE
%token PRIMARY
%token PRIOR
%token PRIVILEGES
%token PROCEDURE
%token PRODUCT
%token PUBLIC
%token QUARTER
%token QUIT
%token RAND
%token READ_ONLY
%token REAL
%token REFERENCES
%token REPEAT
%token REPLACE
%token RESTRICT
%token REVOKE
%token RIGHT
%token ROLLBACK
%token ROWS
%token RPAD
%token RTRIM
%token SCHEMA
%token SCREEN_WIDTH
%token SCROLL
%token SECOND
%token SECONDS_BETWEEN
%token SELECT
%token SEQUENCE
%token SETOPT
%token SET
%token SHOWOPT
%token SIGN
//%token SIMILAR
%token SIMILAR_TO /* helper */
%token NOT_SIMILAR_TO /* helper */
%token INTEGER_CONST
%token REAL_CONST
%token DATE_CONST
%token DATETIME_CONST
%token TIME_CONST
%token SIN
%token SQL_SIZE
%token SMALLINT
%token SOME
%token SPACE
%token SQL
%token SQL_TRUE
%token SQLCA
%token SQLCODE
%token SQLERROR
%token SQLSTATE
%token SQLWARNING
%token SQRT
%token STDEV
%token SUBSTRING
%token SUM
%token SYSDATE
%token SYSDATE_FORMAT
%token SYSTEM
%token TABLE
%token TAN
%token TEMPORARY
%token THEN
%token THREE_DIGITS
%token TIME
%token TIMESTAMP
%token TIMEZONE_HOUR
%token TIMEZONE_MINUTE
%token TINYINT
%token TO
%token TO_CHAR
%token TO_DATE
%token TRANSACTION
%token TRANSLATE
%token TRANSLATION
%token TRUNCATE
%token GENERAL_TITLE
%token TWO_DIGITS
%token UCASE
%token UNION
%token UNIQUE
%token SQL_UNKNOWN
//%token UNSIGNED_INTEGER
%token UPDATE
%token UPPER
%token USAGE
%token USER
%token IDENTIFIER
%token IDENTIFIER_DOT_ASTERISK
%token QUERY_PARAMETER
//%token ERROR_DIGIT_BEFORE_IDENTIFIER
%token USING
%token VALUE
%token VALUES
%token VARBINARY
%token VARCHAR
%token VARYING
%token VENDOR
%token VIEW
%token WEEK
%token WHEN
%token WHENEVER
%token WHERE
%token WHERE_CURRENT_OF
%token WITH
%token WORD_WRAPPED
%token WORK
%token WRAPPED
%token XOR
%token YEAR
%token YEARS_BETWEEN
%token SCAN_ERROR
%token __LAST_TOKEN /* sentinel */
%token '-' '+'
%token '*'
%token '%'
%token '@'
%token ';'
%token ','
%token '.'
%token '$'
//%token '<'
//%token '>'
%token '(' ')'
%token '?'
%token '\''
%token '/'
%type <stringValue> IDENTIFIER
%type <stringValue> IDENTIFIER_DOT_ASTERISK
%type <stringValue> QUERY_PARAMETER
%type <stringValue> CHARACTER_STRING_LITERAL
%type <stringValue> DOUBLE_QUOTED_STRING
/*
%type <field> ColExpression
%type <field> ColView
*/
%type <expr> ColExpression
%type <expr> ColWildCard
//%type <expr> ColView
%type <expr> ColItem
%type <exprList> ColViews
%type <expr> aExpr
%type <expr> aExpr2
%type <expr> aExpr3
%type <expr> aExpr4
%type <expr> aExpr5
%type <expr> aExpr6
%type <expr> aExpr7
%type <expr> aExpr8
%type <expr> aExpr9
%type <expr> aExpr10
%type <exprList> aExprList
%type <exprList> aExprList2
%type <expr> WhereClause
%type <orderByColumns> OrderByClause
%type <booleanValue> OrderByOption
%type <variantValue> OrderByColumnId
%type <selectOptions> SelectOptions
%type <expr> FlatTable
%type <exprList> Tables
%type <exprList> FlatTableList
%type <querySchema> SelectStatement
%type <querySchema> Select
/*todo : list*/
%type <querySchema> StatementList
/*todo: not onlu select*/
%type <querySchema> Statement
%type <colType> SQL_TYPE
%type <integerValue> INTEGER_CONST
%type <realValue> REAL_CONST
/*%type <integerValue> SIGNED_INTEGER */
%{
#ifndef YYDEBUG /* compat. */
# define YYDEBUG 0
#endif
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <assert.h>
#include <limits.h>
//TODO OK?
#ifdef Q_WS_WIN
//workaround for bug on msvc
# undef LLONG_MIN
#endif
#ifndef LLONG_MAX
# define LLONG_MAX 0x7fffffffffffffffLL
#endif
#ifndef LLONG_MIN
# define LLONG_MIN 0x8000000000000000LL
#endif
#ifndef LLONG_MAX
# define ULLONG_MAX 0xffffffffffffffffLL
#endif
#ifdef _WIN32
# include <malloc.h>
#endif
#include <qobject.h>
#include <kdebug.h>
#include <klocale.h>
#include <qptrlist.h>
#include <qcstring.h>
#include <qvariant.h>
#include <connection.h>
#include <queryschema.h>
#include <field.h>
#include <tableschema.h>
#include "parser.h"
#include "parser_p.h"
#include "sqltypes.h"
int yylex();
// using namespace std;
using namespace KexiDB;
#define YY_NO_UNPUT
#define YYSTACK_USE_ALLOCA 1
#define YYMAXDEPTH 255
extern "C"
{
int yywrap()
{
return 1;
}
}
#if 0
struct yyval
{
QString parserUserName;
int integerValue;
KexiDBField::ColumnType coltype;
}
#endif
%}
%union {
QString* stringValue;
Q_LLONG integerValue;
bool booleanValue;
struct realType realValue;
KexiDB::Field::Type colType;
KexiDB::Field *field;
KexiDB::BaseExpr *expr;
KexiDB::NArgExpr *exprList;
KexiDB::ConstExpr *constExpr;
KexiDB::QuerySchema *querySchema;
SelectOptionsInternal *selectOptions;
OrderByColumnInternal::List *orderByColumns;
QVariant *variantValue;
}
//%left '=' NOT_EQUAL '>' GREATER_OR_EQUAL '<' LESS_OR_EQUAL LIKE '%' NOT
//%left '+' '-'
//%left ASTERISK SLASH
/* precedence: lowest to highest */
%left UNION EXCEPT
%left INTERSECT
%left OR
%left AND XOR
%right NOT
//%right '='
//%nonassoc '<' '>'
//%nonassoc '=' '<' '>' "<=" ">=" "<>" ":=" LIKE ILIKE SIMILAR
//%nonassoc '=' LESS_THAN GREATER_THAN LESS_OR_EQUAL GREATER_OR_EQUAL NOT_EQUAL
%nonassoc '=' '<' '>'
//LESS_THAN GREATER_THAN
%nonassoc LESS_OR_EQUAL GREATER_OR_EQUAL
%nonassoc NOT_EQUAL NOT_EQUAL2
%nonassoc SQL_IN LIKE ILIKE SIMILAR_TO NOT_SIMILAR_TO
//%nonassoc LIKE ILIKE SIMILAR
//%nonassoc ESCAPE
//%nonassoc OVERLAPS
%nonassoc BETWEEN
//%nonassoc IN_P
//%left POSTFIXOP // dummy for postfix Op rules
//%left Op OPERATOR // multi-character ops and user-defined operators
//%nonassoc NOTNULL
//%nonassoc ISNULL
//%nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN // sets precedence for IS NULL, etc
%left '+' '-'
%left '*' '/' '%'
%left '^'
%left UMINUS
// Unary Operators
//%left AT ZONE // sets precedence for AT TIME ZONE
//%right UMINUS
%left '[' ']'
%left '(' ')'
//%left TYPECAST
%left '.'
/*
* These might seem to be low-precedence, but actually they are not part
* of the arithmetic hierarchy at all in their use as JOIN operators.
* We make them high-precedence to support their use as function names.
* They wouldn't be given a precedence at all, were it not that we need
* left-associativity among the JOIN rules themselves.
*/
/*%left JOIN UNIONJOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
*/
%%
TopLevelStatement :
StatementList
{
//todo: multiple statements
//todo: not only "select" statements
parser->setOperation(Parser::OP_Select);
parser->setQuerySchema($1);
}
;
StatementList:
Statement ';' StatementList
{
//todo: multiple statements
}
| Statement
| Statement ';'
{
$$ = $1;
}
;
/* Statement CreateTableStatement { YYACCEPT; }
| Statement SelectStatement { }
*/
Statement :
CreateTableStatement
{
YYACCEPT;
}
| SelectStatement
{
$$ = $1;
}
;
CreateTableStatement :
CREATE TABLE IDENTIFIER
{
parser->setOperation(Parser::OP_CreateTable);
parser->createTable($3->latin1());
delete $3;
}
'(' ColDefs ')'
;
ColDefs:
ColDefs ',' ColDef|ColDef
{
}
;
ColDef:
IDENTIFIER ColType
{
KexiDBDbg << "adding field " << *$1 << endl;
field->setName($1->latin1());
parser->table()->addField(field);
field = 0;
delete $1;
}
| IDENTIFIER ColType ColKeys
{
KexiDBDbg << "adding field " << *$1 << endl;
field->setName(*$1);
delete $1;
parser->table()->addField(field);
// if(field->isPrimaryKey())
// parser->table()->addPrimaryKey(field->name());
// delete field;
// field = 0;
}
;
ColKeys:
ColKeys ColKey|ColKey
{
}
;
ColKey:
PRIMARY KEY
{
field->setPrimaryKey(true);
KexiDBDbg << "primary" << endl;
}
| NOT SQL_NULL
{
field->setNotNull(true);
KexiDBDbg << "not_null" << endl;
}
| AUTO_INCREMENT
{
field->setAutoIncrement(true);
KexiDBDbg << "ainc" << endl;
}
;
ColType:
SQL_TYPE
{
field = new Field();
field->setType($1);
}
| SQL_TYPE '(' INTEGER_CONST ')'
{
KexiDBDbg << "sql + length" << endl;
field = new Field();
field->setPrecision($3);
field->setType($1);
}
| VARCHAR '(' INTEGER_CONST ')'
{
field = new Field();
field->setPrecision($3);
field->setType(Field::Text);
}
|
{
// SQLITE compatibillity
field = new Field();
field->setType(Field::InvalidType);
}
;
SelectStatement:
Select ColViews
{
KexiDBDbg << "Select ColViews=" << $2->debugString() << endl;
if (!($$ = buildSelectQuery( $1, $2 )))
return 0;
}
| Select ColViews Tables
{
if (!($$ = buildSelectQuery( $1, $2, $3 )))
return 0;
}
| Select Tables
{
KexiDBDbg << "Select ColViews Tables" << endl;
if (!($$ = buildSelectQuery( $1, 0, $2 )))
return 0;
}
| Select ColViews SelectOptions
{
KexiDBDbg << "Select ColViews Conditions" << endl;
if (!($$ = buildSelectQuery( $1, $2, 0, $3 )))
return 0;
}
| Select ColViews Tables SelectOptions
{
KexiDBDbg << "Select ColViews Tables SelectOptions" << endl;
if (!($$ = buildSelectQuery( $1, $2, $3, $4 )))
return 0;
}
;
Select:
SELECT
{
KexiDBDbg << "SELECT" << endl;
// parser->createSelect();
// parser->setOperation(Parser::OP_Select);
$$ = new QuerySchema();
}
;
SelectOptions: /* todo: more options (having, group by, limit...) */
WhereClause
{
KexiDBDbg << "WhereClause" << endl;
$$ = new SelectOptionsInternal;
$$->whereExpr = $1;
}
| ORDER BY OrderByClause
{
KexiDBDbg << "OrderByClause" << endl;
$$ = new SelectOptionsInternal;
$$->orderByColumns = $3;
}
| WhereClause ORDER BY OrderByClause
{
KexiDBDbg << "WhereClause ORDER BY OrderByClause" << endl;
$$ = new SelectOptionsInternal;
$$->whereExpr = $1;
$$->orderByColumns = $4;
}
| ORDER BY OrderByClause WhereClause
{
KexiDBDbg << "OrderByClause WhereClause" << endl;
$$ = new SelectOptionsInternal;
$$->whereExpr = $4;
$$->orderByColumns = $3;
}
;
WhereClause:
WHERE aExpr
{
$$ = $2;
}
;
/* todo: support "ORDER BY NULL" as described here http://dev.mysql.com/doc/refman/5.1/en/select.html */
/* todo: accept expr and position as well */
OrderByClause:
OrderByColumnId
{
KexiDBDbg << "ORDER BY IDENTIFIER" << endl;
$$ = new OrderByColumnInternal::List;
OrderByColumnInternal orderByColumn;
orderByColumn.setColumnByNameOrNumber( *$1 );
$$->append( orderByColumn );
delete $1;
}
| OrderByColumnId OrderByOption
{
KexiDBDbg << "ORDER BY IDENTIFIER OrderByOption" << endl;
$$ = new OrderByColumnInternal::List;
OrderByColumnInternal orderByColumn;
orderByColumn.setColumnByNameOrNumber( *$1 );
orderByColumn.ascending = $2;
$$->append( orderByColumn );
delete $1;
}
| OrderByColumnId ',' OrderByClause
{
$$ = $3;
OrderByColumnInternal orderByColumn;
orderByColumn.setColumnByNameOrNumber( *$1 );
$$->append( orderByColumn );
delete $1;
}
| OrderByColumnId OrderByOption ',' OrderByClause
{
$$ = $4;
OrderByColumnInternal orderByColumn;
orderByColumn.setColumnByNameOrNumber( *$1 );
orderByColumn.ascending = $2;
$$->append( orderByColumn );
delete $1;
}
;
OrderByColumnId:
IDENTIFIER
{
$$ = new QVariant( *$1 );
KexiDBDbg << "OrderByColumnId: " << *$$ << endl;
delete $1;
}
| IDENTIFIER '.' IDENTIFIER
{
$$ = new QVariant( *$1 + "." + *$3 );
KexiDBDbg << "OrderByColumnId: " << *$$ << endl;
delete $1;
delete $3;
}
| INTEGER_CONST
{
$$ = new QVariant($1);
KexiDBDbg << "OrderByColumnId: " << *$$ << endl;
}
OrderByOption:
ASC
{
$$ = true;
}
| DESC
{
$$ = false;
}
;
aExpr:
aExpr2
;
/* --- binary logical --- */
aExpr2:
aExpr3 AND aExpr2
{
// KexiDBDbg << "AND " << $3.debugString() << endl;
$$ = new BinaryExpr( KexiDBExpr_Logical, $1, AND, $3 );
}
| aExpr3 OR aExpr2
{
$$ = new BinaryExpr( KexiDBExpr_Logical, $1, OR, $3 );
}
| aExpr3 XOR aExpr2
{
$$ = new BinaryExpr( KexiDBExpr_Arithm, $1, XOR, $3 );
}
|
aExpr3
;
/* relational op precedence */
aExpr3:
aExpr4 '>' %prec GREATER_OR_EQUAL aExpr3
{
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, '>', $3);
}
| aExpr4 GREATER_OR_EQUAL aExpr3
{
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, GREATER_OR_EQUAL, $3);
}
| aExpr4 '<' %prec LESS_OR_EQUAL aExpr3
{
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, '<', $3);
}
| aExpr4 LESS_OR_EQUAL aExpr3
{
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, LESS_OR_EQUAL, $3);
}
| aExpr4 '=' aExpr3
{
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, '=', $3);
}
|
aExpr4
;
/* relational (equality) op precedence */
aExpr4:
aExpr5 NOT_EQUAL aExpr4
{
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, NOT_EQUAL, $3);
}
|
aExpr5 NOT_EQUAL2 aExpr4
{
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, NOT_EQUAL2, $3);
}
| aExpr5 LIKE aExpr4
{
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, LIKE, $3);
}
| aExpr5 SQL_IN aExpr4
{
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, SQL_IN, $3);
}
| aExpr5 SIMILAR_TO aExpr4
{
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, SIMILAR_TO, $3);
}
| aExpr5 NOT_SIMILAR_TO aExpr4
{
$$ = new BinaryExpr(KexiDBExpr_Relational, $1, NOT_SIMILAR_TO, $3);
}
|
aExpr5
;
/* --- unary logical right --- */
aExpr5:
aExpr5 SQL_IS_NULL
{
$$ = new UnaryExpr( SQL_IS_NULL, $1 );
}
| aExpr5 SQL_IS_NOT_NULL
{
$$ = new UnaryExpr( SQL_IS_NOT_NULL, $1 );
}
|
aExpr6
;
/* arithm. lowest precedence */
aExpr6:
aExpr7 BITWISE_SHIFT_LEFT aExpr6
{
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, BITWISE_SHIFT_LEFT, $3);
}
| aExpr7 BITWISE_SHIFT_RIGHT aExpr6
{
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, BITWISE_SHIFT_RIGHT, $3);
}
|
aExpr7
;
/* arithm. lower precedence */
aExpr7:
aExpr8 '+' aExpr7
{
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '+', $3);
$$->debug();
}
| aExpr8 '-' %prec UMINUS aExpr7
{
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '-', $3);
}
| aExpr8 '&' aExpr7
{
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '&', $3);
}
| aExpr8 '|' aExpr7
{
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '|', $3);
}
|
aExpr8
;
/* arithm. higher precedence */
aExpr8:
aExpr9 '/' aExpr8
{
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '/', $3);
}
| aExpr9 '*' aExpr8
{
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '*', $3);
}
| aExpr9 '%' aExpr8
{
$$ = new BinaryExpr(KexiDBExpr_Arithm, $1, '%', $3);
}
|
aExpr9
;
/* parenthesis, unary operators, and terminals precedence */
aExpr9:
/* --- unary logical left --- */
'-' aExpr9
{
$$ = new UnaryExpr( '-', $2 );
}
| '+' aExpr9
{
$$ = new UnaryExpr( '+', $2 );
}
| '~' aExpr9
{
$$ = new UnaryExpr( '~', $2 );
}
| NOT aExpr9
{
$$ = new UnaryExpr( NOT, $2 );
}
| IDENTIFIER
{
$$ = new VariableExpr( *$1 );
//TODO: simplify this later if that's 'only one field name' expression
KexiDBDbg << " + identifier: " << *$1 << endl;
delete $1;
}
| QUERY_PARAMETER
{
$$ = new QueryParameterExpr( *$1 );
KexiDBDbg << " + query parameter: " << $$->debugString() << endl;
delete $1;
}
| IDENTIFIER aExprList
{
KexiDBDbg << " + function: " << *$1 << "(" << $2->debugString() << ")" << endl;
$$ = new FunctionExpr(*$1, $2);
delete $1;
}
/*TODO: shall we also support db name? */
| IDENTIFIER '.' IDENTIFIER
{
$$ = new VariableExpr( *$1 + "." + *$3 );
KexiDBDbg << " + identifier.identifier: " << *$1 << "." << *$3 << endl;
delete $1;
delete $3;
}
| SQL_NULL
{
$$ = new ConstExpr( SQL_NULL, QVariant() );
KexiDBDbg << " + NULL" << endl;
// $$ = new Field();
//$$->setName(QString::null);
}
| CHARACTER_STRING_LITERAL
{
$$ = new ConstExpr( CHARACTER_STRING_LITERAL, *$1 );
KexiDBDbg << " + constant " << $1 << endl;
delete $1;
}
| INTEGER_CONST
{
QVariant val;
if ($1 <= INT_MAX && $1 >= INT_MIN)
val = (int)$1;
else if ($1 <= UINT_MAX && $1 >= 0)
val = (uint)$1;
else if ($1 <= (Q_LLONG)LLONG_MAX && $1 >= (Q_LLONG)LLONG_MIN)
val = (Q_LLONG)$1;
// if ($1 < ULLONG_MAX)
// val = (Q_ULLONG)$1;
//TODO ok?
$$ = new ConstExpr( INTEGER_CONST, val );
KexiDBDbg << " + int constant: " << val.toString() << endl;
}
| REAL_CONST
{
$$ = new ConstExpr( REAL_CONST, QPoint( $1.integer, $1.fractional ) );
KexiDBDbg << " + real constant: " << $1.integer << "." << $1.fractional << endl;
}
|
aExpr10
;
aExpr10:
'(' aExpr ')'
{
KexiDBDbg << "(expr)" << endl;
$$ = new UnaryExpr('(', $2);
}
;
aExprList:
'(' aExprList2 ')'
{
// $$ = new NArgExpr(0, 0);
// $$->add( $1 );
// $$->add( $3 );
$$ = $2;
}
;
aExprList2:
aExpr ',' aExprList2
{
$$ = $3;
$$->prepend( $1 );
}
| aExpr ',' aExpr
{
$$ = new NArgExpr(0, 0);
$$->add( $1 );
$$->add( $3 );
}
;
Tables:
FROM FlatTableList
{
$$ = $2;
}
/*
| Tables LEFT JOIN IDENTIFIER SQL_ON ColExpression
{
KexiDBDbg << "LEFT JOIN: '" << *$4 << "' ON " << $6 << endl;
addTable($4->toQString());
delete $4;
}
| Tables LEFT OUTER JOIN IDENTIFIER SQL_ON ColExpression
{
KexiDBDbg << "LEFT OUTER JOIN: '" << $5 << "' ON " << $7 << endl;
addTable($5);
}
| Tables INNER JOIN IDENTIFIER SQL_ON ColExpression
{
KexiDBDbg << "INNER JOIN: '" << *$4 << "' ON " << $6 << endl;
addTable($4->toQString());
delete $4;
}
| Tables RIGHT JOIN IDENTIFIER SQL_ON ColExpression
{
KexiDBDbg << "RIGHT JOIN: '" << *$4 << "' ON " << $6 << endl;
addTable(*$4);
delete $4;
}
| Tables RIGHT OUTER JOIN IDENTIFIER SQL_ON ColExpression
{
KexiDBDbg << "RIGHT OUTER JOIN: '" << *$5 << "' ON " << $7 << endl;
addTable($5->toQString());
delete $5;
}*/
;
/*
FlatTableList:
aFlatTableList
{
$$
}
;*/
FlatTableList:
FlatTableList ',' FlatTable
{
$$ = $1;
$$->add($3);
}
|FlatTable
{
$$ = new NArgExpr(KexiDBExpr_TableList, IDENTIFIER); //ok?
$$->add($1);
}
;
FlatTable:
IDENTIFIER
{
KexiDBDbg << "FROM: '" << *$1 << "'" << endl;
$$ = new VariableExpr(*$1);
/*
//TODO: this isn't ok for more tables:
Field::ListIterator it = parser->select()->fieldsIterator();
for(Field *item; (item = it.current()); ++it)
{
if(item->table() == dummy)
{
item->setTable(schema);
}
if(item->table() && !item->isQueryAsterisk())
{
Field *f = item->table()->field(item->name());
if(!f)
{
ParserError err(i18n("Field List Error"), i18n("Unknown column '%1' in table '%2'").arg(item->name()).arg(schema->name()), ctoken, current);
parser->setError(err);
yyerror("fieldlisterror");
}
}
}*/
delete $1;
}
| IDENTIFIER IDENTIFIER
{
//table + alias
$$ = new BinaryExpr(
KexiDBExpr_SpecialBinary,
new VariableExpr(*$1), 0,
new VariableExpr(*$2)
);
delete $1;
delete $2;
}
| IDENTIFIER AS IDENTIFIER
{
//table + alias
$$ = new BinaryExpr(
KexiDBExpr_SpecialBinary,
new VariableExpr(*$1), AS,
new VariableExpr(*$3)
);
delete $1;
delete $3;
}
;
ColViews:
ColViews ',' ColItem
{
$$ = $1;
$$->add( $3 );
KexiDBDbg << "ColViews: ColViews , ColItem" << endl;
}
|ColItem
{
$$ = new NArgExpr(0,0);
$$->add( $1 );
KexiDBDbg << "ColViews: ColItem" << endl;
}
;
ColItem:
ColExpression
{
// $$ = new Field();
// dummy->addField($$);
// $$->setExpression( $1 );
// parser->select()->addField($$);
$$ = $1;
KexiDBDbg << " added column expr: '" << $1->debugString() << "'" << endl;
}
| ColWildCard
{
$$ = $1;
KexiDBDbg << " added column wildcard: '" << $1->debugString() << "'" << endl;
}
| ColExpression AS IDENTIFIER
{
$$ = new BinaryExpr(
KexiDBExpr_SpecialBinary, $1, AS,
new VariableExpr(*$3)
);
KexiDBDbg << " added column expr: " << $$->debugString() << endl;
delete $3;
}
| ColExpression IDENTIFIER
{
$$ = new BinaryExpr(
KexiDBExpr_SpecialBinary, $1, 0,
new VariableExpr(*$2)
);
KexiDBDbg << " added column expr: " << $$->debugString() << endl;
delete $2;
}
;
ColExpression:
aExpr
{
$$ = $1;
}
/* HANDLED BY 'IDENTIFIER aExprList'
| IDENTIFIER '(' ColViews ')'
{
$$ = new FunctionExpr( $1, $3 );
}*/
/*
| SUM '(' ColExpression ')'
{
FunctionExpr(
// $$ = new AggregationExpr( SUM, );
//TODO
// $$->setName("SUM(" + $3->name() + ")");
//wait $$->containsGroupingAggregate(true);
//wait parser->select()->grouped(true);
}
| SQL_MIN '(' ColExpression ')'
{
$$ = $3;
//TODO
// $$->setName("MIN(" + $3->name() + ")");
//wait $$->containsGroupingAggregate(true);
//wait parser->select()->grouped(true);
}
| SQL_MAX '(' ColExpression ')'
{
$$ = $3;
//TODO
// $$->setName("MAX(" + $3->name() + ")");
//wait $$->containsGroupingAggregate(true);
//wait parser->select()->grouped(true);
}
| AVG '(' ColExpression ')'
{
$$ = $3;
//TODO
// $$->setName("AVG(" + $3->name() + ")");
//wait $$->containsGroupingAggregate(true);
//wait parser->select()->grouped(true);
}*/
//?
| DISTINCT '(' ColExpression ')'
{
$$ = $3;
//TODO
// $$->setName("DISTINCT(" + $3->name() + ")");
}
;
ColWildCard:
'*'
{
$$ = new VariableExpr("*");
KexiDBDbg << "all columns" << endl;
// QueryAsterisk *ast = new QueryAsterisk(parser->select(), dummy);
// parser->select()->addAsterisk(ast);
// requiresTable = true;
}
| IDENTIFIER '.' '*'
{
QString s( *$1 );
s += ".*";
$$ = new VariableExpr(s);
KexiDBDbg << " + all columns from " << s << endl;
delete $1;
}
/*| ERROR_DIGIT_BEFORE_IDENTIFIER
{
$$ = new VariableExpr($1);
KexiDBDbg << " Invalid identifier! " << $1 << endl;
setError(i18n("Invalid identifier \"%1\"").arg($1));
}*/
;
%%