%{ /* * PROGRAM: Dynamic SQL runtime support * MODULE: parse.y * DESCRIPTION: Dynamic SQL parser * * The contents of this file are subject to the Interbase Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy * of the License at http://www.Inprise.com/IPL.html * * Software distributed under the License is distributed on an * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express * or implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code was created by Inprise Corporation * and its predecessors. Portions created by Inprise Corporation are * Copyright (C) Inprise Corporation. * * All Rights Reserved. * Contributor(s): ______________________________________. * * 2002-02-24 Sean Leyne - Code Cleanup of old Win 3.1 port (WINDOWS_ONLY) * 2001.05.20 Neil McCalden: Allow a udf to be used in a 'group by' clause. * 2001.05.30 Claudio Valderrama: DROP TABLE and DROP VIEW lead now to two * different node types so DDL can tell which is which. * 2001.06.13 Claudio Valderrama: SUBSTRING is being surfaced. * 2001.06.30 Claudio valderrama: Feed (line,column) for each node. See node.h. * 2001.07.10 Claudio Valderrama: Better (line,column) report and "--" for comments. * 2001.07.28 John Bellardo: Changes to support parsing LIMIT and FIRST * 2001.08.03 John Bellardo: Finalized syntax for LIMIT, change LIMIT to SKIP * 2001.08.05 Claudio Valderrama: closed Bug #448062 and other spaces that appear * in rdb$*_source fields when altering domains plus one unexpected null pointer. * 2001.08.12 Claudio Valderrama: adjust SUBSTRING's starting pos argument here * and not in gen.c; this closes Bug #450301. * 2001.10.01 Claudio Valderrama: enable explicit GRANT...to ROLE role_name. * 2001.10.06 Claudio Valderrama: Honor explicit USER keyword in GRANTs and REVOKEs. * 2002.07.05 Mark O'Donohue: change keyword DEBUG to KW_DEBUG to avoid * clashes with normal DEBUG macro. * 2002.07.30 Arno Brinkman: * 2002.07.30 Let IN predicate handle value_expressions * 2002.07.30 tokens CASE, NULLIF, COALESCE added * 2002.07.30 See block < CASE expression > what is added to value as case_expression * 2002.07.30 function is split up into aggregate_function, numeric_value_function, string_value_function, generate_value_function * 2002.07.30 new group_by_function and added to grp_column_elem * 2002.07.30 cast removed from function and added as cast_specification to value * 2002.08.04 Claudio Valderrama: allow declaring and defining variables at the same time * 2002.08.04 Dmitry Yemanov: ALTER VIEW * 2002.08.06 Arno Brinkman: ordinal added to grp_column_elem for using positions in group by * 2002.08.07 Dmitry Yemanov: INT64/LARGEINT are replaced with BIGINT and available in dialect 3 only * 2002.08.31 Dmitry Yemanov: allowed user-defined index names for PK/FK/UK constraints * 2002.09.01 Dmitry Yemanov: RECREATE VIEW * 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced * exception handling in SPs/triggers, * implemented ROWS_AFFECTED system variable * 2002.10.21 Nickolay Samofatov: Added support for explicit pessimistic locks * 2002.10.29 Nickolay Samofatov: Added support for savepoints * 2002.12.03 Dmitry Yemanov: Implemented ORDER BY clause in subqueries. * 2002.12.18 Dmitry Yemanov: Added support for SQL-compliant labels and LEAVE statement * 2002.12.28 Dmitry Yemanov: Added support for parametrized events. * 2003.01.14 Dmitry Yemanov: Fixed bug with cursors in triggers. * 2003.01.15 Dmitry Yemanov: Added support for runtime trigger action checks. * 2003.02.10 Mike Nordell : Undefined Microsoft introduced macros to get a clean compile. * 2003.05.24 Nickolay Samofatov: Make SKIP and FIRST non-reserved keywords * 2003.06.13 Nickolay Samofatov: Make INSERTING/UPDATING/DELETING non-reserved keywords * 2003.07.01 Blas Rodriguez Somoza: Change DEBUG and IN to avoid conflicts in win32 build/bison * 2003.08.11 Arno Brinkman: Changed GROUP BY to support all expressions and added "AS" support * with table alias. Also removed group_by_function and ordinal. * 2003.08.14 Arno Brinkman: Added support for derived tables. * 2003.10.05 Dmitry Yemanov: Added support for explicit cursors in PSQL. * 2004.01.16 Vlad Horsun: added support for default parameters and * EXECUTE BLOCK statement * Adriano dos Santos Fernandes */ #include "firebird.h" #include "dyn_consts.h" #include #include #include #include #include "gen/iberror.h" #include "../dsql/dsql.h" #include "../jrd/ibase.h" #include "../jrd/flags.h" #include "../jrd/jrd.h" #include "../jrd/DataTypeUtil.h" #include "../dsql/errd_proto.h" #include "../dsql/make_proto.h" #include "../yvalve/keywords.h" #include "../yvalve/gds_proto.h" #include "../jrd/err_proto.h" #include "../common/intlobj_new.h" #include "../jrd/Attachment.h" #include "../common/StatusArg.h" // since UNIX isn't standard, we have to define // stuff which is in (which isn't available on all UNIXes... const long SHRT_POS_MAX = 32767; const long SHRT_UNSIGNED_MAX = 65535; const long SHRT_NEG_MAX = 32768; const int POSITIVE = 0; const int NEGATIVE = 1; const int UNSIGNED = 2; //const int MIN_CACHE_BUFFERS = 250; //const int DEF_CACHE_BUFFERS = 1000; #define YYSTYPE YYSTYPE #if defined(DEBUG) || defined(DEV_BUILD) #define YYDEBUG 1 #endif #define YYREDUCEPOSNFUNC yyReducePosn #define YYREDUCEPOSNFUNCARG NULL // ASF: Inherited attributes (aka rule parameters) are executed even when in trial mode, but action // rules ({}) are executed only when in full parse mode. NOTRIAL should be used to avoid segfaults // due to accessing invalid pointers in parameters (not yet returned from action rules). #define NOTRIAL(x) (yytrial ? NULL : (x)) inline unsigned trigger_type_suffix(const unsigned slot1, const unsigned slot2, const unsigned slot3) { return ((slot1 << 1) | (slot2 << 3) | (slot3 << 5)); } #include "../dsql/chars.h" using namespace Jrd; using namespace Firebird; %} // token declarations // Tokens are organized chronologically by date added. // See yvalve/keywords.cpp for a list organized alphabetically // Tokens in v4.0 -- not separated into v3 and v4 tokens %token ACTIVE %token ADD %token AFTER %token ALL %token ALTER %token AND %token ANY %token AS %token ASC %token AT %token AVG %token AUTO %token BEFORE %token BEGIN %token BETWEEN %token BLOB %token BY %token CAST %token CHARACTER %token CHECK %token COLLATE %token COMMIT %token COMMITTED %token COMPUTED %token CONCATENATE %token CONDITIONAL %token CONSTRAINT %token CONTAINING %token COUNT %token CREATE %token CSTRING %token CURRENT %token CURSOR %token DATABASE %token DATE %token DB_KEY %token DECIMAL %token DECLARE %token DEFAULT %token KW_DELETE %token DESC %token DISTINCT %token DO %token DOMAIN %token DROP %token ELSE %token END %token ENTRY_POINT %token ESCAPE %token EXCEPTION %token EXECUTE %token EXISTS %token EXIT %token EXTERNAL %token FILTER %token FOR %token FOREIGN %token FROM %token FULL %token FUNCTION %token GDSCODE %token GEQ %token GENERATOR %token GEN_ID %token GRANT %token GROUP %token HAVING %token IF %token KW_IN %token INACTIVE %token INNER %token INPUT_TYPE %token INDEX %token INSERT %token INTEGER %token INTO %token IS %token ISOLATION %token JOIN %token KEY %token KW_CHAR %token KW_DEC %token KW_DOUBLE %token KW_FILE %token KW_FLOAT %token KW_INT %token KW_LONG %token KW_NULL %token KW_NUMERIC %token KW_UPPER %token KW_VALUE %token LENGTH %token LEFT %token LEQ %token LEVEL %token LIKE %token MANUAL %token MAXIMUM %token MERGE %token MINIMUM %token MODULE_NAME %token NAMES %token NATIONAL %token NATURAL %token NCHAR %token NEQ %token NO %token NOT %token NOT_GTR %token NOT_LSS %token OF %token ON %token ONLY %token OPTION %token OR %token ORDER %token OUTER %token OUTPUT_TYPE %token OVERFLOW %token PAGE %token PAGES %token KW_PAGE_SIZE %token PARAMETER %token PASSWORD %token PLAN %token POSITION %token POST_EVENT %token PRECISION %token PRIMARY %token PRIVILEGES %token PROCEDURE %token PROTECTED %token READ %token REAL %token REFERENCES %token RESERVING %token RETAIN %token RETURNING_VALUES %token RETURNS %token REVOKE %token RIGHT %token ROLLBACK %token SEGMENT %token SELECT %token SET %token SHADOW %token KW_SHARED %token SINGULAR %token KW_SIZE %token SMALLINT %token SNAPSHOT %token SOME %token SORT %token SQLCODE %token STABILITY %token STARTING %token STATISTICS %token SUB_TYPE %token SUSPEND %token SUM %token TABLE %token THEN %token TO %token TRANSACTION %token TRIGGER %token UNCOMMITTED %token UNION %token UNIQUE %token UPDATE %token USER %token VALUES %token VARCHAR %token VARIABLE %token VARYING %token VERSION %token VIEW %token WAIT %token WHEN %token WHERE %token WHILE %token WITH %token WORK %token WRITE %token FLOAT_NUMBER %token SYMBOL %token NUMBER %token STRING %token INTRODUCER // New tokens added v5.0 %token ACTION %token ADMIN %token CASCADE %token FREE_IT // ISC SQL extension %token RESTRICT %token ROLE // New tokens added v6.0 %token COLUMN %token KW_TYPE %token EXTRACT %token YEAR %token MONTH %token DAY %token HOUR %token MINUTE %token SECOND %token WEEKDAY // ISC SQL extension %token YEARDAY // ISC SQL extension %token TIME %token TIMESTAMP %token CURRENT_DATE %token CURRENT_TIME %token CURRENT_TIMESTAMP // special aggregate token types returned by lex in v6.0 %token NUMBER64BIT SCALEDINT // CVC: Special Firebird additions. %token CURRENT_USER %token CURRENT_ROLE %token KW_BREAK %token SUBSTRING %token RECREATE %token KW_DESCRIPTOR %token FIRST %token SKIP // tokens added for Firebird 1.5 %token CURRENT_CONNECTION %token CURRENT_TRANSACTION %token BIGINT %token CASE %token NULLIF %token COALESCE %token USING %token NULLS %token LAST %token ROW_COUNT %token LOCK %token SAVEPOINT %token RELEASE %token STATEMENT %token LEAVE %token INSERTING %token UPDATING %token DELETING // tokens added for Firebird 2.0 %token BACKUP %token KW_DIFFERENCE %token OPEN %token CLOSE %token FETCH %token ROWS %token BLOCK %token IIF %token SCALAR_ARRAY %token CROSS %token NEXT %token SEQUENCE %token RESTART %token BOTH %token COLLATION %token COMMENT %token BIT_LENGTH %token CHAR_LENGTH %token CHARACTER_LENGTH %token LEADING %token KW_LOWER %token OCTET_LENGTH %token TRAILING %token TRIM %token RETURNING %token KW_IGNORE %token LIMBO %token UNDO %token REQUESTS %token TIMEOUT // tokens added for Firebird 2.1 %token ABS %token ACCENT %token ACOS %token ALWAYS %token ASCII_CHAR %token ASCII_VAL %token ASIN %token ATAN %token ATAN2 %token BIN_AND %token BIN_OR %token BIN_SHL %token BIN_SHR %token BIN_XOR %token CEIL %token CONNECT %token COS %token COSH %token COT %token DATEADD %token DATEDIFF %token DECODE %token DISCONNECT %token EXP %token FLOOR %token GEN_UUID %token GENERATED %token GLOBAL %token HASH %token INSENSITIVE %token LIST %token LN %token LOG %token LOG10 %token LPAD %token MATCHED %token MATCHING %token MAXVALUE %token MILLISECOND %token MINVALUE %token MOD %token OVERLAY %token PAD %token PI %token PLACING %token POWER %token PRESERVE %token RAND %token RECURSIVE %token REPLACE %token REVERSE %token ROUND %token RPAD %token SENSITIVE %token SIGN %token SIN %token SINH %token SPACE %token SQRT %token START %token TAN %token TANH %token TEMPORARY %token TRUNC %token WEEK // tokens added for Firebird 2.5 %token AUTONOMOUS %token CHAR_TO_UUID %token FIRSTNAME %token GRANTED %token LASTNAME %token MIDDLENAME %token MAPPING %token OS_NAME %token SIMILAR %token UUID_TO_CHAR // new execute statement %token CALLER %token COMMON %token DATA %token SOURCE %token TWO_PHASE %token BIND_PARAM %token BIN_NOT // tokens added for Firebird 3.0 %token BODY %token CONTINUE %token DDL %token DECRYPT %token ENCRYPT %token ENGINE %token NAME %token OVER %token PACKAGE %token PARTITION %token RDB_GET_CONTEXT %token RDB_SET_CONTEXT %token SCROLL %token PRIOR %token KW_ABSOLUTE %token KW_RELATIVE %token ACOSH %token ASINH %token ATANH %token RETURN %token DETERMINISTIC %token IDENTITY %token DENSE_RANK %token FIRST_VALUE %token NTH_VALUE %token LAST_VALUE %token LAG %token LEAD %token RANK %token ROW_NUMBER %token SQLSTATE %token KW_BOOLEAN %token KW_FALSE %token KW_TRUE %token UNKNOWN %token USAGE %token RDB_RECORD_VERSION %token LINGER %token TAGS // precedence declarations for expression evaluation %left OR %left AND %left NOT %left '=' '<' '>' IS BETWEEN LIKE CONTAINING STARTING SIMILAR KW_IN NEQ GEQ LEQ NOT_GTR NOT_LSS %left '+' '-' %left '*' '/' %left UMINUS UPLUS %left CONCATENATE %left COLLATE // Fix the dangling IF-THEN-ELSE problem %nonassoc THEN %nonassoc ELSE /* The same issue exists with ALTER COLUMN now that keywords can be used in order to change their names. The syntax which shows the issue is: ALTER COLUMN where column is part of the alter statement or ALTER COLUMN where column is the name of the column in the relation */ %nonassoc ALTER %nonassoc COLUMN %union { BaseNullable nullableIntVal; BaseNullable nullableBoolVal; bool boolVal; int intVal; unsigned uintVal; SLONG int32Val; SINT64 int64Val; FB_UINT64 uint64Val; BaseNullable nullableInt64Val; BaseNullable nullableUint64Val; Jrd::ScaledNumber scaledNumber; UCHAR blrOp; Jrd::OrderNode::NullsPlacement nullsPlacement; Jrd::ComparativeBoolNode::DsqlFlag cmpBoolFlag; Jrd::dsql_fld* legacyField; Jrd::ReturningClause* returningClause; Firebird::MetaName* metaNamePtr; Firebird::ObjectsArray* metaNameArray; Firebird::PathName* pathNamePtr; Firebird::string* stringPtr; Jrd::IntlString* intlStringPtr; Jrd::DbFileClause* dbFileClause; Firebird::Array >* dbFilesClause; Jrd::ExternalClause* externalClause; Firebird::Array >* parametersClause; Jrd::Node* node; Jrd::ExprNode* exprNode; Jrd::ValueExprNode* valueExprNode; Jrd::BoolExprNode* boolExprNode; Jrd::RecordSourceNode* recSourceNode; Jrd::RelationSourceNode* relSourceNode; Jrd::ValueListNode* valueListNode; Jrd::RecSourceListNode* recSourceListNode; Jrd::RseNode* rseNode; Jrd::PlanNode* planNode; Jrd::PlanNode::AccessType* accessType; Jrd::StmtNode* stmtNode; Jrd::DdlNode* ddlNode; Jrd::SelectExprNode* selectExprNode; Jrd::WithClause* withClause; Jrd::RowsClause* rowsClause; Jrd::FieldNode* fieldNode; Jrd::DecodeNode* decodeNode; Firebird::Array* fieldArray; Firebird::Array >* nestFieldArray; Jrd::TransactionNode* traNode; Firebird::Array* privilegeArray; Jrd::GranteeClause* granteeClause; Firebird::Array* granteeArray; Jrd::GrantRevokeNode* grantRevokeNode; Jrd::CreateCollationNode* createCollationNode; Jrd::CreateDomainNode* createDomainNode; Jrd::AlterDomainNode* alterDomainNode; Jrd::CreateAlterFunctionNode* createAlterFunctionNode; Jrd::CreateAlterProcedureNode* createAlterProcedureNode; Jrd::CreateAlterTriggerNode* createAlterTriggerNode; Jrd::CreateAlterPackageNode* createAlterPackageNode; Jrd::CreateFilterNode::NameNumber* filterNameNumber; Jrd::CreateAlterExceptionNode* createAlterExceptionNode; Jrd::CreateAlterSequenceNode* createAlterSequenceNode; Jrd::CreateShadowNode* createShadowNode; Firebird::Array* packageItems; Jrd::ExceptionArray* exceptionArray; Jrd::CreateAlterPackageNode::Item packageItem; Jrd::CreatePackageBodyNode* createPackageBodyNode; Jrd::BoolSourceClause* boolSourceClause; Jrd::ValueSourceClause* valueSourceClause; Jrd::RelationNode* relationNode; Jrd::RelationNode::AddColumnClause* addColumnClause; Jrd::RelationNode::RefActionClause* refActionClause; Jrd::RelationNode::IndexConstraintClause* indexConstraintClause; Jrd::CreateRelationNode* createRelationNode; Jrd::CreateAlterViewNode* createAlterViewNode; Jrd::CreateIndexNode* createIndexNode; Jrd::AlterDatabaseNode* alterDatabaseNode; Jrd::ExecBlockNode* execBlockNode; Jrd::StoreNode* storeNode; Jrd::UpdateOrInsertNode* updInsNode; Jrd::AggNode* aggNode; Jrd::SysFuncCallNode* sysFuncCallNode; Jrd::ValueIfNode* valueIfNode; Jrd::CompoundStmtNode* compoundStmtNode; Jrd::CursorStmtNode* cursorStmtNode; Jrd::DeclareCursorNode* declCursorNode; Jrd::ErrorHandlerNode* errorHandlerNode; Jrd::ExecStatementNode* execStatementNode; Jrd::MergeNode* mergeNode; Jrd::MergeNode::NotMatched* mergeNotMatchedClause; Jrd::MergeNode::Matched* mergeMatchedClause; Jrd::SelectNode* selectNode; Jrd::SetTransactionNode* setTransactionNode; Jrd::SetTransactionNode::RestrictionOption* setTransactionRestrictionClause; Jrd::DeclareSubProcNode* declareSubProcNode; Jrd::DeclareSubFuncNode* declareSubFuncNode; Jrd::dsql_req* dsqlReq; Jrd::CreateAlterUserNode* createAlterUserNode; } %include types.y %% // list of possible statements top : statement { DSQL_parse = $1; } | statement ';' { DSQL_parse = $1; } ; %type statement statement : dml_statement { $$ = newNode($1); } | ddl_statement { $$ = newNode($1); } | tra_statement { $$ = newNode($1); } ; %type dml_statement dml_statement : delete { $$ = $1; } | insert { $$ = $1; } | merge { $$ = $1; } | exec_procedure { $$ = $1; } | exec_block { $$ = $1; } | savepoint { $$ = $1; } | select { $$ = $1; } | update { $$ = $1; } | update_or_insert { $$ = $1; } ; %type ddl_statement ddl_statement : alter { $$ = $1; } | comment { $$ = $1; } | create { $$ = $1; } | create_or_alter { $$ = $1; } | declare { $$ = $1; } | drop { $$ = $1; } | grant { $$ = $1; } | recreate { $$ = $1; } | revoke { $$ = $1; } | set_statistics { $$ = $1; } ; %type tra_statement tra_statement : set_transaction { $$ = $1; } | commit { $$ = $1; } | rollback { $$ = $1; } ; // GRANT statement %type grant grant : GRANT { $$ = newNode(true); } grant0($2) { $$ = $2; } ; %type grant0() grant0($node) : privileges(NOTRIAL(&$node->privileges)) ON table_noise symbol_table_name TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by { $node->object = newNode(obj_relation, *$4); $node->grantAdminOption = $7; $node->grantor = $8; } | execute_privilege(NOTRIAL(&$node->privileges)) ON PROCEDURE symbol_procedure_name TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by { $node->object = newNode(obj_procedure, *$4); $node->grantAdminOption = $7; $node->grantor = $8; } | execute_privilege(NOTRIAL(&$node->privileges)) ON FUNCTION symbol_UDF_name TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by { $node->object = newNode(obj_udf, *$4); $node->grantAdminOption = $7; $node->grantor = $8; } | execute_privilege(NOTRIAL(&$node->privileges)) ON PACKAGE symbol_package_name TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by { $node->object = newNode(obj_package_header, *$4); $node->grantAdminOption = $7; $node->grantor = $8; } | usage_privilege(NOTRIAL(&$node->privileges)) ON DOMAIN symbol_domain_name TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by { $node->object = newNode(obj_field, *$4); $node->grantAdminOption = $7; $node->grantor = $8; } | usage_privilege(NOTRIAL(&$node->privileges)) ON EXCEPTION symbol_exception_name TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by { $node->object = newNode(obj_exception, *$4); $node->grantAdminOption = $7; $node->grantor = $8; } | usage_privilege(NOTRIAL(&$node->privileges)) ON GENERATOR symbol_generator_name TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by { $node->object = newNode(obj_generator, *$4); $node->grantAdminOption = $7; $node->grantor = $8; } | usage_privilege(NOTRIAL(&$node->privileges)) ON SEQUENCE symbol_generator_name TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by { $node->object = newNode(obj_generator, *$4); $node->grantAdminOption = $7; $node->grantor = $8; } | usage_privilege(NOTRIAL(&$node->privileges)) ON CHARACTER SET symbol_character_set_name TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by { $node->object = newNode(obj_charset, *$5); $node->grantAdminOption = $8; $node->grantor = $9; } | usage_privilege(NOTRIAL(&$node->privileges)) ON COLLATION symbol_collation_name TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by { $node->object = newNode(obj_collation, *$4); $node->grantAdminOption = $7; $node->grantor = $8; } | role_name_list(NOTRIAL(&$node->roles)) TO role_grantee_list(NOTRIAL(&$node->users)) role_admin_option granted_by { $node->grantAdminOption = $4; $node->grantor = $5; } ; table_noise : // nothing | TABLE ; %type privileges() privileges($privilegeArray) : ALL { $privilegeArray->add(PrivilegeClause('A', NULL)); } | ALL PRIVILEGES { $privilegeArray->add(PrivilegeClause('A', NULL)); } | privilege_list($privilegeArray) ; %type privilege_list() privilege_list($privilegeArray) : privilege($privilegeArray) | privilege_list ',' privilege($privilegeArray) ; %type execute_privilege() execute_privilege($privilegeArray) : EXECUTE { $privilegeArray->add(PrivilegeClause('X', NULL)); } ; %type usage_privilege() usage_privilege($privilegeArray) : USAGE { $privilegeArray->add(PrivilegeClause('G', NULL)); } ; %type privilege() privilege($privilegeArray) : SELECT { $privilegeArray->add(PrivilegeClause('S', NULL)); } | INSERT { $privilegeArray->add(PrivilegeClause('I', NULL)); } | KW_DELETE { $privilegeArray->add(PrivilegeClause('D', NULL)); } | UPDATE column_parens_opt { $privilegeArray->add(PrivilegeClause('U', $2)); } | REFERENCES column_parens_opt { $privilegeArray->add(PrivilegeClause('R', $2)); } ; %type grant_option grant_option : /* nothing */ { $$ = false; } | WITH GRANT OPTION { $$ = true; } ; %type role_admin_option role_admin_option : /* nothing */ { $$ = false; } | WITH ADMIN OPTION { $$ = true; } ; %type granted_by granted_by : /* nothing */ { $$ = NULL; } | granted_by_text grantor { $$ = $2; } ; granted_by_text : GRANTED BY | AS ; %type grantor grantor : symbol_user_name | USER symbol_user_name { $$ = $2; } ; // REVOKE statement %type revoke revoke : REVOKE { $$ = newNode(false); } revoke0($2) { $$ = $2; } ; %type revoke0() revoke0($node) : rev_grant_option privileges(NOTRIAL(&$node->privileges)) ON table_noise symbol_table_name FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by { $node->object = newNode(obj_relation, *$5); $node->grantAdminOption = $1; $node->grantor = $8; } | rev_grant_option execute_privilege(NOTRIAL(&$node->privileges)) ON PROCEDURE symbol_procedure_name FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by { $node->object = newNode(obj_procedure, *$5); $node->grantAdminOption = $1; $node->grantor = $8; } | rev_grant_option execute_privilege(NOTRIAL(&$node->privileges)) ON FUNCTION symbol_UDF_name FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by { $node->object = newNode(obj_udf, *$5); $node->grantAdminOption = $1; $node->grantor = $8; } | rev_grant_option execute_privilege(NOTRIAL(&$node->privileges)) ON PACKAGE symbol_package_name FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by { $node->object = newNode(obj_package_header, *$5); $node->grantAdminOption = $1; $node->grantor = $8; } | rev_grant_option usage_privilege(NOTRIAL(&$node->privileges)) ON DOMAIN symbol_domain_name FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by { $node->object = newNode(obj_field, *$5); $node->grantAdminOption = $1; $node->grantor = $8; } | rev_grant_option usage_privilege(NOTRIAL(&$node->privileges)) ON EXCEPTION symbol_exception_name FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by { $node->object = newNode(obj_exception, *$5); $node->grantAdminOption = $1; $node->grantor = $8; } | rev_grant_option usage_privilege(NOTRIAL(&$node->privileges)) ON GENERATOR symbol_generator_name FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by { $node->object = newNode(obj_generator, *$5); $node->grantAdminOption = $1; $node->grantor = $8; } | rev_grant_option usage_privilege(NOTRIAL(&$node->privileges)) ON SEQUENCE symbol_generator_name FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by { $node->object = newNode(obj_generator, *$5); $node->grantAdminOption = $1; $node->grantor = $8; } | rev_grant_option usage_privilege(NOTRIAL(&$node->privileges)) ON CHARACTER SET symbol_character_set_name FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by { $node->object = newNode(obj_charset, *$6); $node->grantAdminOption = $1; $node->grantor = $9; } | rev_grant_option usage_privilege(NOTRIAL(&$node->privileges)) ON COLLATION symbol_collation_name FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by { $node->object = newNode(obj_collation, *$5); $node->grantAdminOption = $1; $node->grantor = $8; } | rev_admin_option role_name_list(NOTRIAL(&$node->roles)) FROM role_grantee_list(NOTRIAL(&$node->users)) granted_by { $node->grantAdminOption = $1; $node->grantor = $5; } | ALL ON ALL FROM non_role_grantee_list(NOTRIAL(&$node->users)) ; %type rev_grant_option rev_grant_option : /* nothing */ { $$ = false; } | GRANT OPTION FOR { $$ = true; } ; %type rev_admin_option rev_admin_option : /* nothing */ { $$ = false; } | ADMIN OPTION FOR { $$ = true; } ; %type non_role_grantee_list() non_role_grantee_list($granteeArray) : grantee($granteeArray) | user_grantee($granteeArray) | non_role_grantee_list ',' grantee($granteeArray) | non_role_grantee_list ',' user_grantee($granteeArray) ; %type grantee() grantee($granteeArray) : PROCEDURE symbol_procedure_name { $granteeArray->add(GranteeClause(obj_procedure, *$2)); } | FUNCTION symbol_UDF_name { $granteeArray->add(GranteeClause(obj_udf, *$2)); } | PACKAGE symbol_package_name { $granteeArray->add(GranteeClause(obj_package_header, *$2)); } | TRIGGER symbol_trigger_name { $granteeArray->add(GranteeClause(obj_trigger, *$2)); } | VIEW symbol_view_name { $granteeArray->add(GranteeClause(obj_view, *$2)); } | ROLE symbol_role_name { $granteeArray->add(GranteeClause(obj_sql_role, *$2)); } ; // CVC: In the future we can deprecate the first implicit form since we'll support // explicit grant/revoke for both USER and ROLE keywords & object types. %type user_grantee() user_grantee($granteeArray) : symbol_user_name { $granteeArray->add(GranteeClause(obj_user_or_role, *$1)); } | USER symbol_user_name { $granteeArray->add(GranteeClause(obj_user, *$2)); } | GROUP symbol_user_name { $granteeArray->add(GranteeClause(obj_user_group, *$2)); } ; %type role_name_list() role_name_list($granteeArray) : role_name($granteeArray) | role_name_list ',' role_name($granteeArray) ; %type role_name() role_name($granteeArray) : symbol_role_name { $granteeArray->add(GranteeClause(obj_sql_role, *$1)); } ; %type role_grantee_list() role_grantee_list($granteeArray) : role_grantee($granteeArray) | role_grantee_list ',' role_grantee($granteeArray) ; %type role_grantee() role_grantee($granteeArray) : grantor { $granteeArray->add(GranteeClause(obj_user, *$1)); } ; // DECLARE operations %type declare declare : DECLARE declare_clause { $$ = $2;} ; %type declare_clause declare_clause : FILTER filter_decl_clause { $$ = $2; } | EXTERNAL FUNCTION udf_decl_clause { $$ = $3; } ; %type udf_decl_clause udf_decl_clause : symbol_UDF_name { $$ = newNode(*$1); } arg_desc_list1(NOTRIAL(&$2->parameters)) RETURNS return_value1($2) ENTRY_POINT utf_string MODULE_NAME utf_string { $$ = $2; $$->external = newNode(); $$->external->name = *$7; $$->external->udfModule = *$9; } ; %type udf_data_type udf_data_type : simple_type | BLOB { $$ = newNode(); $$->dtype = dtype_blob; $$->length = sizeof(bid); } | CSTRING '(' pos_short_integer ')' charset_clause { $$ = newNode(); $$->dtype = dtype_cstring; $$->charLength = (USHORT) $3; if ($5) $$->charSet = *$5; } ; %type arg_desc_list1() arg_desc_list1($parameters) : | arg_desc_list($parameters) | '(' arg_desc_list($parameters) ')' ; %type arg_desc_list() arg_desc_list($parameters) : arg_desc($parameters) | arg_desc_list ',' arg_desc($parameters) ; %type arg_desc() arg_desc($parameters) : udf_data_type param_mechanism { $parameters->add(newNode($1, MetaName())); $parameters->back()->udfMechanism = $2; } ; %type param_mechanism param_mechanism : /* nothing */ { $$ = Nullable::empty(); } // Beware: This means FUN_reference or FUN_blob_struct. | BY KW_DESCRIPTOR { $$ = Nullable::val(FUN_descriptor); } | BY SCALAR_ARRAY { $$ = Nullable::val(FUN_scalar_array); } | KW_NULL { $$ = Nullable::val(FUN_ref_with_null); } ; %type return_value1() return_value1($function) : return_value($function) | '(' return_value($function) ')' ; %type return_value() return_value($function) : udf_data_type return_mechanism { $function->returnType = newNode($1, MetaName()); $function->returnType->udfMechanism = $2; } | PARAMETER pos_short_integer { $function->udfReturnPos = $2; } ; %type return_mechanism return_mechanism : /* nothing */ { $$ = FUN_reference; } | BY KW_VALUE { $$ = FUN_value; } | BY KW_DESCRIPTOR { $$ = FUN_descriptor; } // FUN_refrence with FREE_IT is -ve | FREE_IT { $$ = -1 * FUN_reference; } | BY KW_DESCRIPTOR FREE_IT { $$ = -1 * FUN_descriptor; } ; %type filter_decl_clause filter_decl_clause : symbol_filter_name INPUT_TYPE blob_filter_subtype OUTPUT_TYPE blob_filter_subtype ENTRY_POINT utf_string MODULE_NAME utf_string { CreateFilterNode* node = newNode(*$1); node->inputFilter = $3; node->outputFilter = $5; node->entryPoint = *$7; node->moduleName = *$9; $$ = node; } ; %type blob_filter_subtype blob_filter_subtype : symbol_blob_subtype_name { $$ = newNode(*$1); } | signed_short_integer { $$ = newNode($1); } ; // CREATE metadata operations %type create create : CREATE create_clause { $$ = $2; } ; %type create_clause create_clause : EXCEPTION exception_clause { $$ = $2; } | unique_opt order_direction INDEX symbol_index_name ON simple_table_name { CreateIndexNode* node = newNode(*$4); node->unique = $1; node->descending = $2; node->relation = $6; $$ = node; } index_definition(static_cast($7)) { $$ = $7; } | FUNCTION function_clause { $$ = $2; } | PROCEDURE procedure_clause { $$ = $2; } | TABLE table_clause { $$ = $2; } | GLOBAL TEMPORARY TABLE gtt_table_clause { $$ = $4; } | TRIGGER trigger_clause { $$ = $2; } | VIEW view_clause { $$ = $2; } | GENERATOR generator_clause { $$ = $2; } | SEQUENCE generator_clause { $$ = $2; } | DATABASE db_clause { $$ = $2; } | DOMAIN domain_clause { $$ = $2; } | SHADOW shadow_clause { $$ = $2; } | ROLE role_clause { $$ = $2; } | COLLATION collation_clause { $$ = $2; } | USER create_user_clause { $$ = $2; } | PACKAGE package_clause { $$ = $2; } | PACKAGE BODY package_body_clause { $$ = $3; } ; %type recreate recreate : RECREATE recreate_clause { $$ = $2; } ; %type recreate_clause recreate_clause : PROCEDURE procedure_clause { $$ = newNode($2); } | FUNCTION function_clause { $$ = newNode($2); } | TABLE table_clause { $$ = newNode($2); } | GLOBAL TEMPORARY TABLE gtt_table_clause { $$ = newNode($4); } | VIEW view_clause { $$ = newNode($2); } | TRIGGER trigger_clause { $$ = newNode($2); } | PACKAGE package_clause { $$ = newNode($2); } | PACKAGE BODY package_body_clause { $$ = newNode($3); } | EXCEPTION exception_clause { $$ = newNode($2); } | GENERATOR generator_clause { $$ = newNode($2); } | SEQUENCE generator_clause { $$ = newNode($2); } ; %type create_or_alter create_or_alter : CREATE OR ALTER replace_clause { $$ = $4; } ; %type replace_clause replace_clause : PROCEDURE replace_procedure_clause { $$ = $2; } | FUNCTION replace_function_clause { $$ = $2; } | TRIGGER replace_trigger_clause { $$ = $2; } | PACKAGE replace_package_clause { $$ = $2; } | VIEW replace_view_clause { $$ = $2; } | EXCEPTION replace_exception_clause { $$ = $2; } | GENERATOR replace_sequence_clause { $$ = $2; } | SEQUENCE replace_sequence_clause { $$ = $2; } | USER replace_user_clause { $$ = $2; } ; // CREATE EXCEPTION // ASF: The charset from sql_string is discarded because the database column uses NONE. %type exception_clause exception_clause : symbol_exception_name sql_string { $$ = newNode(*$1, $2->getString()); } ; %type replace_exception_clause replace_exception_clause : symbol_exception_name sql_string { CreateAlterExceptionNode* node = newNode(*$1, $2->getString()); node->alter = true; $$ = node; } ; %type alter_exception_clause alter_exception_clause : symbol_exception_name sql_string { CreateAlterExceptionNode* node = newNode(*$1, $2->getString()); node->create = false; node->alter = true; $$ = node; } ; // CREATE INDEX %type unique_opt unique_opt : /* nothing */ { $$ = false; } | UNIQUE { $$ = true; } ; %type index_definition() index_definition($createIndexNode) : column_list { $createIndexNode->columns = $1; } | column_parens { $createIndexNode->columns = $1; } | computed_by '(' value ')' { $createIndexNode->computed = newNode(); $createIndexNode->computed->value = $3; $createIndexNode->computed->source = makeParseStr(YYPOSNARG(2), YYPOSNARG(4)); } ; // CREATE SHADOW %type shadow_clause shadow_clause : pos_short_integer manual_auto conditional utf_string first_file_length { $$ = newNode($1); $$->manual = $2; $$->conditional = $3; $$->files.add(newNode(*$4)); $$->files.front()->length = $5; } sec_shadow_files(NOTRIAL(&$6->files)) { $$ = $6; } ; %type manual_auto manual_auto : /* nothing */ { $$ = false; } | MANUAL { $$ = true; } | AUTO { $$ = false; } ; %type conditional conditional : /* nothing */ { $$ = false; } | CONDITIONAL { $$ = true; } ; %type first_file_length first_file_length : /* nothing */ { $$ = 0; } | LENGTH equals long_integer page_noise { $$ = $3; } ; %type sec_shadow_files() sec_shadow_files($dbFilesClause) : // nothing | db_file_list($dbFilesClause) ; %type db_file_list() db_file_list($dbFilesClause) : db_file { $dbFilesClause->add($1); } | db_file_list db_file { $dbFilesClause->add($2); } ; // CREATE DOMAIN %type domain_clause domain_clause : symbol_column_name as_opt data_type domain_default_opt { $3->fld_name = *$1; $$ = newNode( newNode($3, MetaName(), $4)); } domain_constraints_opt($5) collate_clause { $$ = $5; if ($7) $$->nameType->type->collate = *$7; } ; %type domain_constraints_opt() domain_constraints_opt($createDomainNode) : // nothing | domain_constraints($createDomainNode) ; %type domain_constraints() domain_constraints($createDomainNode) : domain_constraint($createDomainNode) | domain_constraints domain_constraint($createDomainNode) ; %type domain_constraint() domain_constraint($createDomainNode) : null_constraint { setClause($createDomainNode->notNull, "NOT NULL"); } | check_constraint { setClause($createDomainNode->check, "DOMAIN CHECK CONSTRAINT", $1); } ; as_opt : // nothing | AS ; %type domain_default domain_default : DEFAULT default_value { ValueSourceClause* clause = newNode(); clause->value = $2; clause->source = makeParseStr(YYPOSNARG(1), YYPOSNARG(2)); $$ = clause; } ; %type domain_default_opt domain_default_opt : /* nothing */ { $$ = NULL; } | domain_default ; null_constraint : NOT KW_NULL ; %type check_constraint check_constraint : CHECK '(' search_condition ')' { BoolSourceClause* clause = newNode(); clause->value = $3; clause->source = makeParseStr(YYPOSNARG(1), YYPOSNARG(4)); $$ = clause; } ; // CREATE SEQUENCE/GENERATOR %type generator_clause generator_clause : symbol_generator_name start_with_opt { $$ = newNode(*$1, $2); } ; %type start_with_opt start_with_opt : /* nothing */ { $$ = Nullable::empty(); } | start_with { $$ = Nullable::val($1); } ; %type start_with start_with : START WITH sequence_value { $$ = $3; } ; %type replace_sequence_clause replace_sequence_clause : symbol_generator_name replace_sequence_options { CreateAlterSequenceNode* node = newNode(*$1, $2); node->alter = true; $$ = node; } ; %type replace_sequence_options replace_sequence_options : RESTART { $$ = Nullable::empty(); } | START WITH sequence_value { $$ = Nullable::val($3); } ; %type alter_sequence_clause alter_sequence_clause : symbol_generator_name RESTART restart_value_opt { CreateAlterSequenceNode* node = newNode(*$1, $3); node->create = false; node->alter = true; $$ = node; } ; %type restart_value_opt restart_value_opt : /* nothing */ { $$ = Nullable::empty(); } | WITH sequence_value { $$ = Nullable::val($2); } ; %type set_generator_clause set_generator_clause : SET GENERATOR symbol_generator_name TO sequence_value { CreateAlterSequenceNode* node = newNode(*$3, Nullable::val($5)); node->create = false; node->alter = true; node->legacy = true; $$ = node; } ; %type sequence_value sequence_value : signed_long_integer { $$ = $1; } | NUMBER64BIT { SINT64 signedNumber = (SINT64) $1.number; if (!$1.hex && $1.number > MAX_SINT64) { ERRD_post( Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range)); } $$ = signedNumber; } | '-' NUMBER64BIT { SINT64 signedNumber = (SINT64) $2.number; if ($2.hex && signedNumber == MIN_SINT64) ERRD_post(Arg::Gds(isc_exception_integer_overflow)); $$ = -signedNumber; } ; // CREATE ROLE %type role_clause role_clause : symbol_role_name { $$ = newNode(*$1); } ; // CREATE COLLATION %type collation_clause collation_clause : symbol_collation_name FOR symbol_character_set_name { $$ = newNode(*$1, *$3); } collation_sequence_definition($4) collation_attribute_list_opt($4) collation_specific_attribute_opt($4) { $$ = $4; } ; %type collation_sequence_definition() collation_sequence_definition($createCollation) : // nothing | FROM symbol_collation_name { $createCollation->fromName = *$2; } | FROM EXTERNAL '(' utf_string ')' { $createCollation->fromExternal = *$4; } ; %type collation_attribute_list_opt() collation_attribute_list_opt($createCollation) : // nothing | collation_attribute_list($createCollation) ; %type collation_attribute_list() collation_attribute_list($createCollation) : collation_attribute($createCollation) | collation_attribute_list collation_attribute($createCollation) ; %type collation_attribute() collation_attribute($createCollation) : collation_pad_attribute($createCollation) | collation_case_attribute($createCollation) | collation_accent_attribute($createCollation) ; %type collation_pad_attribute() collation_pad_attribute($createCollation) : NO PAD { $createCollation->unsetAttribute(TEXTTYPE_ATTR_PAD_SPACE); } | PAD SPACE { $createCollation->setAttribute(TEXTTYPE_ATTR_PAD_SPACE); } ; %type collation_case_attribute() collation_case_attribute($createCollation) : CASE SENSITIVE { $createCollation->unsetAttribute(TEXTTYPE_ATTR_CASE_INSENSITIVE); } | CASE INSENSITIVE { $createCollation->setAttribute(TEXTTYPE_ATTR_CASE_INSENSITIVE); } ; %type collation_accent_attribute() collation_accent_attribute($createCollation) : ACCENT SENSITIVE { $createCollation->unsetAttribute(TEXTTYPE_ATTR_ACCENT_INSENSITIVE); } | ACCENT INSENSITIVE { $createCollation->setAttribute(TEXTTYPE_ATTR_ACCENT_INSENSITIVE); } ; %type collation_specific_attribute_opt() collation_specific_attribute_opt($createCollation) : // nothing | utf_string { const string& s = *$1; $createCollation->specificAttributes.clear(); $createCollation->specificAttributes.add((const UCHAR*) s.begin(), s.length()); } ; // ALTER CHARACTER SET %type alter_charset_clause alter_charset_clause : symbol_character_set_name SET DEFAULT COLLATION symbol_collation_name { $$ = newNode(*$1, *$5); } ; // CREATE DATABASE // ASF: CREATE DATABASE command is divided in three pieces: name, initial options and // remote options. // Initial options are basic properties of a database and should be handled here and // in preparse.cpp. // Remote options always come after initial options, so they don't need to be parsed // in preparse.cpp. They are interpreted only in the server, using this grammar. // Although LENGTH is defined as an initial option, it's also used in the server. %type db_clause db_clause : db_name { $$ = newNode(); $$->create = true; } db_initial_desc1($2) db_rem_desc1($2) { $$ = $2; } ; equals : // nothing | '=' ; %type db_name db_name : utf_string ; %type db_initial_desc1() db_initial_desc1($alterDatabaseNode) : // nothing | db_initial_desc($alterDatabaseNode) ; %type db_initial_desc() db_initial_desc($alterDatabaseNode) : db_initial_option($alterDatabaseNode) | db_initial_desc db_initial_option($alterDatabaseNode) ; // With the exception of LENGTH, all clauses here are handled only at the client. %type db_initial_option() db_initial_option($alterDatabaseNode) : KW_PAGE_SIZE equals pos_short_integer | USER utf_string | PASSWORD utf_string | SET NAMES utf_string | LENGTH equals long_integer page_noise { $alterDatabaseNode->createLength = $3; } ; %type db_rem_desc1() db_rem_desc1($alterDatabaseNode) : // nothing | db_rem_desc($alterDatabaseNode) ; %type db_rem_desc() db_rem_desc($alterDatabaseNode) : db_rem_option($alterDatabaseNode) | db_rem_desc db_rem_option($alterDatabaseNode) ; %type db_rem_option() db_rem_option($alterDatabaseNode) : db_file { $alterDatabaseNode->files.add($1); } | DEFAULT CHARACTER SET symbol_character_set_name { $alterDatabaseNode->setDefaultCharSet = *$4; } | DEFAULT CHARACTER SET symbol_character_set_name COLLATION symbol_collation_name { $alterDatabaseNode->setDefaultCharSet = *$4; $alterDatabaseNode->setDefaultCollation = *$6; } | KW_DIFFERENCE KW_FILE utf_string { $alterDatabaseNode->differenceFile = *$3; } ; %type db_file db_file : KW_FILE utf_string { DbFileClause* clause = newNode(*$2); $$ = clause; } file_desc1($3) { $$ = $3; } ; %type file_desc1() file_desc1($dbFileClause) : // nothing | file_desc($dbFileClause) ; %type file_desc() file_desc($dbFileClause) : file_clause($dbFileClause) | file_desc file_clause($dbFileClause) ; %type file_clause() file_clause($dbFileClause) : STARTING file_clause_noise long_integer { $dbFileClause->start = $3; } | LENGTH equals long_integer page_noise { $dbFileClause->length = $3; } ; file_clause_noise : // nothing | AT | AT PAGE ; page_noise : // nothing | PAGE | PAGES ; // CREATE TABLE %type table_clause table_clause : simple_table_name external_file { $$ = newNode($1, $2); } '(' table_elements($3) ')' { $$ = $3; } ; %type gtt_table_clause gtt_table_clause : simple_table_name { $$ = newNode($1); } '(' table_elements($2) ')' gtt_scope { $$ = $2; $$->relationType = static_cast($6); } ; %type gtt_scope gtt_scope : /* nothing */ { $$ = rel_global_temp_delete; } | ON COMMIT KW_DELETE ROWS { $$ = rel_global_temp_delete; } | ON COMMIT PRESERVE ROWS { $$ = rel_global_temp_preserve; } ; %type external_file external_file : /* nothing */ { $$ = NULL; } | EXTERNAL KW_FILE utf_string { $$ = $3; } | EXTERNAL utf_string { $$ = $2; } ; %type table_elements() table_elements($createRelationNode) : table_element($createRelationNode) | table_elements ',' table_element($createRelationNode) ; %type table_element() table_element($createRelationNode) : column_def($createRelationNode) | table_constraint_definition($createRelationNode) ; // column definition %type column_def() column_def($relationNode) : symbol_column_name data_type_or_domain domain_default_opt { RelationNode::AddColumnClause* clause = $$ = newNode(); clause->field = $2; clause->field->fld_name = *$1; clause->defaultValue = $3; $relationNode->clauses.add(clause); } column_constraint_clause(NOTRIAL($4)) collate_clause { if ($6) $4->collate = *$6; } | symbol_column_name data_type_or_domain identity_clause { RelationNode::AddColumnClause* clause = $$ = newNode(); clause->field = $2; clause->field->fld_name = *$1; clause->identity = true; clause->identityStart = $3; $relationNode->clauses.add(clause); } column_constraint_clause(NOTRIAL($4)) collate_clause { if ($6) $4->collate = *$6; } | symbol_column_name non_array_type def_computed { RelationNode::AddColumnClause* clause = newNode(); clause->field = $2; clause->field->fld_name = *$1; clause->computed = $3; $relationNode->clauses.add(clause); clause->field->flags |= FLD_computed; } | symbol_column_name def_computed { RelationNode::AddColumnClause* clause = newNode(); clause->field = newNode(); clause->field->fld_name = *$1; clause->computed = $2; $relationNode->clauses.add(clause); clause->field->flags |= FLD_computed; } ; %type identity_clause identity_clause : GENERATED BY DEFAULT AS IDENTITY identity_clause_options { $$ = $6; } ; %type identity_clause_options identity_clause_options : /* nothing */ { $$ = 0; } | '(' start_with ')' { $$ = $2; } ; // value does allow parens around it, but there is a problem getting the source text. %type def_computed def_computed : computed_clause '(' value ')' { ValueSourceClause* clause = newNode(); clause->value = $3; clause->source = makeParseStr(YYPOSNARG(2), YYPOSNARG(4)); $$ = clause; } ; computed_clause : computed_by | generated_always_clause ; generated_always_clause : GENERATED ALWAYS AS ; computed_by : COMPUTED BY | COMPUTED ; %type data_type_or_domain data_type_or_domain : data_type | symbol_column_name { $$ = newNode(); $$->typeOfName = *$1; } ; %type collate_clause collate_clause : { $$ = NULL; } | COLLATE symbol_collation_name { $$ = $2; } ; %type data_type_descriptor data_type_descriptor : data_type | KW_TYPE OF symbol_column_name { $$ = newNode(); $$->typeOfName = *$3; } | KW_TYPE OF COLUMN symbol_column_name '.' symbol_column_name { $$ = newNode(); $$->typeOfTable = *$4; $$->typeOfName = *$6; } | symbol_column_name { $$ = newNode(); $$->typeOfName = *$1; $$->fullDomain = true; } ; %type default_value default_value : constant { $$ = $1; } | current_user { $$ = $1; } | current_role { $$ = $1; } | internal_info { $$ = $1; } | null_value { $$ = $1; } | datetime_value_expression { $$ = $1; } ; %type column_constraint_clause() column_constraint_clause($addColumnClause) : // nothing | column_constraint_list($addColumnClause) ; %type column_constraint_list() column_constraint_list($addColumnClause) : column_constraint_def($addColumnClause) | column_constraint_list column_constraint_def($addColumnClause) ; %type column_constraint_def() column_constraint_def($addColumnClause) : constraint_name_opt column_constraint($addColumnClause) { if ($1) $addColumnClause->constraints.back()->name = *$1; } ; %type column_constraint() column_constraint($addColumnClause) : null_constraint { RelationNode::AddConstraintClause& constraint = $addColumnClause->constraints.add(); constraint.constraintType = RelationNode::AddConstraintClause::CTYPE_NOT_NULL; } | check_constraint { RelationNode::AddConstraintClause& constraint = $addColumnClause->constraints.add(); constraint.constraintType = RelationNode::AddConstraintClause::CTYPE_CHECK; constraint.check = $1; } | REFERENCES symbol_table_name column_parens_opt referential_trigger_action constraint_index_opt { RelationNode::AddConstraintClause& constraint = $addColumnClause->constraints.add(); constraint.constraintType = RelationNode::AddConstraintClause::CTYPE_FK; constraint.columns.add($addColumnClause->field->fld_name); constraint.refRelation = *$2; constraint.refAction = $4; const ValueListNode* refColumns = $3; if (refColumns) { const NestConst* ptr = refColumns->items.begin(); for (const NestConst* const end = refColumns->items.end(); ptr != end; ++ptr) constraint.refColumns.add((*ptr)->as()->dsqlName); } constraint.index = $5; } | UNIQUE constraint_index_opt { RelationNode::AddConstraintClause& constraint = $addColumnClause->constraints.add(); constraint.constraintType = RelationNode::AddConstraintClause::CTYPE_UNIQUE; constraint.index = $2; } | PRIMARY KEY constraint_index_opt { RelationNode::AddConstraintClause& constraint = $addColumnClause->constraints.add(); constraint.constraintType = RelationNode::AddConstraintClause::CTYPE_PK; constraint.index = $3; } ; // table constraints %type table_constraint_definition() table_constraint_definition($relationNode) : constraint_name_opt table_constraint($relationNode) { if ($1) { static_cast( $relationNode->clauses.back().getObject())->name = *$1; } } ; %type constraint_name_opt constraint_name_opt : /* nothing */ { $$ = NULL; } | CONSTRAINT symbol_constraint_name { $$ = $2; } ; %type table_constraint() table_constraint($relationNode) : UNIQUE column_parens constraint_index_opt { RelationNode::AddConstraintClause& constraint = *newNode(); constraint.constraintType = RelationNode::AddConstraintClause::CTYPE_UNIQUE; const ValueListNode* columns = $2; const NestConst* ptr = columns->items.begin(); for (const NestConst* const end = columns->items.end(); ptr != end; ++ptr) constraint.columns.add((*ptr)->as()->dsqlName); constraint.index = $3; $relationNode->clauses.add(&constraint); } | PRIMARY KEY column_parens constraint_index_opt { RelationNode::AddConstraintClause& constraint = *newNode(); constraint.constraintType = RelationNode::AddConstraintClause::CTYPE_PK; const ValueListNode* columns = $3; const NestConst* ptr = columns->items.begin(); for (const NestConst* const end = columns->items.end(); ptr != end; ++ptr) constraint.columns.add((*ptr)->as()->dsqlName); constraint.index = $4; $relationNode->clauses.add(&constraint); } | FOREIGN KEY column_parens REFERENCES symbol_table_name column_parens_opt referential_trigger_action constraint_index_opt { RelationNode::AddConstraintClause& constraint = *newNode(); constraint.constraintType = RelationNode::AddConstraintClause::CTYPE_FK; const ValueListNode* columns = $3; const NestConst* ptr = columns->items.begin(); for (const NestConst* const end = columns->items.end(); ptr != end; ++ptr) constraint.columns.add((*ptr)->as()->dsqlName); constraint.refRelation = *$5; constraint.refAction = $7; const ValueListNode* refColumns = $6; if (refColumns) { const NestConst* ptr = refColumns->items.begin(); for (const NestConst* const end = refColumns->items.end(); ptr != end; ++ptr) constraint.refColumns.add((*ptr)->as()->dsqlName); } constraint.index = $8; $relationNode->clauses.add(&constraint); } | check_constraint { RelationNode::AddConstraintClause* constraint = newNode(); constraint->constraintType = RelationNode::AddConstraintClause::CTYPE_CHECK; constraint->check = $1; $relationNode->clauses.add(constraint); } ; %type constraint_index_opt constraint_index_opt : // nothing { $$ = newNode(); } | USING order_direction INDEX symbol_index_name { RelationNode::IndexConstraintClause* clause = $$ = newNode(); clause->descending = $2; clause->name = *$4; } /*** | NO INDEX { $$ = NULL; } ***/ ; %type referential_trigger_action referential_trigger_action : /* nothing */ { $$ = NULL; } | update_rule { $$ = newNode($1, 0); } | delete_rule { $$ = newNode(0, $1); } | delete_rule update_rule { $$ = newNode($2, $1); } | update_rule delete_rule { $$ = newNode($1, $2); } ; %type update_rule update_rule : ON UPDATE referential_action { $$ = $3;} ; %type delete_rule delete_rule : ON KW_DELETE referential_action { $$ = $3;} ; %type referential_action referential_action : CASCADE { $$ = RelationNode::RefActionClause::ACTION_CASCADE; } | SET DEFAULT { $$ = RelationNode::RefActionClause::ACTION_SET_DEFAULT; } | SET KW_NULL { $$ = RelationNode::RefActionClause::ACTION_SET_NULL; } | NO ACTION { $$ = RelationNode::RefActionClause::ACTION_NONE; } ; // PROCEDURE %type procedure_clause procedure_clause : psql_procedure_clause | external_procedure_clause ; %type psql_procedure_clause psql_procedure_clause : procedure_clause_start AS local_declaration_list full_proc_block { $$ = $1; $$->source = makeParseStr(YYPOSNARG(3), YYPOSNARG(4)); $$->localDeclList = $3; $$->body = $4; } ; %type external_procedure_clause external_procedure_clause : procedure_clause_start external_clause external_body_clause_opt { $$ = $1; $$->external = $2; if ($3) $$->source = *$3; } ; %type procedure_clause_start procedure_clause_start : symbol_procedure_name { $$ = newNode(*$1); } input_parameters(NOTRIAL(&$2->parameters)) output_parameters(NOTRIAL(&$2->returns)) { $$ = $2; } ; %type alter_procedure_clause alter_procedure_clause : procedure_clause { $$ = $1; $$->alter = true; $$->create = false; } ; %type replace_procedure_clause replace_procedure_clause : procedure_clause { $$ = $1; $$->alter = true; } ; %type input_parameters() input_parameters($parameters) : | '(' ')' | '(' input_proc_parameters($parameters) ')' ; %type output_parameters() output_parameters($parameters) : | RETURNS '(' output_proc_parameters($parameters) ')' ; %type input_proc_parameters() input_proc_parameters($parameters) : input_proc_parameter($parameters) | input_proc_parameters ',' input_proc_parameter($parameters) ; %type input_proc_parameter() input_proc_parameter($parameters) : column_domain_or_non_array_type collate_clause default_par_opt { $parameters->add(newNode($1, optName($2), $3)); } ; %type output_proc_parameters() output_proc_parameters($parameters) : output_proc_parameter | output_proc_parameters ',' output_proc_parameter($parameters) ; %type output_proc_parameter() output_proc_parameter($parameters) : column_domain_or_non_array_type collate_clause { $parameters->add(newNode($1, optName($2))); } ; %type column_domain_or_non_array_type column_domain_or_non_array_type : symbol_column_name domain_or_non_array_type { $$ = $2; $$->fld_name = *$1; } ; %type default_par_opt default_par_opt : // nothing { $$ = NULL; } | DEFAULT default_value { ValueSourceClause* clause = newNode(); clause->value = $2; clause->source = makeParseStr(YYPOSNARG(1), YYPOSNARG(2)); $$ = clause; } | '=' default_value { ValueSourceClause* clause = newNode(); clause->value = $2; clause->source = makeParseStr(YYPOSNARG(1), YYPOSNARG(2)); $$ = clause; } ; // FUNCTION %type function_clause function_clause : psql_function_clause | external_function_clause; %type psql_function_clause psql_function_clause : function_clause_start AS local_declaration_list full_proc_block { $$ = $1; $$->source = makeParseStr(YYPOSNARG(3), YYPOSNARG(4)); $$->localDeclList = $3; $$->body = $4; } ; %type external_function_clause external_function_clause : function_clause_start external_clause external_body_clause_opt { $$ = $1; $$->external = $2; if ($3) $$->source = *$3; } ; %type function_clause_start function_clause_start : symbol_UDF_name { $$ = newNode(*$1); } input_parameters(NOTRIAL(&$2->parameters)) RETURNS domain_or_non_array_type collate_clause deterministic_opt { $$ = $2; $$->returnType = newNode($5, optName($6)); $$->deterministic = $7; } ; %type deterministic_opt deterministic_opt : { $$ = false; } | NOT DETERMINISTIC { $$ = false; } | DETERMINISTIC { $$ = true; } ; %type external_clause external_clause : EXTERNAL NAME utf_string ENGINE valid_symbol_name { $$ = newNode(); $$->name = *$3; $$->engine = *$5; } | EXTERNAL ENGINE valid_symbol_name { $$ = newNode(); $$->engine = *$3; } ; %type external_body_clause_opt external_body_clause_opt : /* nothing */ { $$ = NULL; } | AS utf_string { $$ = $2; } ; %type alter_function_clause alter_function_clause : function_clause { $$ = $1; $$->alter = true; $$->create = false; } ; %type replace_function_clause replace_function_clause : function_clause { $$ = $1; $$->alter = true; } ; // PACKAGE %type package_clause package_clause : symbol_package_name AS BEGIN package_items_opt END { CreateAlterPackageNode* node = newNode(*$1); node->source = makeParseStr(YYPOSNARG(3), YYPOSNARG(5)); node->items = $4; $$ = node; } ; %type package_items_opt package_items_opt : package_items | { $$ = newNode >(); } ; %type package_items package_items : package_item { $$ = newNode >(); $$->add($1); } | package_items package_item { $$ = $1; $$->add($2); } ; %type package_item package_item : FUNCTION function_clause_start ';' { $$ = CreateAlterPackageNode::Item::create($2); } | PROCEDURE procedure_clause_start ';' { $$ = CreateAlterPackageNode::Item::create($2); } ; %type alter_package_clause alter_package_clause : package_clause { $$ = $1; $$->alter = true; $$->create = false; } ; %type replace_package_clause replace_package_clause : package_clause { $$ = $1; $$->alter = true; } ; // PACKAGE BODY %type package_body_clause package_body_clause : symbol_package_name AS BEGIN package_items package_body_items_opt END { CreatePackageBodyNode* node = newNode(*$1); node->source = makeParseStr(YYPOSNARG(3), YYPOSNARG(6)); node->declaredItems = $4; node->items = $5; $$ = node; } | symbol_package_name AS BEGIN package_body_items_opt END { CreatePackageBodyNode* node = newNode(*$1); node->source = makeParseStr(YYPOSNARG(3), YYPOSNARG(5)); node->items = $4; $$ = node; } ; %type package_body_items_opt package_body_items_opt : /* nothing */ { $$ = newNode >(); } | package_body_items ; %type package_body_items package_body_items : package_body_item { $$ = newNode >(); $$->add($1); } | package_body_items package_body_item { $$ = $1; $$->add($2); } ; %type package_body_item package_body_item : FUNCTION psql_function_clause { $$ = CreateAlterPackageNode::Item::create($2); } | FUNCTION external_function_clause ';' { $$ = CreateAlterPackageNode::Item::create($2); } | PROCEDURE psql_procedure_clause { $$ = CreateAlterPackageNode::Item::create($2); } | PROCEDURE external_procedure_clause ';' { $$ = CreateAlterPackageNode::Item::create($2); } ; %type local_declaration_list local_declaration_list : /* nothing */ { $$ = NULL; } | local_declarations ; %type local_declarations local_declarations : local_declaration { $$ = newNode(); $$->statements.add($1); } | local_declarations local_declaration { $1->statements.add($2); $$ = $1; } ; %type local_declaration local_declaration : DECLARE var_decl_opt local_declaration_item ';' { $$ = $3; $$->line = YYPOSNARG(1).firstLine; $$->column = YYPOSNARG(1).firstColumn; } | DECLARE PROCEDURE symbol_procedure_name { $$ = newNode(); } input_parameters(NOTRIAL(&$4->parameters)) output_parameters(NOTRIAL(&$4->returns)) AS local_declaration_list full_proc_block { DeclareSubProcNode* node = newNode(*$3); node->dsqlBlock = $4; node->dsqlBlock->localDeclList = $8; node->dsqlBlock->body = $9; for (size_t i = 0; i < node->dsqlBlock->parameters.getCount(); ++i) node->dsqlBlock->parameters[i]->parameterExpr = make_parameter(); $$ = node; } | DECLARE FUNCTION symbol_UDF_name { $$ = newNode(); } input_parameters(NOTRIAL(&$4->parameters)) RETURNS domain_or_non_array_type collate_clause deterministic_opt AS local_declaration_list full_proc_block { DeclareSubFuncNode* node = newNode(*$3); node->dsqlDeterministic = $9; node->dsqlBlock = $4; node->dsqlBlock->localDeclList = $11; node->dsqlBlock->body = $12; for (size_t i = 0; i < node->dsqlBlock->parameters.getCount(); ++i) node->dsqlBlock->parameters[i]->parameterExpr = make_parameter(); node->dsqlBlock->returns.add(newNode($7, optName($8))); $$ = node; } ; %type local_declaration_item local_declaration_item : var_declaration_item | cursor_declaration_item ; %type var_declaration_item var_declaration_item : column_domain_or_non_array_type collate_clause default_par_opt { DeclareVariableNode* node = newNode(); node->dsqlDef = newNode($1, optName($2), $3); $$ = node; } ; var_decl_opt : // nothing | VARIABLE ; %type cursor_declaration_item cursor_declaration_item : symbol_cursor_name scroll_opt CURSOR FOR '(' select ')' { DeclareCursorNode* node = newNode(*$1, DeclareCursorNode::CUR_TYPE_EXPLICIT); node->dsqlScroll = $2; node->dsqlSelect = $6; $$ = node; } ; %type scroll_opt scroll_opt : /* nothing */ { $$ = false; } | NO SCROLL { $$ = false; } | SCROLL { $$ = true; } ; %type proc_block proc_block : proc_statement | full_proc_block ; %type full_proc_block full_proc_block : BEGIN full_proc_block_body END { $$ = newNode(YYPOSNARG(1).firstLine, YYPOSNARG(1).firstColumn, $2); } ; %type full_proc_block_body full_proc_block_body : // nothing { $$ = newNode(); } | proc_statements { BlockNode* node = newNode(); node->action = $1; $$ = node; } | proc_statements excp_hndl_statements { BlockNode* node = newNode(); node->action = $1; node->handlers = $2; $$ = node; } ; %type proc_statements proc_statements : proc_block { $$ = newNode(); $$->statements.add($1); } | proc_statements proc_block { $1->statements.add($2); $$ = $1; } ; %type proc_statement proc_statement : simple_proc_statement ';' { $$ = newNode(YYPOSNARG(1).firstLine, YYPOSNARG(1).firstColumn, $1); } | complex_proc_statement { $$ = newNode(YYPOSNARG(1).firstLine, YYPOSNARG(1).firstColumn, $1); } ; %type simple_proc_statement simple_proc_statement : assignment | insert { $$ = $1; } | merge { $$ = $1; } | update | update_or_insert { $$ = $1; } | delete | singleton_select | exec_procedure | exec_sql { $$ = $1; } | exec_into { $$ = $1; } | exec_function | excp_statement { $$ = $1; } | raise_statement | post_event | cursor_statement | breakleave | continue | SUSPEND { $$ = newNode(); } | EXIT { $$ = newNode(); } | RETURN value { $$ = newNode($2); } ; %type complex_proc_statement complex_proc_statement : in_autonomous_transaction | if_then_else | while | for_select | for_exec_into { $$ = $1; } ; %type in_autonomous_transaction in_autonomous_transaction : KW_IN AUTONOMOUS TRANSACTION DO proc_block { InAutonomousTransactionNode* node = newNode(); node->action = $5; $$ = node; } ; %type excp_statement excp_statement : EXCEPTION symbol_exception_name { $$ = newNode(*$2); } | EXCEPTION symbol_exception_name value { $$ = newNode(*$2, $3); } | EXCEPTION symbol_exception_name USING '(' value_list ')' { $$ = newNode(*$2, (ValueExprNode*) NULL, $5); } ; %type raise_statement raise_statement : EXCEPTION { $$ = newNode(); } ; %type for_select for_select : label_def_opt FOR select INTO variable_list cursor_def DO proc_block { ForNode* node = newNode(); node->dsqlLabelName = $1; node->dsqlSelect = $3; node->dsqlInto = $5; node->dsqlCursor = $6; node->statement = $8; $$ = node; } ; %type exec_sql exec_sql : EXECUTE STATEMENT { $$ = newNode(); } exec_stmt_inputs($3) exec_stmt_options($3) { $$ = $3; } ; %type exec_into exec_into : exec_sql INTO variable_list { $$ = $1; $$->outputs = $3; } ; %type for_exec_into for_exec_into : label_def_opt FOR exec_into DO proc_block { $$ = $3; $$->dsqlLabelName = $1; $$->innerStmt = $5; } ; %type exec_stmt_inputs() exec_stmt_inputs($execStatementNode) : value { $execStatementNode->sql = $1; } | '(' value ')' '(' named_params_list($execStatementNode) ')' { $execStatementNode->sql = $2; } | '(' value ')' '(' not_named_params_list($execStatementNode) ')' { $execStatementNode->sql = $2; } ; %type named_params_list() named_params_list($execStatementNode) : named_param($execStatementNode) | named_params_list ',' named_param($execStatementNode) ; %type named_param() named_param($execStatementNode) : symbol_variable_name BIND_PARAM value { if (!$execStatementNode->inputNames) $execStatementNode->inputNames = FB_NEW(getPool()) EDS::ParamNames(getPool()); $execStatementNode->inputNames->add($1); if (!$execStatementNode->inputs) $execStatementNode->inputs = newNode($3); else $execStatementNode->inputs->add($3); } ; %type not_named_params_list() not_named_params_list($execStatementNode) : not_named_param($execStatementNode) | not_named_params_list ',' not_named_param($execStatementNode) ; %type not_named_param() not_named_param($execStatementNode) : value { if (!$execStatementNode->inputs) $execStatementNode->inputs = newNode($1); else $execStatementNode->inputs->add($1); } ; %type exec_stmt_options() exec_stmt_options($execStatementNode) : // nothing | exec_stmt_options_list($execStatementNode) ; %type exec_stmt_options_list() exec_stmt_options_list($execStatementNode) : exec_stmt_options_list exec_stmt_option($execStatementNode) | exec_stmt_option($execStatementNode) ; %type exec_stmt_option() exec_stmt_option($execStatementNode) : ON EXTERNAL DATA SOURCE value { setClause($execStatementNode->dataSource, "EXTERNAL DATA SOURCE", $5); } | ON EXTERNAL value { setClause($execStatementNode->dataSource, "EXTERNAL DATA SOURCE", $3); } | AS USER value { setClause($execStatementNode->userName, "USER", $3); } | PASSWORD value { setClause($execStatementNode->password, "PASSWORD", $2); } | ROLE value { setClause($execStatementNode->role, "ROLE", $2); } | WITH AUTONOMOUS TRANSACTION { setClause($execStatementNode->traScope, "TRANSACTION", EDS::traAutonomous); } | WITH COMMON TRANSACTION { setClause($execStatementNode->traScope, "TRANSACTION", EDS::traCommon); } | WITH CALLER PRIVILEGES { setClause($execStatementNode->useCallerPrivs, "CALLER PRIVILEGES"); } /* | WITH TWO_PHASE TRANSACTION { setClause($execStatementNode->traScope, "TRANSACTION", EDS::traTwoPhase); } */ ; %type if_then_else if_then_else : IF '(' search_condition ')' THEN proc_block ELSE proc_block { IfNode* node = newNode(); node->condition = $3; node->trueAction = $6; node->falseAction = $8; $$ = node; } | IF '(' search_condition ')' THEN proc_block { IfNode* node = newNode(); node->condition = $3; node->trueAction = $6; $$ = node; } ; %type post_event post_event : POST_EVENT value event_argument_opt { PostEventNode* node = newNode(); node->event = $2; node->argument = $3; $$ = node; } ; %type event_argument_opt event_argument_opt : /* nothing */ { $$ = NULL; } ///| ',' value { $$ = $2; } ; %type singleton_select singleton_select : select INTO variable_list { ForNode* node = newNode(); node->dsqlSelect = $1; node->dsqlInto = $3; $$ = node; } ; %type variable variable : ':' symbol_variable_name { VariableNode* node = newNode(); node->dsqlName = *$2; $$ = node; } ; %type variable_list variable_list : variable { $$ = newNode($1); } | column_name { $$ = newNode($1); } | variable_list ',' column_name { $$ = $1->add($3); } | variable_list ',' variable { $$ = $1->add($3); } ; %type while while : label_def_opt WHILE '(' search_condition ')' DO proc_block { LoopNode* node = newNode(); node->dsqlLabelName = $1; node->dsqlExpr = $4; node->statement = $7; $$ = node; } ; %type label_def_opt label_def_opt : /* nothing */ { $$ = NULL; } | symbol_label_name ':' { $$ = $1; } ; %type breakleave breakleave : KW_BREAK { $$ = newNode(blr_leave); } | LEAVE label_use_opt { ContinueLeaveNode* node = newNode(blr_leave); node->dsqlLabelName = $2; $$ = node; } ; %type continue continue : CONTINUE label_use_opt { ContinueLeaveNode* node = newNode(blr_continue_loop); node->dsqlLabelName = $2; $$ = node; } ; %type label_use_opt label_use_opt : /* nothing */ { $$ = NULL; } | symbol_label_name ; %type cursor_def cursor_def : // nothing { $$ = NULL; } | AS CURSOR symbol_cursor_name { $$ = newNode(*$3, DeclareCursorNode::CUR_TYPE_FOR); } ; %type excp_hndl_statements excp_hndl_statements : excp_hndl_statement { $$ = newNode(); $$->statements.add($1); } | excp_hndl_statements excp_hndl_statement { $1->statements.add($2); $$ = $1; } ; %type excp_hndl_statement excp_hndl_statement : WHEN { $$ = newNode(); } errors(NOTRIAL(&$2->conditions)) DO proc_block { ErrorHandlerNode* node = $2; node->action = $5; $$ = node; } ; %type errors() errors($exceptionArray) : err($exceptionArray) | errors ',' err($exceptionArray) ; %type err() err($exceptionArray) : SQLCODE signed_short_integer { ExceptionItem& item = $exceptionArray->add(); item.type = ExceptionItem::SQL_CODE; item.code = $2; } | GDSCODE symbol_gdscode_name { ExceptionItem& item = $exceptionArray->add(); item.type = ExceptionItem::GDS_CODE; item.name = $2->c_str(); } | EXCEPTION symbol_exception_name { ExceptionItem& item = $exceptionArray->add(); item.type = ExceptionItem::XCP_CODE; item.name = $2->c_str(); } | ANY { ExceptionItem& item = $exceptionArray->add(); item.type = ExceptionItem::XCP_DEFAULT; } ; %type cursor_statement cursor_statement : open_cursor | fetch_cursor | close_cursor ; %type open_cursor open_cursor : OPEN symbol_cursor_name { $$ = newNode(blr_cursor_open, *$2); } ; %type close_cursor close_cursor : CLOSE symbol_cursor_name { $$ = newNode(blr_cursor_close, *$2); } ; %type fetch_cursor fetch_cursor : FETCH { $$ = newNode(blr_cursor_fetch_scroll); } fetch_scroll($2) FROM symbol_cursor_name INTO variable_list { CursorStmtNode* cursorStmt = $2; cursorStmt->dsqlName = *$5; cursorStmt->dsqlIntoStmt = $7; $$ = cursorStmt; } | FETCH symbol_cursor_name INTO variable_list { $$ = newNode(blr_cursor_fetch, *$2, $4); } ; %type fetch_scroll() fetch_scroll($cursorStmtNode) : FIRST { $cursorStmtNode->scrollOp = blr_scroll_bof; } | LAST { $cursorStmtNode->scrollOp = blr_scroll_eof; } | PRIOR { $cursorStmtNode->scrollOp = blr_scroll_backward; } | NEXT { $cursorStmtNode->scrollOp = blr_scroll_forward; } | KW_ABSOLUTE value { $cursorStmtNode->scrollOp = blr_scroll_absolute; $cursorStmtNode->scrollExpr = $2; } | KW_RELATIVE value { $cursorStmtNode->scrollOp = blr_scroll_relative; $cursorStmtNode->scrollExpr = $2; } ; // EXECUTE PROCEDURE %type exec_procedure exec_procedure : EXECUTE PROCEDURE symbol_procedure_name proc_inputs proc_outputs_opt { $$ = newNode(QualifiedName(*$3), $4, $5); } | EXECUTE PROCEDURE symbol_package_name '.' symbol_procedure_name proc_inputs proc_outputs_opt { $$ = newNode(QualifiedName(*$5, *$3), $6, $7); } ; %type proc_inputs proc_inputs : /* nothing */ { $$ = NULL; } | value_list { $$ = $1; } | '(' value_list ')' { $$ = $2; } ; %type proc_outputs_opt proc_outputs_opt : /* nothing */ { $$ = NULL; } | RETURNING_VALUES variable_list { $$ = $2; } | RETURNING_VALUES '(' variable_list ')' { $$ = $3; } ; // EXECUTE BLOCK %type exec_block exec_block : EXECUTE BLOCK { $$ = newNode(); } block_input_params(NOTRIAL(&$3->parameters)) output_parameters(NOTRIAL(&$3->returns)) AS local_declaration_list full_proc_block { ExecBlockNode* node = $3; node->localDeclList = $7; node->body = $8; $$ = node; } ; %type block_input_params() block_input_params($parameters) : // nothing | '(' block_parameters($parameters) ')' ; %type block_parameters() block_parameters($parameters) : block_parameter($parameters) | block_parameters ',' block_parameter($parameters) ; %type block_parameter() block_parameter($parameters) : column_domain_or_non_array_type collate_clause '=' parameter { $parameters->add(newNode($1, optName($2), (ValueSourceClause*) NULL, $4)); } ; // CREATE VIEW %type view_clause view_clause : simple_table_name column_parens_opt AS select_expr check_opt { CreateAlterViewNode* node = newNode($1, $2, $4); node->source = makeParseStr(YYPOSNARG(4), YYPOSNARG(5)); node->withCheckOption = $5; $$ = node; } ; %type replace_view_clause replace_view_clause : view_clause { $1->alter = true; $$ = $1; } ; %type alter_view_clause alter_view_clause : view_clause { $1->alter = true; $1->create = false; $$ = $1; } ; %type check_opt check_opt : /* nothing */ { $$ = false; } | WITH CHECK OPTION { $$ = true; } ; // CREATE TRIGGER %type trigger_clause trigger_clause : symbol_trigger_name trigger_active trigger_type trigger_position AS local_declaration_list full_proc_block { $$ = newNode(*$1); $$->active = $2; $$->type = $3; $$->position = $4; $$->source = makeParseStr(YYPOSNARG(5), YYPOSNARG(7)); $$->localDeclList = $6; $$->body = $7; } | symbol_trigger_name trigger_active trigger_type trigger_position external_clause external_body_clause_opt { $$ = newNode(*$1); $$->active = $2; $$->type = $3; $$->position = $4; $$->external = $5; if ($6) $$->source = *$6; } | symbol_trigger_name trigger_active trigger_type trigger_position ON symbol_table_name AS local_declaration_list full_proc_block { $$ = newNode(*$1); $$->active = $2; $$->type = $3; $$->position = $4; $$->relationName = *$6; $$->source = makeParseStr(YYPOSNARG(7), YYPOSNARG(9)); $$->localDeclList = $8; $$->body = $9; } | symbol_trigger_name trigger_active trigger_type trigger_position ON symbol_table_name external_clause external_body_clause_opt { $$ = newNode(*$1); $$->active = $2; $$->type = $3; $$->position = $4; $$->relationName = *$6; $$->external = $7; if ($8) $$->source = *$8; } | symbol_trigger_name FOR symbol_table_name trigger_active trigger_type trigger_position AS local_declaration_list full_proc_block { $$ = newNode(*$1); $$->active = $4; $$->type = $5; $$->position = $6; $$->relationName = *$3; $$->source = makeParseStr(YYPOSNARG(7), YYPOSNARG(9)); $$->localDeclList = $8; $$->body = $9; } | symbol_trigger_name FOR symbol_table_name trigger_active trigger_type trigger_position external_clause external_body_clause_opt { $$ = newNode(*$1); $$->active = $4; $$->type = $5; $$->position = $6; $$->relationName = *$3; $$->external = $7; if ($8) $$->source = *$8; } ; %type replace_trigger_clause replace_trigger_clause : trigger_clause { $$ = $1; $$->alter = true; } ; %type trigger_active trigger_active : ACTIVE { $$ = Nullable::val(true); } | INACTIVE { $$ = Nullable::val(false); } | { $$ = Nullable::empty(); } ; %type trigger_type trigger_type : trigger_type_prefix trigger_type_suffix { $$ = $1 + $2 - 1; } | ON trigger_db_type { $$ = $2; } | trigger_type_prefix trigger_ddl_type { $$ = $1 + $2; } ; %type trigger_db_type trigger_db_type : CONNECT { $$ = TRIGGER_TYPE_DB | DB_TRIGGER_CONNECT; } | DISCONNECT { $$ = TRIGGER_TYPE_DB | DB_TRIGGER_DISCONNECT; } | TRANSACTION START { $$ = TRIGGER_TYPE_DB | DB_TRIGGER_TRANS_START; } | TRANSACTION COMMIT { $$ = TRIGGER_TYPE_DB | DB_TRIGGER_TRANS_COMMIT; } | TRANSACTION ROLLBACK { $$ = TRIGGER_TYPE_DB | DB_TRIGGER_TRANS_ROLLBACK; } ; %type trigger_ddl_type trigger_ddl_type : trigger_ddl_type_items | ANY DDL STATEMENT { $$ = TRIGGER_TYPE_DDL | (0x7FFFFFFFFFFFFFFFULL & ~(FB_UINT64) TRIGGER_TYPE_MASK & ~1ULL); } ; %type trigger_ddl_type_items trigger_ddl_type_items : CREATE TABLE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_TABLE); } | ALTER TABLE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_TABLE); } | DROP TABLE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_TABLE); } | CREATE PROCEDURE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_PROCEDURE); } | ALTER PROCEDURE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_PROCEDURE); } | DROP PROCEDURE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_PROCEDURE); } | CREATE FUNCTION { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_FUNCTION); } | ALTER FUNCTION { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_FUNCTION); } | DROP FUNCTION { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_FUNCTION); } | CREATE TRIGGER { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_TRIGGER); } | ALTER TRIGGER { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_TRIGGER); } | DROP TRIGGER { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_TRIGGER); } | CREATE EXCEPTION { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_EXCEPTION); } | ALTER EXCEPTION { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_EXCEPTION); } | DROP EXCEPTION { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_EXCEPTION); } | CREATE VIEW { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_VIEW); } | ALTER VIEW { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_VIEW); } | DROP VIEW { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_VIEW); } | CREATE DOMAIN { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_DOMAIN); } | ALTER DOMAIN { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_DOMAIN); } | DROP DOMAIN { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_DOMAIN); } | CREATE ROLE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_ROLE); } | ALTER ROLE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_ROLE); } | DROP ROLE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_ROLE); } | CREATE SEQUENCE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_SEQUENCE); } | ALTER SEQUENCE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_SEQUENCE); } | DROP SEQUENCE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_SEQUENCE); } | CREATE USER { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_USER); } | ALTER USER { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_USER); } | DROP USER { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_USER); } | CREATE INDEX { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_INDEX); } | ALTER INDEX { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_INDEX); } | DROP INDEX { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_INDEX); } | CREATE COLLATION { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_COLLATION); } | DROP COLLATION { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_COLLATION); } | ALTER CHARACTER SET { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_CHARACTER_SET); } | CREATE PACKAGE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_PACKAGE); } | ALTER PACKAGE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_PACKAGE); } | DROP PACKAGE { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_PACKAGE); } | CREATE PACKAGE BODY { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_PACKAGE_BODY); } | DROP PACKAGE BODY { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_PACKAGE_BODY); } | trigger_ddl_type OR trigger_ddl_type { $$ = $1 | $3; } ; %type trigger_type_prefix trigger_type_prefix : BEFORE { $$ = 0; } | AFTER { $$ = 1; } ; %type trigger_type_suffix trigger_type_suffix : INSERT { $$ = trigger_type_suffix(1, 0, 0); } | UPDATE { $$ = trigger_type_suffix(2, 0, 0); } | KW_DELETE { $$ = trigger_type_suffix(3, 0, 0); } | INSERT OR UPDATE { $$ = trigger_type_suffix(1, 2, 0); } | INSERT OR KW_DELETE { $$ = trigger_type_suffix(1, 3, 0); } | UPDATE OR INSERT { $$ = trigger_type_suffix(2, 1, 0); } | UPDATE OR KW_DELETE { $$ = trigger_type_suffix(2, 3, 0); } | KW_DELETE OR INSERT { $$ = trigger_type_suffix(3, 1, 0); } | KW_DELETE OR UPDATE { $$ = trigger_type_suffix(3, 2, 0); } | INSERT OR UPDATE OR KW_DELETE { $$ = trigger_type_suffix(1, 2, 3); } | INSERT OR KW_DELETE OR UPDATE { $$ = trigger_type_suffix(1, 3, 2); } | UPDATE OR INSERT OR KW_DELETE { $$ = trigger_type_suffix(2, 1, 3); } | UPDATE OR KW_DELETE OR INSERT { $$ = trigger_type_suffix(2, 3, 1); } | KW_DELETE OR INSERT OR UPDATE { $$ = trigger_type_suffix(3, 1, 2); } | KW_DELETE OR UPDATE OR INSERT { $$ = trigger_type_suffix(3, 2, 1); } ; %type trigger_position trigger_position : /* nothing */ { $$ = Nullable::empty(); } | POSITION nonneg_short_integer { $$ = Nullable::val($2); } ; // ALTER statement %type alter alter : ALTER alter_clause { $$ = $2; } | set_generator_clause { $$ = $1; } ; %type alter_clause alter_clause : EXCEPTION alter_exception_clause { $$ = $2; } | TABLE simple_table_name { $$ = newNode($2); } alter_ops($3) { $$ = $3; } | VIEW alter_view_clause { $$ = $2; } | TRIGGER alter_trigger_clause { $$ = $2; } | PROCEDURE alter_procedure_clause { $$ = $2; } | PACKAGE alter_package_clause { $$ = $2; } | DATABASE { $$ = newNode(); } alter_db($2) { $$ = $2; } | DOMAIN alter_domain { $$ = $2; } | INDEX alter_index_clause { $$ = $2; } | EXTERNAL FUNCTION alter_udf_clause { $$ = $3; } | FUNCTION alter_function_clause { $$ = $2; } | ROLE alter_role_clause { $$ = $2; } | USER alter_user_clause { $$ = $2; } | CURRENT USER alter_cur_user_clause { $$ = $3; } | CHARACTER SET alter_charset_clause { $$ = $3; } | GENERATOR alter_sequence_clause { $$ = $2; } | SEQUENCE alter_sequence_clause { $$ = $2; } ; %type alter_domain alter_domain : keyword_or_column { $$ = newNode(*$1); } alter_domain_ops($2) { $$ = $2; } ; %type alter_domain_ops() alter_domain_ops($alterDomainNode) : alter_domain_op($alterDomainNode) | alter_domain_ops alter_domain_op($alterDomainNode) ; %type alter_domain_op() alter_domain_op($alterDomainNode) : SET domain_default { setClause($alterDomainNode->setDefault, "DOMAIN DEFAULT", $2); } | ADD CONSTRAINT check_constraint { setClause($alterDomainNode->setConstraint, "DOMAIN CONSTRAINT", $3); } | ADD check_constraint { setClause($alterDomainNode->setConstraint, "DOMAIN CONSTRAINT", $2); } | DROP DEFAULT { setClause($alterDomainNode->dropDefault, "DOMAIN DROP DEFAULT"); } | DROP CONSTRAINT { setClause($alterDomainNode->dropConstraint, "DOMAIN DROP CONSTRAINT"); } | KW_NULL { setClause($alterDomainNode->notNullFlag, "[NOT] NULL", false); } | NOT KW_NULL { setClause($alterDomainNode->notNullFlag, "[NOT] NULL", true); } | TO symbol_column_name { setClause($alterDomainNode->renameTo, "DOMAIN NAME", *$2); } | KW_TYPE non_array_type { //// FIXME: ALTER DOMAIN doesn't support collations, and altered domain's //// collation is always lost. dsql_fld* type = $2; type->collate = ""; setClause($alterDomainNode->type, "DOMAIN TYPE", type); } ; %type alter_ops() alter_ops($relationNode) : alter_op($relationNode) | alter_ops ',' alter_op($relationNode) ; %type alter_op() alter_op($relationNode) : DROP symbol_column_name drop_behaviour { RelationNode::DropColumnClause* clause = newNode(); clause->name = *$2; clause->cascade = $3; $relationNode->clauses.add(clause); } | DROP CONSTRAINT symbol_constraint_name { RelationNode::DropConstraintClause* clause = newNode(); clause->name = *$3; $relationNode->clauses.add(clause); } | ADD column_def($relationNode) | ADD table_constraint_definition($relationNode) | col_opt alter_column_name POSITION pos_short_integer { RelationNode::AlterColPosClause* clause = newNode(); clause->name = *$2; clause->newPos = $4; $relationNode->clauses.add(clause); } | col_opt alter_column_name TO symbol_column_name { RelationNode::AlterColNameClause* clause = newNode(); clause->fromName = *$2; clause->toName = *$4; $relationNode->clauses.add(clause); } | col_opt alter_column_name KW_NULL { RelationNode::AlterColNullClause* clause = newNode(); clause->name = *$2; clause->notNullFlag = false; $relationNode->clauses.add(clause); } | col_opt alter_column_name NOT KW_NULL { RelationNode::AlterColNullClause* clause = newNode(); clause->name = *$2; clause->notNullFlag = true; $relationNode->clauses.add(clause); } | col_opt symbol_column_name KW_TYPE alter_data_type_or_domain { RelationNode::AlterColTypeClause* clause = newNode(); clause->field = $4; clause->field->fld_name = *$2; $relationNode->clauses.add(clause); } | col_opt symbol_column_name KW_TYPE non_array_type def_computed { RelationNode::AlterColTypeClause* clause = newNode(); clause->field = newNode(); clause->field->fld_name = *$2; clause->computed = $5; $relationNode->clauses.add(clause); clause->field->flags |= FLD_computed; } | col_opt symbol_column_name def_computed { RelationNode::AlterColTypeClause* clause = newNode(); clause->field = newNode(); clause->field->fld_name = *$2; clause->computed = $3; $relationNode->clauses.add(clause); clause->field->flags |= FLD_computed; } | col_opt symbol_column_name SET domain_default { RelationNode::AlterColTypeClause* clause = newNode(); clause->field = newNode(); clause->field->fld_name = *$2; clause->defaultValue = $4; $relationNode->clauses.add(clause); } | col_opt symbol_column_name DROP DEFAULT { RelationNode::AlterColTypeClause* clause = newNode(); clause->field = newNode(); clause->field->fld_name = *$2; clause->dropDefault = true; $relationNode->clauses.add(clause); } | col_opt symbol_column_name RESTART restart_value_opt { RelationNode::AlterColTypeClause* clause = newNode(); clause->field = newNode(); clause->field->fld_name = *$2; clause->identityRestart = true; clause->identityRestartValue = $4; $relationNode->clauses.add(clause); } ; %type alter_column_name alter_column_name : keyword_or_column ; // below are reserved words that could be used as column identifiers // in the previous versions %type keyword_or_column keyword_or_column : valid_symbol_name | ADMIN // added in IB 5.0 | COLUMN // added in IB 6.0 | EXTRACT | YEAR | MONTH | DAY | HOUR | MINUTE | SECOND | TIME | TIMESTAMP | CURRENT_DATE | CURRENT_TIME | CURRENT_TIMESTAMP | CURRENT_USER // added in FB 1.0 | CURRENT_ROLE | RECREATE | CURRENT_CONNECTION // added in FB 1.5 | CURRENT_TRANSACTION | BIGINT | CASE | RELEASE | ROW_COUNT | SAVEPOINT | OPEN // added in FB 2.0 | CLOSE | FETCH | ROWS | USING | CROSS | BIT_LENGTH | BOTH | CHAR_LENGTH | CHARACTER_LENGTH | COMMENT | LEADING | KW_LOWER | OCTET_LENGTH | TRAILING | TRIM | CONNECT // added in FB 2.1 | DISCONNECT | GLOBAL | INSENSITIVE | RECURSIVE | SENSITIVE | START | SIMILAR // added in FB 2.5 | OVER // added in FB 3.0 | SCROLL | RETURN | DETERMINISTIC | SQLSTATE ; col_opt : ALTER | ALTER COLUMN ; %type alter_data_type_or_domain alter_data_type_or_domain : non_array_type | symbol_column_name { $$ = newNode(); $$->typeOfName = *$1; } ; %type drop_behaviour drop_behaviour : { $$ = false; } | RESTRICT { $$ = false; } | CASCADE { $$ = true; } ; %type alter_index_clause alter_index_clause : symbol_index_name ACTIVE { $$ = newNode(*$1, true); } | symbol_index_name INACTIVE { $$ = newNode(*$1, false); } ; %type alter_udf_clause alter_udf_clause : symbol_UDF_name entry_op module_op { AlterExternalFunctionNode* node = newNode(*$1); if ($2) node->clauses.name = *$2; if ($3) node->clauses.udfModule = *$3; $$ = node; } ; %type entry_op entry_op : /* nothing */ { $$ = NULL; } | ENTRY_POINT utf_string { $$ = $2; } ; %type module_op module_op : /* nothing */ { $$ = NULL; } | MODULE_NAME utf_string { $$ = $2; } ; %type alter_role_clause alter_role_clause : symbol_role_name alter_role_enable AUTO ADMIN MAPPING { $$ = newNode(*$1, $2); } ; %type alter_role_enable alter_role_enable : SET { $$ = true; } | DROP { $$ = false; } ; // ALTER DATABASE %type alter_db() alter_db($alterDatabaseNode) : db_alter_clause($alterDatabaseNode) | alter_db db_alter_clause($alterDatabaseNode) ; %type db_alter_clause() db_alter_clause($alterDatabaseNode) : ADD db_file_list(NOTRIAL(&$alterDatabaseNode->files)) | ADD KW_DIFFERENCE KW_FILE utf_string { $alterDatabaseNode->differenceFile = *$4; } | DROP KW_DIFFERENCE KW_FILE { $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_DROP_DIFFERENCE; } | BEGIN BACKUP { $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_BEGIN_BACKUP; } | END BACKUP { $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_END_BACKUP; } | SET DEFAULT CHARACTER SET symbol_character_set_name { $alterDatabaseNode->setDefaultCharSet = *$5; } | ENCRYPT WITH valid_symbol_name { $alterDatabaseNode->cryptPlugin = *$3; } | DECRYPT { $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_DECRYPT; } | SET LINGER TO long_integer { $alterDatabaseNode->linger = $4; } | DROP LINGER { $alterDatabaseNode->linger = 0; } ; // ALTER TRIGGER %type alter_trigger_clause alter_trigger_clause : symbol_trigger_name trigger_active trigger_type_opt trigger_position AS local_declaration_list full_proc_block { $$ = newNode(*$1); $$->alter = true; $$->create = false; $$->active = $2; $$->type = $3; $$->position = $4; $$->source = makeParseStr(YYPOSNARG(5), YYPOSNARG(7)); $$->localDeclList = $6; $$->body = $7; } | symbol_trigger_name trigger_active trigger_type_opt trigger_position external_clause external_body_clause_opt { $$ = newNode(*$1); $$->alter = true; $$->create = false; $$->active = $2; $$->type = $3; $$->position = $4; $$->external = $5; if ($6) $$->source = *$6; } | symbol_trigger_name trigger_active trigger_type_opt trigger_position { $$ = newNode(*$1); $$->alter = true; $$->create = false; $$->active = $2; $$->type = $3; $$->position = $4; } ; %type trigger_type_opt trigger_type_opt // we do not allow alter database triggers, hence we do not use trigger_type here : trigger_type_prefix trigger_type_suffix { $$ = Nullable::val($1 + $2 - 1); } | { $$ = Nullable::empty(); } ; // DROP metadata operations %type drop drop : DROP drop_clause { $$ = $2; } ; %type drop_clause drop_clause : EXCEPTION symbol_exception_name { $$ = newNode(*$2); } | INDEX symbol_index_name { $$ = newNode(*$2); } | PROCEDURE symbol_procedure_name { $$ = newNode(*$2); } | TABLE symbol_table_name { $$ = newNode(*$2, false); } | TRIGGER symbol_trigger_name { $$ = newNode(*$2); } | VIEW symbol_view_name { $$ = newNode(*$2, true); } | FILTER symbol_filter_name { $$ = newNode(*$2); } | DOMAIN symbol_domain_name { $$ = newNode(*$2); } | EXTERNAL FUNCTION symbol_UDF_name { $$ = newNode(*$3); } | FUNCTION symbol_UDF_name { $$ = newNode(*$2); } | SHADOW pos_short_integer { $$ = newNode($2); } | ROLE symbol_role_name { $$ = newNode(*$2); } | GENERATOR symbol_generator_name { $$ = newNode(*$2); } | SEQUENCE symbol_generator_name { $$ = newNode(*$2); } | COLLATION symbol_collation_name { $$ = newNode(*$2); } | USER symbol_user_name { $$ = newNode(*$2); } | PACKAGE symbol_package_name { $$ = newNode(*$2); } | PACKAGE BODY symbol_package_name { $$ = newNode(*$3); } ; // these are the allowable datatypes %type data_type data_type : non_array_type | array_type ; %type domain_or_non_array_type domain_or_non_array_type : domain_or_non_array_type_name | domain_or_non_array_type_name NOT KW_NULL { $$ = $1; $$->notNull = true; } ; %type domain_or_non_array_type_name domain_or_non_array_type_name : non_array_type | domain_type ; %type domain_type domain_type : KW_TYPE OF symbol_column_name { $$ = newNode(); $$->typeOfName = *$3; } | KW_TYPE OF COLUMN symbol_column_name '.' symbol_column_name { $$ = newNode(); $$->typeOfName = *$6; $$->typeOfTable = *$4; } | symbol_column_name { $$ = newNode(); $$->typeOfName = *$1; $$->fullDomain = true; } ; %type non_array_type non_array_type : simple_type | blob_type ; %type array_type array_type : non_charset_simple_type '[' array_spec ']' { $1->ranges = $3; $1->dimensions = $1->ranges->items.getCount() / 2; $1->elementDtype = $1->dtype; $$ = $1; } | character_type '[' array_spec ']' charset_clause { $1->ranges = $3; $1->dimensions = $1->ranges->items.getCount() / 2; $1->elementDtype = $1->dtype; if ($5) $1->charSet = *$5; $$ = $1; } ; %type array_spec array_spec : array_range | array_spec ',' array_range { $$ = $1->add($3->items[0])->add($3->items[1]); } ; %type array_range array_range : signed_long_integer { if ($1 < 1) $$ = newNode(MAKE_const_slong($1))->add(MAKE_const_slong(1)); else $$ = newNode(MAKE_const_slong(1))->add(MAKE_const_slong($1)); } | signed_long_integer ':' signed_long_integer { $$ = newNode(MAKE_const_slong($1))->add(MAKE_const_slong($3)); } ; %type simple_type simple_type : non_charset_simple_type | character_type charset_clause { $$ = $1; if ($2) $$->charSet = *$2; } ; %type non_charset_simple_type non_charset_simple_type : national_character_type | numeric_type | float_type | BIGINT { $$ = newNode(); if (client_dialect < SQL_DIALECT_V6_TRANSITION) { ERRD_post (Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_sql_dialect_datatype_unsupport) << Arg::Num(client_dialect) << Arg::Str("BIGINT")); } if (db_dialect < SQL_DIALECT_V6_TRANSITION) { ERRD_post (Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_sql_db_dialect_dtype_unsupport) << Arg::Num(db_dialect) << Arg::Str("BIGINT")); } $$->dtype = dtype_int64; $$->length = sizeof(SINT64); } | integer_keyword { $$ = newNode(); $$->dtype = dtype_long; $$->length = sizeof(SLONG); } | SMALLINT { $$ = newNode(); $$->dtype = dtype_short; $$->length = sizeof(SSHORT); } | DATE { $$ = newNode(); stmt_ambiguous = true; if (client_dialect <= SQL_DIALECT_V5) { // Post warning saying that DATE is equivalent to TIMESTAMP ERRD_post_warning(Arg::Warning(isc_sqlwarn) << Arg::Num(301) << Arg::Warning(isc_dtype_renamed)); $$->dtype = dtype_timestamp; $$->length = sizeof(GDS_TIMESTAMP); } else if (client_dialect == SQL_DIALECT_V6_TRANSITION) yyabandon(-104, isc_transitional_date); else { $$->dtype = dtype_sql_date; $$->length = sizeof(ULONG); } } | TIME { $$ = newNode(); if (client_dialect < SQL_DIALECT_V6_TRANSITION) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_sql_dialect_datatype_unsupport) << Arg::Num(client_dialect) << Arg::Str("TIME")); } if (db_dialect < SQL_DIALECT_V6_TRANSITION) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_sql_db_dialect_dtype_unsupport) << Arg::Num(db_dialect) << Arg::Str("TIME")); } $$->dtype = dtype_sql_time; $$->length = sizeof(SLONG); } | TIMESTAMP { $$ = newNode(); $$->dtype = dtype_timestamp; $$->length = sizeof(GDS_TIMESTAMP); } | KW_BOOLEAN { $$ = newNode(); $$->dtype = dtype_boolean; $$->length = sizeof(UCHAR); } ; integer_keyword : INTEGER | KW_INT ; // allow a blob to be specified with any combination of segment length and subtype %type blob_type blob_type : BLOB { $$ = newNode(); } blob_subtype(NOTRIAL($2)) blob_segsize charset_clause { $$ = $2; $$->dtype = dtype_blob; $$->length = sizeof(ISC_QUAD); $$->segLength = $4; if ($5) $$->charSet = *$5; } | BLOB '(' unsigned_short_integer ')' { $$ = newNode(); $$->dtype = dtype_blob; $$->length = sizeof(ISC_QUAD); $$->segLength = (USHORT) $3; $$->subType = 0; } | BLOB '(' unsigned_short_integer ',' signed_short_integer ')' { $$ = newNode(); $$->dtype = dtype_blob; $$->length = sizeof(ISC_QUAD); $$->segLength = (USHORT) $3; $$->subType = (USHORT) $5; } | BLOB '(' ',' signed_short_integer ')' { $$ = newNode(); $$->dtype = dtype_blob; $$->length = sizeof(ISC_QUAD); $$->segLength = 80; $$->subType = (USHORT) $4; } ; %type blob_segsize blob_segsize : /* nothing */ { $$ = (USHORT) 80; } | SEGMENT KW_SIZE unsigned_short_integer { $$ = (USHORT) $3; } ; %type blob_subtype() blob_subtype($field) : // nothing { $field->subType = (USHORT) 0; } | SUB_TYPE signed_short_integer { $field->subType = (USHORT) $2; } | SUB_TYPE symbol_blob_subtype_name { $field->subTypeName = *$2; } ; %type charset_clause charset_clause : /* nothing */ { $$ = NULL; } | CHARACTER SET symbol_character_set_name { $$ = $3; } ; // character type %type national_character_type national_character_type : national_character_keyword '(' pos_short_integer ')' { $$ = newNode(); $$->dtype = dtype_text; $$->charLength = (USHORT) $3; $$->flags |= FLD_national; } | national_character_keyword { $$ = newNode(); $$->dtype = dtype_text; $$->charLength = 1; $$->flags |= FLD_national; } | national_character_keyword VARYING '(' pos_short_integer ')' { $$ = newNode(); $$->dtype = dtype_varying; $$->charLength = (USHORT) $4; $$->flags |= FLD_national; } ; %type character_type character_type : character_keyword '(' pos_short_integer ')' { $$ = newNode(); $$->dtype = dtype_text; $$->charLength = (USHORT) $3; } | character_keyword { $$ = newNode(); $$->dtype = dtype_text; $$->charLength = 1; } | varying_keyword '(' pos_short_integer ')' { $$ = newNode(); $$->dtype = dtype_varying; $$->charLength = (USHORT) $3; } ; varying_keyword : VARCHAR | CHARACTER VARYING | KW_CHAR VARYING ; character_keyword : CHARACTER | KW_CHAR ; national_character_keyword : NCHAR | NATIONAL CHARACTER | NATIONAL KW_CHAR ; // numeric type %type numeric_type numeric_type : KW_NUMERIC prec_scale { $$ = $2; $$->subType = dsc_num_type_numeric; } | decimal_keyword prec_scale { $$ = $2; $$->subType = dsc_num_type_decimal; if ($$->dtype == dtype_short) { $$->dtype = dtype_long; $$->length = sizeof(SLONG); } } ; %type prec_scale prec_scale : // nothing { $$ = newNode(); $$->dtype = dtype_long; $$->length = sizeof(SLONG); $$->precision = 9; } | '(' signed_long_integer ')' { $$ = newNode(); if ($2 < 1 || $2 > 18) yyabandon(-842, isc_precision_err); // Precision must be between 1 and 18. if ($2 > 9) { if ( ( (client_dialect <= SQL_DIALECT_V5) && (db_dialect > SQL_DIALECT_V5) ) || ( (client_dialect > SQL_DIALECT_V5) && (db_dialect <= SQL_DIALECT_V5) ) ) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-817) << Arg::Gds(isc_ddl_not_allowed_by_db_sql_dial) << Arg::Num(db_dialect)); } if (client_dialect <= SQL_DIALECT_V5) { $$->dtype = dtype_double; $$->length = sizeof(double); } else { if (client_dialect == SQL_DIALECT_V6_TRANSITION) { ERRD_post_warning(Arg::Warning(isc_dsql_warn_precision_ambiguous)); ERRD_post_warning(Arg::Warning(isc_dsql_warn_precision_ambiguous1)); ERRD_post_warning(Arg::Warning(isc_dsql_warn_precision_ambiguous2)); } $$->dtype = dtype_int64; $$->length = sizeof(SINT64); } } else { if ($2 < 5) { $$->dtype = dtype_short; $$->length = sizeof(SSHORT); } else { $$->dtype = dtype_long; $$->length = sizeof(SLONG); } } $$->precision = (USHORT) $2; } | '(' signed_long_integer ',' signed_long_integer ')' { $$ = newNode(); if ($2 < 1 || $2 > 18) yyabandon (-842, isc_precision_err); // Precision should be between 1 and 18 if ($4 > $2 || $4 < 0) yyabandon (-842, isc_scale_nogt); // Scale must be between 0 and precision if ($2 > 9) { if ( ( (client_dialect <= SQL_DIALECT_V5) && (db_dialect > SQL_DIALECT_V5) ) || ( (client_dialect > SQL_DIALECT_V5) && (db_dialect <= SQL_DIALECT_V5) ) ) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-817) << Arg::Gds(isc_ddl_not_allowed_by_db_sql_dial) << Arg::Num(db_dialect)); } if (client_dialect <= SQL_DIALECT_V5) { $$->dtype = dtype_double; $$->length = sizeof(double); } else { if (client_dialect == SQL_DIALECT_V6_TRANSITION) { ERRD_post_warning(Arg::Warning(isc_dsql_warn_precision_ambiguous)); ERRD_post_warning(Arg::Warning(isc_dsql_warn_precision_ambiguous1)); ERRD_post_warning(Arg::Warning(isc_dsql_warn_precision_ambiguous2)); } // client_dialect >= SQL_DIALECT_V6 $$->dtype = dtype_int64; $$->length = sizeof(SINT64); } } else { if ($2 < 5) { $$->dtype = dtype_short; $$->length = sizeof(SSHORT); } else { $$->dtype = dtype_long; $$->length = sizeof(SLONG); } } $$->precision = (USHORT) $2; $$->scale = - (SSHORT) $4; } ; decimal_keyword : DECIMAL | KW_DEC ; // floating point type %type float_type float_type : KW_FLOAT precision_opt { $$ = newNode(); if ($2 > 7) { $$->dtype = dtype_double; $$->length = sizeof(double); } else { $$->dtype = dtype_real; $$->length = sizeof(float); } } | KW_LONG KW_FLOAT precision_opt { $$ = newNode(); $$->dtype = dtype_double; $$->length = sizeof(double); } | REAL { $$ = newNode(); $$->dtype = dtype_real; $$->length = sizeof(float); } | KW_DOUBLE PRECISION { $$ = newNode(); $$->dtype = dtype_double; $$->length = sizeof(double); } ; %type precision_opt precision_opt : /* nothing */ { $$ = 0; } | '(' nonneg_short_integer ')' { $$ = $2; } ; // transaction statements %type savepoint savepoint : set_savepoint | release_savepoint | undo_savepoint ; %type set_savepoint set_savepoint : SAVEPOINT symbol_savepoint_name { UserSavepointNode* node = newNode(); node->command = UserSavepointNode::CMD_SET; node->name = *$2; $$ = node; } ; %type release_savepoint release_savepoint : RELEASE SAVEPOINT symbol_savepoint_name release_only_opt { UserSavepointNode* node = newNode(); node->command = ($4 ? UserSavepointNode::CMD_RELEASE_ONLY : UserSavepointNode::CMD_RELEASE); node->name = *$3; $$ = node; } ; %type release_only_opt release_only_opt : /* nothing */ { $$ = false; } | ONLY { $$ = true; } ; %type undo_savepoint undo_savepoint : ROLLBACK optional_work TO optional_savepoint symbol_savepoint_name { UserSavepointNode* node = newNode(); node->command = UserSavepointNode::CMD_ROLLBACK; node->name = *$5; $$ = node; } ; optional_savepoint : // nothing | SAVEPOINT ; %type commit commit : COMMIT optional_work optional_retain { $$ = newNode(CommitRollbackNode::CMD_COMMIT, $3); } ; %type rollback rollback : ROLLBACK optional_work optional_retain { $$ = newNode(CommitRollbackNode::CMD_ROLLBACK, $3); } ; optional_work : // nothing | WORK ; %type optional_retain optional_retain : /* nothing */ { $$ = false; } | RETAIN opt_snapshot { $$ = true; } ; opt_snapshot : // nothing | SNAPSHOT ; %type set_transaction set_transaction : SET TRANSACTION { $$ = newNode(); } tran_option_list_opt($3) { $$ = $3; } ; %type tran_option_list_opt() tran_option_list_opt($setTransactionNode) : // nothing | tran_option_list($setTransactionNode) ; %type tran_option_list() tran_option_list($setTransactionNode) : tran_option($setTransactionNode) | tran_option_list tran_option($setTransactionNode) ; %type tran_option() tran_option($setTransactionNode) // access mode : READ ONLY { setClause($setTransactionNode->readOnly, "READ {ONLY | WRITE}", true); } | READ WRITE { setClause($setTransactionNode->readOnly, "READ {ONLY | WRITE}", false); } // wait mode | WAIT { setClause($setTransactionNode->wait, "[NO] WAIT", true); } | NO WAIT { setClause($setTransactionNode->wait, "[NO] WAIT", false); } // isolation mode | isolation_mode { setClause($setTransactionNode->isoLevel, "ISOLATION LEVEL", $1); } // misc options | NO AUTO UNDO { setClause($setTransactionNode->noAutoUndo, "NO AUTO UNDO", true); } | KW_IGNORE LIMBO { setClause($setTransactionNode->ignoreLimbo, "IGNORE LIMBO", true); } | RESTART REQUESTS { setClause($setTransactionNode->restartRequests, "RESTART REQUESTS", true); } // timeout | LOCK TIMEOUT nonneg_short_integer { setClause($setTransactionNode->lockTimeout, "LOCK TIMEOUT", (USHORT) $3); } // reserve options | RESERVING { checkDuplicateClause($setTransactionNode->reserveList, "RESERVING"); } restr_list($setTransactionNode) ; %type isolation_mode isolation_mode : ISOLATION LEVEL iso_mode { $$ = $3;} | iso_mode ; %type iso_mode iso_mode : snap_shot | READ UNCOMMITTED version_mode { $$ = $3; } | READ COMMITTED version_mode { $$ = $3; } ; %type snap_shot snap_shot : SNAPSHOT { $$ = SetTransactionNode::ISO_LEVEL_CONCURRENCY; } | SNAPSHOT TABLE { $$ = SetTransactionNode::ISO_LEVEL_CONSISTENCY; } | SNAPSHOT TABLE STABILITY { $$ = SetTransactionNode::ISO_LEVEL_CONSISTENCY; } ; %type version_mode version_mode : /* nothing */ { $$ = SetTransactionNode::ISO_LEVEL_READ_COMMITTED_NO_REC_VERSION; } | VERSION { $$ = SetTransactionNode::ISO_LEVEL_READ_COMMITTED_REC_VERSION; } | NO VERSION { $$ = SetTransactionNode::ISO_LEVEL_READ_COMMITTED_NO_REC_VERSION; } ; %type lock_type lock_type : /* nothing */ { $$ = 0; } | KW_SHARED { $$ = SetTransactionNode::LOCK_MODE_SHARED; } | PROTECTED { $$ = SetTransactionNode::LOCK_MODE_PROTECTED; } ; %type lock_mode lock_mode : READ { $$ = SetTransactionNode::LOCK_MODE_READ; } | WRITE { $$ = SetTransactionNode::LOCK_MODE_WRITE; } ; %type restr_list() restr_list($setTransactionNode) : restr_option { $setTransactionNode->reserveList.add($1); } | restr_list ',' restr_option { $setTransactionNode->reserveList.add($3); } ; %type restr_option restr_option : table_list table_lock { $$ = newNode($1, $2); } ; %type table_lock table_lock : /* nothing */ { $$ = 0; } | FOR lock_type lock_mode { $$ = $2 | $3; } ; %type table_list table_list : symbol_table_name { ObjectsArray* node = newNode >(); node->add(*$1); $$ = node; } | table_list ',' symbol_table_name { ObjectsArray* node = $1; node->add(*$3); $$ = node; } ; %type set_statistics set_statistics : SET STATISTICS INDEX symbol_index_name { $$ = newNode(*$4); } ; %type comment comment : COMMENT ON ddl_type0 IS ddl_desc { $$ = newNode($3, "", "", *$5); } | COMMENT ON ddl_type1 symbol_ddl_name IS ddl_desc { $$ = newNode($3, *$4, "", *$6); } | COMMENT ON ddl_type2 symbol_ddl_name ddl_subname IS ddl_desc { $$ = newNode($3, *$4, *$5, *$7); } | COMMENT ON USER symbol_user_name IS ddl_desc { CreateAlterUserNode* node = newNode(CreateAlterUserNode::USER_MOD, *$4); node->comment = $6; $$ = node; } ; %type ddl_type0 ddl_type0 : DATABASE { $$ = obj_database; } ; %type ddl_type1 ddl_type1 : DOMAIN { $$ = obj_field; } | TABLE { $$ = obj_relation; } | VIEW { $$ = obj_view; } | PROCEDURE { $$ = obj_procedure; } | TRIGGER { $$ = obj_trigger; } | EXTERNAL FUNCTION { $$ = obj_udf; } | FUNCTION { $$ = obj_udf; } | FILTER { $$ = obj_blob_filter; } | EXCEPTION { $$ = obj_exception; } | GENERATOR { $$ = obj_generator; } | SEQUENCE { $$ = obj_generator; } | INDEX { $$ = obj_index; } | ROLE { $$ = obj_sql_role; } | CHARACTER SET { $$ = obj_charset; } | COLLATION { $$ = obj_collation; } | PACKAGE { $$ = obj_package_header; } /*** | SECURITY CLASS { $$ = ddl_sec_class; } ***/ ; %type ddl_type2 ddl_type2 : COLUMN { $$ = obj_relation; } | ddl_param_opt PARAMETER { $$ = $1; } ; %type ddl_param_opt ddl_param_opt : { $$ = obj_parameter; } | PROCEDURE { $$ = obj_procedure; } | FUNCTION { $$ = obj_udf; } ; %type ddl_subname ddl_subname : '.' symbol_ddl_name { $$ = $2; } ; %type ddl_desc ddl_desc : utf_string { $$ = $1; } | KW_NULL { $$ = newString(""); } ; // SELECT statement %type select select : select_expr for_update_clause lock_clause { SelectNode* node = newNode(); node->dsqlExpr = $1; node->dsqlForUpdate = $2; node->dsqlWithLock = $3; $$ = node; } ; %type for_update_clause for_update_clause : /* nothing */ { $$ = false; } | FOR UPDATE for_update_list { $$ = true; /* for_update_list is ignored */ } ; %type for_update_list for_update_list : /* nothing */ { $$ = NULL; } | OF column_list { $$ = $2; } ; %type lock_clause lock_clause : /* nothing */ { $$ = false; } | WITH LOCK { $$ = true; } ; // SELECT expression %type select_expr select_expr : with_clause select_expr_body order_clause rows_clause { SelectExprNode* node = $$ = newNode(); node->querySpec = $2; node->orderClause = $3; node->rowsClause = $4; node->withClause = $1; } ; %type with_clause with_clause : // nothing { $$ = NULL; } | WITH RECURSIVE with_list { $$ = $3; $$->recursive = true; } | WITH with_list { $$ = $2; } ; %type with_list with_list : with_item { $$ = newNode(); $$->add($1); } | with_item ',' with_list { $$ = $3; $$->add($1); } ; %type with_item with_item : symbol_table_alias_name derived_column_list AS '(' select_expr ')' { $$ = $5; $$->dsqlFlags |= RecordSourceNode::DFLAG_DERIVED; $$->alias = $1->c_str(); $$->columns = $2; } ; %type column_select column_select : select_expr { $$ = $1; $$->dsqlFlags |= RecordSourceNode::DFLAG_VALUE; } ; %type column_singleton column_singleton : column_select { $1->dsqlFlags |= RecordSourceNode::DFLAG_SINGLETON; $$ = newNode(blr_via, $1); } ; %type select_expr_body select_expr_body : query_term { $$ = $1; } | select_expr_body UNION distinct_noise query_term { UnionSourceNode* node = $1->as(); if (node && !node->dsqlAll) node->dsqlClauses->add($4); else { node = newNode(); node->dsqlClauses = newNode($1)->add($4); } $$ = node; } | select_expr_body UNION ALL query_term { UnionSourceNode* node = $1->as(); if (node && node->dsqlAll) node->dsqlClauses->add($4); else { node = newNode(); node->dsqlAll = true; node->dsqlClauses = newNode($1)->add($4); } $$ = node; } ; %type query_term query_term : query_spec ; %type query_spec query_spec : SELECT limit_clause distinct_clause select_list from_clause where_clause group_clause having_clause plan_clause { RseNode* rse = newNode(); rse->dsqlFirst = $2 ? $2->items[1] : NULL; rse->dsqlSkip = $2 ? $2->items[0] : NULL; rse->dsqlDistinct = $3; rse->dsqlSelectList = $4; rse->dsqlFrom = $5; rse->dsqlWhere = $6; rse->dsqlGroup = $7; rse->dsqlHaving = $8; rse->rse_plan = $9; $$ = rse; } ; %type limit_clause limit_clause : /* nothing */ { $$ = NULL; } | first_clause skip_clause { $$ = newNode($2)->add($1); } | first_clause { $$ = newNode(1u)->add($1); } | skip_clause { $$ = newNode($1)->add(NULL); } ; %type first_clause first_clause : FIRST long_integer { $$ = MAKE_const_slong($2); } | FIRST '(' value ')' { $$ = $3; } | FIRST parameter { $$ = $2; } ; %type skip_clause skip_clause : SKIP long_integer { $$ = MAKE_const_slong($2); } | SKIP '(' value ')' { $$ = $3; } | SKIP parameter { $$ = $2; } ; %type distinct_clause distinct_clause : DISTINCT { $$ = newNode(0); } | all_noise { $$ = NULL; } ; %type select_list select_list : select_items { $$ = $1; } | '*' { $$ = NULL; } ; %type select_items select_items : select_item { $$ = newNode($1); } | select_items ',' select_item { $$ = $1->add($3); } ; %type select_item select_item : value_opt_alias | symbol_table_alias_name '.' '*' { FieldNode* fieldNode = newNode(); fieldNode->dsqlQualifier = *$1; $$ = fieldNode; } ; %type value_opt_alias value_opt_alias : value | value as_noise symbol_item_alias_name { $$ = newNode(*$3, $1); } ; as_noise : | AS ; // FROM clause %type from_clause from_clause : FROM from_list { $$ = $2; } ; %type from_list from_list : table_reference { $$ = newNode($1); } | from_list ',' table_reference { $$ = $1->add($3); } ; %type table_reference table_reference : joined_table | table_primary ; %type table_primary table_primary : table_proc | derived_table { $$ = $1; } | '(' joined_table ')' { $$ = $2; } ; %type derived_table derived_table : '(' select_expr ')' as_noise correlation_name derived_column_list { $$ = $2; $$->dsqlFlags |= RecordSourceNode::DFLAG_DERIVED; if ($5) $$->alias = $5->c_str(); $$->columns = $6; } ; %type correlation_name correlation_name : /* nothing */ { $$ = NULL; } | symbol_table_alias_name ; %type derived_column_list derived_column_list : /* nothing */ { $$ = NULL; } | '(' alias_list ')' { $$ = $2; } ; %type alias_list alias_list : symbol_item_alias_name { ObjectsArray* node = newNode >(); node->add(*$1); $$ = node; } | alias_list ',' symbol_item_alias_name { ObjectsArray* node = $1; node->add(*$3); $$ = node; } ; %type joined_table joined_table : cross_join | natural_join | qualified_join ; %type cross_join cross_join : table_reference CROSS JOIN table_primary { RseNode* rse = newNode(); rse->dsqlExplicitJoin = true; rse->rse_jointype = blr_inner; rse->dsqlFrom = newNode($1)->add($4); $$ = rse; } ; %type natural_join natural_join : table_reference NATURAL join_type JOIN table_primary { RseNode* rse = newNode(); rse->dsqlExplicitJoin = true; rse->rse_jointype = $3; rse->dsqlFrom = newNode($1)->add($5); rse->dsqlJoinUsing = newNode(0u); // using list with size 0 -> natural $$ = rse; } ; %type qualified_join qualified_join : table_reference join_type JOIN table_reference join_condition { RseNode* rse = newNode(); rse->dsqlExplicitJoin = true; rse->rse_jointype = $2; rse->dsqlFrom = newNode($1); rse->dsqlFrom->add($4); rse->dsqlWhere = $5; $$ = rse; } | table_reference join_type JOIN table_reference named_columns_join { RseNode* rse = newNode(); rse->dsqlExplicitJoin = true; rse->rse_jointype = $2; rse->dsqlFrom = newNode($1); rse->dsqlFrom->add($4); rse->dsqlJoinUsing = $5; $$ = rse; } ; %type join_condition join_condition : ON search_condition { $$ = $2; } ; %type named_columns_join named_columns_join : USING '(' column_list ')' { $$ = $3; } ; %type table_proc table_proc : symbol_procedure_name table_proc_inputs as_noise symbol_table_alias_name { ProcedureSourceNode* node = newNode(QualifiedName(*$1)); node->sourceList = $2; node->alias = $4->c_str(); $$ = node; } | symbol_procedure_name table_proc_inputs { ProcedureSourceNode* node = newNode(QualifiedName(*$1)); node->sourceList = $2; $$ = node; } | symbol_package_name '.' symbol_procedure_name table_proc_inputs as_noise symbol_table_alias_name { ProcedureSourceNode* node = newNode( QualifiedName(*$3, *$1)); node->sourceList = $4; node->alias = $6->c_str(); $$ = node; } | symbol_package_name '.' symbol_procedure_name table_proc_inputs { ProcedureSourceNode* node = newNode( QualifiedName(*$3, *$1)); node->sourceList = $4; $$ = node; } ; %type table_proc_inputs table_proc_inputs : /* nothing */ { $$ = NULL; } | '(' value_list ')' { $$ = $2; } ; %type table_name table_name : simple_table_name | symbol_table_name as_noise symbol_table_alias_name { RelationSourceNode* node = newNode(*$1); node->alias = $3->c_str(); $$ = node; } ; %type simple_table_name simple_table_name : symbol_table_name { $$ = newNode(*$1); } ; %type join_type join_type : /* nothing */ { $$ = blr_inner; } | INNER { $$ = blr_inner; } | LEFT outer_noise { $$ = blr_left; } | RIGHT outer_noise { $$ = blr_right; } | FULL outer_noise { $$ = blr_full; } ; outer_noise : | OUTER ; // other clauses in the select expression %type group_clause group_clause : /* nothing */ { $$ = NULL; } | GROUP BY group_by_list { $$ = $3; } ; %type group_by_list group_by_list : group_by_item { $$ = newNode($1); } | group_by_list ',' group_by_item { $$ = $1->add($3); } ; // Except aggregate-functions are all expressions supported in group_by_item, // they are caught inside pass1.cpp %type group_by_item group_by_item : value ; %type having_clause having_clause : /* nothing */ { $$ = NULL; } | HAVING search_condition { $$ = $2; } ; %type where_clause where_clause : /* nothing */ { $$ = NULL; } | WHERE search_condition { $$ = $2; } ; // PLAN clause to specify an access plan for a query %type plan_clause plan_clause : /* nothing */ { $$ = NULL; } | PLAN plan_expression { $$ = $2; } ; %type plan_expression plan_expression : plan_type { $$ = newNode(PlanNode::TYPE_RETRIEVE); } '(' plan_item_list($2) ')' { $$ = $2; } ; plan_type : // nothing | JOIN | SORT MERGE | MERGE | HASH | SORT ; %type plan_item_list() plan_item_list($planNode) : plan_item { $planNode->subNodes.add($1); } | plan_item_list ',' plan_item { $planNode->subNodes.insert(0, $3); } ; %type plan_item plan_item : table_or_alias_list access_type { $$ = newNode(PlanNode::TYPE_RETRIEVE); $$->dsqlNames = $1; $$->accessType = $2; } | plan_expression ; %type table_or_alias_list table_or_alias_list : symbol_table_name { ObjectsArray* node = newNode >(); node->add(*$1); $$ = node; } | table_or_alias_list symbol_table_name { ObjectsArray* node = $1; node->add(*$2); $$ = node; } ; %type access_type access_type : NATURAL { $$ = newNode(PlanNode::AccessType::TYPE_SEQUENTIAL); } | INDEX { $$ = newNode(PlanNode::AccessType::TYPE_INDICES); } '(' index_list($2) ')' { $$ = $2; } | ORDER { $$ = newNode(PlanNode::AccessType::TYPE_NAVIGATIONAL); } symbol_index_name extra_indices_opt($2) { $$ = $2; $$->items.insert(0).indexName = *$3; } ; %type index_list() index_list($accessType) : symbol_index_name { PlanNode::AccessItem& item = $accessType->items.add(); item.indexName = *$1; } | index_list ', ' symbol_index_name { PlanNode::AccessItem& item = $accessType->items.insert(0); item.indexName = *$3; } ; %type extra_indices_opt() extra_indices_opt($accessType) : // nothing | INDEX '(' index_list($accessType) ')' ; // ORDER BY clause %type order_clause order_clause : /* nothing */ { $$ = NULL; } | ORDER BY order_list { $$ = $3; } ; %type order_list order_list : order_item { $$ = newNode($1); } | order_list ',' order_item { $$ = $1->add($3); } ; %type order_item order_item : value order_direction nulls_clause { OrderNode* node = newNode($1); node->descending = $2; node->nullsPlacement = $3; $$ = node; } ; %type order_direction order_direction : /* nothing */ { $$ = false; } | ASC { $$ = false; } | DESC { $$ = true; } ; %type nulls_clause nulls_clause : /* nothing */ { $$ = OrderNode::NULLS_DEFAULT; } | NULLS nulls_placement { $$ = $2; } ; %type nulls_placement nulls_placement : FIRST { $$ = OrderNode::NULLS_FIRST; } | LAST { $$ = OrderNode::NULLS_LAST; } ; // ROWS clause %type rows_clause rows_clause : // nothing { $$ = NULL; } // equivalent to FIRST value | ROWS value { $$ = newNode(); $$->length = $2; } // equivalent to FIRST (upper_value - lower_value + 1) SKIP (lower_value - 1) | ROWS value TO value { $$ = newNode(); $$->skip = newNode(blr_subtract, true, $2, MAKE_const_slong(1)); $$->length = newNode(blr_add, true, newNode(blr_subtract, true, $4, $2), MAKE_const_slong(1)); } ; // INSERT statement // IBO hack: replace column_parens_opt by ins_column_parens_opt. %type insert insert : insert_start ins_column_parens_opt(NOTRIAL(&$1->dsqlFields)) VALUES '(' value_list ')' returning_clause { StoreNode* node = $$ = $1; node->dsqlValues = $5; node->dsqlReturning = $7; } | insert_start ins_column_parens_opt(NOTRIAL(&$1->dsqlFields)) select_expr returning_clause { StoreNode* node = $$ = $1; node->dsqlRse = $3; node->dsqlReturning = $4; $$ = node; } | insert_start DEFAULT VALUES returning_clause { StoreNode* node = $$ = $1; node->dsqlReturning = $4; $$ = node; } ; %type insert_start insert_start : INSERT INTO simple_table_name { StoreNode* node = newNode(); node->dsqlRelation = $3; $$ = node; } ; // MERGE statement %type merge merge : MERGE INTO table_name USING table_reference ON search_condition { MergeNode* node = $$ = newNode(); node->relation = $3; node->usingClause = $5; node->condition = $7; } merge_when_clause($8) returning_clause { MergeNode* node = $$ = $8; node->returning = $10; } ; %type merge_when_clause() merge_when_clause($mergeNode) : merge_when_matched_clause($mergeNode) | merge_when_not_matched_clause($mergeNode) | merge_when_clause merge_when_matched_clause($mergeNode) | merge_when_clause merge_when_not_matched_clause($mergeNode) ; %type merge_when_matched_clause() merge_when_matched_clause($mergeNode) : WHEN MATCHED { $$ = &$mergeNode->whenMatched.add(); } merge_update_specification(NOTRIAL($3)) ; %type merge_when_not_matched_clause() merge_when_not_matched_clause($mergeNode) : WHEN NOT MATCHED { $$ = &$mergeNode->whenNotMatched.add(); } merge_insert_specification(NOTRIAL($4)) ; %type merge_update_specification() merge_update_specification($mergeMatchedClause) : THEN UPDATE SET assignments { $mergeMatchedClause->assignments = $4; } | AND search_condition THEN UPDATE SET assignments { $mergeMatchedClause->condition = $2; $mergeMatchedClause->assignments = $6; } | THEN KW_DELETE | AND search_condition THEN KW_DELETE { $mergeMatchedClause->condition = $2; } ; %type merge_insert_specification() merge_insert_specification($mergeNotMatchedClause) : THEN INSERT ins_column_parens_opt(NOTRIAL(&$mergeNotMatchedClause->fields)) VALUES '(' value_list ')' { $mergeNotMatchedClause->values = $6; } | AND search_condition THEN INSERT ins_column_parens_opt(NOTRIAL(&$mergeNotMatchedClause->fields)) VALUES '(' value_list ')' { $mergeNotMatchedClause->values = $8; $mergeNotMatchedClause->condition = $2; } ; // DELETE statement %type delete delete : delete_searched | delete_positioned ; %type delete_searched delete_searched : KW_DELETE FROM table_name where_clause plan_clause order_clause rows_clause returning_clause { EraseNode* node = newNode(); node->dsqlRelation = $3; node->dsqlBoolean = $4; node->dsqlPlan = $5; node->dsqlOrder = $6; node->dsqlRows = $7; node->dsqlReturning = $8; $$ = node; } ; %type delete_positioned delete_positioned : KW_DELETE FROM table_name cursor_clause returning_clause { EraseNode* node = newNode(); node->dsqlRelation = $3; node->dsqlCursorName = *$4; node->dsqlReturning = $5; $$ = node; } ; // UPDATE statement %type update update : update_searched | update_positioned ; %type update_searched update_searched : UPDATE table_name SET assignments where_clause plan_clause order_clause rows_clause returning_clause { ModifyNode* node = newNode(); node->dsqlRelation = $2; node->statement = $4; node->dsqlBoolean = $5; node->dsqlPlan = $6; node->dsqlOrder = $7; node->dsqlRows = $8; node->dsqlReturning = $9; $$ = node; } ; %type update_positioned update_positioned : UPDATE table_name SET assignments cursor_clause returning_clause { ModifyNode* node = newNode(); node->dsqlRelation = $2; node->statement = $4; node->dsqlCursorName = *$5; node->dsqlReturning = $6; $$ = node; } ; // UPDATE OR INSERT statement %type update_or_insert update_or_insert : UPDATE OR INSERT INTO simple_table_name { UpdateOrInsertNode* node = $$ = newNode(); node->relation = $5; } ins_column_parens_opt(NOTRIAL(&$6->fields)) VALUES '(' value_list ')' update_or_insert_matching_opt(NOTRIAL(&$6->matching)) returning_clause { UpdateOrInsertNode* node = $$ = $6; node->values = $10; node->returning = $13; } ; %type update_or_insert_matching_opt() update_or_insert_matching_opt($fieldArray) : // nothing | MATCHING ins_column_parens($fieldArray) ; %type returning_clause returning_clause : /* nothing */ { $$ = NULL; } | RETURNING value_opt_alias_list { $$ = FB_NEW(getPool()) ReturningClause(getPool()); $$->first = $2; } | RETURNING value_opt_alias_list INTO variable_list { $$ = FB_NEW(getPool()) ReturningClause(getPool()); $$->first = $2; $$->second = $4; } ; %type value_opt_alias_list value_opt_alias_list : value_opt_alias { $$ = newNode($1); } | value_opt_alias_list ',' value_opt_alias { $$ = $1->add($3); } ; %type cursor_clause cursor_clause : WHERE CURRENT OF symbol_cursor_name { $$ = newNode(*$4); } ; // Assignments %type assignments assignments : assignment { $$ = newNode(); $$->statements.add($1); } | assignments ',' assignment { $1->statements.add($3); $$ = $1; } ; %type assignment assignment : update_column_name '=' value { AssignmentNode* node = newNode(); node->asgnTo = $1; node->asgnFrom = $3; $$ = node; } ; %type exec_function exec_function : udf { AssignmentNode* node = newNode(); node->asgnTo = newNode(); node->asgnFrom = $1; $$ = node; } | non_aggregate_function { AssignmentNode* node = newNode(); node->asgnTo = newNode(); node->asgnFrom = $1; $$ = node; } ; // column specifications %type column_parens_opt column_parens_opt : /* nothing */ { $$ = NULL; } | column_parens ; %type column_parens column_parens : '(' column_list ')' { $$ = $2; } ; %type column_list column_list : simple_column_name { $$ = newNode($1); } | column_list ',' simple_column_name { $$ = $1->add($3); } ; // begin IBO hack %type ins_column_parens_opt() ins_column_parens_opt($fieldArray) : // nothing | ins_column_parens($fieldArray) ; %type ins_column_parens() ins_column_parens($fieldArray) : '(' ins_column_list($fieldArray) ')' ; %type ins_column_list() ins_column_list($fieldArray) : update_column_name { $fieldArray->add($1); } | ins_column_list ',' update_column_name { $fieldArray->add($3); } ; // end IBO hack %type column_name column_name : simple_column_name | symbol_table_alias_name '.' symbol_column_name { FieldNode* fieldNode = newNode(); fieldNode->dsqlQualifier = *$1; fieldNode->dsqlName = *$3; $$ = fieldNode; } ; %type simple_column_name simple_column_name : symbol_column_name { FieldNode* fieldNode = newNode(); fieldNode->dsqlName = *$1; $$ = fieldNode; } ; %type update_column_name update_column_name : simple_column_name // CVC: This option should be deprecated! The only allowed syntax should be // Update...set column = expr, without qualifier for the column. | symbol_table_alias_name '.' symbol_column_name { FieldNode* fieldNode = newNode(); fieldNode->dsqlQualifier = *$1; fieldNode->dsqlName = *$3; $$ = fieldNode; } ; // boolean expressions %type search_condition search_condition : value { $$ = valueToBool($1); } ; %type boolean_value_expression boolean_value_expression : predicate | value OR value { $$ = newNode(blr_or, valueToBool($1), valueToBool($3)); } | value AND value { $$ = newNode(blr_and, valueToBool($1), valueToBool($3)); } | NOT value { $$ = newNode(valueToBool($2)); } | '(' boolean_value_expression ')' { $$ = $2; } | value IS boolean_literal { $$ = newNode(blr_equiv, newNode(valueToBool($1)), $3); } | value IS NOT boolean_literal { ComparativeBoolNode* node = newNode(blr_equiv, newNode(valueToBool($1)), $4); $$ = newNode(node); } ; %type predicate predicate : comparison_predicate | distinct_predicate | between_predicate | binary_pattern_predicate | ternary_pattern_predicate | in_predicate | null_predicate | quantified_predicate | exists_predicate | singular_predicate ; // comparisons %type comparison_predicate comparison_predicate : value comparison_operator value %prec '=' { $$ = newNode($2, $1, $3); } ; %type comparison_operator comparison_operator : '=' { $$ = blr_eql; } | '<' { $$ = blr_lss; } | '>' { $$ = blr_gtr; } | GEQ { $$ = blr_geq; } | LEQ { $$ = blr_leq; } | NOT_GTR { $$ = blr_leq; } | NOT_LSS { $$ = blr_geq; } | NEQ { $$ = blr_neq; } // quantified comparisons %type quantified_predicate quantified_predicate : value comparison_operator quantified_flag '(' column_select ')' { ComparativeBoolNode* node = newNode($2, $1); node->dsqlFlag = $3; node->dsqlSpecialArg = $5; $$ = node; } ; %type quantified_flag quantified_flag : ALL { $$ = ComparativeBoolNode::DFLAG_ANSI_ALL; } | SOME { $$ = ComparativeBoolNode::DFLAG_ANSI_ANY; } | ANY { $$ = ComparativeBoolNode::DFLAG_ANSI_ANY; } ; // other predicates %type distinct_predicate distinct_predicate : value IS DISTINCT FROM value %prec IS { ComparativeBoolNode* node = newNode(blr_equiv, $1, $5); $$ = newNode(node); } | value IS NOT DISTINCT FROM value %prec IS { $$ = newNode(blr_equiv, $1, $6); } ; %type between_predicate between_predicate : value BETWEEN value_between AND value_between %prec BETWEEN { $$ = newNode(blr_between, $1, $3, $5); } | value NOT BETWEEN value_between AND value_between %prec BETWEEN { ComparativeBoolNode* node = newNode(blr_between, $1, $4, $6); $$ = newNode(node); } ; // Special value for BETWEEN, to avoid conflicts with boolean expressions. %type value_between value_between : value_primary | '(' boolean_value_expression ')' { $$ = newNode($2); } ; %type binary_pattern_predicate binary_pattern_predicate : value binary_pattern_operator value %prec CONTAINING { $$ = newNode($2, $1, $3); } | value NOT binary_pattern_operator value %prec CONTAINING { ComparativeBoolNode* cmpNode = newNode($3, $1, $4); $$ = newNode(cmpNode); } ; %type binary_pattern_operator binary_pattern_operator : CONTAINING { $$ = blr_containing; } | STARTING { $$ = blr_starting; } | STARTING WITH { $$ = blr_starting; } ; %type ternary_pattern_predicate ternary_pattern_predicate : value LIKE value %prec LIKE { $$ = newNode(blr_like, $1, $3); } | value LIKE value ESCAPE value %prec LIKE { $$ = newNode(blr_like, $1, $3, $5); } | value NOT LIKE value %prec LIKE { ComparativeBoolNode* node = newNode(blr_like, $1, $4); $$ = newNode(node); } | value NOT LIKE value ESCAPE value %prec LIKE { ComparativeBoolNode* node = newNode(blr_like, $1, $4, $6); $$ = newNode(node); } | value SIMILAR TO value %prec SIMILAR { $$ = newNode(blr_similar, $1, $4); } | value SIMILAR TO value ESCAPE value %prec SIMILAR { $$ = newNode(blr_similar, $1, $4, $6); } | value NOT SIMILAR TO value %prec SIMILAR { ComparativeBoolNode* node = newNode(blr_similar, $1, $5); $$ = newNode(node); } | value NOT SIMILAR TO value ESCAPE value %prec SIMILAR { ComparativeBoolNode* node = newNode(blr_similar, $1, $5, $7); $$ = newNode(node); } ; %type in_predicate in_predicate : value KW_IN in_predicate_value { ComparativeBoolNode* node = newNode(blr_eql, $1); node->dsqlFlag = ComparativeBoolNode::DFLAG_ANSI_ANY; node->dsqlSpecialArg = $3; $$ = node; } | value NOT KW_IN in_predicate_value { ComparativeBoolNode* node = newNode(blr_eql, $1); node->dsqlFlag = ComparativeBoolNode::DFLAG_ANSI_ANY; node->dsqlSpecialArg = $4; $$ = newNode(node); } ; %type exists_predicate exists_predicate : EXISTS '(' select_expr ')' { $$ = newNode(blr_any, $3); } ; %type singular_predicate singular_predicate : SINGULAR '(' select_expr ')' { $$ = newNode(blr_unique, $3); } ; %type null_predicate null_predicate : value IS KW_NULL { $$ = newNode($1); } | value IS UNKNOWN { $$ = newNode($1, true); } | value IS NOT KW_NULL { $$ = newNode(newNode($1)); } | value IS NOT UNKNOWN { $$ = newNode(newNode($1, true)); } ; // set values %type in_predicate_value in_predicate_value : table_subquery { $$ = $1; } | '(' value_list ')' { $$ = $2; } ; %type table_subquery table_subquery : '(' column_select ')' { $$ = $2; } ; // USER control SQL interface %type create_user_clause create_user_clause : symbol_user_name passwd_clause { $$ = newNode(CreateAlterUserNode::USER_ADD, *$1); $$->password = $2; } user_fixed_opts(NOTRIAL($3)) user_var_opts(NOTRIAL($3)) { $$ = $3; } ; %type alter_user_clause alter_user_clause : symbol_user_name set_noise passwd_opt { $$ = newNode(CreateAlterUserNode::USER_MOD, *$1); $$->password = $3; } user_fixed_opts(NOTRIAL($4)) user_var_opts(NOTRIAL($4)) { $$ = $4; } ; %type alter_cur_user_clause alter_cur_user_clause : set_noise passwd_opt { $$ = newNode(CreateAlterUserNode::USER_MOD, ""); $$->password = $2; } user_fixed_opts(NOTRIAL($3)) user_var_opts(NOTRIAL($3)) { $$ = $3; } ; %type replace_user_clause replace_user_clause : symbol_user_name set_noise passwd_opt { $$ = newNode(CreateAlterUserNode::USER_RPL, *$1); $$->password = $3; } user_fixed_opts(NOTRIAL($4)) user_var_opts(NOTRIAL($4)) { $$ = $4; } ; set_noise : // nothing | SET ; %type passwd_opt passwd_opt : /* nothing */ { $$ = NULL; } | passwd_clause ; %type passwd_clause passwd_clause : PASSWORD utf_string { $$ = $2; } ; %type user_fixed_opts() user_fixed_opts($node) : // nothing | user_fixed_list($node) ; %type user_fixed_list() user_fixed_list($node) : user_fixed_opt($node) | user_fixed_list user_fixed_opt($node) ; %type user_fixed_opt() user_fixed_opt($node) : FIRSTNAME utf_string { setClause($node->firstName, "FIRSTNAME", $2); } | MIDDLENAME utf_string { setClause($node->middleName, "MIDDLENAME", $2); } | LASTNAME utf_string { setClause($node->lastName, "LASTNAME", $2); } | GRANT ADMIN ROLE { setClause($node->adminRole, "ADMIN ROLE", Nullable(true)); } | REVOKE ADMIN ROLE { setClause($node->adminRole, "ADMIN ROLE", Nullable(false)); } | ACTIVE { setClause($node->active, "ACTIVE/INACTIVE", Nullable(true)); } | INACTIVE { setClause($node->active, "ACTIVE/INACTIVE", Nullable(false)); } ; %type user_var_opts() user_var_opts($node) : // nothing | TAGS '(' user_var_list($node) ')' ; %type user_var_list() user_var_list($node) : user_var_option($node) | user_var_list ',' user_var_option($node) ; %type user_var_option() user_var_option($node) : valid_symbol_name '=' utf_string { $node->addProperty($1, $3); } | DROP valid_symbol_name { $node->addProperty($2); } ; // value types %type value value : value_primary | boolean_value_expression { $$ = newNode($1); } ; %type value_primary value_primary : nonparenthesized_value | '(' value_primary ')' { $$ = $2; } ; %type nonparenthesized_value nonparenthesized_value : column_name { $$ = $1; } | array_element | function { $$ = $1; } | u_constant | boolean_literal | parameter | variable | cast_specification | case_expression | next_value_expression { $$ = $1; } | udf { $$ = $1; } | '-' value_primary %prec UMINUS { $$ = newNode($2); } | '+' value_primary %prec UPLUS { $$ = $2; } | value_primary '+' value_primary { $$ = newNode(blr_add, (client_dialect < SQL_DIALECT_V6_TRANSITION), $1, $3); } | value_primary CONCATENATE value_primary { $$ = newNode($1, $3); } | value_primary COLLATE symbol_collation_name { $$ = newNode($1, *$3); } | value_primary '-' value_primary { $$ = newNode(blr_subtract, (client_dialect < SQL_DIALECT_V6_TRANSITION), $1, $3); } | value_primary '*' value_primary { $$ = newNode(blr_multiply, (client_dialect < SQL_DIALECT_V6_TRANSITION), $1, $3); } | value_primary '/' value_primary { $$ = newNode(blr_divide, (client_dialect < SQL_DIALECT_V6_TRANSITION), $1, $3); } | '(' column_singleton ')' { $$ = $2; } | current_user { $$ = $1; } | current_role { $$ = $1; } | internal_info { $$ = $1; } | recordKeyType { $$ = newNode($1); } | symbol_table_alias_name '.' recordKeyType { $$ = newNode($3, *$1); } | KW_VALUE { $$ = newNode(); } | datetime_value_expression { $$ = $1; } | null_value { $$ = $1; } ; %type recordKeyType recordKeyType : DB_KEY { $$ = blr_dbkey; } | RDB_RECORD_VERSION { $$ = blr_record_version2; } ; %type datetime_value_expression datetime_value_expression : CURRENT_DATE { if (client_dialect < SQL_DIALECT_V6_TRANSITION) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_sql_dialect_datatype_unsupport) << Arg::Num(client_dialect) << Arg::Str("DATE")); } if (db_dialect < SQL_DIALECT_V6_TRANSITION) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_sql_db_dialect_dtype_unsupport) << Arg::Num(db_dialect) << Arg::Str("DATE")); } $$ = newNode(); } | CURRENT_TIME time_precision_opt { if (client_dialect < SQL_DIALECT_V6_TRANSITION) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_sql_dialect_datatype_unsupport) << Arg::Num(client_dialect) << Arg::Str("TIME")); } if (db_dialect < SQL_DIALECT_V6_TRANSITION) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_sql_db_dialect_dtype_unsupport) << Arg::Num(db_dialect) << Arg::Str("TIME")); } $$ = newNode($2); } | CURRENT_TIMESTAMP timestamp_precision_opt { $$ = newNode($2); } ; %type time_precision_opt time_precision_opt : /* nothing */ { $$ = DEFAULT_TIME_PRECISION; } | '(' nonneg_short_integer ')' { $$ = $2; } ; %type timestamp_precision_opt timestamp_precision_opt : /* nothing */ { $$ = DEFAULT_TIMESTAMP_PRECISION; } | '(' nonneg_short_integer ')' { $$ = $2; } ; %type array_element array_element : column_name '[' value_list ']' { ArrayNode* node = newNode($1); node->field->dsqlIndices = $3; $$ = node; } ; %type value_list_opt value_list_opt : /* nothing */ { $$ = newNode(0); } | value_list { $$ = $1; } ; %type value_list value_list : value { $$ = newNode($1); } | value_list ',' value { $$ = $1->add($3); } ; %type constant constant : u_constant | '-' u_numeric_constant { $$ = newNode($2); } | boolean_literal ; %type u_numeric_constant u_numeric_constant : NUMBER { $$ = MAKE_const_slong($1); } | FLOAT_NUMBER { $$ = MAKE_constant($1->c_str(), CONSTANT_DOUBLE); } | NUMBER64BIT { SINT64 signedNumber = (SINT64) $1.number; if ($1.hex && signedNumber < 0) $$ = newNode(MAKE_const_sint64(-signedNumber, $1.scale)); else $$ = MAKE_const_sint64(signedNumber, $1.scale); } | SCALEDINT { $$ = MAKE_const_sint64((SINT64) $1.number, $1.scale); } ; %type u_constant u_constant : u_numeric_constant | sql_string { $$ = MAKE_str_constant($1, lex.att_charset); } | DATE STRING { if (client_dialect < SQL_DIALECT_V6_TRANSITION) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_sql_dialect_datatype_unsupport) << Arg::Num(client_dialect) << Arg::Str("DATE")); } if (db_dialect < SQL_DIALECT_V6_TRANSITION) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_sql_db_dialect_dtype_unsupport) << Arg::Num(db_dialect) << Arg::Str("DATE")); } $$ = MAKE_constant($2->getString().c_str(), CONSTANT_DATE); } | TIME STRING { if (client_dialect < SQL_DIALECT_V6_TRANSITION) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_sql_dialect_datatype_unsupport) << Arg::Num(client_dialect) << Arg::Str("TIME")); } if (db_dialect < SQL_DIALECT_V6_TRANSITION) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_sql_db_dialect_dtype_unsupport) << Arg::Num(db_dialect) << Arg::Str("TIME")); } $$ = MAKE_constant($2->getString().c_str(), CONSTANT_TIME); } | TIMESTAMP STRING { $$ = MAKE_constant($2->getString().c_str(), CONSTANT_TIMESTAMP); } ; %type boolean_literal boolean_literal : KW_FALSE { $$ = MAKE_constant("", CONSTANT_BOOLEAN); } | KW_TRUE { $$ = MAKE_constant("1", CONSTANT_BOOLEAN); } ; %type parameter parameter : '?' { $$ = make_parameter(); } ; %type current_user current_user : USER { $$ = newNode(); } | CURRENT_USER { $$ = newNode(); } ; %type current_role current_role : CURRENT_ROLE { $$ = newNode(); } ; %type internal_info internal_info : CURRENT_CONNECTION { $$ = newNode(MAKE_const_slong(INFO_TYPE_CONNECTION_ID)); } | CURRENT_TRANSACTION { $$ = newNode(MAKE_const_slong(INFO_TYPE_TRANSACTION_ID)); } | GDSCODE { $$ = newNode(MAKE_const_slong(INFO_TYPE_GDSCODE)); } | SQLCODE { $$ = newNode(MAKE_const_slong(INFO_TYPE_SQLCODE)); } | SQLSTATE { $$ = newNode(MAKE_const_slong(INFO_TYPE_SQLSTATE)); } | ROW_COUNT { $$ = newNode(MAKE_const_slong(INFO_TYPE_ROWS_AFFECTED)); } ; %type sql_string sql_string : STRING // string in current charset | INTRODUCER STRING // string in specific charset { $$ = $2; $$->setCharSet(*$1); StrMark* mark = strMarks.get($2); if (mark) // hex string is not in strMarks mark->introduced = true; } ; %type utf_string utf_string : sql_string { $$ = newString($1->toUtf8(scratch)); } ; %type signed_short_integer signed_short_integer : nonneg_short_integer | '-' neg_short_integer { $$ = -$2; } ; %type nonneg_short_integer nonneg_short_integer : NUMBER { if ($1 > SHRT_POS_MAX) yyabandon(-842, isc_expec_short); // Short integer expected $$ = $1; } ; %type neg_short_integer neg_short_integer : NUMBER { if ($1 > SHRT_NEG_MAX) yyabandon(-842, isc_expec_short); // Short integer expected $$ = $1; } ; %type pos_short_integer pos_short_integer : nonneg_short_integer { if ($1 == 0) yyabandon(-842, isc_expec_positive); // Positive number expected $$ = $1; } ; %type unsigned_short_integer unsigned_short_integer : NUMBER { if ($1 > SHRT_UNSIGNED_MAX) yyabandon(-842, isc_expec_ushort); // Unsigned short integer expected $$ = $1; } ; %type signed_long_integer signed_long_integer : long_integer | '-' long_integer { $$ = -$2; } ; %type long_integer long_integer : NUMBER { $$ = $1;} ; // functions %type function function : aggregate_function { $$ = $1; } | non_aggregate_function | over_clause ; %type non_aggregate_function non_aggregate_function : numeric_value_function | string_value_function | system_function_expression ; %type aggregate_function aggregate_function : COUNT '(' '*' ')' { $$ = newNode(false, (client_dialect < SQL_DIALECT_V6_TRANSITION)); } | COUNT '(' all_noise value ')' { $$ = newNode(false, (client_dialect < SQL_DIALECT_V6_TRANSITION), $4); } | COUNT '(' DISTINCT value ')' { $$ = newNode(true, (client_dialect < SQL_DIALECT_V6_TRANSITION), $4); } | SUM '(' all_noise value ')' { $$ = newNode(false, (client_dialect < SQL_DIALECT_V6_TRANSITION), $4); } | SUM '(' DISTINCT value ')' { $$ = newNode(true, (client_dialect < SQL_DIALECT_V6_TRANSITION), $4); } | AVG '(' all_noise value ')' { $$ = newNode(false, (client_dialect < SQL_DIALECT_V6_TRANSITION), $4); } | AVG '(' DISTINCT value ')' { $$ = newNode(true, (client_dialect < SQL_DIALECT_V6_TRANSITION), $4); } | MINIMUM '(' all_noise value ')' { $$ = newNode(MaxMinAggNode::TYPE_MIN, $4); } | MINIMUM '(' DISTINCT value ')' { $$ = newNode(MaxMinAggNode::TYPE_MIN, $4); } | MAXIMUM '(' all_noise value ')' { $$ = newNode(MaxMinAggNode::TYPE_MAX, $4); } | MAXIMUM '(' DISTINCT value ')' { $$ = newNode(MaxMinAggNode::TYPE_MAX, $4); } | LIST '(' all_noise value delimiter_opt ')' { $$ = newNode(false, $4, $5); } | LIST '(' DISTINCT value delimiter_opt ')' { $$ = newNode(true, $4, $5); } ; %type window_function window_function : DENSE_RANK '(' ')' { $$ = newNode(); } | RANK '(' ')' { $$ = newNode(); } | ROW_NUMBER '(' ')' { $$ = newNode(); } | FIRST_VALUE '(' value ')' { $$ = newNode($3); } | LAST_VALUE '(' value ')' { $$ = newNode($3); } | NTH_VALUE '(' value ',' value ')' nth_from { $$ = newNode($3, $5, $7); } | LAG '(' value ',' value ',' value ')' { $$ = newNode($3, $5, $7); } | LAG '(' value ',' value ')' { $$ = newNode($3, $5, newNode()); } | LAG '(' value ')' { $$ = newNode($3, MAKE_const_slong(1), newNode()); } | LEAD '(' value ',' value ',' value ')' { $$ = newNode($3, $5, $7); } | LEAD '(' value ',' value ')' { $$ = newNode($3, $5, newNode()); } | LEAD '(' value ')' { $$ = newNode($3, MAKE_const_slong(1), newNode()); } ; %type nth_from nth_from : /* nothing */ { $$ = MAKE_const_slong(NthValueWinNode::FROM_FIRST); } | FROM FIRST { $$ = MAKE_const_slong(NthValueWinNode::FROM_FIRST); } | FROM LAST { $$ = MAKE_const_slong(NthValueWinNode::FROM_LAST); } ; %type aggregate_window_function aggregate_window_function : aggregate_function | window_function ; %type over_clause over_clause : aggregate_window_function OVER '(' window_partition_opt order_clause ')' { $$ = newNode($1, $4, $5); } ; %type window_partition_opt window_partition_opt : /* nothing */ { $$ = NULL; } | PARTITION BY value_list { $$ = $3; } ; %type delimiter_opt delimiter_opt : /* nothing */ { $$ = MAKE_str_constant(newIntlString(","), lex.att_charset); } | ',' value { $$ = $2; } ; %type numeric_value_function numeric_value_function : extract_expression | length_expression ; %type extract_expression extract_expression : EXTRACT '(' timestamp_part FROM value ')' { $$ = newNode($3, $5); } ; %type length_expression length_expression : bit_length_expression | char_length_expression | octet_length_expression ; %type bit_length_expression bit_length_expression : BIT_LENGTH '(' value ')' { $$ = newNode(blr_strlen_bit, $3); } ; %type char_length_expression char_length_expression : CHAR_LENGTH '(' value ')' { $$ = newNode(blr_strlen_char, $3); } | CHARACTER_LENGTH '(' value ')' { $$ = newNode(blr_strlen_char, $3); } ; %type octet_length_expression octet_length_expression : OCTET_LENGTH '(' value ')' { $$ = newNode(blr_strlen_octet, $3); } ; %type system_function_expression system_function_expression : system_function_std_syntax '(' value_list_opt ')' { $$ = newNode(*$1, $3); } | system_function_special_syntax { $$ = $1; } ; %type system_function_std_syntax system_function_std_syntax : ABS | ACOS | ACOSH | ASCII_CHAR | ASCII_VAL | ASIN | ASINH | ATAN | ATAN2 | ATANH | BIN_AND | BIN_NOT | BIN_OR | BIN_SHL | BIN_SHR | BIN_XOR | CEIL | CHAR_TO_UUID | COS | COSH | COT | EXP | FLOOR | GEN_UUID | HASH | LEFT | LN | LOG | LOG10 | LPAD | MAXVALUE | MINVALUE | MOD | PI | POWER | RAND | RDB_GET_CONTEXT | RDB_SET_CONTEXT | REPLACE | REVERSE | RIGHT | ROUND | RPAD | SIGN | SIN | SINH | SQRT | TAN | TANH | TRUNC | UUID_TO_CHAR ; %type system_function_special_syntax system_function_special_syntax : DATEADD '(' value timestamp_part TO value ')' { $$ = newNode(*$1, newNode($3)->add(MAKE_const_slong($4))->add($6)); $$->dsqlSpecialSyntax = true; } | DATEADD '(' timestamp_part ',' value ',' value ')' { $$ = newNode(*$1, newNode($5)->add(MAKE_const_slong($3))->add($7)); $$->dsqlSpecialSyntax = true; } | DATEDIFF '(' timestamp_part FROM value TO value ')' { $$ = newNode(*$1, newNode(MAKE_const_slong($3))->add($5)->add($7)); $$->dsqlSpecialSyntax = true; } | DATEDIFF '(' timestamp_part ',' value ',' value ')' { $$ = newNode(*$1, newNode(MAKE_const_slong($3))->add($5)->add($7)); $$->dsqlSpecialSyntax = true; } | OVERLAY '(' value PLACING value FROM value FOR value ')' { $$ = newNode(*$1, newNode($3)->add($5)->add($7)->add($9)); $$->dsqlSpecialSyntax = true; } | OVERLAY '(' value PLACING value FROM value ')' { $$ = newNode(*$1, newNode($3)->add($5)->add($7)); $$->dsqlSpecialSyntax = true; } | POSITION '(' value KW_IN value ')' { $$ = newNode(*$1, newNode($3)->add($5)); $$->dsqlSpecialSyntax = true; } | POSITION '(' value_list_opt ')' { $$ = newNode(*$1, $3); } ; %type string_value_function string_value_function : substring_function | trim_function | KW_UPPER '(' value ')' { $$ = newNode(blr_upcase, $3); } | KW_LOWER '(' value ')' { $$ = newNode(blr_lowcase, $3); } ; %type substring_function substring_function : SUBSTRING '(' value FROM value string_length_opt ')' { // SQL spec requires numbering to start with 1, // hence we decrement the first parameter to make it // compatible with the engine's implementation ArithmeticNode* subtractNode = newNode( blr_subtract, true, $5, MAKE_const_slong(1)); $$ = newNode($3, subtractNode, $6); } | SUBSTRING '(' value SIMILAR value ESCAPE value ')' { $$ = newNode($3, $5, $7); } ; %type string_length_opt string_length_opt : /* nothing */ { $$ = NULL; } | FOR value { $$ = $2; } ; %type trim_function trim_function : TRIM '(' trim_specification value FROM value ')' { $$ = newNode($3, $6, $4); } | TRIM '(' value FROM value ')' { $$ = newNode(blr_trim_both, $5, $3); } | TRIM '(' trim_specification FROM value ')' { $$ = newNode($3, $5); } | TRIM '(' value ')' { $$ = newNode(blr_trim_both, $3); } ; %type trim_specification trim_specification : BOTH { $$ = blr_trim_both; } | TRAILING { $$ = blr_trim_trailing; } | LEADING { $$ = blr_trim_leading; } ; %type udf udf : symbol_UDF_call_name '(' value_list ')' { $$ = newNode(QualifiedName(*$1, ""), $3); } | symbol_UDF_call_name '(' ')' { $$ = newNode(QualifiedName(*$1, ""), newNode(0)); } | symbol_package_name '.' symbol_UDF_name '(' value_list ')' { $$ = newNode(QualifiedName(*$3, *$1), $5); } | symbol_package_name '.' symbol_UDF_name '(' ')' { $$ = newNode(QualifiedName(*$3, *$1), newNode(0)); } ; %type cast_specification cast_specification : CAST '(' value AS data_type_descriptor ')' { $$ = newNode($3, $5); } ; // case expressions %type case_expression case_expression : case_abbreviation | case_specification ; %type case_abbreviation case_abbreviation : NULLIF '(' value ',' value ')' { ComparativeBoolNode* condition = newNode(blr_eql, $3, $5); $$ = newNode(condition, newNode(), $3); } | IIF '(' search_condition ',' value ',' value ')' { $$ = newNode($3, $5, $7); } | COALESCE '(' value ',' value_list ')' { $$ = newNode($5->addFront($3)); } | DECODE '(' value ',' decode_pairs ')' { ValueListNode* list = $5; ValueListNode* conditions = newNode(list->items.getCount() / 2); ValueListNode* values = newNode(list->items.getCount() / 2); for (size_t i = 0; i < list->items.getCount(); i += 2) { conditions->items[i / 2] = list->items[i]; values->items[i / 2] = list->items[i + 1]; } $$ = newNode($3, conditions, values); } | DECODE '(' value ',' decode_pairs ',' value ')' { ValueListNode* list = $5; ValueListNode* conditions = newNode(list->items.getCount() / 2); ValueListNode* values = newNode(list->items.getCount() / 2 + 1); for (size_t i = 0; i < list->items.getCount(); i += 2) { conditions->items[i / 2] = list->items[i]; values->items[i / 2] = list->items[i + 1]; } values->items[list->items.getCount() / 2] = $7; $$ = newNode($3, conditions, values); } ; %type case_specification case_specification : simple_case { $$ = $1; } | searched_case { $$ = $1; } ; %type simple_case simple_case : CASE case_operand { $$ = newNode($2, newNode(0u), newNode(0u)); } simple_when_clause(NOTRIAL($3->conditions), NOTRIAL($3->values)) else_case_result_opt END { DecodeNode* node = $$ = $3; node->label = "CASE"; if ($5) node->values->add($5); } ; %type simple_when_clause(, ) simple_when_clause($conditions, $values) : WHEN when_operand THEN case_result { $conditions->add($2); $values->add($4); } | simple_when_clause WHEN when_operand THEN case_result { $conditions->add($3); $values->add($5); } ; %type else_case_result_opt else_case_result_opt : /* nothing */ { $$ = NULL; } | ELSE case_result { $$ = $2; } %type searched_case searched_case : CASE searched_when_clause END { $$ = $2; } | CASE searched_when_clause ELSE case_result END { ValueIfNode* last = $2; ValueIfNode* next; while ((next = last->falseValue->as())) last = next; fb_assert(last->falseValue->is()); last->falseValue = $4; $$ = $2; } ; %type searched_when_clause searched_when_clause : WHEN search_condition THEN case_result { $$ = newNode($2, $4, newNode()); } | searched_when_clause WHEN search_condition THEN case_result { ValueIfNode* cond = newNode($3, $5, newNode()); ValueIfNode* last = $1; ValueIfNode* next; while ((next = last->falseValue->as())) last = next; fb_assert(last->falseValue->is()); last->falseValue = cond; $$ = $1; } ; %type when_operand when_operand : value ; %type case_operand case_operand : value ; %type case_result case_result : value ; %type decode_pairs decode_pairs : value ',' value { $$ = newNode(0u)->add($1)->add($3); } | decode_pairs ',' value ',' value { $$ = $1->add($3)->add($5); } ; // next value expression %type next_value_expression next_value_expression : NEXT KW_VALUE FOR symbol_generator_name { $$ = newNode((client_dialect < SQL_DIALECT_V6_TRANSITION), *$4, MAKE_const_slong(1)); } | GEN_ID '(' symbol_generator_name ',' value ')' { $$ = newNode((client_dialect < SQL_DIALECT_V6_TRANSITION), *$3, $5); } ; %type timestamp_part timestamp_part : YEAR { $$ = blr_extract_year; } | MONTH { $$ = blr_extract_month; } | DAY { $$ = blr_extract_day; } | HOUR { $$ = blr_extract_hour; } | MINUTE { $$ = blr_extract_minute; } | SECOND { $$ = blr_extract_second; } | MILLISECOND { $$ = blr_extract_millisecond; } | WEEK { $$ = blr_extract_week; } | WEEKDAY { $$ = blr_extract_weekday; } | YEARDAY { $$ = blr_extract_yearday; } ; all_noise : | ALL ; distinct_noise : | DISTINCT ; %type null_value null_value : KW_NULL { $$ = newNode(); } | UNKNOWN { dsql_fld* field = newNode(); field->dtype = dtype_boolean; field->length = sizeof(UCHAR); CastNode* castNode = newNode(newNode(), field); castNode->dsqlAlias = "CONSTANT"; $$ = castNode; } ; // Performs special mapping of keywords into symbols %type symbol_UDF_call_name symbol_UDF_call_name : SYMBOL ; %type symbol_UDF_name symbol_UDF_name : valid_symbol_name ; %type symbol_blob_subtype_name symbol_blob_subtype_name : valid_symbol_name ; %type symbol_character_set_name symbol_character_set_name : valid_symbol_name ; %type symbol_collation_name symbol_collation_name : valid_symbol_name ; %type symbol_column_name symbol_column_name : valid_symbol_name ; %type symbol_constraint_name symbol_constraint_name : valid_symbol_name ; %type symbol_cursor_name symbol_cursor_name : valid_symbol_name ; %type symbol_domain_name symbol_domain_name : valid_symbol_name ; %type symbol_exception_name symbol_exception_name : valid_symbol_name ; %type symbol_filter_name symbol_filter_name : valid_symbol_name ; %type symbol_gdscode_name symbol_gdscode_name : valid_symbol_name ; %type symbol_generator_name symbol_generator_name : valid_symbol_name ; %type symbol_index_name symbol_index_name : valid_symbol_name ; %type symbol_item_alias_name symbol_item_alias_name : valid_symbol_name ; %type symbol_label_name symbol_label_name : valid_symbol_name ; %type symbol_ddl_name symbol_ddl_name : valid_symbol_name ; %type symbol_procedure_name symbol_procedure_name : valid_symbol_name ; %type symbol_role_name symbol_role_name : valid_symbol_name ; %type symbol_table_alias_name symbol_table_alias_name : valid_symbol_name ; %type symbol_table_name symbol_table_name : valid_symbol_name ; %type symbol_trigger_name symbol_trigger_name : valid_symbol_name ; %type symbol_user_name symbol_user_name : valid_symbol_name ; %type symbol_variable_name symbol_variable_name : valid_symbol_name ; %type symbol_view_name symbol_view_name : valid_symbol_name ; %type symbol_savepoint_name symbol_savepoint_name : valid_symbol_name ; %type symbol_package_name symbol_package_name : valid_symbol_name ; // symbols %type valid_symbol_name valid_symbol_name : SYMBOL | non_reserved_word ; // list of non-reserved words %type non_reserved_word non_reserved_word : ACTION // added in IB 5.0/ | CASCADE | FREE_IT | RESTRICT | ROLE | KW_TYPE // added in IB 6.0 | KW_BREAK // added in FB 1.0 | KW_DESCRIPTOR | SUBSTRING | COALESCE // added in FB 1.5 | LAST | LEAVE | LOCK | NULLIF | NULLS | STATEMENT | INSERTING | UPDATING | DELETING | FIRST | SKIP | BLOCK // added in FB 2.0 | BACKUP | KW_DIFFERENCE | IIF | SCALAR_ARRAY | WEEKDAY | YEARDAY | SEQUENCE | NEXT | RESTART | COLLATION | RETURNING | KW_IGNORE | LIMBO | UNDO | REQUESTS | TIMEOUT | ABS // added in FB 2.1 | ACCENT | ACOS | ALWAYS | ASCII_CHAR | ASCII_VAL | ASIN | ATAN | ATAN2 | BIN_AND | BIN_OR | BIN_SHL | BIN_SHR | BIN_XOR | CEIL | COS | COSH | COT | DATEADD | DATEDIFF | DECODE | EXP | FLOOR | GEN_UUID | GENERATED | HASH | LIST | LN | LOG | LOG10 | LPAD | MATCHED | MATCHING | MAXVALUE | MILLISECOND | MINVALUE | MOD | OVERLAY | PAD | PI | PLACING | POWER | PRESERVE | RAND | REPLACE | REVERSE | ROUND | RPAD | SIGN | SIN | SINH | SPACE | SQRT | TAN | TANH | TEMPORARY | TRUNC | WEEK | AUTONOMOUS // added in FB 2.5 | CHAR_TO_UUID | FIRSTNAME | MIDDLENAME | LASTNAME | MAPPING | OS_NAME | UUID_TO_CHAR | GRANTED | CALLER // new execute statement | COMMON | DATA | SOURCE | TWO_PHASE | BIN_NOT | ACTIVE // old keywords, that were reserved pre-Firebird.2.5 // | ADD // words commented it this list remain reserved due to conflicts | AFTER | ASC | AUTO | BEFORE | COMMITTED | COMPUTED | CONDITIONAL | CONTAINING | CSTRING | DATABASE // | DB_KEY | DESC | DO | DOMAIN | ENTRY_POINT | EXCEPTION | EXIT | KW_FILE // | GDSCODE | GENERATOR | GEN_ID | IF | INACTIVE // | INDEX | INPUT_TYPE | ISOLATION | KEY | LENGTH | LEVEL // | KW_LONG | MANUAL | MODULE_NAME | NAMES | OPTION | OUTPUT_TYPE | OVERFLOW | PAGE | PAGES | KW_PAGE_SIZE | PASSWORD // | PLAN // | POST_EVENT | PRIVILEGES | PROTECTED | READ | RESERVING | RETAIN // | RETURNING_VALUES | SEGMENT | SHADOW | KW_SHARED | SINGULAR | KW_SIZE | SNAPSHOT | SORT // | SQLCODE | STABILITY | STARTING | STATISTICS | SUB_TYPE | SUSPEND | TRANSACTION | UNCOMMITTED // | VARIABLE // | VIEW | WAIT // | WEEK // | WHILE | WORK | WRITE // end of old keywords, that were reserved pre-Firebird.2.5 | KW_ABSOLUTE // added in FB 3.0 | ACOSH | ASINH | ATANH | BODY | CONTINUE | DDL | DECRYPT | ENCRYPT | ENGINE | IDENTITY | NAME | PACKAGE | PARTITION | PRIOR | RDB_GET_CONTEXT | RDB_SET_CONTEXT | KW_RELATIVE | DENSE_RANK | FIRST_VALUE | NTH_VALUE | LAST_VALUE | LAG | LEAD | RANK | ROW_NUMBER | USAGE | LINGER | TAGS ; %%