8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 21:23:03 +01:00
firebird-mirror/src/dsql/parse.y

7170 lines
180 KiB
Plaintext

%{
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#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 <limits.h> (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 <metaNamePtr> ACTIVE
%token <metaNamePtr> ADD
%token <metaNamePtr> AFTER
%token <metaNamePtr> ALL
%token <metaNamePtr> ALTER
%token <metaNamePtr> AND
%token <metaNamePtr> ANY
%token <metaNamePtr> AS
%token <metaNamePtr> ASC
%token <metaNamePtr> AT
%token <metaNamePtr> AVG
%token <metaNamePtr> AUTO
%token <metaNamePtr> BEFORE
%token <metaNamePtr> BEGIN
%token <metaNamePtr> BETWEEN
%token <metaNamePtr> BLOB
%token <metaNamePtr> BY
%token <metaNamePtr> CAST
%token <metaNamePtr> CHARACTER
%token <metaNamePtr> CHECK
%token <metaNamePtr> COLLATE
%token <metaNamePtr> COMMIT
%token <metaNamePtr> COMMITTED
%token <metaNamePtr> COMPUTED
%token <metaNamePtr> CONCATENATE
%token <metaNamePtr> CONDITIONAL
%token <metaNamePtr> CONSTRAINT
%token <metaNamePtr> CONTAINING
%token <metaNamePtr> COUNT
%token <metaNamePtr> CREATE
%token <metaNamePtr> CSTRING
%token <metaNamePtr> CURRENT
%token <metaNamePtr> CURSOR
%token <metaNamePtr> DATABASE
%token <metaNamePtr> DATE
%token <metaNamePtr> DB_KEY
%token <metaNamePtr> DECIMAL
%token <metaNamePtr> DECLARE
%token <metaNamePtr> DEFAULT
%token <metaNamePtr> KW_DELETE
%token <metaNamePtr> DESC
%token <metaNamePtr> DISTINCT
%token <metaNamePtr> DO
%token <metaNamePtr> DOMAIN
%token <metaNamePtr> DROP
%token <metaNamePtr> ELSE
%token <metaNamePtr> END
%token <metaNamePtr> ENTRY_POINT
%token <metaNamePtr> ESCAPE
%token <metaNamePtr> EXCEPTION
%token <metaNamePtr> EXECUTE
%token <metaNamePtr> EXISTS
%token <metaNamePtr> EXIT
%token <metaNamePtr> EXTERNAL
%token <metaNamePtr> FILTER
%token <metaNamePtr> FOR
%token <metaNamePtr> FOREIGN
%token <metaNamePtr> FROM
%token <metaNamePtr> FULL
%token <metaNamePtr> FUNCTION
%token <metaNamePtr> GDSCODE
%token <metaNamePtr> GEQ
%token <metaNamePtr> GENERATOR
%token <metaNamePtr> GEN_ID
%token <metaNamePtr> GRANT
%token <metaNamePtr> GROUP
%token <metaNamePtr> HAVING
%token <metaNamePtr> IF
%token <metaNamePtr> KW_IN
%token <metaNamePtr> INACTIVE
%token <metaNamePtr> INNER
%token <metaNamePtr> INPUT_TYPE
%token <metaNamePtr> INDEX
%token <metaNamePtr> INSERT
%token <metaNamePtr> INTEGER
%token <metaNamePtr> INTO
%token <metaNamePtr> IS
%token <metaNamePtr> ISOLATION
%token <metaNamePtr> JOIN
%token <metaNamePtr> KEY
%token <metaNamePtr> KW_CHAR
%token <metaNamePtr> KW_DEC
%token <metaNamePtr> KW_DOUBLE
%token <metaNamePtr> KW_FILE
%token <metaNamePtr> KW_FLOAT
%token <metaNamePtr> KW_INT
%token <metaNamePtr> KW_LONG
%token <metaNamePtr> KW_NULL
%token <metaNamePtr> KW_NUMERIC
%token <metaNamePtr> KW_UPPER
%token <metaNamePtr> KW_VALUE
%token <metaNamePtr> LENGTH
%token <metaNamePtr> LEFT
%token <metaNamePtr> LEQ
%token <metaNamePtr> LEVEL
%token <metaNamePtr> LIKE
%token <metaNamePtr> MANUAL
%token <metaNamePtr> MAXIMUM
%token <metaNamePtr> MERGE
%token <metaNamePtr> MINIMUM
%token <metaNamePtr> MODULE_NAME
%token <metaNamePtr> NAMES
%token <metaNamePtr> NATIONAL
%token <metaNamePtr> NATURAL
%token <metaNamePtr> NCHAR
%token <metaNamePtr> NEQ
%token <metaNamePtr> NO
%token <metaNamePtr> NOT
%token <metaNamePtr> NOT_GTR
%token <metaNamePtr> NOT_LSS
%token <metaNamePtr> OF
%token <metaNamePtr> ON
%token <metaNamePtr> ONLY
%token <metaNamePtr> OPTION
%token <metaNamePtr> OR
%token <metaNamePtr> ORDER
%token <metaNamePtr> OUTER
%token <metaNamePtr> OUTPUT_TYPE
%token <metaNamePtr> OVERFLOW
%token <metaNamePtr> PAGE
%token <metaNamePtr> PAGES
%token <metaNamePtr> KW_PAGE_SIZE
%token <metaNamePtr> PARAMETER
%token <metaNamePtr> PASSWORD
%token <metaNamePtr> PLAN
%token <metaNamePtr> POSITION
%token <metaNamePtr> POST_EVENT
%token <metaNamePtr> PRECISION
%token <metaNamePtr> PRIMARY
%token <metaNamePtr> PRIVILEGES
%token <metaNamePtr> PROCEDURE
%token <metaNamePtr> PROTECTED
%token <metaNamePtr> READ
%token <metaNamePtr> REAL
%token <metaNamePtr> REFERENCES
%token <metaNamePtr> RESERVING
%token <metaNamePtr> RETAIN
%token <metaNamePtr> RETURNING_VALUES
%token <metaNamePtr> RETURNS
%token <metaNamePtr> REVOKE
%token <metaNamePtr> RIGHT
%token <metaNamePtr> ROLLBACK
%token <metaNamePtr> SEGMENT
%token <metaNamePtr> SELECT
%token <metaNamePtr> SET
%token <metaNamePtr> SHADOW
%token <metaNamePtr> KW_SHARED
%token <metaNamePtr> SINGULAR
%token <metaNamePtr> KW_SIZE
%token <metaNamePtr> SMALLINT
%token <metaNamePtr> SNAPSHOT
%token <metaNamePtr> SOME
%token <metaNamePtr> SORT
%token <metaNamePtr> SQLCODE
%token <metaNamePtr> STABILITY
%token <metaNamePtr> STARTING
%token <metaNamePtr> STATISTICS
%token <metaNamePtr> SUB_TYPE
%token <metaNamePtr> SUSPEND
%token <metaNamePtr> SUM
%token <metaNamePtr> TABLE
%token <metaNamePtr> THEN
%token <metaNamePtr> TO
%token <metaNamePtr> TRANSACTION
%token <metaNamePtr> TRIGGER
%token <metaNamePtr> UNCOMMITTED
%token <metaNamePtr> UNION
%token <metaNamePtr> UNIQUE
%token <metaNamePtr> UPDATE
%token <metaNamePtr> USER
%token <metaNamePtr> VALUES
%token <metaNamePtr> VARCHAR
%token <metaNamePtr> VARIABLE
%token <metaNamePtr> VARYING
%token <metaNamePtr> VERSION
%token <metaNamePtr> VIEW
%token <metaNamePtr> WAIT
%token <metaNamePtr> WHEN
%token <metaNamePtr> WHERE
%token <metaNamePtr> WHILE
%token <metaNamePtr> WITH
%token <metaNamePtr> WORK
%token <metaNamePtr> WRITE
%token <stringPtr> FLOAT_NUMBER
%token <metaNamePtr> SYMBOL
%token <int32Val> NUMBER
%token <intlStringPtr> STRING
%token <metaNamePtr> INTRODUCER
// New tokens added v5.0
%token <metaNamePtr> ACTION
%token <metaNamePtr> ADMIN
%token <metaNamePtr> CASCADE
%token <metaNamePtr> FREE_IT // ISC SQL extension
%token <metaNamePtr> RESTRICT
%token <metaNamePtr> ROLE
// New tokens added v6.0
%token <metaNamePtr> COLUMN
%token <metaNamePtr> KW_TYPE
%token <metaNamePtr> EXTRACT
%token <metaNamePtr> YEAR
%token <metaNamePtr> MONTH
%token <metaNamePtr> DAY
%token <metaNamePtr> HOUR
%token <metaNamePtr> MINUTE
%token <metaNamePtr> SECOND
%token <metaNamePtr> WEEKDAY // ISC SQL extension
%token <metaNamePtr> YEARDAY // ISC SQL extension
%token <metaNamePtr> TIME
%token <metaNamePtr> TIMESTAMP
%token <metaNamePtr> CURRENT_DATE
%token <metaNamePtr> CURRENT_TIME
%token <metaNamePtr> CURRENT_TIMESTAMP
// special aggregate token types returned by lex in v6.0
%token <scaledNumber> NUMBER64BIT SCALEDINT
// CVC: Special Firebird additions.
%token <metaNamePtr> CURRENT_USER
%token <metaNamePtr> CURRENT_ROLE
%token <metaNamePtr> KW_BREAK
%token <metaNamePtr> SUBSTRING
%token <metaNamePtr> RECREATE
%token <metaNamePtr> KW_DESCRIPTOR
%token <metaNamePtr> FIRST
%token <metaNamePtr> SKIP
// tokens added for Firebird 1.5
%token <metaNamePtr> CURRENT_CONNECTION
%token <metaNamePtr> CURRENT_TRANSACTION
%token <metaNamePtr> BIGINT
%token <metaNamePtr> CASE
%token <metaNamePtr> NULLIF
%token <metaNamePtr> COALESCE
%token <metaNamePtr> USING
%token <metaNamePtr> NULLS
%token <metaNamePtr> LAST
%token <metaNamePtr> ROW_COUNT
%token <metaNamePtr> LOCK
%token <metaNamePtr> SAVEPOINT
%token <metaNamePtr> RELEASE
%token <metaNamePtr> STATEMENT
%token <metaNamePtr> LEAVE
%token <metaNamePtr> INSERTING
%token <metaNamePtr> UPDATING
%token <metaNamePtr> DELETING
// tokens added for Firebird 2.0
%token <metaNamePtr> BACKUP
%token <metaNamePtr> KW_DIFFERENCE
%token <metaNamePtr> OPEN
%token <metaNamePtr> CLOSE
%token <metaNamePtr> FETCH
%token <metaNamePtr> ROWS
%token <metaNamePtr> BLOCK
%token <metaNamePtr> IIF
%token <metaNamePtr> SCALAR_ARRAY
%token <metaNamePtr> CROSS
%token <metaNamePtr> NEXT
%token <metaNamePtr> SEQUENCE
%token <metaNamePtr> RESTART
%token <metaNamePtr> BOTH
%token <metaNamePtr> COLLATION
%token <metaNamePtr> COMMENT
%token <metaNamePtr> BIT_LENGTH
%token <metaNamePtr> CHAR_LENGTH
%token <metaNamePtr> CHARACTER_LENGTH
%token <metaNamePtr> LEADING
%token <metaNamePtr> KW_LOWER
%token <metaNamePtr> OCTET_LENGTH
%token <metaNamePtr> TRAILING
%token <metaNamePtr> TRIM
%token <metaNamePtr> RETURNING
%token <metaNamePtr> KW_IGNORE
%token <metaNamePtr> LIMBO
%token <metaNamePtr> UNDO
%token <metaNamePtr> REQUESTS
%token <metaNamePtr> TIMEOUT
// tokens added for Firebird 2.1
%token <metaNamePtr> ABS
%token <metaNamePtr> ACCENT
%token <metaNamePtr> ACOS
%token <metaNamePtr> ALWAYS
%token <metaNamePtr> ASCII_CHAR
%token <metaNamePtr> ASCII_VAL
%token <metaNamePtr> ASIN
%token <metaNamePtr> ATAN
%token <metaNamePtr> ATAN2
%token <metaNamePtr> BIN_AND
%token <metaNamePtr> BIN_OR
%token <metaNamePtr> BIN_SHL
%token <metaNamePtr> BIN_SHR
%token <metaNamePtr> BIN_XOR
%token <metaNamePtr> CEIL
%token <metaNamePtr> CONNECT
%token <metaNamePtr> COS
%token <metaNamePtr> COSH
%token <metaNamePtr> COT
%token <metaNamePtr> DATEADD
%token <metaNamePtr> DATEDIFF
%token <metaNamePtr> DECODE
%token <metaNamePtr> DISCONNECT
%token <metaNamePtr> EXP
%token <metaNamePtr> FLOOR
%token <metaNamePtr> GEN_UUID
%token <metaNamePtr> GENERATED
%token <metaNamePtr> GLOBAL
%token <metaNamePtr> HASH
%token <metaNamePtr> INSENSITIVE
%token <metaNamePtr> LIST
%token <metaNamePtr> LN
%token <metaNamePtr> LOG
%token <metaNamePtr> LOG10
%token <metaNamePtr> LPAD
%token <metaNamePtr> MATCHED
%token <metaNamePtr> MATCHING
%token <metaNamePtr> MAXVALUE
%token <metaNamePtr> MILLISECOND
%token <metaNamePtr> MINVALUE
%token <metaNamePtr> MOD
%token <metaNamePtr> OVERLAY
%token <metaNamePtr> PAD
%token <metaNamePtr> PI
%token <metaNamePtr> PLACING
%token <metaNamePtr> POWER
%token <metaNamePtr> PRESERVE
%token <metaNamePtr> RAND
%token <metaNamePtr> RECURSIVE
%token <metaNamePtr> REPLACE
%token <metaNamePtr> REVERSE
%token <metaNamePtr> ROUND
%token <metaNamePtr> RPAD
%token <metaNamePtr> SENSITIVE
%token <metaNamePtr> SIGN
%token <metaNamePtr> SIN
%token <metaNamePtr> SINH
%token <metaNamePtr> SPACE
%token <metaNamePtr> SQRT
%token <metaNamePtr> START
%token <metaNamePtr> TAN
%token <metaNamePtr> TANH
%token <metaNamePtr> TEMPORARY
%token <metaNamePtr> TRUNC
%token <metaNamePtr> WEEK
// tokens added for Firebird 2.5
%token <metaNamePtr> AUTONOMOUS
%token <metaNamePtr> CHAR_TO_UUID
%token <metaNamePtr> FIRSTNAME
%token <metaNamePtr> GRANTED
%token <metaNamePtr> LASTNAME
%token <metaNamePtr> MIDDLENAME
%token <metaNamePtr> MAPPING
%token <metaNamePtr> OS_NAME
%token <metaNamePtr> SIMILAR
%token <metaNamePtr> UUID_TO_CHAR
// new execute statement
%token <metaNamePtr> CALLER
%token <metaNamePtr> COMMON
%token <metaNamePtr> DATA
%token <metaNamePtr> SOURCE
%token <metaNamePtr> TWO_PHASE
%token <metaNamePtr> BIND_PARAM
%token <metaNamePtr> BIN_NOT
// tokens added for Firebird 3.0
%token <metaNamePtr> BODY
%token <metaNamePtr> CONTINUE
%token <metaNamePtr> DDL
%token <metaNamePtr> DECRYPT
%token <metaNamePtr> ENCRYPT
%token <metaNamePtr> ENGINE
%token <metaNamePtr> NAME
%token <metaNamePtr> OVER
%token <metaNamePtr> PACKAGE
%token <metaNamePtr> PARTITION
%token <metaNamePtr> RDB_GET_CONTEXT
%token <metaNamePtr> RDB_SET_CONTEXT
%token <metaNamePtr> SCROLL
%token <metaNamePtr> PRIOR
%token <metaNamePtr> KW_ABSOLUTE
%token <metaNamePtr> KW_RELATIVE
%token <metaNamePtr> ACOSH
%token <metaNamePtr> ASINH
%token <metaNamePtr> ATANH
%token <metaNamePtr> RETURN
%token <metaNamePtr> DETERMINISTIC
%token <metaNamePtr> IDENTITY
%token <metaNamePtr> DENSE_RANK
%token <metaNamePtr> FIRST_VALUE
%token <metaNamePtr> NTH_VALUE
%token <metaNamePtr> LAST_VALUE
%token <metaNamePtr> LAG
%token <metaNamePtr> LEAD
%token <metaNamePtr> RANK
%token <metaNamePtr> ROW_NUMBER
%token <metaNamePtr> SQLSTATE
%token <metaNamePtr> KW_BOOLEAN
%token <metaNamePtr> KW_FALSE
%token <metaNamePtr> KW_TRUE
%token <metaNamePtr> UNKNOWN
%token <metaNamePtr> USAGE
%token <metaNamePtr> RDB_RECORD_VERSION
%token <metaNamePtr> LINGER
%token <metaNamePtr> 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<int> nullableIntVal;
BaseNullable<bool> nullableBoolVal;
bool boolVal;
int intVal;
unsigned uintVal;
SLONG int32Val;
SINT64 int64Val;
FB_UINT64 uint64Val;
BaseNullable<SINT64> nullableInt64Val;
BaseNullable<FB_UINT64> 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<Firebird::MetaName>* metaNameArray;
Firebird::PathName* pathNamePtr;
Firebird::string* stringPtr;
Jrd::IntlString* intlStringPtr;
Jrd::DbFileClause* dbFileClause;
Firebird::Array<NestConst<Jrd::DbFileClause> >* dbFilesClause;
Jrd::ExternalClause* externalClause;
Firebird::Array<NestConst<Jrd::ParameterClause> >* 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<Jrd::FieldNode*>* fieldArray;
Firebird::Array<NestConst<Jrd::FieldNode> >* nestFieldArray;
Jrd::TransactionNode* traNode;
Firebird::Array<Jrd::PrivilegeClause>* privilegeArray;
Jrd::GranteeClause* granteeClause;
Firebird::Array<Jrd::GranteeClause>* 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<Jrd::CreateAlterPackageNode::Item>* 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 <dsqlReq> statement
statement
: dml_statement { $$ = newNode<DsqlDmlRequest>($1); }
| ddl_statement { $$ = newNode<DsqlDdlRequest>($1); }
| tra_statement { $$ = newNode<DsqlTransactionRequest>($1); }
;
%type <stmtNode> 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 <ddlNode> 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 <traNode> tra_statement
tra_statement
: set_transaction { $$ = $1; }
| commit { $$ = $1; }
| rollback { $$ = $1; }
;
// GRANT statement
%type <grantRevokeNode> grant
grant
: GRANT
{ $$ = newNode<GrantRevokeNode>(true); }
grant0($2)
{ $$ = $2; }
;
%type grant0(<grantRevokeNode>)
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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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(<privilegeArray>)
privileges($privilegeArray)
: ALL { $privilegeArray->add(PrivilegeClause('A', NULL)); }
| ALL PRIVILEGES { $privilegeArray->add(PrivilegeClause('A', NULL)); }
| privilege_list($privilegeArray)
;
%type privilege_list(<privilegeArray>)
privilege_list($privilegeArray)
: privilege($privilegeArray)
| privilege_list ',' privilege($privilegeArray)
;
%type execute_privilege(<privilegeArray>)
execute_privilege($privilegeArray)
: EXECUTE { $privilegeArray->add(PrivilegeClause('X', NULL)); }
;
%type usage_privilege(<privilegeArray>)
usage_privilege($privilegeArray)
: USAGE { $privilegeArray->add(PrivilegeClause('G', NULL)); }
;
%type privilege(<privilegeArray>)
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 <boolVal> grant_option
grant_option
: /* nothing */ { $$ = false; }
| WITH GRANT OPTION { $$ = true; }
;
%type <boolVal> role_admin_option
role_admin_option
: /* nothing */ { $$ = false; }
| WITH ADMIN OPTION { $$ = true; }
;
%type <metaNamePtr> granted_by
granted_by
: /* nothing */ { $$ = NULL; }
| granted_by_text grantor { $$ = $2; }
;
granted_by_text
: GRANTED BY
| AS
;
%type <metaNamePtr> grantor
grantor
: symbol_user_name
| USER symbol_user_name { $$ = $2; }
;
// REVOKE statement
%type <grantRevokeNode> revoke
revoke
: REVOKE
{ $$ = newNode<GrantRevokeNode>(false); }
revoke0($2)
{ $$ = $2; }
;
%type revoke0(<grantRevokeNode>)
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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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<GranteeClause>(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 <boolVal> rev_grant_option
rev_grant_option
: /* nothing */ { $$ = false; }
| GRANT OPTION FOR { $$ = true; }
;
%type <boolVal> rev_admin_option
rev_admin_option
: /* nothing */ { $$ = false; }
| ADMIN OPTION FOR { $$ = true; }
;
%type non_role_grantee_list(<granteeArray>)
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(<granteeArray>)
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(<granteeArray>)
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(<granteeArray>)
role_name_list($granteeArray)
: role_name($granteeArray)
| role_name_list ',' role_name($granteeArray)
;
%type role_name(<granteeArray>)
role_name($granteeArray)
: symbol_role_name
{ $granteeArray->add(GranteeClause(obj_sql_role, *$1)); }
;
%type role_grantee_list(<granteeArray>)
role_grantee_list($granteeArray)
: role_grantee($granteeArray)
| role_grantee_list ',' role_grantee($granteeArray)
;
%type role_grantee(<granteeArray>)
role_grantee($granteeArray)
: grantor { $granteeArray->add(GranteeClause(obj_user, *$1)); }
;
// DECLARE operations
%type <ddlNode> declare
declare
: DECLARE declare_clause { $$ = $2;}
;
%type <ddlNode> declare_clause
declare_clause
: FILTER filter_decl_clause { $$ = $2; }
| EXTERNAL FUNCTION udf_decl_clause { $$ = $3; }
;
%type <createAlterFunctionNode> udf_decl_clause
udf_decl_clause
: symbol_UDF_name
{ $$ = newNode<CreateAlterFunctionNode>(*$1); }
arg_desc_list1(NOTRIAL(&$2->parameters))
RETURNS return_value1($2)
ENTRY_POINT utf_string MODULE_NAME utf_string
{
$$ = $2;
$$->external = newNode<ExternalClause>();
$$->external->name = *$7;
$$->external->udfModule = *$9;
}
;
%type <legacyField> udf_data_type
udf_data_type
: simple_type
| BLOB
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_blob;
$$->length = sizeof(bid);
}
| CSTRING '(' pos_short_integer ')' charset_clause
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_cstring;
$$->charLength = (USHORT) $3;
if ($5)
$$->charSet = *$5;
}
;
%type arg_desc_list1(<parametersClause>)
arg_desc_list1($parameters)
:
| arg_desc_list($parameters)
| '(' arg_desc_list($parameters) ')'
;
%type arg_desc_list(<parametersClause>)
arg_desc_list($parameters)
: arg_desc($parameters)
| arg_desc_list ',' arg_desc($parameters)
;
%type arg_desc(<parametersClause>)
arg_desc($parameters)
: udf_data_type param_mechanism
{
$parameters->add(newNode<ParameterClause>($1, MetaName()));
$parameters->back()->udfMechanism = $2;
}
;
%type <nullableIntVal> param_mechanism
param_mechanism
: /* nothing */ { $$ = Nullable<int>::empty(); } // Beware: This means FUN_reference or FUN_blob_struct.
| BY KW_DESCRIPTOR { $$ = Nullable<int>::val(FUN_descriptor); }
| BY SCALAR_ARRAY { $$ = Nullable<int>::val(FUN_scalar_array); }
| KW_NULL { $$ = Nullable<int>::val(FUN_ref_with_null); }
;
%type return_value1(<createAlterFunctionNode>)
return_value1($function)
: return_value($function)
| '(' return_value($function) ')'
;
%type return_value(<createAlterFunctionNode>)
return_value($function)
: udf_data_type return_mechanism
{
$function->returnType = newNode<ParameterClause>($1, MetaName());
$function->returnType->udfMechanism = $2;
}
| PARAMETER pos_short_integer
{ $function->udfReturnPos = $2; }
;
%type <int32Val> 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 <ddlNode> 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<CreateFilterNode>(*$1);
node->inputFilter = $3;
node->outputFilter = $5;
node->entryPoint = *$7;
node->moduleName = *$9;
$$ = node;
}
;
%type <filterNameNumber> blob_filter_subtype
blob_filter_subtype
: symbol_blob_subtype_name
{ $$ = newNode<CreateFilterNode::NameNumber>(*$1); }
| signed_short_integer
{ $$ = newNode<CreateFilterNode::NameNumber>($1); }
;
// CREATE metadata operations
%type <ddlNode> create
create
: CREATE create_clause { $$ = $2; }
;
%type <ddlNode> create_clause
create_clause
: EXCEPTION exception_clause { $$ = $2; }
| unique_opt order_direction INDEX symbol_index_name ON simple_table_name
{
CreateIndexNode* node = newNode<CreateIndexNode>(*$4);
node->unique = $1;
node->descending = $2;
node->relation = $6;
$$ = node;
}
index_definition(static_cast<CreateIndexNode*>($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 <ddlNode> recreate
recreate
: RECREATE recreate_clause { $$ = $2; }
;
%type <ddlNode> recreate_clause
recreate_clause
: PROCEDURE procedure_clause
{ $$ = newNode<RecreateProcedureNode>($2); }
| FUNCTION function_clause
{ $$ = newNode<RecreateFunctionNode>($2); }
| TABLE table_clause
{ $$ = newNode<RecreateTableNode>($2); }
| GLOBAL TEMPORARY TABLE gtt_table_clause
{ $$ = newNode<RecreateTableNode>($4); }
| VIEW view_clause
{ $$ = newNode<RecreateViewNode>($2); }
| TRIGGER trigger_clause
{ $$ = newNode<RecreateTriggerNode>($2); }
| PACKAGE package_clause
{ $$ = newNode<RecreatePackageNode>($2); }
| PACKAGE BODY package_body_clause
{ $$ = newNode<RecreatePackageBodyNode>($3); }
| EXCEPTION exception_clause
{ $$ = newNode<RecreateExceptionNode>($2); }
| GENERATOR generator_clause
{ $$ = newNode<RecreateSequenceNode>($2); }
| SEQUENCE generator_clause
{ $$ = newNode<RecreateSequenceNode>($2); }
;
%type <ddlNode> create_or_alter
create_or_alter
: CREATE OR ALTER replace_clause { $$ = $4; }
;
%type <ddlNode> 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 <createAlterExceptionNode> exception_clause
exception_clause
: symbol_exception_name sql_string
{ $$ = newNode<CreateAlterExceptionNode>(*$1, $2->getString()); }
;
%type <createAlterExceptionNode> replace_exception_clause
replace_exception_clause
: symbol_exception_name sql_string
{
CreateAlterExceptionNode* node = newNode<CreateAlterExceptionNode>(*$1, $2->getString());
node->alter = true;
$$ = node;
}
;
%type <createAlterExceptionNode> alter_exception_clause
alter_exception_clause
: symbol_exception_name sql_string
{
CreateAlterExceptionNode* node = newNode<CreateAlterExceptionNode>(*$1, $2->getString());
node->create = false;
node->alter = true;
$$ = node;
}
;
// CREATE INDEX
%type <boolVal> unique_opt
unique_opt
: /* nothing */ { $$ = false; }
| UNIQUE { $$ = true; }
;
%type index_definition(<createIndexNode>)
index_definition($createIndexNode)
: column_list
{ $createIndexNode->columns = $1; }
| column_parens
{ $createIndexNode->columns = $1; }
| computed_by '(' value ')'
{
$createIndexNode->computed = newNode<ValueSourceClause>();
$createIndexNode->computed->value = $3;
$createIndexNode->computed->source = makeParseStr(YYPOSNARG(2), YYPOSNARG(4));
}
;
// CREATE SHADOW
%type <createShadowNode> shadow_clause
shadow_clause
: pos_short_integer manual_auto conditional utf_string first_file_length
{
$$ = newNode<CreateShadowNode>($1);
$$->manual = $2;
$$->conditional = $3;
$$->files.add(newNode<DbFileClause>(*$4));
$$->files.front()->length = $5;
}
sec_shadow_files(NOTRIAL(&$6->files))
{ $$ = $6; }
;
%type <boolVal> manual_auto
manual_auto
: /* nothing */ { $$ = false; }
| MANUAL { $$ = true; }
| AUTO { $$ = false; }
;
%type <boolVal> conditional
conditional
: /* nothing */ { $$ = false; }
| CONDITIONAL { $$ = true; }
;
%type <int32Val> first_file_length
first_file_length
: /* nothing */ { $$ = 0; }
| LENGTH equals long_integer page_noise { $$ = $3; }
;
%type sec_shadow_files(<dbFilesClause>)
sec_shadow_files($dbFilesClause)
: // nothing
| db_file_list($dbFilesClause)
;
%type db_file_list(<dbFilesClause>)
db_file_list($dbFilesClause)
: db_file { $dbFilesClause->add($1); }
| db_file_list db_file { $dbFilesClause->add($2); }
;
// CREATE DOMAIN
%type <createDomainNode> domain_clause
domain_clause
: symbol_column_name as_opt data_type domain_default_opt
{
$3->fld_name = *$1;
$<createDomainNode>$ = newNode<CreateDomainNode>(
newNode<ParameterClause>($3, MetaName(), $4));
}
domain_constraints_opt($5) collate_clause
{
$$ = $5;
if ($7)
$$->nameType->type->collate = *$7;
}
;
%type domain_constraints_opt(<createDomainNode>)
domain_constraints_opt($createDomainNode)
: // nothing
| domain_constraints($createDomainNode)
;
%type domain_constraints(<createDomainNode>)
domain_constraints($createDomainNode)
: domain_constraint($createDomainNode)
| domain_constraints domain_constraint($createDomainNode)
;
%type domain_constraint(<createDomainNode>)
domain_constraint($createDomainNode)
: null_constraint
{ setClause($createDomainNode->notNull, "NOT NULL"); }
| check_constraint
{ setClause($createDomainNode->check, "DOMAIN CHECK CONSTRAINT", $1); }
;
as_opt
: // nothing
| AS
;
%type <valueSourceClause> domain_default
domain_default
: DEFAULT default_value
{
ValueSourceClause* clause = newNode<ValueSourceClause>();
clause->value = $2;
clause->source = makeParseStr(YYPOSNARG(1), YYPOSNARG(2));
$$ = clause;
}
;
%type <valueSourceClause> domain_default_opt
domain_default_opt
: /* nothing */ { $$ = NULL; }
| domain_default
;
null_constraint
: NOT KW_NULL
;
%type <boolSourceClause> check_constraint
check_constraint
: CHECK '(' search_condition ')'
{
BoolSourceClause* clause = newNode<BoolSourceClause>();
clause->value = $3;
clause->source = makeParseStr(YYPOSNARG(1), YYPOSNARG(4));
$$ = clause;
}
;
// CREATE SEQUENCE/GENERATOR
%type <createAlterSequenceNode> generator_clause
generator_clause
: symbol_generator_name start_with_opt
{ $$ = newNode<CreateAlterSequenceNode>(*$1, $2); }
;
%type <nullableInt64Val> start_with_opt
start_with_opt
: /* nothing */ { $$ = Nullable<SINT64>::empty(); }
| start_with { $$ = Nullable<SINT64>::val($1); }
;
%type <int64Val> start_with
start_with
: START WITH sequence_value { $$ = $3; }
;
%type <createAlterSequenceNode> replace_sequence_clause
replace_sequence_clause
: symbol_generator_name replace_sequence_options
{
CreateAlterSequenceNode* node = newNode<CreateAlterSequenceNode>(*$1, $2);
node->alter = true;
$$ = node;
}
;
%type <nullableInt64Val> replace_sequence_options
replace_sequence_options
: RESTART { $$ = Nullable<SINT64>::empty(); }
| START WITH sequence_value { $$ = Nullable<SINT64>::val($3); }
;
%type <createAlterSequenceNode> alter_sequence_clause
alter_sequence_clause
: symbol_generator_name RESTART restart_value_opt
{
CreateAlterSequenceNode* node = newNode<CreateAlterSequenceNode>(*$1, $3);
node->create = false;
node->alter = true;
$$ = node;
}
;
%type <nullableInt64Val> restart_value_opt
restart_value_opt
: /* nothing */ { $$ = Nullable<SINT64>::empty(); }
| WITH sequence_value { $$ = Nullable<SINT64>::val($2); }
;
%type <createAlterSequenceNode> set_generator_clause
set_generator_clause
: SET GENERATOR symbol_generator_name TO sequence_value
{
CreateAlterSequenceNode* node = newNode<CreateAlterSequenceNode>(*$3,
Nullable<SINT64>::val($5));
node->create = false;
node->alter = true;
node->legacy = true;
$$ = node;
}
;
%type <int64Val> 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 <ddlNode> role_clause
role_clause
: symbol_role_name { $$ = newNode<CreateRoleNode>(*$1); }
;
// CREATE COLLATION
%type <createCollationNode> collation_clause
collation_clause
: symbol_collation_name FOR symbol_character_set_name
{ $<createCollationNode>$ = newNode<CreateCollationNode>(*$1, *$3); }
collation_sequence_definition($4)
collation_attribute_list_opt($4) collation_specific_attribute_opt($4)
{ $$ = $4; }
;
%type collation_sequence_definition(<createCollationNode>)
collation_sequence_definition($createCollation)
: // nothing
| FROM symbol_collation_name
{ $createCollation->fromName = *$2; }
| FROM EXTERNAL '(' utf_string ')'
{ $createCollation->fromExternal = *$4; }
;
%type collation_attribute_list_opt(<createCollationNode>)
collation_attribute_list_opt($createCollation)
: // nothing
| collation_attribute_list($createCollation)
;
%type collation_attribute_list(<createCollationNode>)
collation_attribute_list($createCollation)
: collation_attribute($createCollation)
| collation_attribute_list collation_attribute($createCollation)
;
%type collation_attribute(<createCollationNode>)
collation_attribute($createCollation)
: collation_pad_attribute($createCollation)
| collation_case_attribute($createCollation)
| collation_accent_attribute($createCollation)
;
%type collation_pad_attribute(<createCollationNode>)
collation_pad_attribute($createCollation)
: NO PAD { $createCollation->unsetAttribute(TEXTTYPE_ATTR_PAD_SPACE); }
| PAD SPACE { $createCollation->setAttribute(TEXTTYPE_ATTR_PAD_SPACE); }
;
%type collation_case_attribute(<createCollationNode>)
collation_case_attribute($createCollation)
: CASE SENSITIVE { $createCollation->unsetAttribute(TEXTTYPE_ATTR_CASE_INSENSITIVE); }
| CASE INSENSITIVE { $createCollation->setAttribute(TEXTTYPE_ATTR_CASE_INSENSITIVE); }
;
%type collation_accent_attribute(<createCollationNode>)
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(<createCollationNode>)
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 <ddlNode> alter_charset_clause
alter_charset_clause
: symbol_character_set_name SET DEFAULT COLLATION symbol_collation_name
{ $$ = newNode<AlterCharSetNode>(*$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 <alterDatabaseNode> db_clause
db_clause
: db_name
{
$$ = newNode<AlterDatabaseNode>();
$$->create = true;
}
db_initial_desc1($2) db_rem_desc1($2)
{ $$ = $2; }
;
equals
: // nothing
| '='
;
%type <stringPtr> db_name
db_name
: utf_string
;
%type db_initial_desc1(<alterDatabaseNode>)
db_initial_desc1($alterDatabaseNode)
: // nothing
| db_initial_desc($alterDatabaseNode)
;
%type db_initial_desc(<alterDatabaseNode>)
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(<alterDatabaseNode>)
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(<alterDatabaseNode>)
db_rem_desc1($alterDatabaseNode)
: // nothing
| db_rem_desc($alterDatabaseNode)
;
%type db_rem_desc(<alterDatabaseNode>)
db_rem_desc($alterDatabaseNode)
: db_rem_option($alterDatabaseNode)
| db_rem_desc db_rem_option($alterDatabaseNode)
;
%type db_rem_option(<alterDatabaseNode>)
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 <dbFileClause> db_file
db_file
: KW_FILE utf_string
{
DbFileClause* clause = newNode<DbFileClause>(*$2);
$$ = clause;
}
file_desc1($3)
{ $$ = $3; }
;
%type file_desc1(<dbFileClause>)
file_desc1($dbFileClause)
: // nothing
| file_desc($dbFileClause)
;
%type file_desc(<dbFileClause>)
file_desc($dbFileClause)
: file_clause($dbFileClause)
| file_desc file_clause($dbFileClause)
;
%type file_clause(<dbFileClause>)
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 <createRelationNode> table_clause
table_clause
: simple_table_name external_file
{ $<createRelationNode>$ = newNode<CreateRelationNode>($1, $2); }
'(' table_elements($3) ')'
{ $$ = $3; }
;
%type <createRelationNode> gtt_table_clause
gtt_table_clause
: simple_table_name
{ $<createRelationNode>$ = newNode<CreateRelationNode>($1); }
'(' table_elements($2) ')' gtt_scope
{
$$ = $2;
$$->relationType = static_cast<rel_t>($6);
}
;
%type <intVal> 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 <stringPtr> external_file
external_file
: /* nothing */ { $$ = NULL; }
| EXTERNAL KW_FILE utf_string { $$ = $3; }
| EXTERNAL utf_string { $$ = $2; }
;
%type table_elements(<createRelationNode>)
table_elements($createRelationNode)
: table_element($createRelationNode)
| table_elements ',' table_element($createRelationNode)
;
%type table_element(<createRelationNode>)
table_element($createRelationNode)
: column_def($createRelationNode)
| table_constraint_definition($createRelationNode)
;
// column definition
%type column_def(<relationNode>)
column_def($relationNode)
: symbol_column_name data_type_or_domain domain_default_opt
{
RelationNode::AddColumnClause* clause = $<addColumnClause>$ =
newNode<RelationNode::AddColumnClause>();
clause->field = $2;
clause->field->fld_name = *$1;
clause->defaultValue = $3;
$relationNode->clauses.add(clause);
}
column_constraint_clause(NOTRIAL($<addColumnClause>4)) collate_clause
{
if ($6)
$<addColumnClause>4->collate = *$6;
}
| symbol_column_name data_type_or_domain identity_clause
{
RelationNode::AddColumnClause* clause = $<addColumnClause>$ =
newNode<RelationNode::AddColumnClause>();
clause->field = $2;
clause->field->fld_name = *$1;
clause->identity = true;
clause->identityStart = $3;
$relationNode->clauses.add(clause);
}
column_constraint_clause(NOTRIAL($<addColumnClause>4)) collate_clause
{
if ($6)
$<addColumnClause>4->collate = *$6;
}
| symbol_column_name non_array_type def_computed
{
RelationNode::AddColumnClause* clause = newNode<RelationNode::AddColumnClause>();
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<RelationNode::AddColumnClause>();
clause->field = newNode<dsql_fld>();
clause->field->fld_name = *$1;
clause->computed = $2;
$relationNode->clauses.add(clause);
clause->field->flags |= FLD_computed;
}
;
%type <int64Val> identity_clause
identity_clause
: GENERATED BY DEFAULT AS IDENTITY identity_clause_options { $$ = $6; }
;
%type <int64Val> 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 <valueSourceClause> def_computed
def_computed
: computed_clause '(' value ')'
{
ValueSourceClause* clause = newNode<ValueSourceClause>();
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 <legacyField> data_type_or_domain
data_type_or_domain
: data_type
| symbol_column_name
{
$$ = newNode<dsql_fld>();
$$->typeOfName = *$1;
}
;
%type <metaNamePtr> collate_clause
collate_clause
: { $$ = NULL; }
| COLLATE symbol_collation_name { $$ = $2; }
;
%type <legacyField> data_type_descriptor
data_type_descriptor
: data_type
| KW_TYPE OF symbol_column_name
{
$$ = newNode<dsql_fld>();
$$->typeOfName = *$3;
}
| KW_TYPE OF COLUMN symbol_column_name '.' symbol_column_name
{
$$ = newNode<dsql_fld>();
$$->typeOfTable = *$4;
$$->typeOfName = *$6;
}
| symbol_column_name
{
$$ = newNode<dsql_fld>();
$$->typeOfName = *$1;
$$->fullDomain = true;
}
;
%type <valueExprNode> 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(<addColumnClause>)
column_constraint_clause($addColumnClause)
: // nothing
| column_constraint_list($addColumnClause)
;
%type column_constraint_list(<addColumnClause>)
column_constraint_list($addColumnClause)
: column_constraint_def($addColumnClause)
| column_constraint_list column_constraint_def($addColumnClause)
;
%type column_constraint_def(<addColumnClause>)
column_constraint_def($addColumnClause)
: constraint_name_opt column_constraint($addColumnClause)
{
if ($1)
$addColumnClause->constraints.back()->name = *$1;
}
;
%type column_constraint(<addColumnClause>)
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<ValueExprNode>* ptr = refColumns->items.begin();
for (const NestConst<ValueExprNode>* const end = refColumns->items.end(); ptr != end; ++ptr)
constraint.refColumns.add((*ptr)->as<FieldNode>()->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(<relationNode>)
table_constraint_definition($relationNode)
: constraint_name_opt table_constraint($relationNode)
{
if ($1)
{
static_cast<RelationNode::AddConstraintClause*>(
$relationNode->clauses.back().getObject())->name = *$1;
}
}
;
%type <metaNamePtr> constraint_name_opt
constraint_name_opt
: /* nothing */ { $$ = NULL; }
| CONSTRAINT symbol_constraint_name { $$ = $2; }
;
%type table_constraint(<relationNode>)
table_constraint($relationNode)
: UNIQUE column_parens constraint_index_opt
{
RelationNode::AddConstraintClause& constraint = *newNode<RelationNode::AddConstraintClause>();
constraint.constraintType = RelationNode::AddConstraintClause::CTYPE_UNIQUE;
const ValueListNode* columns = $2;
const NestConst<ValueExprNode>* ptr = columns->items.begin();
for (const NestConst<ValueExprNode>* const end = columns->items.end(); ptr != end; ++ptr)
constraint.columns.add((*ptr)->as<FieldNode>()->dsqlName);
constraint.index = $3;
$relationNode->clauses.add(&constraint);
}
| PRIMARY KEY column_parens constraint_index_opt
{
RelationNode::AddConstraintClause& constraint = *newNode<RelationNode::AddConstraintClause>();
constraint.constraintType = RelationNode::AddConstraintClause::CTYPE_PK;
const ValueListNode* columns = $3;
const NestConst<ValueExprNode>* ptr = columns->items.begin();
for (const NestConst<ValueExprNode>* const end = columns->items.end(); ptr != end; ++ptr)
constraint.columns.add((*ptr)->as<FieldNode>()->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<RelationNode::AddConstraintClause>();
constraint.constraintType = RelationNode::AddConstraintClause::CTYPE_FK;
const ValueListNode* columns = $3;
const NestConst<ValueExprNode>* ptr = columns->items.begin();
for (const NestConst<ValueExprNode>* const end = columns->items.end(); ptr != end; ++ptr)
constraint.columns.add((*ptr)->as<FieldNode>()->dsqlName);
constraint.refRelation = *$5;
constraint.refAction = $7;
const ValueListNode* refColumns = $6;
if (refColumns)
{
const NestConst<ValueExprNode>* ptr = refColumns->items.begin();
for (const NestConst<ValueExprNode>* const end = refColumns->items.end(); ptr != end; ++ptr)
constraint.refColumns.add((*ptr)->as<FieldNode>()->dsqlName);
}
constraint.index = $8;
$relationNode->clauses.add(&constraint);
}
| check_constraint
{
RelationNode::AddConstraintClause* constraint = newNode<RelationNode::AddConstraintClause>();
constraint->constraintType = RelationNode::AddConstraintClause::CTYPE_CHECK;
constraint->check = $1;
$relationNode->clauses.add(constraint);
}
;
%type <indexConstraintClause> constraint_index_opt
constraint_index_opt
: // nothing
{ $$ = newNode<RelationNode::IndexConstraintClause>(); }
| USING order_direction INDEX symbol_index_name
{
RelationNode::IndexConstraintClause* clause = $$ =
newNode<RelationNode::IndexConstraintClause>();
clause->descending = $2;
clause->name = *$4;
}
/***
| NO INDEX
{ $$ = NULL; }
***/
;
%type <refActionClause> referential_trigger_action
referential_trigger_action
: /* nothing */ { $$ = NULL; }
| update_rule { $$ = newNode<RelationNode::RefActionClause>($1, 0); }
| delete_rule { $$ = newNode<RelationNode::RefActionClause>(0, $1); }
| delete_rule update_rule { $$ = newNode<RelationNode::RefActionClause>($2, $1); }
| update_rule delete_rule { $$ = newNode<RelationNode::RefActionClause>($1, $2); }
;
%type <uintVal> update_rule
update_rule
: ON UPDATE referential_action { $$ = $3;}
;
%type <uintVal> delete_rule
delete_rule
: ON KW_DELETE referential_action { $$ = $3;}
;
%type <uintVal> 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 <createAlterProcedureNode> procedure_clause
procedure_clause
: psql_procedure_clause
| external_procedure_clause
;
%type <createAlterProcedureNode> 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 <createAlterProcedureNode> external_procedure_clause
external_procedure_clause
: procedure_clause_start external_clause external_body_clause_opt
{
$$ = $1;
$$->external = $2;
if ($3)
$$->source = *$3;
}
;
%type <createAlterProcedureNode> procedure_clause_start
procedure_clause_start
: symbol_procedure_name
{ $$ = newNode<CreateAlterProcedureNode>(*$1); }
input_parameters(NOTRIAL(&$2->parameters)) output_parameters(NOTRIAL(&$2->returns))
{ $$ = $2; }
;
%type <createAlterProcedureNode> alter_procedure_clause
alter_procedure_clause
: procedure_clause
{
$$ = $1;
$$->alter = true;
$$->create = false;
}
;
%type <createAlterProcedureNode> replace_procedure_clause
replace_procedure_clause
: procedure_clause
{
$$ = $1;
$$->alter = true;
}
;
%type input_parameters(<parametersClause>)
input_parameters($parameters)
:
| '(' ')'
| '(' input_proc_parameters($parameters) ')'
;
%type output_parameters(<parametersClause>)
output_parameters($parameters)
:
| RETURNS '(' output_proc_parameters($parameters) ')'
;
%type input_proc_parameters(<parametersClause>)
input_proc_parameters($parameters)
: input_proc_parameter($parameters)
| input_proc_parameters ',' input_proc_parameter($parameters)
;
%type input_proc_parameter(<parametersClause>)
input_proc_parameter($parameters)
: column_domain_or_non_array_type collate_clause default_par_opt
{ $parameters->add(newNode<ParameterClause>($1, optName($2), $3)); }
;
%type output_proc_parameters(<parametersClause>)
output_proc_parameters($parameters)
: output_proc_parameter
| output_proc_parameters ',' output_proc_parameter($parameters)
;
%type output_proc_parameter(<parametersClause>)
output_proc_parameter($parameters)
: column_domain_or_non_array_type collate_clause
{ $parameters->add(newNode<ParameterClause>($1, optName($2))); }
;
%type <legacyField> 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 <valueSourceClause> default_par_opt
default_par_opt
: // nothing
{ $$ = NULL; }
| DEFAULT default_value
{
ValueSourceClause* clause = newNode<ValueSourceClause>();
clause->value = $2;
clause->source = makeParseStr(YYPOSNARG(1), YYPOSNARG(2));
$$ = clause;
}
| '=' default_value
{
ValueSourceClause* clause = newNode<ValueSourceClause>();
clause->value = $2;
clause->source = makeParseStr(YYPOSNARG(1), YYPOSNARG(2));
$$ = clause;
}
;
// FUNCTION
%type <createAlterFunctionNode> function_clause
function_clause
: psql_function_clause
| external_function_clause;
%type <createAlterFunctionNode> 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 <createAlterFunctionNode> external_function_clause
external_function_clause
: function_clause_start external_clause external_body_clause_opt
{
$$ = $1;
$$->external = $2;
if ($3)
$$->source = *$3;
}
;
%type <createAlterFunctionNode> function_clause_start
function_clause_start
: symbol_UDF_name
{ $$ = newNode<CreateAlterFunctionNode>(*$1); }
input_parameters(NOTRIAL(&$2->parameters))
RETURNS domain_or_non_array_type collate_clause deterministic_opt
{
$$ = $2;
$$->returnType = newNode<ParameterClause>($5, optName($6));
$$->deterministic = $7;
}
;
%type <boolVal> deterministic_opt
deterministic_opt
: { $$ = false; }
| NOT DETERMINISTIC { $$ = false; }
| DETERMINISTIC { $$ = true; }
;
%type <externalClause> external_clause
external_clause
: EXTERNAL NAME utf_string ENGINE valid_symbol_name
{
$$ = newNode<ExternalClause>();
$$->name = *$3;
$$->engine = *$5;
}
| EXTERNAL ENGINE valid_symbol_name
{
$$ = newNode<ExternalClause>();
$$->engine = *$3;
}
;
%type <stringPtr> external_body_clause_opt
external_body_clause_opt
: /* nothing */ { $$ = NULL; }
| AS utf_string { $$ = $2; }
;
%type <createAlterFunctionNode> alter_function_clause
alter_function_clause
: function_clause
{
$$ = $1;
$$->alter = true;
$$->create = false;
}
;
%type <createAlterFunctionNode> replace_function_clause
replace_function_clause
: function_clause
{
$$ = $1;
$$->alter = true;
}
;
// PACKAGE
%type <createAlterPackageNode> package_clause
package_clause
: symbol_package_name AS BEGIN package_items_opt END
{
CreateAlterPackageNode* node = newNode<CreateAlterPackageNode>(*$1);
node->source = makeParseStr(YYPOSNARG(3), YYPOSNARG(5));
node->items = $4;
$$ = node;
}
;
%type <packageItems> package_items_opt
package_items_opt
: package_items
|
{ $$ = newNode<Array<CreateAlterPackageNode::Item> >(); }
;
%type <packageItems> package_items
package_items
: package_item
{
$$ = newNode<Array<CreateAlterPackageNode::Item> >();
$$->add($1);
}
| package_items package_item
{
$$ = $1;
$$->add($2);
}
;
%type <packageItem> package_item
package_item
: FUNCTION function_clause_start ';'
{ $$ = CreateAlterPackageNode::Item::create($2); }
| PROCEDURE procedure_clause_start ';'
{ $$ = CreateAlterPackageNode::Item::create($2); }
;
%type <createAlterPackageNode> alter_package_clause
alter_package_clause
: package_clause
{
$$ = $1;
$$->alter = true;
$$->create = false;
}
;
%type <createAlterPackageNode> replace_package_clause
replace_package_clause
: package_clause
{
$$ = $1;
$$->alter = true;
}
;
// PACKAGE BODY
%type <createPackageBodyNode> package_body_clause
package_body_clause
: symbol_package_name AS BEGIN package_items package_body_items_opt END
{
CreatePackageBodyNode* node = newNode<CreatePackageBodyNode>(*$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<CreatePackageBodyNode>(*$1);
node->source = makeParseStr(YYPOSNARG(3), YYPOSNARG(5));
node->items = $4;
$$ = node;
}
;
%type <packageItems> package_body_items_opt
package_body_items_opt
: /* nothing */ { $$ = newNode<Array<CreateAlterPackageNode::Item> >(); }
| package_body_items
;
%type <packageItems> package_body_items
package_body_items
: package_body_item
{
$$ = newNode<Array<CreateAlterPackageNode::Item> >();
$$->add($1);
}
| package_body_items package_body_item
{
$$ = $1;
$$->add($2);
}
;
%type <packageItem> 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 <compoundStmtNode> local_declaration_list
local_declaration_list
: /* nothing */ { $$ = NULL; }
| local_declarations
;
%type <compoundStmtNode> local_declarations
local_declarations
: local_declaration
{
$$ = newNode<CompoundStmtNode>();
$$->statements.add($1);
}
| local_declarations local_declaration
{
$1->statements.add($2);
$$ = $1;
}
;
%type <stmtNode> 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
{ $<execBlockNode>$ = newNode<ExecBlockNode>(); }
input_parameters(NOTRIAL(&$<execBlockNode>4->parameters))
output_parameters(NOTRIAL(&$<execBlockNode>4->returns)) AS
local_declaration_list
full_proc_block
{
DeclareSubProcNode* node = newNode<DeclareSubProcNode>(*$3);
node->dsqlBlock = $<execBlockNode>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
{ $<execBlockNode>$ = newNode<ExecBlockNode>(); }
input_parameters(NOTRIAL(&$<execBlockNode>4->parameters))
RETURNS domain_or_non_array_type collate_clause deterministic_opt AS
local_declaration_list
full_proc_block
{
DeclareSubFuncNode* node = newNode<DeclareSubFuncNode>(*$3);
node->dsqlDeterministic = $9;
node->dsqlBlock = $<execBlockNode>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<ParameterClause>($<legacyField>7, optName($8)));
$$ = node;
}
;
%type <stmtNode> local_declaration_item
local_declaration_item
: var_declaration_item
| cursor_declaration_item
;
%type <stmtNode> var_declaration_item
var_declaration_item
: column_domain_or_non_array_type collate_clause default_par_opt
{
DeclareVariableNode* node = newNode<DeclareVariableNode>();
node->dsqlDef = newNode<ParameterClause>($1, optName($2), $3);
$$ = node;
}
;
var_decl_opt
: // nothing
| VARIABLE
;
%type <stmtNode> cursor_declaration_item
cursor_declaration_item
: symbol_cursor_name scroll_opt CURSOR FOR '(' select ')'
{
DeclareCursorNode* node = newNode<DeclareCursorNode>(*$1,
DeclareCursorNode::CUR_TYPE_EXPLICIT);
node->dsqlScroll = $2;
node->dsqlSelect = $6;
$$ = node;
}
;
%type <boolVal> scroll_opt
scroll_opt
: /* nothing */ { $$ = false; }
| NO SCROLL { $$ = false; }
| SCROLL { $$ = true; }
;
%type <stmtNode> proc_block
proc_block
: proc_statement
| full_proc_block
;
%type <stmtNode> full_proc_block
full_proc_block
: BEGIN full_proc_block_body END
{ $$ = newNode<LineColumnNode>(YYPOSNARG(1).firstLine, YYPOSNARG(1).firstColumn, $2); }
;
%type <stmtNode> full_proc_block_body
full_proc_block_body
: // nothing
{ $$ = newNode<CompoundStmtNode>(); }
| proc_statements
{
BlockNode* node = newNode<BlockNode>();
node->action = $1;
$$ = node;
}
| proc_statements excp_hndl_statements
{
BlockNode* node = newNode<BlockNode>();
node->action = $1;
node->handlers = $2;
$$ = node;
}
;
%type <compoundStmtNode> proc_statements
proc_statements
: proc_block
{
$$ = newNode<CompoundStmtNode>();
$$->statements.add($1);
}
| proc_statements proc_block
{
$1->statements.add($2);
$$ = $1;
}
;
%type <stmtNode> proc_statement
proc_statement
: simple_proc_statement ';'
{ $$ = newNode<LineColumnNode>(YYPOSNARG(1).firstLine, YYPOSNARG(1).firstColumn, $1); }
| complex_proc_statement
{ $$ = newNode<LineColumnNode>(YYPOSNARG(1).firstLine, YYPOSNARG(1).firstColumn, $1); }
;
%type <stmtNode> 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<SuspendNode>(); }
| EXIT { $$ = newNode<ExitNode>(); }
| RETURN value { $$ = newNode<ReturnNode>($2); }
;
%type <stmtNode> complex_proc_statement
complex_proc_statement
: in_autonomous_transaction
| if_then_else
| while
| for_select
| for_exec_into { $$ = $1; }
;
%type <stmtNode> in_autonomous_transaction
in_autonomous_transaction
: KW_IN AUTONOMOUS TRANSACTION DO proc_block
{
InAutonomousTransactionNode* node = newNode<InAutonomousTransactionNode>();
node->action = $5;
$$ = node;
}
;
%type <stmtNode> excp_statement
excp_statement
: EXCEPTION symbol_exception_name
{ $$ = newNode<ExceptionNode>(*$2); }
| EXCEPTION symbol_exception_name value
{ $$ = newNode<ExceptionNode>(*$2, $3); }
| EXCEPTION symbol_exception_name USING '(' value_list ')'
{ $$ = newNode<ExceptionNode>(*$2, (ValueExprNode*) NULL, $5); }
;
%type <stmtNode> raise_statement
raise_statement
: EXCEPTION { $$ = newNode<ExceptionNode>(); }
;
%type <stmtNode> for_select
for_select
: label_def_opt FOR select INTO variable_list cursor_def DO proc_block
{
ForNode* node = newNode<ForNode>();
node->dsqlLabelName = $1;
node->dsqlSelect = $3;
node->dsqlInto = $5;
node->dsqlCursor = $6;
node->statement = $8;
$$ = node;
}
;
%type <execStatementNode> exec_sql
exec_sql
: EXECUTE STATEMENT
{ $<execStatementNode>$ = newNode<ExecStatementNode>(); }
exec_stmt_inputs($<execStatementNode>3) exec_stmt_options($<execStatementNode>3)
{
$$ = $<execStatementNode>3;
}
;
%type <execStatementNode> exec_into
exec_into
: exec_sql INTO variable_list
{
$$ = $<execStatementNode>1;
$$->outputs = $3;
}
;
%type <execStatementNode> for_exec_into
for_exec_into
: label_def_opt FOR exec_into DO proc_block
{
$$ = $<execStatementNode>3;
$$->dsqlLabelName = $1;
$$->innerStmt = $5;
}
;
%type exec_stmt_inputs(<execStatementNode>)
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(<execStatementNode>)
named_params_list($execStatementNode)
: named_param($execStatementNode)
| named_params_list ',' named_param($execStatementNode)
;
%type named_param(<execStatementNode>)
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<ValueListNode>($3);
else
$execStatementNode->inputs->add($3);
}
;
%type not_named_params_list(<execStatementNode>)
not_named_params_list($execStatementNode)
: not_named_param($execStatementNode)
| not_named_params_list ',' not_named_param($execStatementNode)
;
%type not_named_param(<execStatementNode>)
not_named_param($execStatementNode)
: value
{
if (!$execStatementNode->inputs)
$execStatementNode->inputs = newNode<ValueListNode>($1);
else
$execStatementNode->inputs->add($1);
}
;
%type exec_stmt_options(<execStatementNode>)
exec_stmt_options($execStatementNode)
: // nothing
| exec_stmt_options_list($execStatementNode)
;
%type exec_stmt_options_list(<execStatementNode>)
exec_stmt_options_list($execStatementNode)
: exec_stmt_options_list exec_stmt_option($execStatementNode)
| exec_stmt_option($execStatementNode)
;
%type exec_stmt_option(<execStatementNode>)
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 <stmtNode> if_then_else
if_then_else
: IF '(' search_condition ')' THEN proc_block ELSE proc_block
{
IfNode* node = newNode<IfNode>();
node->condition = $3;
node->trueAction = $6;
node->falseAction = $8;
$$ = node;
}
| IF '(' search_condition ')' THEN proc_block
{
IfNode* node = newNode<IfNode>();
node->condition = $3;
node->trueAction = $6;
$$ = node;
}
;
%type <stmtNode> post_event
post_event
: POST_EVENT value event_argument_opt
{
PostEventNode* node = newNode<PostEventNode>();
node->event = $2;
node->argument = $3;
$$ = node;
}
;
%type <valueExprNode> event_argument_opt
event_argument_opt
: /* nothing */ { $$ = NULL; }
///| ',' value { $$ = $2; }
;
%type <stmtNode> singleton_select
singleton_select
: select INTO variable_list
{
ForNode* node = newNode<ForNode>();
node->dsqlSelect = $1;
node->dsqlInto = $3;
$$ = node;
}
;
%type <valueExprNode> variable
variable
: ':' symbol_variable_name
{
VariableNode* node = newNode<VariableNode>();
node->dsqlName = *$2;
$$ = node;
}
;
%type <valueListNode> variable_list
variable_list
: variable { $$ = newNode<ValueListNode>($1); }
| column_name { $$ = newNode<ValueListNode>($1); }
| variable_list ',' column_name { $$ = $1->add($3); }
| variable_list ',' variable { $$ = $1->add($3); }
;
%type <stmtNode> while
while
: label_def_opt WHILE '(' search_condition ')' DO proc_block
{
LoopNode* node = newNode<LoopNode>();
node->dsqlLabelName = $1;
node->dsqlExpr = $4;
node->statement = $7;
$$ = node;
}
;
%type <metaNamePtr> label_def_opt
label_def_opt
: /* nothing */ { $$ = NULL; }
| symbol_label_name ':' { $$ = $1; }
;
%type <stmtNode> breakleave
breakleave
: KW_BREAK
{ $$ = newNode<ContinueLeaveNode>(blr_leave); }
| LEAVE label_use_opt
{
ContinueLeaveNode* node = newNode<ContinueLeaveNode>(blr_leave);
node->dsqlLabelName = $2;
$$ = node;
}
;
%type <stmtNode> continue
continue
: CONTINUE label_use_opt
{
ContinueLeaveNode* node = newNode<ContinueLeaveNode>(blr_continue_loop);
node->dsqlLabelName = $2;
$$ = node;
}
;
%type <metaNamePtr> label_use_opt
label_use_opt
: /* nothing */ { $$ = NULL; }
| symbol_label_name
;
%type <declCursorNode> cursor_def
cursor_def
: // nothing
{ $$ = NULL; }
| AS CURSOR symbol_cursor_name
{ $$ = newNode<DeclareCursorNode>(*$3, DeclareCursorNode::CUR_TYPE_FOR); }
;
%type <compoundStmtNode> excp_hndl_statements
excp_hndl_statements
: excp_hndl_statement
{
$$ = newNode<CompoundStmtNode>();
$$->statements.add($1);
}
| excp_hndl_statements excp_hndl_statement
{
$1->statements.add($2);
$$ = $1;
}
;
%type <stmtNode> excp_hndl_statement
excp_hndl_statement
: WHEN
{ $<errorHandlerNode>$ = newNode<ErrorHandlerNode>(); }
errors(NOTRIAL(&$<errorHandlerNode>2->conditions)) DO proc_block
{
ErrorHandlerNode* node = $<errorHandlerNode>2;
node->action = $5;
$$ = node;
}
;
%type errors(<exceptionArray>)
errors($exceptionArray)
: err($exceptionArray)
| errors ',' err($exceptionArray)
;
%type err(<exceptionArray>)
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 <stmtNode> cursor_statement
cursor_statement
: open_cursor
| fetch_cursor
| close_cursor
;
%type <stmtNode> open_cursor
open_cursor
: OPEN symbol_cursor_name
{ $$ = newNode<CursorStmtNode>(blr_cursor_open, *$2); }
;
%type <stmtNode> close_cursor
close_cursor
: CLOSE symbol_cursor_name
{ $$ = newNode<CursorStmtNode>(blr_cursor_close, *$2); }
;
%type <stmtNode> fetch_cursor
fetch_cursor
: FETCH
{ $<cursorStmtNode>$ = newNode<CursorStmtNode>(blr_cursor_fetch_scroll); }
fetch_scroll($<cursorStmtNode>2) FROM symbol_cursor_name INTO variable_list
{
CursorStmtNode* cursorStmt = $<cursorStmtNode>2;
cursorStmt->dsqlName = *$5;
cursorStmt->dsqlIntoStmt = $7;
$$ = cursorStmt;
}
| FETCH symbol_cursor_name INTO variable_list
{ $$ = newNode<CursorStmtNode>(blr_cursor_fetch, *$2, $4); }
;
%type fetch_scroll(<cursorStmtNode>)
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 <stmtNode> exec_procedure
exec_procedure
: EXECUTE PROCEDURE symbol_procedure_name proc_inputs proc_outputs_opt
{ $$ = newNode<ExecProcedureNode>(QualifiedName(*$3), $4, $5); }
| EXECUTE PROCEDURE symbol_package_name '.' symbol_procedure_name proc_inputs proc_outputs_opt
{ $$ = newNode<ExecProcedureNode>(QualifiedName(*$5, *$3), $6, $7); }
;
%type <valueListNode> proc_inputs
proc_inputs
: /* nothing */ { $$ = NULL; }
| value_list { $$ = $1; }
| '(' value_list ')' { $$ = $2; }
;
%type <valueListNode> proc_outputs_opt
proc_outputs_opt
: /* nothing */ { $$ = NULL; }
| RETURNING_VALUES variable_list { $$ = $2; }
| RETURNING_VALUES '(' variable_list ')' { $$ = $3; }
;
// EXECUTE BLOCK
%type <execBlockNode> exec_block
exec_block
: EXECUTE BLOCK
{ $<execBlockNode>$ = newNode<ExecBlockNode>(); }
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(<parametersClause>)
block_input_params($parameters)
: // nothing
| '(' block_parameters($parameters) ')'
;
%type block_parameters(<parametersClause>)
block_parameters($parameters)
: block_parameter($parameters)
| block_parameters ',' block_parameter($parameters)
;
%type block_parameter(<parametersClause>)
block_parameter($parameters)
: column_domain_or_non_array_type collate_clause '=' parameter
{ $parameters->add(newNode<ParameterClause>($1, optName($2), (ValueSourceClause*) NULL, $4)); }
;
// CREATE VIEW
%type <createAlterViewNode> view_clause
view_clause
: simple_table_name column_parens_opt AS select_expr check_opt
{
CreateAlterViewNode* node = newNode<CreateAlterViewNode>($1, $2, $4);
node->source = makeParseStr(YYPOSNARG(4), YYPOSNARG(5));
node->withCheckOption = $5;
$$ = node;
}
;
%type <ddlNode> replace_view_clause
replace_view_clause
: view_clause
{
$1->alter = true;
$$ = $1;
}
;
%type <ddlNode> alter_view_clause
alter_view_clause
: view_clause
{
$1->alter = true;
$1->create = false;
$$ = $1;
}
;
%type <boolVal> check_opt
check_opt
: /* nothing */ { $$ = false; }
| WITH CHECK OPTION { $$ = true; }
;
// CREATE TRIGGER
%type <createAlterTriggerNode> trigger_clause
trigger_clause
: symbol_trigger_name trigger_active trigger_type trigger_position
AS local_declaration_list full_proc_block
{
$$ = newNode<CreateAlterTriggerNode>(*$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<CreateAlterTriggerNode>(*$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<CreateAlterTriggerNode>(*$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<CreateAlterTriggerNode>(*$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<CreateAlterTriggerNode>(*$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<CreateAlterTriggerNode>(*$1);
$$->active = $4;
$$->type = $5;
$$->position = $6;
$$->relationName = *$3;
$$->external = $7;
if ($8)
$$->source = *$8;
}
;
%type <createAlterTriggerNode> replace_trigger_clause
replace_trigger_clause
: trigger_clause
{
$$ = $1;
$$->alter = true;
}
;
%type <nullableBoolVal> trigger_active
trigger_active
: ACTIVE
{ $$ = Nullable<bool>::val(true); }
| INACTIVE
{ $$ = Nullable<bool>::val(false); }
|
{ $$ = Nullable<bool>::empty(); }
;
%type <uint64Val> 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 <uint64Val> 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 <uint64Val> trigger_ddl_type
trigger_ddl_type
: trigger_ddl_type_items
| ANY DDL STATEMENT
{
$$ = TRIGGER_TYPE_DDL | (0x7FFFFFFFFFFFFFFFULL & ~(FB_UINT64) TRIGGER_TYPE_MASK & ~1ULL);
}
;
%type <uint64Val> 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 <uint64Val> trigger_type_prefix
trigger_type_prefix
: BEFORE { $$ = 0; }
| AFTER { $$ = 1; }
;
%type <uint64Val> 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 <nullableIntVal> trigger_position
trigger_position
: /* nothing */ { $$ = Nullable<int>::empty(); }
| POSITION nonneg_short_integer { $$ = Nullable<int>::val($2); }
;
// ALTER statement
%type <ddlNode> alter
alter
: ALTER alter_clause { $$ = $2; }
| set_generator_clause { $$ = $1; }
;
%type <ddlNode> alter_clause
alter_clause
: EXCEPTION alter_exception_clause { $$ = $2; }
| TABLE simple_table_name
{ $$ = newNode<AlterRelationNode>($2); }
alter_ops($<relationNode>3)
{ $$ = $<relationNode>3; }
| VIEW alter_view_clause { $$ = $2; }
| TRIGGER alter_trigger_clause { $$ = $2; }
| PROCEDURE alter_procedure_clause { $$ = $2; }
| PACKAGE alter_package_clause { $$ = $2; }
| DATABASE
{ $<alterDatabaseNode>$ = newNode<AlterDatabaseNode>(); }
alter_db($<alterDatabaseNode>2)
{ $$ = $<alterDatabaseNode>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 <alterDomainNode> alter_domain
alter_domain
: keyword_or_column
{ $<alterDomainNode>$ = newNode<AlterDomainNode>(*$1); }
alter_domain_ops($2)
{ $$ = $2; }
;
%type alter_domain_ops(<alterDomainNode>)
alter_domain_ops($alterDomainNode)
: alter_domain_op($alterDomainNode)
| alter_domain_ops alter_domain_op($alterDomainNode)
;
%type alter_domain_op(<alterDomainNode>)
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(<relationNode>)
alter_ops($relationNode)
: alter_op($relationNode)
| alter_ops ',' alter_op($relationNode)
;
%type alter_op(<relationNode>)
alter_op($relationNode)
: DROP symbol_column_name drop_behaviour
{
RelationNode::DropColumnClause* clause = newNode<RelationNode::DropColumnClause>();
clause->name = *$2;
clause->cascade = $3;
$relationNode->clauses.add(clause);
}
| DROP CONSTRAINT symbol_constraint_name
{
RelationNode::DropConstraintClause* clause = newNode<RelationNode::DropConstraintClause>();
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<RelationNode::AlterColPosClause>();
clause->name = *$2;
clause->newPos = $4;
$relationNode->clauses.add(clause);
}
| col_opt alter_column_name TO symbol_column_name
{
RelationNode::AlterColNameClause* clause = newNode<RelationNode::AlterColNameClause>();
clause->fromName = *$2;
clause->toName = *$4;
$relationNode->clauses.add(clause);
}
| col_opt alter_column_name KW_NULL
{
RelationNode::AlterColNullClause* clause = newNode<RelationNode::AlterColNullClause>();
clause->name = *$2;
clause->notNullFlag = false;
$relationNode->clauses.add(clause);
}
| col_opt alter_column_name NOT KW_NULL
{
RelationNode::AlterColNullClause* clause = newNode<RelationNode::AlterColNullClause>();
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<RelationNode::AlterColTypeClause>();
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<RelationNode::AlterColTypeClause>();
clause->field = newNode<dsql_fld>();
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<RelationNode::AlterColTypeClause>();
clause->field = newNode<dsql_fld>();
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<RelationNode::AlterColTypeClause>();
clause->field = newNode<dsql_fld>();
clause->field->fld_name = *$2;
clause->defaultValue = $4;
$relationNode->clauses.add(clause);
}
| col_opt symbol_column_name DROP DEFAULT
{
RelationNode::AlterColTypeClause* clause = newNode<RelationNode::AlterColTypeClause>();
clause->field = newNode<dsql_fld>();
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<RelationNode::AlterColTypeClause>();
clause->field = newNode<dsql_fld>();
clause->field->fld_name = *$2;
clause->identityRestart = true;
clause->identityRestartValue = $4;
$relationNode->clauses.add(clause);
}
;
%type <metaNamePtr> 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 <metaNamePtr> 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 <legacyField> alter_data_type_or_domain
alter_data_type_or_domain
: non_array_type
| symbol_column_name
{
$$ = newNode<dsql_fld>();
$$->typeOfName = *$1;
}
;
%type <boolVal> drop_behaviour
drop_behaviour
: { $$ = false; }
| RESTRICT { $$ = false; }
| CASCADE { $$ = true; }
;
%type <ddlNode> alter_index_clause
alter_index_clause
: symbol_index_name ACTIVE { $$ = newNode<AlterIndexNode>(*$1, true); }
| symbol_index_name INACTIVE { $$ = newNode<AlterIndexNode>(*$1, false); }
;
%type <ddlNode> alter_udf_clause
alter_udf_clause
: symbol_UDF_name entry_op module_op
{
AlterExternalFunctionNode* node = newNode<AlterExternalFunctionNode>(*$1);
if ($2)
node->clauses.name = *$2;
if ($3)
node->clauses.udfModule = *$3;
$$ = node;
}
;
%type <stringPtr> entry_op
entry_op
: /* nothing */ { $$ = NULL; }
| ENTRY_POINT utf_string { $$ = $2; }
;
%type <stringPtr> module_op
module_op
: /* nothing */ { $$ = NULL; }
| MODULE_NAME utf_string { $$ = $2; }
;
%type <ddlNode> alter_role_clause
alter_role_clause
: symbol_role_name alter_role_enable AUTO ADMIN MAPPING
{ $$ = newNode<AlterRoleNode>(*$1, $2); }
;
%type <boolVal> alter_role_enable
alter_role_enable
: SET { $$ = true; }
| DROP { $$ = false; }
;
// ALTER DATABASE
%type alter_db(<alterDatabaseNode>)
alter_db($alterDatabaseNode)
: db_alter_clause($alterDatabaseNode)
| alter_db db_alter_clause($alterDatabaseNode)
;
%type db_alter_clause(<alterDatabaseNode>)
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 <createAlterTriggerNode> alter_trigger_clause
alter_trigger_clause
: symbol_trigger_name trigger_active trigger_type_opt trigger_position
AS local_declaration_list full_proc_block
{
$$ = newNode<CreateAlterTriggerNode>(*$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<CreateAlterTriggerNode>(*$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<CreateAlterTriggerNode>(*$1);
$$->alter = true;
$$->create = false;
$$->active = $2;
$$->type = $3;
$$->position = $4;
}
;
%type <nullableUint64Val> 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<FB_UINT64>::val($1 + $2 - 1); }
|
{ $$ = Nullable<FB_UINT64>::empty(); }
;
// DROP metadata operations
%type <ddlNode> drop
drop
: DROP drop_clause { $$ = $2; }
;
%type <ddlNode> drop_clause
drop_clause
: EXCEPTION symbol_exception_name
{ $$ = newNode<DropExceptionNode>(*$2); }
| INDEX symbol_index_name
{ $$ = newNode<DropIndexNode>(*$2); }
| PROCEDURE symbol_procedure_name
{ $$ = newNode<DropProcedureNode>(*$2); }
| TABLE symbol_table_name
{ $$ = newNode<DropRelationNode>(*$2, false); }
| TRIGGER symbol_trigger_name
{ $$ = newNode<DropTriggerNode>(*$2); }
| VIEW symbol_view_name
{ $$ = newNode<DropRelationNode>(*$2, true); }
| FILTER symbol_filter_name
{ $$ = newNode<DropFilterNode>(*$2); }
| DOMAIN symbol_domain_name
{ $$ = newNode<DropDomainNode>(*$2); }
| EXTERNAL FUNCTION symbol_UDF_name
{ $$ = newNode<DropFunctionNode>(*$3); }
| FUNCTION symbol_UDF_name
{ $$ = newNode<DropFunctionNode>(*$2); }
| SHADOW pos_short_integer
{ $$ = newNode<DropShadowNode>($2); }
| ROLE symbol_role_name
{ $$ = newNode<DropRoleNode>(*$2); }
| GENERATOR symbol_generator_name
{ $$ = newNode<DropSequenceNode>(*$2); }
| SEQUENCE symbol_generator_name
{ $$ = newNode<DropSequenceNode>(*$2); }
| COLLATION symbol_collation_name
{ $$ = newNode<DropCollationNode>(*$2); }
| USER symbol_user_name
{ $$ = newNode<DropUserNode>(*$2); }
| PACKAGE symbol_package_name
{ $$ = newNode<DropPackageNode>(*$2); }
| PACKAGE BODY symbol_package_name
{ $$ = newNode<DropPackageBodyNode>(*$3); }
;
// these are the allowable datatypes
%type <legacyField> data_type
data_type
: non_array_type
| array_type
;
%type <legacyField> 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 <legacyField> domain_or_non_array_type_name
domain_or_non_array_type_name
: non_array_type
| domain_type
;
%type <legacyField> domain_type
domain_type
: KW_TYPE OF symbol_column_name
{
$$ = newNode<dsql_fld>();
$$->typeOfName = *$3;
}
| KW_TYPE OF COLUMN symbol_column_name '.' symbol_column_name
{
$$ = newNode<dsql_fld>();
$$->typeOfName = *$6;
$$->typeOfTable = *$4;
}
| symbol_column_name
{
$$ = newNode<dsql_fld>();
$$->typeOfName = *$1;
$$->fullDomain = true;
}
;
%type <legacyField> non_array_type
non_array_type
: simple_type
| blob_type
;
%type <legacyField> 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 <valueListNode> array_spec
array_spec
: array_range
| array_spec ',' array_range { $$ = $1->add($3->items[0])->add($3->items[1]); }
;
%type <valueListNode> array_range
array_range
: signed_long_integer
{
if ($1 < 1)
$$ = newNode<ValueListNode>(MAKE_const_slong($1))->add(MAKE_const_slong(1));
else
$$ = newNode<ValueListNode>(MAKE_const_slong(1))->add(MAKE_const_slong($1));
}
| signed_long_integer ':' signed_long_integer
{ $$ = newNode<ValueListNode>(MAKE_const_slong($1))->add(MAKE_const_slong($3)); }
;
%type <legacyField> simple_type
simple_type
: non_charset_simple_type
| character_type charset_clause
{
$$ = $1;
if ($2)
$$->charSet = *$2;
}
;
%type <legacyField> non_charset_simple_type
non_charset_simple_type
: national_character_type
| numeric_type
| float_type
| BIGINT
{
$$ = newNode<dsql_fld>();
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<dsql_fld>();
$$->dtype = dtype_long;
$$->length = sizeof(SLONG);
}
| SMALLINT
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_short;
$$->length = sizeof(SSHORT);
}
| DATE
{
$$ = newNode<dsql_fld>();
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<dsql_fld>();
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<dsql_fld>();
$$->dtype = dtype_timestamp;
$$->length = sizeof(GDS_TIMESTAMP);
}
| KW_BOOLEAN
{
$$ = newNode<dsql_fld>();
$$->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 <legacyField> blob_type
blob_type
: BLOB { $$ = newNode<dsql_fld>(); } 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<dsql_fld>();
$$->dtype = dtype_blob;
$$->length = sizeof(ISC_QUAD);
$$->segLength = (USHORT) $3;
$$->subType = 0;
}
| BLOB '(' unsigned_short_integer ',' signed_short_integer ')'
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_blob;
$$->length = sizeof(ISC_QUAD);
$$->segLength = (USHORT) $3;
$$->subType = (USHORT) $5;
}
| BLOB '(' ',' signed_short_integer ')'
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_blob;
$$->length = sizeof(ISC_QUAD);
$$->segLength = 80;
$$->subType = (USHORT) $4;
}
;
%type <uintVal> blob_segsize
blob_segsize
: /* nothing */ { $$ = (USHORT) 80; }
| SEGMENT KW_SIZE unsigned_short_integer { $$ = (USHORT) $3; }
;
%type blob_subtype(<legacyField>)
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 <metaNamePtr> charset_clause
charset_clause
: /* nothing */ { $$ = NULL; }
| CHARACTER SET symbol_character_set_name { $$ = $3; }
;
// character type
%type <legacyField> national_character_type
national_character_type
: national_character_keyword '(' pos_short_integer ')'
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_text;
$$->charLength = (USHORT) $3;
$$->flags |= FLD_national;
}
| national_character_keyword
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_text;
$$->charLength = 1;
$$->flags |= FLD_national;
}
| national_character_keyword VARYING '(' pos_short_integer ')'
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_varying;
$$->charLength = (USHORT) $4;
$$->flags |= FLD_national;
}
;
%type <legacyField> character_type
character_type
: character_keyword '(' pos_short_integer ')'
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_text;
$$->charLength = (USHORT) $3;
}
| character_keyword
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_text;
$$->charLength = 1;
}
| varying_keyword '(' pos_short_integer ')'
{
$$ = newNode<dsql_fld>();
$$->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 <legacyField> 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 <legacyField> prec_scale
prec_scale
: // nothing
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_long;
$$->length = sizeof(SLONG);
$$->precision = 9;
}
| '(' signed_long_integer ')'
{
$$ = newNode<dsql_fld>();
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<dsql_fld>();
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 <legacyField> float_type
float_type
: KW_FLOAT precision_opt
{
$$ = newNode<dsql_fld>();
if ($2 > 7)
{
$$->dtype = dtype_double;
$$->length = sizeof(double);
}
else
{
$$->dtype = dtype_real;
$$->length = sizeof(float);
}
}
| KW_LONG KW_FLOAT precision_opt
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_double;
$$->length = sizeof(double);
}
| REAL
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_real;
$$->length = sizeof(float);
}
| KW_DOUBLE PRECISION
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_double;
$$->length = sizeof(double);
}
;
%type <int32Val> precision_opt
precision_opt
: /* nothing */ { $$ = 0; }
| '(' nonneg_short_integer ')' { $$ = $2; }
;
// transaction statements
%type <stmtNode> savepoint
savepoint
: set_savepoint
| release_savepoint
| undo_savepoint
;
%type <stmtNode> set_savepoint
set_savepoint
: SAVEPOINT symbol_savepoint_name
{
UserSavepointNode* node = newNode<UserSavepointNode>();
node->command = UserSavepointNode::CMD_SET;
node->name = *$2;
$$ = node;
}
;
%type <stmtNode> release_savepoint
release_savepoint
: RELEASE SAVEPOINT symbol_savepoint_name release_only_opt
{
UserSavepointNode* node = newNode<UserSavepointNode>();
node->command = ($4 ? UserSavepointNode::CMD_RELEASE_ONLY : UserSavepointNode::CMD_RELEASE);
node->name = *$3;
$$ = node;
}
;
%type <boolVal> release_only_opt
release_only_opt
: /* nothing */ { $$ = false; }
| ONLY { $$ = true; }
;
%type <stmtNode> undo_savepoint
undo_savepoint
: ROLLBACK optional_work TO optional_savepoint symbol_savepoint_name
{
UserSavepointNode* node = newNode<UserSavepointNode>();
node->command = UserSavepointNode::CMD_ROLLBACK;
node->name = *$5;
$$ = node;
}
;
optional_savepoint
: // nothing
| SAVEPOINT
;
%type <traNode> commit
commit
: COMMIT optional_work optional_retain
{ $$ = newNode<CommitRollbackNode>(CommitRollbackNode::CMD_COMMIT, $3); }
;
%type <traNode> rollback
rollback
: ROLLBACK optional_work optional_retain
{ $$ = newNode<CommitRollbackNode>(CommitRollbackNode::CMD_ROLLBACK, $3); }
;
optional_work
: // nothing
| WORK
;
%type <boolVal> optional_retain
optional_retain
: /* nothing */ { $$ = false; }
| RETAIN opt_snapshot { $$ = true; }
;
opt_snapshot
: // nothing
| SNAPSHOT
;
%type <setTransactionNode> set_transaction
set_transaction
: SET TRANSACTION
{ $$ = newNode<SetTransactionNode>(); }
tran_option_list_opt($3)
{ $$ = $3; }
;
%type tran_option_list_opt(<setTransactionNode>)
tran_option_list_opt($setTransactionNode)
: // nothing
| tran_option_list($setTransactionNode)
;
%type tran_option_list(<setTransactionNode>)
tran_option_list($setTransactionNode)
: tran_option($setTransactionNode)
| tran_option_list tran_option($setTransactionNode)
;
%type tran_option(<setTransactionNode>)
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 <uintVal> isolation_mode
isolation_mode
: ISOLATION LEVEL iso_mode { $$ = $3;}
| iso_mode
;
%type <uintVal> iso_mode
iso_mode
: snap_shot
| READ UNCOMMITTED version_mode { $$ = $3; }
| READ COMMITTED version_mode { $$ = $3; }
;
%type <uintVal> snap_shot
snap_shot
: SNAPSHOT { $$ = SetTransactionNode::ISO_LEVEL_CONCURRENCY; }
| SNAPSHOT TABLE { $$ = SetTransactionNode::ISO_LEVEL_CONSISTENCY; }
| SNAPSHOT TABLE STABILITY { $$ = SetTransactionNode::ISO_LEVEL_CONSISTENCY; }
;
%type <uintVal> 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 <uintVal> lock_type
lock_type
: /* nothing */ { $$ = 0; }
| KW_SHARED { $$ = SetTransactionNode::LOCK_MODE_SHARED; }
| PROTECTED { $$ = SetTransactionNode::LOCK_MODE_PROTECTED; }
;
%type <uintVal> lock_mode
lock_mode
: READ { $$ = SetTransactionNode::LOCK_MODE_READ; }
| WRITE { $$ = SetTransactionNode::LOCK_MODE_WRITE; }
;
%type restr_list(<setTransactionNode>)
restr_list($setTransactionNode)
: restr_option
{ $setTransactionNode->reserveList.add($1); }
| restr_list ',' restr_option
{ $setTransactionNode->reserveList.add($3); }
;
%type <setTransactionRestrictionClause> restr_option
restr_option
: table_list table_lock
{ $$ = newNode<SetTransactionNode::RestrictionOption>($1, $2); }
;
%type <uintVal> table_lock
table_lock
: /* nothing */ { $$ = 0; }
| FOR lock_type lock_mode { $$ = $2 | $3; }
;
%type <metaNameArray> table_list
table_list
: symbol_table_name
{
ObjectsArray<MetaName>* node = newNode<ObjectsArray<MetaName> >();
node->add(*$1);
$$ = node;
}
| table_list ',' symbol_table_name
{
ObjectsArray<MetaName>* node = $1;
node->add(*$3);
$$ = node;
}
;
%type <ddlNode> set_statistics
set_statistics
: SET STATISTICS INDEX symbol_index_name
{ $$ = newNode<SetStatisticsNode>(*$4); }
;
%type <ddlNode> comment
comment
: COMMENT ON ddl_type0 IS ddl_desc
{ $$ = newNode<CommentOnNode>($3, "", "", *$5); }
| COMMENT ON ddl_type1 symbol_ddl_name IS ddl_desc
{ $$ = newNode<CommentOnNode>($3, *$4, "", *$6); }
| COMMENT ON ddl_type2 symbol_ddl_name ddl_subname IS ddl_desc
{ $$ = newNode<CommentOnNode>($3, *$4, *$5, *$7); }
| COMMENT ON USER symbol_user_name IS ddl_desc
{
CreateAlterUserNode* node =
newNode<CreateAlterUserNode>(CreateAlterUserNode::USER_MOD, *$4);
node->comment = $6;
$$ = node;
}
;
%type <intVal> ddl_type0
ddl_type0
: DATABASE
{ $$ = obj_database; }
;
%type <intVal> 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 <intVal> ddl_type2
ddl_type2
: COLUMN { $$ = obj_relation; }
| ddl_param_opt PARAMETER { $$ = $1; }
;
%type <intVal> ddl_param_opt
ddl_param_opt
: { $$ = obj_parameter; }
| PROCEDURE { $$ = obj_procedure; }
| FUNCTION { $$ = obj_udf; }
;
%type <metaNamePtr> ddl_subname
ddl_subname
: '.' symbol_ddl_name { $$ = $2; }
;
%type <stringPtr> ddl_desc
ddl_desc
: utf_string { $$ = $1; }
| KW_NULL { $$ = newString(""); }
;
// SELECT statement
%type <selectNode> select
select
: select_expr for_update_clause lock_clause
{
SelectNode* node = newNode<SelectNode>();
node->dsqlExpr = $1;
node->dsqlForUpdate = $2;
node->dsqlWithLock = $3;
$$ = node;
}
;
%type <boolVal> for_update_clause
for_update_clause
: /* nothing */ { $$ = false; }
| FOR UPDATE for_update_list { $$ = true; /* for_update_list is ignored */ }
;
%type <valueListNode> for_update_list
for_update_list
: /* nothing */ { $$ = NULL; }
| OF column_list { $$ = $2; }
;
%type <boolVal> lock_clause
lock_clause
: /* nothing */ { $$ = false; }
| WITH LOCK { $$ = true; }
;
// SELECT expression
%type <selectExprNode> select_expr
select_expr
: with_clause select_expr_body order_clause rows_clause
{
SelectExprNode* node = $$ = newNode<SelectExprNode>();
node->querySpec = $2;
node->orderClause = $3;
node->rowsClause = $4;
node->withClause = $1;
}
;
%type <withClause> with_clause
with_clause
: // nothing
{ $$ = NULL; }
| WITH RECURSIVE with_list
{
$$ = $3;
$$->recursive = true;
}
| WITH with_list
{ $$ = $2; }
;
%type <withClause> with_list
with_list
: with_item
{
$$ = newNode<WithClause>();
$$->add($1);
}
| with_item ',' with_list
{
$$ = $3;
$$->add($1);
}
;
%type <selectExprNode> 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 <selectExprNode> column_select
column_select
: select_expr
{
$$ = $1;
$$->dsqlFlags |= RecordSourceNode::DFLAG_VALUE;
}
;
%type <valueExprNode> column_singleton
column_singleton
: column_select
{
$1->dsqlFlags |= RecordSourceNode::DFLAG_SINGLETON;
$$ = newNode<SubQueryNode>(blr_via, $1);
}
;
%type <recSourceNode> select_expr_body
select_expr_body
: query_term
{ $$ = $1; }
| select_expr_body UNION distinct_noise query_term
{
UnionSourceNode* node = $1->as<UnionSourceNode>();
if (node && !node->dsqlAll)
node->dsqlClauses->add($4);
else
{
node = newNode<UnionSourceNode>();
node->dsqlClauses = newNode<RecSourceListNode>($1)->add($4);
}
$$ = node;
}
| select_expr_body UNION ALL query_term
{
UnionSourceNode* node = $1->as<UnionSourceNode>();
if (node && node->dsqlAll)
node->dsqlClauses->add($4);
else
{
node = newNode<UnionSourceNode>();
node->dsqlAll = true;
node->dsqlClauses = newNode<RecSourceListNode>($1)->add($4);
}
$$ = node;
}
;
%type <rseNode> query_term
query_term
: query_spec
;
%type <rseNode> query_spec
query_spec
: SELECT limit_clause
distinct_clause
select_list
from_clause
where_clause
group_clause
having_clause
plan_clause
{
RseNode* rse = newNode<RseNode>();
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 <valueListNode> limit_clause
limit_clause
: /* nothing */ { $$ = NULL; }
| first_clause skip_clause { $$ = newNode<ValueListNode>($2)->add($1); }
| first_clause { $$ = newNode<ValueListNode>(1u)->add($1); }
| skip_clause { $$ = newNode<ValueListNode>($1)->add(NULL); }
;
%type <valueExprNode> first_clause
first_clause
: FIRST long_integer { $$ = MAKE_const_slong($2); }
| FIRST '(' value ')' { $$ = $3; }
| FIRST parameter { $$ = $2; }
;
%type <valueExprNode> skip_clause
skip_clause
: SKIP long_integer { $$ = MAKE_const_slong($2); }
| SKIP '(' value ')' { $$ = $3; }
| SKIP parameter { $$ = $2; }
;
%type <valueListNode> distinct_clause
distinct_clause
: DISTINCT { $$ = newNode<ValueListNode>(0); }
| all_noise { $$ = NULL; }
;
%type <valueListNode> select_list
select_list
: select_items { $$ = $1; }
| '*' { $$ = NULL; }
;
%type <valueListNode> select_items
select_items
: select_item { $$ = newNode<ValueListNode>($1); }
| select_items ',' select_item { $$ = $1->add($3); }
;
%type <valueExprNode> select_item
select_item
: value_opt_alias
| symbol_table_alias_name '.' '*'
{
FieldNode* fieldNode = newNode<FieldNode>();
fieldNode->dsqlQualifier = *$1;
$$ = fieldNode;
}
;
%type <valueExprNode> value_opt_alias
value_opt_alias
: value
| value as_noise symbol_item_alias_name { $$ = newNode<DsqlAliasNode>(*$3, $1); }
;
as_noise
:
| AS
;
// FROM clause
%type <recSourceListNode> from_clause
from_clause
: FROM from_list { $$ = $2; }
;
%type <recSourceListNode> from_list
from_list
: table_reference { $$ = newNode<RecSourceListNode>($1); }
| from_list ',' table_reference { $$ = $1->add($3); }
;
%type <recSourceNode> table_reference
table_reference
: joined_table
| table_primary
;
%type <recSourceNode> table_primary
table_primary
: table_proc
| derived_table { $$ = $1; }
| '(' joined_table ')' { $$ = $2; }
;
%type <selectExprNode> 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 <metaNamePtr> correlation_name
correlation_name
: /* nothing */ { $$ = NULL; }
| symbol_table_alias_name
;
%type <metaNameArray> derived_column_list
derived_column_list
: /* nothing */ { $$ = NULL; }
| '(' alias_list ')' { $$ = $2; }
;
%type <metaNameArray> alias_list
alias_list
: symbol_item_alias_name
{
ObjectsArray<MetaName>* node = newNode<ObjectsArray<MetaName> >();
node->add(*$1);
$$ = node;
}
| alias_list ',' symbol_item_alias_name
{
ObjectsArray<MetaName>* node = $1;
node->add(*$3);
$$ = node;
}
;
%type <recSourceNode> joined_table
joined_table
: cross_join
| natural_join
| qualified_join
;
%type <recSourceNode> cross_join
cross_join
: table_reference CROSS JOIN table_primary
{
RseNode* rse = newNode<RseNode>();
rse->dsqlExplicitJoin = true;
rse->rse_jointype = blr_inner;
rse->dsqlFrom = newNode<RecSourceListNode>($1)->add($4);
$$ = rse;
}
;
%type <recSourceNode> natural_join
natural_join
: table_reference NATURAL join_type JOIN table_primary
{
RseNode* rse = newNode<RseNode>();
rse->dsqlExplicitJoin = true;
rse->rse_jointype = $3;
rse->dsqlFrom = newNode<RecSourceListNode>($1)->add($5);
rse->dsqlJoinUsing = newNode<ValueListNode>(0u); // using list with size 0 -> natural
$$ = rse;
}
;
%type <recSourceNode> qualified_join
qualified_join
: table_reference join_type JOIN table_reference join_condition
{
RseNode* rse = newNode<RseNode>();
rse->dsqlExplicitJoin = true;
rse->rse_jointype = $2;
rse->dsqlFrom = newNode<RecSourceListNode>($1);
rse->dsqlFrom->add($4);
rse->dsqlWhere = $5;
$$ = rse;
}
| table_reference join_type JOIN table_reference named_columns_join
{
RseNode* rse = newNode<RseNode>();
rse->dsqlExplicitJoin = true;
rse->rse_jointype = $2;
rse->dsqlFrom = newNode<RecSourceListNode>($1);
rse->dsqlFrom->add($4);
rse->dsqlJoinUsing = $5;
$$ = rse;
}
;
%type <boolExprNode> join_condition
join_condition
: ON search_condition { $$ = $2; }
;
%type <valueListNode> named_columns_join
named_columns_join
: USING '(' column_list ')' { $$ = $3; }
;
%type <recSourceNode> table_proc
table_proc
: symbol_procedure_name table_proc_inputs as_noise symbol_table_alias_name
{
ProcedureSourceNode* node = newNode<ProcedureSourceNode>(QualifiedName(*$1));
node->sourceList = $2;
node->alias = $4->c_str();
$$ = node;
}
| symbol_procedure_name table_proc_inputs
{
ProcedureSourceNode* node = newNode<ProcedureSourceNode>(QualifiedName(*$1));
node->sourceList = $2;
$$ = node;
}
| symbol_package_name '.' symbol_procedure_name table_proc_inputs as_noise symbol_table_alias_name
{
ProcedureSourceNode* node = newNode<ProcedureSourceNode>(
QualifiedName(*$3, *$1));
node->sourceList = $4;
node->alias = $6->c_str();
$$ = node;
}
| symbol_package_name '.' symbol_procedure_name table_proc_inputs
{
ProcedureSourceNode* node = newNode<ProcedureSourceNode>(
QualifiedName(*$3, *$1));
node->sourceList = $4;
$$ = node;
}
;
%type <valueListNode> table_proc_inputs
table_proc_inputs
: /* nothing */ { $$ = NULL; }
| '(' value_list ')' { $$ = $2; }
;
%type <relSourceNode> table_name
table_name
: simple_table_name
| symbol_table_name as_noise symbol_table_alias_name
{
RelationSourceNode* node = newNode<RelationSourceNode>(*$1);
node->alias = $3->c_str();
$$ = node;
}
;
%type <relSourceNode> simple_table_name
simple_table_name
: symbol_table_name
{ $$ = newNode<RelationSourceNode>(*$1); }
;
%type <blrOp> 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 <valueListNode> group_clause
group_clause
: /* nothing */ { $$ = NULL; }
| GROUP BY group_by_list { $$ = $3; }
;
%type <valueListNode> group_by_list
group_by_list
: group_by_item { $$ = newNode<ValueListNode>($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 <valueExprNode> group_by_item
group_by_item
: value
;
%type <boolExprNode> having_clause
having_clause
: /* nothing */ { $$ = NULL; }
| HAVING search_condition { $$ = $2; }
;
%type <boolExprNode> where_clause
where_clause
: /* nothing */ { $$ = NULL; }
| WHERE search_condition { $$ = $2; }
;
// PLAN clause to specify an access plan for a query
%type <planNode> plan_clause
plan_clause
: /* nothing */ { $$ = NULL; }
| PLAN plan_expression { $$ = $2; }
;
%type <planNode> plan_expression
plan_expression
: plan_type { $$ = newNode<PlanNode>(PlanNode::TYPE_RETRIEVE); } '(' plan_item_list($2) ')'
{ $$ = $2; }
;
plan_type
: // nothing
| JOIN
| SORT MERGE
| MERGE
| HASH
| SORT
;
%type plan_item_list(<planNode>)
plan_item_list($planNode)
: plan_item { $planNode->subNodes.add($1); }
| plan_item_list ',' plan_item { $planNode->subNodes.insert(0, $3); }
;
%type <planNode> plan_item
plan_item
: table_or_alias_list access_type
{
$$ = newNode<PlanNode>(PlanNode::TYPE_RETRIEVE);
$$->dsqlNames = $1;
$$->accessType = $2;
}
| plan_expression
;
%type <metaNameArray> table_or_alias_list
table_or_alias_list
: symbol_table_name
{
ObjectsArray<MetaName>* node = newNode<ObjectsArray<MetaName> >();
node->add(*$1);
$$ = node;
}
| table_or_alias_list symbol_table_name
{
ObjectsArray<MetaName>* node = $1;
node->add(*$2);
$$ = node;
}
;
%type <accessType> access_type
access_type
: NATURAL
{ $$ = newNode<PlanNode::AccessType>(PlanNode::AccessType::TYPE_SEQUENTIAL); }
| INDEX { $$ = newNode<PlanNode::AccessType>(PlanNode::AccessType::TYPE_INDICES); }
'(' index_list($2) ')'
{ $$ = $2; }
| ORDER { $$ = newNode<PlanNode::AccessType>(PlanNode::AccessType::TYPE_NAVIGATIONAL); }
symbol_index_name extra_indices_opt($2)
{
$$ = $2;
$$->items.insert(0).indexName = *$3;
}
;
%type index_list(<accessType>)
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(<accessType>)
extra_indices_opt($accessType)
: // nothing
| INDEX '(' index_list($accessType) ')'
;
// ORDER BY clause
%type <valueListNode> order_clause
order_clause
: /* nothing */ { $$ = NULL; }
| ORDER BY order_list { $$ = $3; }
;
%type <valueListNode> order_list
order_list
: order_item { $$ = newNode<ValueListNode>($1); }
| order_list ',' order_item { $$ = $1->add($3); }
;
%type <valueExprNode> order_item
order_item
: value order_direction nulls_clause
{
OrderNode* node = newNode<OrderNode>($1);
node->descending = $2;
node->nullsPlacement = $3;
$$ = node;
}
;
%type <boolVal> order_direction
order_direction
: /* nothing */ { $$ = false; }
| ASC { $$ = false; }
| DESC { $$ = true; }
;
%type <nullsPlacement> nulls_clause
nulls_clause
: /* nothing */ { $$ = OrderNode::NULLS_DEFAULT; }
| NULLS nulls_placement { $$ = $2; }
;
%type <nullsPlacement> nulls_placement
nulls_placement
: FIRST { $$ = OrderNode::NULLS_FIRST; }
| LAST { $$ = OrderNode::NULLS_LAST; }
;
// ROWS clause
%type <rowsClause> rows_clause
rows_clause
: // nothing
{ $$ = NULL; }
// equivalent to FIRST value
| ROWS value
{
$$ = newNode<RowsClause>();
$$->length = $2;
}
// equivalent to FIRST (upper_value - lower_value + 1) SKIP (lower_value - 1)
| ROWS value TO value
{
$$ = newNode<RowsClause>();
$$->skip = newNode<ArithmeticNode>(blr_subtract, true, $2, MAKE_const_slong(1));
$$->length = newNode<ArithmeticNode>(blr_add, true,
newNode<ArithmeticNode>(blr_subtract, true, $4, $2), MAKE_const_slong(1));
}
;
// INSERT statement
// IBO hack: replace column_parens_opt by ins_column_parens_opt.
%type <storeNode> 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 <storeNode> insert_start
insert_start
: INSERT INTO simple_table_name
{
StoreNode* node = newNode<StoreNode>();
node->dsqlRelation = $3;
$$ = node;
}
;
// MERGE statement
%type <mergeNode> merge
merge
: MERGE INTO table_name USING table_reference ON search_condition
{
MergeNode* node = $$ = newNode<MergeNode>();
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(<mergeNode>)
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(<mergeNode>)
merge_when_matched_clause($mergeNode)
: WHEN MATCHED
{ $<mergeMatchedClause>$ = &$mergeNode->whenMatched.add(); }
merge_update_specification(NOTRIAL($<mergeMatchedClause>3))
;
%type merge_when_not_matched_clause(<mergeNode>)
merge_when_not_matched_clause($mergeNode)
: WHEN NOT MATCHED
{ $<mergeNotMatchedClause>$ = &$mergeNode->whenNotMatched.add(); }
merge_insert_specification(NOTRIAL($<mergeNotMatchedClause>4))
;
%type merge_update_specification(<mergeMatchedClause>)
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(<mergeNotMatchedClause>)
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 <stmtNode> delete
delete
: delete_searched
| delete_positioned
;
%type <stmtNode> delete_searched
delete_searched
: KW_DELETE FROM table_name where_clause plan_clause order_clause rows_clause returning_clause
{
EraseNode* node = newNode<EraseNode>();
node->dsqlRelation = $3;
node->dsqlBoolean = $4;
node->dsqlPlan = $5;
node->dsqlOrder = $6;
node->dsqlRows = $7;
node->dsqlReturning = $8;
$$ = node;
}
;
%type <stmtNode> delete_positioned
delete_positioned
: KW_DELETE FROM table_name cursor_clause returning_clause
{
EraseNode* node = newNode<EraseNode>();
node->dsqlRelation = $3;
node->dsqlCursorName = *$4;
node->dsqlReturning = $5;
$$ = node;
}
;
// UPDATE statement
%type <stmtNode> update
update
: update_searched
| update_positioned
;
%type <stmtNode> update_searched
update_searched
: UPDATE table_name SET assignments where_clause plan_clause
order_clause rows_clause returning_clause
{
ModifyNode* node = newNode<ModifyNode>();
node->dsqlRelation = $2;
node->statement = $4;
node->dsqlBoolean = $5;
node->dsqlPlan = $6;
node->dsqlOrder = $7;
node->dsqlRows = $8;
node->dsqlReturning = $9;
$$ = node;
}
;
%type <stmtNode> update_positioned
update_positioned
: UPDATE table_name SET assignments cursor_clause returning_clause
{
ModifyNode* node = newNode<ModifyNode>();
node->dsqlRelation = $2;
node->statement = $4;
node->dsqlCursorName = *$5;
node->dsqlReturning = $6;
$$ = node;
}
;
// UPDATE OR INSERT statement
%type <updInsNode> update_or_insert
update_or_insert
: UPDATE OR INSERT INTO simple_table_name
{
UpdateOrInsertNode* node = $$ = newNode<UpdateOrInsertNode>();
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(<nestFieldArray>)
update_or_insert_matching_opt($fieldArray)
: // nothing
| MATCHING ins_column_parens($fieldArray)
;
%type <returningClause> 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 <valueListNode> value_opt_alias_list
value_opt_alias_list
: value_opt_alias { $$ = newNode<ValueListNode>($1); }
| value_opt_alias_list ',' value_opt_alias { $$ = $1->add($3); }
;
%type <metaNamePtr> cursor_clause
cursor_clause
: WHERE CURRENT OF symbol_cursor_name { $$ = newNode<MetaName>(*$4); }
;
// Assignments
%type <compoundStmtNode> assignments
assignments
: assignment
{
$$ = newNode<CompoundStmtNode>();
$$->statements.add($1);
}
| assignments ',' assignment
{
$1->statements.add($3);
$$ = $1;
}
;
%type <stmtNode> assignment
assignment
: update_column_name '=' value
{
AssignmentNode* node = newNode<AssignmentNode>();
node->asgnTo = $1;
node->asgnFrom = $3;
$$ = node;
}
;
%type <stmtNode> exec_function
exec_function
: udf
{
AssignmentNode* node = newNode<AssignmentNode>();
node->asgnTo = newNode<NullNode>();
node->asgnFrom = $1;
$$ = node;
}
| non_aggregate_function
{
AssignmentNode* node = newNode<AssignmentNode>();
node->asgnTo = newNode<NullNode>();
node->asgnFrom = $1;
$$ = node;
}
;
// column specifications
%type <valueListNode> column_parens_opt
column_parens_opt
: /* nothing */ { $$ = NULL; }
| column_parens
;
%type <valueListNode> column_parens
column_parens
: '(' column_list ')' { $$ = $2; }
;
%type <valueListNode> column_list
column_list
: simple_column_name { $$ = newNode<ValueListNode>($1); }
| column_list ',' simple_column_name { $$ = $1->add($3); }
;
// begin IBO hack
%type ins_column_parens_opt(<nestFieldArray>)
ins_column_parens_opt($fieldArray)
: // nothing
| ins_column_parens($fieldArray)
;
%type ins_column_parens(<nestFieldArray>)
ins_column_parens($fieldArray)
: '(' ins_column_list($fieldArray) ')'
;
%type ins_column_list(<nestFieldArray>)
ins_column_list($fieldArray)
: update_column_name { $fieldArray->add($1); }
| ins_column_list ',' update_column_name { $fieldArray->add($3); }
;
// end IBO hack
%type <fieldNode> column_name
column_name
: simple_column_name
| symbol_table_alias_name '.' symbol_column_name
{
FieldNode* fieldNode = newNode<FieldNode>();
fieldNode->dsqlQualifier = *$1;
fieldNode->dsqlName = *$3;
$$ = fieldNode;
}
;
%type <fieldNode> simple_column_name
simple_column_name
: symbol_column_name
{
FieldNode* fieldNode = newNode<FieldNode>();
fieldNode->dsqlName = *$1;
$$ = fieldNode;
}
;
%type <fieldNode> 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>();
fieldNode->dsqlQualifier = *$1;
fieldNode->dsqlName = *$3;
$$ = fieldNode;
}
;
// boolean expressions
%type <boolExprNode> search_condition
search_condition
: value { $$ = valueToBool($1); }
;
%type <boolExprNode> boolean_value_expression
boolean_value_expression
: predicate
| value OR value
{ $$ = newNode<BinaryBoolNode>(blr_or, valueToBool($1), valueToBool($3)); }
| value AND value
{ $$ = newNode<BinaryBoolNode>(blr_and, valueToBool($1), valueToBool($3)); }
| NOT value
{ $$ = newNode<NotBoolNode>(valueToBool($2)); }
| '(' boolean_value_expression ')'
{ $$ = $2; }
| value IS boolean_literal
{ $$ = newNode<ComparativeBoolNode>(blr_equiv, newNode<BoolAsValueNode>(valueToBool($1)), $3); }
| value IS NOT boolean_literal
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>(blr_equiv,
newNode<BoolAsValueNode>(valueToBool($1)), $4);
$$ = newNode<NotBoolNode>(node);
}
;
%type <boolExprNode> 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 <boolExprNode> comparison_predicate
comparison_predicate
: value comparison_operator value %prec '='
{ $$ = newNode<ComparativeBoolNode>($2, $1, $3); }
;
%type <blrOp> 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 <boolExprNode> quantified_predicate
quantified_predicate
: value comparison_operator quantified_flag '(' column_select ')'
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>($2, $1);
node->dsqlFlag = $3;
node->dsqlSpecialArg = $5;
$$ = node;
}
;
%type <cmpBoolFlag> quantified_flag
quantified_flag
: ALL { $$ = ComparativeBoolNode::DFLAG_ANSI_ALL; }
| SOME { $$ = ComparativeBoolNode::DFLAG_ANSI_ANY; }
| ANY { $$ = ComparativeBoolNode::DFLAG_ANSI_ANY; }
;
// other predicates
%type <boolExprNode> distinct_predicate
distinct_predicate
: value IS DISTINCT FROM value %prec IS
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>(blr_equiv, $1, $5);
$$ = newNode<NotBoolNode>(node);
}
| value IS NOT DISTINCT FROM value %prec IS
{ $$ = newNode<ComparativeBoolNode>(blr_equiv, $1, $6); }
;
%type <boolExprNode> between_predicate
between_predicate
: value BETWEEN value_between AND value_between %prec BETWEEN
{ $$ = newNode<ComparativeBoolNode>(blr_between, $1, $3, $5); }
| value NOT BETWEEN value_between AND value_between %prec BETWEEN
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>(blr_between, $1, $4, $6);
$$ = newNode<NotBoolNode>(node);
}
;
// Special value for BETWEEN, to avoid conflicts with boolean expressions.
%type <valueExprNode> value_between
value_between
: value_primary
| '(' boolean_value_expression ')' { $$ = newNode<BoolAsValueNode>($2); }
;
%type <boolExprNode> binary_pattern_predicate
binary_pattern_predicate
: value binary_pattern_operator value %prec CONTAINING
{ $$ = newNode<ComparativeBoolNode>($2, $1, $3); }
| value NOT binary_pattern_operator value %prec CONTAINING
{
ComparativeBoolNode* cmpNode = newNode<ComparativeBoolNode>($3, $1, $4);
$$ = newNode<NotBoolNode>(cmpNode);
}
;
%type <blrOp> binary_pattern_operator
binary_pattern_operator
: CONTAINING { $$ = blr_containing; }
| STARTING { $$ = blr_starting; }
| STARTING WITH { $$ = blr_starting; }
;
%type <boolExprNode> ternary_pattern_predicate
ternary_pattern_predicate
: value LIKE value %prec LIKE
{ $$ = newNode<ComparativeBoolNode>(blr_like, $1, $3); }
| value LIKE value ESCAPE value %prec LIKE
{ $$ = newNode<ComparativeBoolNode>(blr_like, $1, $3, $5); }
| value NOT LIKE value %prec LIKE
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>(blr_like, $1, $4);
$$ = newNode<NotBoolNode>(node);
}
| value NOT LIKE value ESCAPE value %prec LIKE
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>(blr_like, $1, $4, $6);
$$ = newNode<NotBoolNode>(node);
}
| value SIMILAR TO value %prec SIMILAR
{ $$ = newNode<ComparativeBoolNode>(blr_similar, $1, $4); }
| value SIMILAR TO value ESCAPE value %prec SIMILAR
{ $$ = newNode<ComparativeBoolNode>(blr_similar, $1, $4, $6); }
| value NOT SIMILAR TO value %prec SIMILAR
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>(blr_similar, $1, $5);
$$ = newNode<NotBoolNode>(node);
}
| value NOT SIMILAR TO value ESCAPE value %prec SIMILAR
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>(blr_similar, $1, $5, $7);
$$ = newNode<NotBoolNode>(node);
}
;
%type <boolExprNode> in_predicate
in_predicate
: value KW_IN in_predicate_value
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>(blr_eql, $1);
node->dsqlFlag = ComparativeBoolNode::DFLAG_ANSI_ANY;
node->dsqlSpecialArg = $3;
$$ = node;
}
| value NOT KW_IN in_predicate_value
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>(blr_eql, $1);
node->dsqlFlag = ComparativeBoolNode::DFLAG_ANSI_ANY;
node->dsqlSpecialArg = $4;
$$ = newNode<NotBoolNode>(node);
}
;
%type <boolExprNode> exists_predicate
exists_predicate
: EXISTS '(' select_expr ')'
{ $$ = newNode<RseBoolNode>(blr_any, $3); }
;
%type <boolExprNode> singular_predicate
singular_predicate
: SINGULAR '(' select_expr ')'
{ $$ = newNode<RseBoolNode>(blr_unique, $3); }
;
%type <boolExprNode> null_predicate
null_predicate
: value IS KW_NULL
{ $$ = newNode<MissingBoolNode>($1); }
| value IS UNKNOWN
{ $$ = newNode<MissingBoolNode>($1, true); }
| value IS NOT KW_NULL
{ $$ = newNode<NotBoolNode>(newNode<MissingBoolNode>($1)); }
| value IS NOT UNKNOWN
{ $$ = newNode<NotBoolNode>(newNode<MissingBoolNode>($1, true)); }
;
// set values
%type <exprNode> in_predicate_value
in_predicate_value
: table_subquery { $$ = $1; }
| '(' value_list ')' { $$ = $2; }
;
%type <selectExprNode> table_subquery
table_subquery
: '(' column_select ')' { $$ = $2; }
;
// USER control SQL interface
%type <createAlterUserNode> create_user_clause
create_user_clause
: symbol_user_name passwd_clause
{
$$ = newNode<CreateAlterUserNode>(CreateAlterUserNode::USER_ADD, *$1);
$$->password = $2;
}
user_fixed_opts(NOTRIAL($3))
user_var_opts(NOTRIAL($3))
{
$$ = $3;
}
;
%type <createAlterUserNode> alter_user_clause
alter_user_clause
: symbol_user_name set_noise passwd_opt
{
$$ = newNode<CreateAlterUserNode>(CreateAlterUserNode::USER_MOD, *$1);
$$->password = $3;
}
user_fixed_opts(NOTRIAL($4))
user_var_opts(NOTRIAL($4))
{
$$ = $4;
}
;
%type <createAlterUserNode> alter_cur_user_clause
alter_cur_user_clause
: set_noise passwd_opt
{
$$ = newNode<CreateAlterUserNode>(CreateAlterUserNode::USER_MOD, "");
$$->password = $2;
}
user_fixed_opts(NOTRIAL($3))
user_var_opts(NOTRIAL($3))
{
$$ = $3;
}
;
%type <createAlterUserNode> replace_user_clause
replace_user_clause
: symbol_user_name set_noise passwd_opt
{
$$ = newNode<CreateAlterUserNode>(CreateAlterUserNode::USER_RPL, *$1);
$$->password = $3;
}
user_fixed_opts(NOTRIAL($4))
user_var_opts(NOTRIAL($4))
{
$$ = $4;
}
;
set_noise
: // nothing
| SET
;
%type <stringPtr> passwd_opt
passwd_opt
: /* nothing */ { $$ = NULL; }
| passwd_clause
;
%type <stringPtr> passwd_clause
passwd_clause
: PASSWORD utf_string { $$ = $2; }
;
%type user_fixed_opts(<createAlterUserNode>)
user_fixed_opts($node)
: // nothing
| user_fixed_list($node)
;
%type user_fixed_list(<createAlterUserNode>)
user_fixed_list($node)
: user_fixed_opt($node)
| user_fixed_list user_fixed_opt($node)
;
%type user_fixed_opt(<createAlterUserNode>)
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<bool>(true)); }
| REVOKE ADMIN ROLE { setClause($node->adminRole, "ADMIN ROLE", Nullable<bool>(false)); }
| ACTIVE { setClause($node->active, "ACTIVE/INACTIVE", Nullable<bool>(true)); }
| INACTIVE { setClause($node->active, "ACTIVE/INACTIVE", Nullable<bool>(false)); }
;
%type user_var_opts(<createAlterUserNode>)
user_var_opts($node)
: // nothing
| TAGS '(' user_var_list($node) ')'
;
%type user_var_list(<createAlterUserNode>)
user_var_list($node)
: user_var_option($node)
| user_var_list ',' user_var_option($node)
;
%type user_var_option(<createAlterUserNode>)
user_var_option($node)
: valid_symbol_name '=' utf_string
{
$node->addProperty($1, $3);
}
| DROP valid_symbol_name
{
$node->addProperty($2);
}
;
// value types
%type <valueExprNode> value
value
: value_primary
| boolean_value_expression
{ $$ = newNode<BoolAsValueNode>($1); }
;
%type <valueExprNode> value_primary
value_primary
: nonparenthesized_value
| '(' value_primary ')' { $$ = $2; }
;
%type <valueExprNode> 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<NegateNode>($2); }
| '+' value_primary %prec UPLUS
{ $$ = $2; }
| value_primary '+' value_primary
{ $$ = newNode<ArithmeticNode>(blr_add, (client_dialect < SQL_DIALECT_V6_TRANSITION), $1, $3); }
| value_primary CONCATENATE value_primary
{ $$ = newNode<ConcatenateNode>($1, $3); }
| value_primary COLLATE symbol_collation_name
{ $$ = newNode<CollateNode>($1, *$3); }
| value_primary '-' value_primary
{ $$ = newNode<ArithmeticNode>(blr_subtract, (client_dialect < SQL_DIALECT_V6_TRANSITION), $1, $3); }
| value_primary '*' value_primary
{ $$ = newNode<ArithmeticNode>(blr_multiply, (client_dialect < SQL_DIALECT_V6_TRANSITION), $1, $3); }
| value_primary '/' value_primary
{ $$ = newNode<ArithmeticNode>(blr_divide, (client_dialect < SQL_DIALECT_V6_TRANSITION), $1, $3); }
| '(' column_singleton ')'
{ $$ = $2; }
| current_user
{ $$ = $1; }
| current_role
{ $$ = $1; }
| internal_info
{ $$ = $1; }
| recordKeyType
{ $$ = newNode<RecordKeyNode>($1); }
| symbol_table_alias_name '.' recordKeyType
{ $$ = newNode<RecordKeyNode>($3, *$1); }
| KW_VALUE
{ $$ = newNode<DomainValidationNode>(); }
| datetime_value_expression
{ $$ = $1; }
| null_value
{ $$ = $1; }
;
%type <blrOp> recordKeyType
recordKeyType
: DB_KEY { $$ = blr_dbkey; }
| RDB_RECORD_VERSION { $$ = blr_record_version2; }
;
%type <valueExprNode> 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<CurrentDateNode>();
}
| 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<CurrentTimeNode>($2);
}
| CURRENT_TIMESTAMP timestamp_precision_opt
{ $$ = newNode<CurrentTimeStampNode>($2); }
;
%type <uintVal> time_precision_opt
time_precision_opt
: /* nothing */ { $$ = DEFAULT_TIME_PRECISION; }
| '(' nonneg_short_integer ')' { $$ = $2; }
;
%type <uintVal> timestamp_precision_opt
timestamp_precision_opt
: /* nothing */ { $$ = DEFAULT_TIMESTAMP_PRECISION; }
| '(' nonneg_short_integer ')' { $$ = $2; }
;
%type <valueExprNode> array_element
array_element
: column_name '[' value_list ']'
{
ArrayNode* node = newNode<ArrayNode>($1);
node->field->dsqlIndices = $3;
$$ = node;
}
;
%type <valueListNode> value_list_opt
value_list_opt
: /* nothing */ { $$ = newNode<ValueListNode>(0); }
| value_list { $$ = $1; }
;
%type <valueListNode> value_list
value_list
: value { $$ = newNode<ValueListNode>($1); }
| value_list ',' value { $$ = $1->add($3); }
;
%type <valueExprNode> constant
constant
: u_constant
| '-' u_numeric_constant { $$ = newNode<NegateNode>($2); }
| boolean_literal
;
%type <valueExprNode> 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<NegateNode>(MAKE_const_sint64(-signedNumber, $1.scale));
else
$$ = MAKE_const_sint64(signedNumber, $1.scale);
}
| SCALEDINT
{ $$ = MAKE_const_sint64((SINT64) $1.number, $1.scale); }
;
%type <valueExprNode> 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 <valueExprNode> boolean_literal
boolean_literal
: KW_FALSE { $$ = MAKE_constant("", CONSTANT_BOOLEAN); }
| KW_TRUE { $$ = MAKE_constant("1", CONSTANT_BOOLEAN); }
;
%type <valueExprNode> parameter
parameter
: '?' { $$ = make_parameter(); }
;
%type <valueExprNode> current_user
current_user
: USER { $$ = newNode<CurrentUserNode>(); }
| CURRENT_USER { $$ = newNode<CurrentUserNode>(); }
;
%type <valueExprNode> current_role
current_role
: CURRENT_ROLE { $$ = newNode<CurrentRoleNode>(); }
;
%type <valueExprNode> internal_info
internal_info
: CURRENT_CONNECTION
{ $$ = newNode<InternalInfoNode>(MAKE_const_slong(INFO_TYPE_CONNECTION_ID)); }
| CURRENT_TRANSACTION
{ $$ = newNode<InternalInfoNode>(MAKE_const_slong(INFO_TYPE_TRANSACTION_ID)); }
| GDSCODE
{ $$ = newNode<InternalInfoNode>(MAKE_const_slong(INFO_TYPE_GDSCODE)); }
| SQLCODE
{ $$ = newNode<InternalInfoNode>(MAKE_const_slong(INFO_TYPE_SQLCODE)); }
| SQLSTATE
{ $$ = newNode<InternalInfoNode>(MAKE_const_slong(INFO_TYPE_SQLSTATE)); }
| ROW_COUNT
{ $$ = newNode<InternalInfoNode>(MAKE_const_slong(INFO_TYPE_ROWS_AFFECTED)); }
;
%type <intlStringPtr> 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 <stringPtr> utf_string
utf_string
: sql_string
{ $$ = newString($1->toUtf8(scratch)); }
;
%type <int32Val> signed_short_integer
signed_short_integer
: nonneg_short_integer
| '-' neg_short_integer
{ $$ = -$2; }
;
%type <int32Val> nonneg_short_integer
nonneg_short_integer
: NUMBER
{
if ($1 > SHRT_POS_MAX)
yyabandon(-842, isc_expec_short); // Short integer expected
$$ = $1;
}
;
%type <int32Val> neg_short_integer
neg_short_integer
: NUMBER
{
if ($1 > SHRT_NEG_MAX)
yyabandon(-842, isc_expec_short); // Short integer expected
$$ = $1;
}
;
%type <int32Val> pos_short_integer
pos_short_integer
: nonneg_short_integer
{
if ($1 == 0)
yyabandon(-842, isc_expec_positive); // Positive number expected
$$ = $1;
}
;
%type <int32Val> unsigned_short_integer
unsigned_short_integer
: NUMBER
{
if ($1 > SHRT_UNSIGNED_MAX)
yyabandon(-842, isc_expec_ushort); // Unsigned short integer expected
$$ = $1;
}
;
%type <int32Val> signed_long_integer
signed_long_integer
: long_integer
| '-' long_integer { $$ = -$2; }
;
%type <int32Val> long_integer
long_integer
: NUMBER { $$ = $1;}
;
// functions
%type <valueExprNode> function
function
: aggregate_function { $$ = $1; }
| non_aggregate_function
| over_clause
;
%type <valueExprNode> non_aggregate_function
non_aggregate_function
: numeric_value_function
| string_value_function
| system_function_expression
;
%type <aggNode> aggregate_function
aggregate_function
: COUNT '(' '*' ')'
{ $$ = newNode<CountAggNode>(false, (client_dialect < SQL_DIALECT_V6_TRANSITION)); }
| COUNT '(' all_noise value ')'
{ $$ = newNode<CountAggNode>(false, (client_dialect < SQL_DIALECT_V6_TRANSITION), $4); }
| COUNT '(' DISTINCT value ')'
{ $$ = newNode<CountAggNode>(true, (client_dialect < SQL_DIALECT_V6_TRANSITION), $4); }
| SUM '(' all_noise value ')'
{
$$ = newNode<SumAggNode>(false,
(client_dialect < SQL_DIALECT_V6_TRANSITION), $4);
}
| SUM '(' DISTINCT value ')'
{
$$ = newNode<SumAggNode>(true,
(client_dialect < SQL_DIALECT_V6_TRANSITION), $4);
}
| AVG '(' all_noise value ')'
{
$$ = newNode<AvgAggNode>(false,
(client_dialect < SQL_DIALECT_V6_TRANSITION), $4);
}
| AVG '(' DISTINCT value ')'
{
$$ = newNode<AvgAggNode>(true,
(client_dialect < SQL_DIALECT_V6_TRANSITION), $4);
}
| MINIMUM '(' all_noise value ')'
{ $$ = newNode<MaxMinAggNode>(MaxMinAggNode::TYPE_MIN, $4); }
| MINIMUM '(' DISTINCT value ')'
{ $$ = newNode<MaxMinAggNode>(MaxMinAggNode::TYPE_MIN, $4); }
| MAXIMUM '(' all_noise value ')'
{ $$ = newNode<MaxMinAggNode>(MaxMinAggNode::TYPE_MAX, $4); }
| MAXIMUM '(' DISTINCT value ')'
{ $$ = newNode<MaxMinAggNode>(MaxMinAggNode::TYPE_MAX, $4); }
| LIST '(' all_noise value delimiter_opt ')'
{ $$ = newNode<ListAggNode>(false, $4, $5); }
| LIST '(' DISTINCT value delimiter_opt ')'
{ $$ = newNode<ListAggNode>(true, $4, $5); }
;
%type <aggNode> window_function
window_function
: DENSE_RANK '(' ')'
{ $$ = newNode<DenseRankWinNode>(); }
| RANK '(' ')'
{ $$ = newNode<RankWinNode>(); }
| ROW_NUMBER '(' ')'
{ $$ = newNode<RowNumberWinNode>(); }
| FIRST_VALUE '(' value ')'
{ $$ = newNode<FirstValueWinNode>($3); }
| LAST_VALUE '(' value ')'
{ $$ = newNode<LastValueWinNode>($3); }
| NTH_VALUE '(' value ',' value ')' nth_from
{ $$ = newNode<NthValueWinNode>($3, $5, $7); }
| LAG '(' value ',' value ',' value ')'
{ $$ = newNode<LagWinNode>($3, $5, $7); }
| LAG '(' value ',' value ')'
{ $$ = newNode<LagWinNode>($3, $5, newNode<NullNode>()); }
| LAG '(' value ')'
{ $$ = newNode<LagWinNode>($3, MAKE_const_slong(1), newNode<NullNode>()); }
| LEAD '(' value ',' value ',' value ')'
{ $$ = newNode<LeadWinNode>($3, $5, $7); }
| LEAD '(' value ',' value ')'
{ $$ = newNode<LeadWinNode>($3, $5, newNode<NullNode>()); }
| LEAD '(' value ')'
{ $$ = newNode<LeadWinNode>($3, MAKE_const_slong(1), newNode<NullNode>()); }
;
%type <valueExprNode> 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 <aggNode> aggregate_window_function
aggregate_window_function
: aggregate_function
| window_function
;
%type <valueExprNode> over_clause
over_clause
: aggregate_window_function OVER '(' window_partition_opt order_clause ')'
{ $$ = newNode<OverNode>($1, $4, $5); }
;
%type <valueListNode> window_partition_opt
window_partition_opt
: /* nothing */ { $$ = NULL; }
| PARTITION BY value_list { $$ = $3; }
;
%type <valueExprNode> delimiter_opt
delimiter_opt
: /* nothing */ { $$ = MAKE_str_constant(newIntlString(","), lex.att_charset); }
| ',' value { $$ = $2; }
;
%type <valueExprNode> numeric_value_function
numeric_value_function
: extract_expression
| length_expression
;
%type <valueExprNode> extract_expression
extract_expression
: EXTRACT '(' timestamp_part FROM value ')' { $$ = newNode<ExtractNode>($3, $5); }
;
%type <valueExprNode> length_expression
length_expression
: bit_length_expression
| char_length_expression
| octet_length_expression
;
%type <valueExprNode> bit_length_expression
bit_length_expression
: BIT_LENGTH '(' value ')' { $$ = newNode<StrLenNode>(blr_strlen_bit, $3); }
;
%type <valueExprNode> char_length_expression
char_length_expression
: CHAR_LENGTH '(' value ')' { $$ = newNode<StrLenNode>(blr_strlen_char, $3); }
| CHARACTER_LENGTH '(' value ')' { $$ = newNode<StrLenNode>(blr_strlen_char, $3); }
;
%type <valueExprNode> octet_length_expression
octet_length_expression
: OCTET_LENGTH '(' value ')' { $$ = newNode<StrLenNode>(blr_strlen_octet, $3); }
;
%type <valueExprNode> system_function_expression
system_function_expression
: system_function_std_syntax '(' value_list_opt ')'
{ $$ = newNode<SysFuncCallNode>(*$1, $3); }
| system_function_special_syntax
{ $$ = $1; }
;
%type <metaNamePtr> 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 <sysFuncCallNode> system_function_special_syntax
system_function_special_syntax
: DATEADD '(' value timestamp_part TO value ')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>($3)->add(MAKE_const_slong($4))->add($6));
$$->dsqlSpecialSyntax = true;
}
| DATEADD '(' timestamp_part ',' value ',' value ')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>($5)->add(MAKE_const_slong($3))->add($7));
$$->dsqlSpecialSyntax = true;
}
| DATEDIFF '(' timestamp_part FROM value TO value ')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>(MAKE_const_slong($3))->add($5)->add($7));
$$->dsqlSpecialSyntax = true;
}
| DATEDIFF '(' timestamp_part ',' value ',' value ')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>(MAKE_const_slong($3))->add($5)->add($7));
$$->dsqlSpecialSyntax = true;
}
| OVERLAY '(' value PLACING value FROM value FOR value ')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>($3)->add($5)->add($7)->add($9));
$$->dsqlSpecialSyntax = true;
}
| OVERLAY '(' value PLACING value FROM value ')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>($3)->add($5)->add($7));
$$->dsqlSpecialSyntax = true;
}
| POSITION '(' value KW_IN value ')'
{
$$ = newNode<SysFuncCallNode>(*$1, newNode<ValueListNode>($3)->add($5));
$$->dsqlSpecialSyntax = true;
}
| POSITION '(' value_list_opt ')'
{ $$ = newNode<SysFuncCallNode>(*$1, $3); }
;
%type <valueExprNode> string_value_function
string_value_function
: substring_function
| trim_function
| KW_UPPER '(' value ')'
{ $$ = newNode<StrCaseNode>(blr_upcase, $3); }
| KW_LOWER '(' value ')'
{ $$ = newNode<StrCaseNode>(blr_lowcase, $3); }
;
%type <valueExprNode> 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<ArithmeticNode>(
blr_subtract, true, $5, MAKE_const_slong(1));
$$ = newNode<SubstringNode>($3, subtractNode, $6);
}
| SUBSTRING '(' value SIMILAR value ESCAPE value ')'
{ $$ = newNode<SubstringSimilarNode>($3, $5, $7); }
;
%type <valueExprNode> string_length_opt
string_length_opt
: /* nothing */ { $$ = NULL; }
| FOR value { $$ = $2; }
;
%type <valueExprNode> trim_function
trim_function
: TRIM '(' trim_specification value FROM value ')'
{ $$ = newNode<TrimNode>($3, $6, $4); }
| TRIM '(' value FROM value ')'
{ $$ = newNode<TrimNode>(blr_trim_both, $5, $3); }
| TRIM '(' trim_specification FROM value ')'
{ $$ = newNode<TrimNode>($3, $5); }
| TRIM '(' value ')'
{ $$ = newNode<TrimNode>(blr_trim_both, $3); }
;
%type <blrOp> trim_specification
trim_specification
: BOTH { $$ = blr_trim_both; }
| TRAILING { $$ = blr_trim_trailing; }
| LEADING { $$ = blr_trim_leading; }
;
%type <valueExprNode> udf
udf
: symbol_UDF_call_name '(' value_list ')'
{ $$ = newNode<UdfCallNode>(QualifiedName(*$1, ""), $3); }
| symbol_UDF_call_name '(' ')'
{ $$ = newNode<UdfCallNode>(QualifiedName(*$1, ""), newNode<ValueListNode>(0)); }
| symbol_package_name '.' symbol_UDF_name '(' value_list ')'
{ $$ = newNode<UdfCallNode>(QualifiedName(*$3, *$1), $5); }
| symbol_package_name '.' symbol_UDF_name '(' ')'
{ $$ = newNode<UdfCallNode>(QualifiedName(*$3, *$1), newNode<ValueListNode>(0)); }
;
%type <valueExprNode> cast_specification
cast_specification
: CAST '(' value AS data_type_descriptor ')'
{ $$ = newNode<CastNode>($3, $5); }
;
// case expressions
%type <valueExprNode> case_expression
case_expression
: case_abbreviation
| case_specification
;
%type <valueExprNode> case_abbreviation
case_abbreviation
: NULLIF '(' value ',' value ')'
{
ComparativeBoolNode* condition = newNode<ComparativeBoolNode>(blr_eql, $3, $5);
$$ = newNode<ValueIfNode>(condition, newNode<NullNode>(), $3);
}
| IIF '(' search_condition ',' value ',' value ')'
{ $$ = newNode<ValueIfNode>($3, $5, $7); }
| COALESCE '(' value ',' value_list ')'
{ $$ = newNode<CoalesceNode>($5->addFront($3)); }
| DECODE '(' value ',' decode_pairs ')'
{
ValueListNode* list = $5;
ValueListNode* conditions = newNode<ValueListNode>(list->items.getCount() / 2);
ValueListNode* values = newNode<ValueListNode>(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<DecodeNode>($3, conditions, values);
}
| DECODE '(' value ',' decode_pairs ',' value ')'
{
ValueListNode* list = $5;
ValueListNode* conditions = newNode<ValueListNode>(list->items.getCount() / 2);
ValueListNode* values = newNode<ValueListNode>(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<DecodeNode>($3, conditions, values);
}
;
%type <valueExprNode> case_specification
case_specification
: simple_case { $$ = $1; }
| searched_case { $$ = $1; }
;
%type <decodeNode> simple_case
simple_case
: CASE case_operand
{ $$ = newNode<DecodeNode>($2, newNode<ValueListNode>(0u), newNode<ValueListNode>(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(<valueListNode>, <valueListNode>)
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 <valueExprNode> else_case_result_opt
else_case_result_opt
: /* nothing */ { $$ = NULL; }
| ELSE case_result { $$ = $2; }
%type <valueExprNode> 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<ValueIfNode>()))
last = next;
fb_assert(last->falseValue->is<NullNode>());
last->falseValue = $4;
$$ = $2;
}
;
%type <valueIfNode> searched_when_clause
searched_when_clause
: WHEN search_condition THEN case_result
{ $$ = newNode<ValueIfNode>($2, $4, newNode<NullNode>()); }
| searched_when_clause WHEN search_condition THEN case_result
{
ValueIfNode* cond = newNode<ValueIfNode>($3, $5, newNode<NullNode>());
ValueIfNode* last = $1;
ValueIfNode* next;
while ((next = last->falseValue->as<ValueIfNode>()))
last = next;
fb_assert(last->falseValue->is<NullNode>());
last->falseValue = cond;
$$ = $1;
}
;
%type <valueExprNode> when_operand
when_operand
: value
;
%type <valueExprNode> case_operand
case_operand
: value
;
%type <valueExprNode> case_result
case_result
: value
;
%type <valueListNode> decode_pairs
decode_pairs
: value ',' value
{ $$ = newNode<ValueListNode>(0u)->add($1)->add($3); }
| decode_pairs ',' value ',' value
{ $$ = $1->add($3)->add($5); }
;
// next value expression
%type <valueExprNode> next_value_expression
next_value_expression
: NEXT KW_VALUE FOR symbol_generator_name
{
$$ = newNode<GenIdNode>((client_dialect < SQL_DIALECT_V6_TRANSITION),
*$4, MAKE_const_slong(1));
}
| GEN_ID '(' symbol_generator_name ',' value ')'
{ $$ = newNode<GenIdNode>((client_dialect < SQL_DIALECT_V6_TRANSITION), *$3, $5); }
;
%type <blrOp> 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 <valueExprNode> null_value
null_value
: KW_NULL
{ $$ = newNode<NullNode>(); }
| UNKNOWN
{
dsql_fld* field = newNode<dsql_fld>();
field->dtype = dtype_boolean;
field->length = sizeof(UCHAR);
CastNode* castNode = newNode<CastNode>(newNode<NullNode>(), field);
castNode->dsqlAlias = "CONSTANT";
$$ = castNode;
}
;
// Performs special mapping of keywords into symbols
%type <metaNamePtr> symbol_UDF_call_name
symbol_UDF_call_name
: SYMBOL
;
%type <metaNamePtr> symbol_UDF_name
symbol_UDF_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_blob_subtype_name
symbol_blob_subtype_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_character_set_name
symbol_character_set_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_collation_name
symbol_collation_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_column_name
symbol_column_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_constraint_name
symbol_constraint_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_cursor_name
symbol_cursor_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_domain_name
symbol_domain_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_exception_name
symbol_exception_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_filter_name
symbol_filter_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_gdscode_name
symbol_gdscode_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_generator_name
symbol_generator_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_index_name
symbol_index_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_item_alias_name
symbol_item_alias_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_label_name
symbol_label_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_ddl_name
symbol_ddl_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_procedure_name
symbol_procedure_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_role_name
symbol_role_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_table_alias_name
symbol_table_alias_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_table_name
symbol_table_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_trigger_name
symbol_trigger_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_user_name
symbol_user_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_variable_name
symbol_variable_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_view_name
symbol_view_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_savepoint_name
symbol_savepoint_name
: valid_symbol_name
;
%type <metaNamePtr> symbol_package_name
symbol_package_name
: valid_symbol_name
;
// symbols
%type <metaNamePtr> valid_symbol_name
valid_symbol_name
: SYMBOL
| non_reserved_word
;
// list of non-reserved words
%type <metaNamePtr> 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
;
%%