8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 16:43:03 +01:00
firebird-mirror/src/dsql/parse.y
Dmitry Yemanov f0740d2a32
Wipe out multi-file database support (#8047)
* Wipe out multi-file database support

* Fix (fingers crossed) Windows build, some more cleanup and code simplification

* Fix gstat build on Windows and also Android/MacOS builds
2024-12-28 09:27:34 +03:00

9696 lines
245 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 "iberror.h"
#include "../dsql/dsql.h"
#include "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/gds_proto.h"
#include "../jrd/err_proto.h"
#include "../common/intlobj_new.h"
#include "../jrd/Attachment.h"
#include "../common/StatusArg.h"
// This is needed here to provide backward compatibility when working with SSPI plugin
#include "../auth/trusted/AuthSspi.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> 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> 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> CHAR
%token <metaNamePtr> DEC
%token <metaNamePtr> DOUBLE
%token <metaNamePtr> FILE
%token <metaNamePtr> FLOAT
%token <metaNamePtr> INT
%token <metaNamePtr> LONG
%token <metaNamePtr> NULL
%token <metaNamePtr> NUMERIC
%token <metaNamePtr> UPPER
%token <metaNamePtr> 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> 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> SHARED
%token <metaNamePtr> SINGULAR
%token <metaNamePtr> 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 DECIMAL_NUMBER
%token <lim64ptr> LIMIT64_NUMBER LIMIT64_INT NUM128
%token <metaNamePtr> SYMBOL
%token <int32Val> NUMBER32BIT
%token <intlStringPtr> STRING
%token <metaNamePtr> INTRODUCER
// New tokens added v5.0
%token <metaNamePtr> ACTION
%token <metaNamePtr> ADMIN
%token <metaNamePtr> BLOBID
%token <metaNamePtr> CASCADE
%token <metaNamePtr> FREE_IT // ISC SQL extension
%token <metaNamePtr> RESTRICT
%token <metaNamePtr> ROLE
%token <metaNamePtr> TEMP
// New tokens added v6.0
%token <metaNamePtr> COLUMN
%token <metaNamePtr> 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> BREAK
%token <metaNamePtr> SUBSTRING
%token <metaNamePtr> RECREATE
%token <metaNamePtr> 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> 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> LOWER
%token <metaNamePtr> OCTET_LENGTH
%token <metaNamePtr> TRAILING
%token <metaNamePtr> TRIM
%token <metaNamePtr> RETURNING
%token <metaNamePtr> 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> ABSOLUTE
%token <metaNamePtr> 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> BOOLEAN
%token <metaNamePtr> FALSE
%token <metaNamePtr> TRUE
%token <metaNamePtr> UNKNOWN
%token <metaNamePtr> USAGE
%token <metaNamePtr> RDB_RECORD_VERSION
%token <metaNamePtr> LINGER
%token <metaNamePtr> TAGS
%token <metaNamePtr> PLUGIN
%token <metaNamePtr> SERVERWIDE
%token <metaNamePtr> INCREMENT
%token <metaNamePtr> TRUSTED
%token <metaNamePtr> ROW
%token <metaNamePtr> OFFSET
%token <metaNamePtr> STDDEV_SAMP
%token <metaNamePtr> STDDEV_POP
%token <metaNamePtr> VAR_SAMP
%token <metaNamePtr> VAR_POP
%token <metaNamePtr> COVAR_SAMP
%token <metaNamePtr> COVAR_POP
%token <metaNamePtr> CORR
%token <metaNamePtr> REGR_AVGX
%token <metaNamePtr> REGR_AVGY
%token <metaNamePtr> REGR_COUNT
%token <metaNamePtr> REGR_INTERCEPT
%token <metaNamePtr> REGR_R2
%token <metaNamePtr> REGR_SLOPE
%token <metaNamePtr> REGR_SXX
%token <metaNamePtr> REGR_SXY
%token <metaNamePtr> REGR_SYY
// tokens added for Firebird 4.0
%token <metaNamePtr> BASE64_DECODE
%token <metaNamePtr> BASE64_ENCODE
%token <metaNamePtr> BINARY
%token <metaNamePtr> BIND
%token <metaNamePtr> COMPARE_DECFLOAT
%token <metaNamePtr> CONSISTENCY
%token <metaNamePtr> COUNTER
%token <metaNamePtr> CRYPT_HASH
%token <metaNamePtr> CTR_BIG_ENDIAN
%token <metaNamePtr> CTR_LENGTH
%token <metaNamePtr> CTR_LITTLE_ENDIAN
%token <metaNamePtr> CUME_DIST
%token <metaNamePtr> DECFLOAT
%token <metaNamePtr> DEFINER
%token <metaNamePtr> DISABLE
%token <metaNamePtr> ENABLE
%token <metaNamePtr> EXCESS
%token <metaNamePtr> EXCLUDE
%token <metaNamePtr> EXTENDED
%token <metaNamePtr> FIRST_DAY
%token <metaNamePtr> FOLLOWING
%token <metaNamePtr> HEX_DECODE
%token <metaNamePtr> HEX_ENCODE
%token <metaNamePtr> IDLE
%token <metaNamePtr> INCLUDE
%token <metaNamePtr> INT128
%token <metaNamePtr> INVOKER
%token <metaNamePtr> IV
%token <metaNamePtr> LAST_DAY
%token <metaNamePtr> LATERAL
%token <metaNamePtr> LEGACY
%token <metaNamePtr> LOCAL
%token <metaNamePtr> LOCALTIME
%token <metaNamePtr> LOCALTIMESTAMP
%token <metaNamePtr> LPARAM
%token <metaNamePtr> MAKE_DBKEY
%token <metaNamePtr> MESSAGE
%token <metaNamePtr> MODE
%token <metaNamePtr> NATIVE
%token <metaNamePtr> NORMALIZE_DECFLOAT
%token <metaNamePtr> NTILE
%token <metaNamePtr> NUMBER
%token <metaNamePtr> OTHERS
%token <metaNamePtr> OVERRIDING
%token <metaNamePtr> PERCENT_RANK
%token <metaNamePtr> PRECEDING
%token <metaNamePtr> PRIVILEGE
%token <metaNamePtr> PUBLICATION
%token <metaNamePtr> QUANTIZE
%token <metaNamePtr> RANGE
%token <metaNamePtr> RESETTING
%token <metaNamePtr> RDB_ERROR
%token <metaNamePtr> RDB_GET_TRANSACTION_CN
%token <metaNamePtr> RDB_ROLE_IN_USE
%token <metaNamePtr> RDB_SYSTEM_PRIVILEGE
%token <metaNamePtr> RESET
%token <metaNamePtr> RSA_DECRYPT
%token <metaNamePtr> RSA_ENCRYPT
%token <metaNamePtr> RSA_PRIVATE
%token <metaNamePtr> RSA_PUBLIC
%token <metaNamePtr> RSA_SIGN_HASH
%token <metaNamePtr> RSA_VERIFY_HASH
%token <metaNamePtr> SALT_LENGTH
%token <metaNamePtr> SECURITY
%token <metaNamePtr> SESSION
%token <metaNamePtr> SIGNATURE
%token <metaNamePtr> SQL
%token <metaNamePtr> SYSTEM
%token <metaNamePtr> TIES
%token <metaNamePtr> TIMEZONE_HOUR
%token <metaNamePtr> TIMEZONE_MINUTE
%token <metaNamePtr> TOTALORDER
%token <metaNamePtr> TRAPS
%token <metaNamePtr> UNBOUNDED
%token <metaNamePtr> VARBINARY
%token <metaNamePtr> WINDOW
%token <metaNamePtr> WITHOUT
%token <metaNamePtr> ZONE
// external connections pool management
%token <metaNamePtr> CONNECTIONS
%token <metaNamePtr> POOL
%token <metaNamePtr> LIFETIME
%token <metaNamePtr> CLEAR
%token <metaNamePtr> OLDEST
// tokens added for Firebird 4.0.1
%token <metaNamePtr> DEBUG
%token <metaNamePtr> PKCS_1_5
// tokens added for Firebird 4.0.2
%token <metaNamePtr> BLOB_APPEND
// tokens added for Firebird 5.0
%token <metaNamePtr> LOCKED
%token <metaNamePtr> OPTIMIZE
%token <metaNamePtr> QUARTER
%token <metaNamePtr> TARGET
%token <metaNamePtr> TIMEZONE_NAME
%token <metaNamePtr> UNICODE_CHAR
%token <metaNamePtr> UNICODE_VAL
%token <metaNamePtr> OWNER
// tokens added for Firebird 6.0
%token <metaNamePtr> ANY_VALUE
%token <metaNamePtr> BTRIM
%token <metaNamePtr> CALL
%token <metaNamePtr> FORMAT
%token <metaNamePtr> LTRIM
%token <metaNamePtr> NAMED_ARG_ASSIGN
%token <metaNamePtr> RTRIM
// precedence declarations for expression evaluation
%left OR
%left AND
%left NOT
%left '=' '<' '>' BETWEEN LIKE CONTAINING STARTING SIMILAR IN NEQ GEQ LEQ NOT_GTR NOT_LSS
%left IS
%left '+' '-'
%left '*' '/'
%left UMINUS UPLUS
%left CONCATENATE
%left COLLATE
%left AT
// 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 YYSTYPE
{
YYSTYPE()
{}
std::optional<int> nullableIntVal;
Firebird::TriState triState;
std::optional<Jrd::SqlSecurity> nullableSqlSecurityVal;
std::optional<Jrd::OverrideClause> nullableOverrideClause;
struct { bool first; bool second; } boolPair;
bool boolVal;
int intVal;
unsigned uintVal;
SLONG int32Val;
SINT64 int64Val;
FB_UINT64 uint64Val;
std::optional<SINT64> nullableInt64Val;
std::optional<FB_UINT64> nullableUint64Val;
Jrd::ScaledNumber scaledNumber;
UCHAR blrOp;
Jrd::OrderNode::NullsPlacement nullsPlacement;
Jrd::ComparativeBoolNode::DsqlFlag cmpBoolFlag;
Jrd::dsql_fld* legacyField;
Jrd::ReturningClause* returningClause;
Jrd::MetaName* metaNamePtr;
Firebird::ObjectsArray<Jrd::MetaName>* metaNameArray;
Firebird::PathName* pathNamePtr;
Jrd::QualifiedName* qualifiedNamePtr;
Firebird::string* stringPtr;
Jrd::IntlString* intlStringPtr;
Jrd::Lim64String* lim64ptr;
Jrd::ExternalClause* externalClause;
Firebird::NonPooledPair<Jrd::MetaName*, Jrd::ValueExprNode*>* namedArgument;
Firebird::NonPooledPair<Firebird::ObjectsArray<Jrd::MetaName>*, Jrd::ValueListNode*>* namedArguments;
Firebird::Array<NestConst<Jrd::ParameterClause> >* parametersClause;
Jrd::WindowClause* windowClause;
Jrd::WindowClause::FrameExtent* windowClauseFrameExtent;
Jrd::WindowClause::Frame* windowClauseFrame;
Jrd::WindowClause::Exclusion windowClauseExclusion;
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::NamedWindowClause* namedWindowClause;
Jrd::NamedWindowsClause* namedWindowsClause;
Jrd::TransactionNode* traNode;
Jrd::SessionManagementNode* mngNode;
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::AddConstraintClause* addConstraintClause;
Jrd::RelationNode::RefActionClause* refActionClause;
Jrd::RelationNode::IndexConstraintClause* indexConstraintClause;
Jrd::RelationNode::IdentityOptions* identityOptions;
IdentityType identityType;
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::LocalDeclarationsNode* localDeclarationsNode;
Jrd::MergeNode* mergeNode;
Jrd::MergeNode::NotMatched* mergeNotMatchedClause;
Jrd::MergeNode::Matched* mergeMatchedClause;
Jrd::SelectNode* selectNode;
Jrd::ForNode* forNode;
Jrd::SetTransactionNode* setTransactionNode;
Jrd::SetTransactionNode::RestrictionOption* setTransactionRestrictionClause;
Jrd::DeclareSubProcNode* declareSubProcNode;
Jrd::DeclareSubFuncNode* declareSubFuncNode;
Jrd::DsqlStatement* dsqlStatement;
Jrd::CreateAlterUserNode* createAlterUserNode;
Jrd::MappingNode* mappingNode;
Jrd::MappingNode::OP mappingOp;
Jrd::SetRoleNode* setRoleNode;
Jrd::SetSessionNode* setSessionNode;
Jrd::CreateAlterRoleNode* createAlterRoleNode;
Jrd::SetDecFloatRoundNode* setDecFloatRoundNode;
Jrd::SetDecFloatTrapsNode* setDecFloatTrapsNode;
Jrd::SetBindNode* setBindNode;
Jrd::SessionResetNode* sessionResetNode;
}
%include types.y
%%
// list of possible statements
top
: statement
{
if (requireSemicolon)
yyerrorIncompleteCmd(YYPOSNARG(1));
parsedStatement = $1;
}
| statement ';'
{ parsedStatement = $1; }
;
%type <dsqlStatement> statement
statement
: dml_statement
{ $$ = FB_NEW_POOL(*statementPool) DsqlDmlStatement(*statementPool, scratch->getAttachment(), $1); }
| ddl_statement
{ $$ = FB_NEW_POOL(*statementPool) DsqlDdlStatement(*statementPool, scratch->getAttachment(), $1); }
| tra_statement
{ $$ = FB_NEW_POOL(*statementPool) DsqlTransactionStatement(*statementPool, scratch->getAttachment(), $1); }
| mng_statement
{
$$ = FB_NEW_POOL(*statementPool) DsqlSessionManagementStatement(
*statementPool, scratch->getAttachment(), $1);
}
;
%type <stmtNode> dml_statement
dml_statement
: delete { $$ = $1; }
| insert { $$ = $1; }
| merge { $$ = $1; }
| exec_procedure { $$ = $1; }
| call { $$ = $1; }
| exec_block { $$ = $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; }
| savepoint { $$ = $1; }
| commit { $$ = $1; }
| rollback { $$ = $1; }
;
%type <mngNode> mng_statement
mng_statement
: set_debug_option { $$ = $1; }
| set_decfloat_round { $$ = $1; }
| set_decfloat_traps { $$ = $1; }
| session_statement { $$ = $1; }
| set_role { $$ = $1; }
| session_reset { $$ = $1; }
| set_time_zone { $$ = $1; }
| set_bind { $$ = $1; }
| set_optimize { $$ = $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 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 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 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;
}
***/
| ddl_privileges(NOTRIAL(&$node->privileges)) object
TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by
{
$node->object = $2;
$node->grantAdminOption = $5;
$node->grantor = $6;
$node->isDdl = true;
}
| db_ddl_privileges(NOTRIAL(&$node->privileges)) DATABASE
TO non_role_grantee_list(NOTRIAL(&$node->users)) grant_option granted_by
{
$node->object = newNode<GranteeClause>(obj_database, getSecurityClassName(obj_database));
$node->grantAdminOption = $5;
$node->grantor = $6;
$node->isDdl = true;
}
| role_name_list(NOTRIAL($node)) TO role_grantee_list(NOTRIAL(&$node->users))
role_admin_option granted_by
{
$node->grantAdminOption = $4;
$node->grantor = $5;
}
;
%type <granteeClause> object
object
: TABLE
{ $$ = newNode<GranteeClause>(obj_relations, getSecurityClassName(obj_relations)); }
| VIEW
{ $$ = newNode<GranteeClause>(obj_views, getSecurityClassName(obj_views)); }
| PROCEDURE
{ $$ = newNode<GranteeClause>(obj_procedures, getSecurityClassName(obj_procedures)); }
| FUNCTION
{ $$ = newNode<GranteeClause>(obj_functions, getSecurityClassName(obj_functions)); }
| PACKAGE
{ $$ = newNode<GranteeClause>(obj_packages, getSecurityClassName(obj_packages)); }
| GENERATOR
{ $$ = newNode<GranteeClause>(obj_generators, getSecurityClassName(obj_generators)); }
| SEQUENCE
{ $$ = newNode<GranteeClause>(obj_generators, getSecurityClassName(obj_generators)); }
| DOMAIN
{ $$ = newNode<GranteeClause>(obj_domains, getSecurityClassName(obj_domains)); }
| EXCEPTION
{ $$ = newNode<GranteeClause>(obj_exceptions, getSecurityClassName(obj_exceptions)); }
| ROLE
{ $$ = newNode<GranteeClause>(obj_roles, getSecurityClassName(obj_roles)); }
| CHARACTER SET
{ $$ = newNode<GranteeClause>(obj_charsets, getSecurityClassName(obj_charsets)); }
| COLLATION
{ $$ = newNode<GranteeClause>(obj_collations, getSecurityClassName(obj_collations)); }
| FILTER
{ $$ = newNode<GranteeClause>(obj_filters, getSecurityClassName(obj_filters)); }
;
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)); }
| 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 ddl_privileges(<privilegeArray>)
ddl_privileges($privilegeArray)
: ALL privileges_opt
{
$privilegeArray->add(PrivilegeClause('C', NULL));
$privilegeArray->add(PrivilegeClause('L', NULL));
$privilegeArray->add(PrivilegeClause('O', NULL));
}
| ddl_privilege_list($privilegeArray)
;
privileges_opt
: // nothing
| PRIVILEGES
;
%type ddl_privilege_list(<privilegeArray>)
ddl_privilege_list($privilegeArray)
: ddl_privilege($privilegeArray)
| ddl_privilege_list ',' ddl_privilege($privilegeArray)
;
%type ddl_privilege(<privilegeArray>)
ddl_privilege($privilegeArray)
: CREATE { $privilegeArray->add(PrivilegeClause('C', NULL)); }
| ALTER ANY { $privilegeArray->add(PrivilegeClause('L', NULL)); }
| DROP ANY { $privilegeArray->add(PrivilegeClause('O', NULL)); }
;
%type db_ddl_privileges(<privilegeArray>)
db_ddl_privileges($privilegeArray)
: ALL privileges_opt
{
$privilegeArray->add(PrivilegeClause('L', NULL));
$privilegeArray->add(PrivilegeClause('O', NULL));
}
| db_ddl_privilege_list($privilegeArray)
;
%type db_ddl_privilege_list(<privilegeArray>)
db_ddl_privilege_list($privilegeArray)
: db_ddl_privilege($privilegeArray)
| db_ddl_privilege_list ',' db_ddl_privilege($privilegeArray)
;
%type db_ddl_privilege(<privilegeArray>)
db_ddl_privilege($privilegeArray)
: CREATE { $privilegeArray->add(PrivilegeClause('C', NULL)); }
| ALTER { $privilegeArray->add(PrivilegeClause('L', NULL)); }
| DROP { $privilegeArray->add(PrivilegeClause('O', NULL)); }
;
%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 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 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 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_grant_option ddl_privileges(NOTRIAL(&$node->privileges)) object
FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by
{
$node->object = $3;
$node->grantAdminOption = $1;
$node->grantor = $6;
$node->isDdl = true;
}
| rev_grant_option db_ddl_privileges(NOTRIAL(&$node->privileges)) DATABASE
FROM non_role_grantee_list(NOTRIAL(&$node->users)) granted_by
{
$node->object = newNode<GranteeClause>(obj_database, getSecurityClassName(obj_database));
$node->grantAdminOption = $1;
$node->grantor = $6;
$node->isDdl = true;
}
| rev_admin_option role_name_list(NOTRIAL($node))
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)); }
| SYSTEM PRIVILEGE valid_symbol_name
{ $granteeArray->add(GranteeClause(obj_privilege, *$3)); }
;
// 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(<grantRevokeNode>)
role_name_list($grantRevokeNode)
: role_name($grantRevokeNode)
| role_name_list ',' role_name($grantRevokeNode)
;
%type role_name(<grantRevokeNode>)
role_name($grantRevokeNode)
: symbol_role_name
{
$grantRevokeNode->roles.add(GranteeClause(obj_sql_role, *$1));
$grantRevokeNode->defaultRoles.add(false);
}
| DEFAULT symbol_role_name
{
$grantRevokeNode->roles.add(GranteeClause(obj_sql_role, *$2));
$grantRevokeNode->defaultRoles.add(true);
}
;
%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)
: symbol_user_name { $granteeArray->add(GranteeClause(obj_user_or_role, *$1)); }
| USER symbol_user_name { $granteeArray->add(GranteeClause(obj_user, *$2)); }
| ROLE symbol_user_name { $granteeArray->add(GranteeClause(obj_sql_role, *$2)); }
;
// DECLARE operations
%type <ddlNode> declare
declare
: DECLARE declare_clause { $$ = $2;}
;
%type <ddlNode> declare_clause
declare_clause
: FILTER filter_decl_clause { $$ = $2; }
| EXTERNAL FUNCTION if_not_exists_opt udf_decl_clause
{
const auto node = $4;
node->createIfNotExistsOnly = $3;
$$ = node;
}
;
%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));
$parameters->back()->udfMechanism = $2;
}
;
%type <nullableIntVal> param_mechanism
param_mechanism
: /* nothing */ { $$ = std::nullopt; } // Beware: This means FUN_reference or FUN_blob_struct.
| BY DESCRIPTOR { $$ = FUN_descriptor; }
| BY SCALAR_ARRAY { $$ = FUN_scalar_array; }
| NULL { $$ = 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);
$function->returnType->udfMechanism = $2;
}
| PARAMETER pos_short_integer
{ $function->udfReturnPos = $2; }
;
%type <int32Val> return_mechanism
return_mechanism
: /* nothing */ { $$ = FUN_reference; }
| BY VALUE { $$ = FUN_value; }
| BY DESCRIPTOR { $$ = FUN_descriptor; }
// FUN_refrence with FREE_IT is -ve
| FREE_IT { $$ = -1 * FUN_reference; }
| BY 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 if_not_exists_opt exception_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| unique_opt order_direction INDEX if_not_exists_opt symbol_index_name index_active_opt ON simple_table_name
{
const auto node = newNode<CreateIndexNode>(*$5);
node->active = $6;
node->unique = $1;
node->descending = $2;
node->createIfNotExistsOnly = $4;
node->relation = $8;
$$ = node;
}
index_definition(static_cast<CreateIndexNode*>($9))
{
$$ = $9;
}
| FUNCTION if_not_exists_opt function_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| PROCEDURE if_not_exists_opt procedure_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| TABLE if_not_exists_opt table_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| GLOBAL TEMPORARY TABLE if_not_exists_opt gtt_table_clause
{
const auto node = $5;
node->createIfNotExistsOnly = $4;
$$ = node;
}
| TRIGGER if_not_exists_opt trigger_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| VIEW if_not_exists_opt view_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| GENERATOR if_not_exists_opt generator_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| SEQUENCE if_not_exists_opt generator_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| DATABASE db_clause { $$ = $2; }
| DOMAIN if_not_exists_opt domain_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| SHADOW if_not_exists_opt shadow_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| ROLE if_not_exists_opt role_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
node->createFlag = true;
$$ = node;
}
| COLLATION if_not_exists_opt collation_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| USER if_not_exists_opt create_user_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| PACKAGE if_not_exists_opt package_clause
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| PACKAGE BODY if_not_exists_opt package_body_clause
{
const auto node = $4;
node->createIfNotExistsOnly = $3;
$$ = node;
}
| MAPPING if_not_exists_opt create_map_clause(false)
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
$$ = node;
}
| GLOBAL MAPPING if_not_exists_opt create_map_clause(true)
{
const auto node = $4;
node->createIfNotExistsOnly = $3;
$$ = node;
}
;
%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); }
| USER create_user_clause
{ $$ = newNode<RecreateUserNode>($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; }
| PACKAGE BODY replace_package_body_clause { $$ = $3; }
| 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; }
| MAPPING replace_map_clause(false) { $$ = $2; }
| GLOBAL MAPPING replace_map_clause(true) { $$ = $3; }
;
// 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> index_active_opt
index_active_opt
: /* nothing */ { $$ = true; }
| index_active { $$ = $1; }
;
%type <boolVal> unique_opt
unique_opt
: /* nothing */ { $$ = false; }
| UNIQUE { $$ = true; }
;
%type index_definition(<createIndexNode>)
index_definition($createIndexNode)
: index_column_expr($createIndexNode) index_condition_opt
{
$createIndexNode->partial = $2;
}
;
%type index_column_expr(<createIndexNode>)
index_column_expr($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));
}
;
%type <boolSourceClause> index_condition_opt
index_condition_opt
: /* nothing */
{ $$ = nullptr; }
| WHERE search_condition
{
auto clause = newNode<BoolSourceClause>();
clause->value = $2;
clause->source = makeParseStr(YYPOSNARG(1), YYPOSNARG(2));
$$ = clause;
}
;
// CREATE SHADOW
%type <createShadowNode> shadow_clause
shadow_clause
: pos_short_integer manual_auto conditional utf_string
{ $$ = newNode<CreateShadowNode>($1, $2, $3, *$4); }
;
%type <boolVal> manual_auto
manual_auto
: /* nothing */ { $$ = false; }
| MANUAL { $$ = true; }
| AUTO { $$ = false; }
;
%type <boolVal> conditional
conditional
: /* nothing */ { $$ = false; }
| CONDITIONAL { $$ = true; }
;
// 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, $4));
}
domain_constraints_opt($5) collate_clause
{
$$ = $5;
setCollate($3, $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 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
{ $$ = newNode<CreateAlterSequenceNode>(*$1); }
create_sequence_options($2)
{ $$ = $2; }
;
%type create_sequence_options(<createAlterSequenceNode>)
create_sequence_options($seqNode)
: /* nothing */
| create_seq_option($seqNode) create_sequence_options($seqNode)
;
%type create_seq_option(<createAlterSequenceNode>)
create_seq_option($seqNode)
: start_with_opt($seqNode)
| step_option($seqNode)
;
%type start_with_opt(<createAlterSequenceNode>)
start_with_opt($seqNode)
: START WITH sequence_value
{
setClause($seqNode->value, "START WITH", $3);
setClause($seqNode->restartSpecified, "RESTART", true);
}
;
%type step_option(<createAlterSequenceNode>)
step_option($seqNode)
: INCREMENT by_noise signed_long_integer
{ setClause($seqNode->step, "INCREMENT BY", $3); }
;
by_noise
: // nothing
| BY
%type <createAlterSequenceNode> replace_sequence_clause
replace_sequence_clause
: symbol_generator_name
{
CreateAlterSequenceNode* node = newNode<CreateAlterSequenceNode>(*$1);
node->alter = true;
$$ = node;
}
replace_sequence_options($2)
{
// Remove this to implement CORE-5137
if (!$2->restartSpecified && !$2->step.has_value())
yyerrorIncompleteCmd(YYPOSNARG(3));
$$ = $2;
}
;
%type replace_sequence_options(<createAlterSequenceNode>)
replace_sequence_options($seqNode)
: /* nothing */
| replace_seq_option($seqNode) replace_sequence_options($seqNode)
;
%type replace_seq_option(<createAlterSequenceNode>)
replace_seq_option($seqNode)
: RESTART
{
setClause($seqNode->restartSpecified, "RESTART", true);
}
| start_with_opt($seqNode)
| step_option($seqNode)
;
%type <createAlterSequenceNode> alter_sequence_clause
alter_sequence_clause
: symbol_generator_name
{
CreateAlterSequenceNode* node = newNode<CreateAlterSequenceNode>(*$1);
node->create = false;
node->alter = true;
$$ = node;
}
alter_sequence_options($2)
{
if (!$2->restartSpecified && !$2->value.has_value() && !$2->step.has_value())
yyerrorIncompleteCmd(YYPOSNARG(3));
$$ = $2;
}
%type alter_sequence_options(<createAlterSequenceNode>)
alter_sequence_options($seqNode)
: /* nothing */
| alter_seq_option($seqNode) alter_sequence_options($seqNode)
;
%type alter_seq_option(<createAlterSequenceNode>)
alter_seq_option($seqNode)
: restart_option($seqNode)
| step_option($seqNode)
;
%type restart_option(<createAlterSequenceNode>)
restart_option($seqNode)
: RESTART with_opt
{
setClause($seqNode->restartSpecified, "RESTART", true);
setClause($seqNode->value, "RESTART WITH", $2);
}
%type <nullableInt64Val> with_opt
with_opt
: /* Nothign */ { $$ = std::nullopt; }
| WITH sequence_value { $$ = $2; }
;
%type <createAlterSequenceNode> set_generator_clause
set_generator_clause
: SET GENERATOR symbol_generator_name TO sequence_value
{
CreateAlterSequenceNode* node = newNode<CreateAlterSequenceNode>(*$3);
node->create = false;
node->alter = true;
node->legacy = true;
node->restartSpecified = true;
node->value = $5;
$$ = 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;
}
| '-' LIMIT64_INT
{
$$ = MIN_SINT64;
}
;
// CREATE / ALTER ROLE
%type <createAlterRoleNode> role_clause
role_clause
: symbol_role_name
{ $$ = newNode<CreateAlterRoleNode>(*$1); }
opt_system_privileges($2)
{ $$ = $2; }
;
%type opt_system_privileges(<createAlterRoleNode>)
opt_system_privileges($createAlterRole)
: // nothing
| set_system_privileges($createAlterRole)
| drop_system_privileges($createAlterRole)
;
%type set_system_privileges(<createAlterRoleNode>)
set_system_privileges($createAlterRole)
: SET SYSTEM PRIVILEGES TO system_privileges_list($createAlterRole)
%type drop_system_privileges(<createAlterRoleNode>)
drop_system_privileges($createAlterRole)
: DROP SYSTEM PRIVILEGES { $createAlterRole->sysPrivDrop = true; }
%type system_privileges_list(<createAlterRoleNode>)
system_privileges_list($createAlterRole)
: system_privilege($createAlterRole)
| system_privileges_list ',' system_privilege($createAlterRole)
;
%type system_privilege(<createAlterRoleNode>)
system_privilege($createAlterRole)
: valid_symbol_name { $createAlterRole->addPrivilege($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); }
;
//
%type <ddlNode> alter_eds_conn_pool_clause
alter_eds_conn_pool_clause
: SET SIZE unsigned_short_integer
{ $$ = newNode<AlterEDSPoolSetNode>(AlterEDSPoolSetNode::POOL_SIZE, $3); }
| SET LIFETIME unsigned_short_integer eds_pool_lifetime_mult
{ $$ = newNode<AlterEDSPoolSetNode>(AlterEDSPoolSetNode::POOL_LIFETIME, $3 * $4); }
| CLEAR sql_string
{ $$ = newNode<AlterEDSPoolClearNode>(AlterEDSPoolClearNode::POOL_DB, $2->getString()); }
| CLEAR ALL
{ $$ = newNode<AlterEDSPoolClearNode>(AlterEDSPoolClearNode::POOL_ALL); }
| CLEAR OLDEST
{ $$ = newNode<AlterEDSPoolClearNode>(AlterEDSPoolClearNode::POOL_OLDEST); }
;
%type <intVal> eds_pool_lifetime_mult
eds_pool_lifetime_mult
: HOUR { $$ = 3600; }
| MINUTE { $$ = 60; }
| SECOND { $$ = 1; }
;
// 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)
: PAGE_SIZE equals NUMBER32BIT
| USER symbol_user_name
| USER utf_string
| OWNER symbol_user_name
| OWNER utf_string
| ROLE valid_symbol_name
| ROLE utf_string
| PASSWORD utf_string
| SET NAMES utf_string
;
%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)
: 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;
}
| DIFFERENCE FILE utf_string
{ $alterDatabaseNode->differenceFile = *$3; }
;
// CREATE TABLE
%type <createRelationNode> table_clause
table_clause
: simple_table_name external_file
{
$<createRelationNode>$ = newNode<CreateRelationNode>($1, $2);
}
'(' table_elements($3) ')' table_attributes($3)
{
$$ = $3;
}
;
%type table_attributes(<relationNode>)
table_attributes($relationNode)
: /* nothing */
| table_attribute($relationNode) table_attributes($relationNode)
;
%type table_attribute(<relationNode>)
table_attribute($relationNode)
: sql_security_clause
{ setClause($relationNode->ssDefiner, "SQL SECURITY", $1); }
| publication_state
{ setClause($relationNode->replicationState, "PUBLICATION", $1); }
;
%type <boolVal> sql_security_clause
sql_security_clause
: SQL SECURITY DEFINER { $$ = true; }
| SQL SECURITY INVOKER { $$ = false; }
;
%type <triState> sql_security_clause_opt
sql_security_clause_opt
: /* nothing */ { $$ = TriState(); }
| sql_security_clause { $$ = $1; }
;
%type <boolVal> publication_state
publication_state
: ENABLE PUBLICATION { $$ = true; }
| DISABLE PUBLICATION { $$ = false; }
;
%type <createRelationNode> gtt_table_clause
gtt_table_clause
: simple_table_name
{
$<createRelationNode>$ = newNode<CreateRelationNode>($1);
$<createRelationNode>$->relationType = std::nullopt;
}
'(' table_elements($2) ')' gtt_ops($2)
{
$$ = $2;
if (!$$->relationType.has_value())
$$->relationType = rel_global_temp_delete;
}
;
%type gtt_ops(<createRelationNode>)
gtt_ops($createRelationNode)
: gtt_op($createRelationNode)
| gtt_ops ',' gtt_op($createRelationNode)
;
%type gtt_op(<createRelationNode>)
gtt_op($createRelationNode)
: // nothing by default. Will be set "on commit delete rows" in dsqlPass
| sql_security_clause_opt
{ setClause($createRelationNode->ssDefiner, "SQL SECURITY", $1); }
| ON COMMIT DELETE ROWS
{ setClause($createRelationNode->relationType, "ON COMMIT DELETE ROWS", rel_global_temp_delete); }
| ON COMMIT PRESERVE ROWS
{ setClause($createRelationNode->relationType, "ON COMMIT PRESERVE ROWS", rel_global_temp_preserve); }
;
%type <stringPtr> external_file
external_file
: /* nothing */ { $$ = NULL; }
| EXTERNAL 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 <addColumnClause> 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
{
setCollate($2, $6);
$$ = $<addColumnClause>4;
}
| 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->identityOptions = $3;
$relationNode->clauses.add(clause);
}
column_constraint_clause(NOTRIAL($<addColumnClause>4)) collate_clause
{
setCollate($2, $6);
$$ = $<addColumnClause>4;
}
| 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;
$$ = clause;
}
| 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;
$$ = clause;
}
;
%type <identityOptions> identity_clause
identity_clause
: GENERATED identity_clause_type AS IDENTITY
{ $$ = newNode<RelationNode::IdentityOptions>($2); }
identity_clause_options_opt($5)
{ $$ = $5; }
;
%type <identityType> identity_clause_type
identity_clause_type
: BY DEFAULT { $$ = IDENT_TYPE_BY_DEFAULT; }
| ALWAYS { $$ = IDENT_TYPE_ALWAYS; }
;
%type identity_clause_options_opt(<identityOptions>)
identity_clause_options_opt($identityOptions)
: // nothing
| '(' identity_clause_options($identityOptions) ')'
;
%type identity_clause_options(<identityOptions>)
identity_clause_options($identityOptions)
: identity_clause_options identity_clause_option($identityOptions)
| identity_clause_option($identityOptions)
;
%type identity_clause_option(<identityOptions>)
identity_clause_option($identityOptions)
: START WITH sequence_value
{ setClause($identityOptions->startValue, "START WITH", $3); }
| INCREMENT by_noise signed_long_integer
{ setClause($identityOptions->increment, "INCREMENT BY", $3); }
;
// 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
| TYPE OF symbol_column_name
{
$$ = newNode<dsql_fld>();
$$->typeOfName = *$3;
}
| 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
{
setClause($addColumnClause->notNullSpecified, "NOT NULL");
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(nodeAs<FieldNode>(*ptr)->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 <addConstraintClause> table_constraint_definition(<relationNode>)
table_constraint_definition($relationNode)
: constraint_name_opt table_constraint($relationNode)
{
if ($1)
$2->name = *$1;
$$ = $2;
}
;
%type <metaNamePtr> constraint_name_opt
constraint_name_opt
: /* nothing */ { $$ = NULL; }
| CONSTRAINT symbol_constraint_name { $$ = $2; }
;
%type <addConstraintClause> 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(nodeAs<FieldNode>(*ptr)->dsqlName);
constraint.index = $3;
$relationNode->clauses.add(&constraint);
$$ = &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(nodeAs<FieldNode>(*ptr)->dsqlName);
constraint.index = $4;
$relationNode->clauses.add(&constraint);
$$ = &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(nodeAs<FieldNode>(*ptr)->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(nodeAs<FieldNode>(*ptr)->dsqlName);
}
constraint.index = $8;
$relationNode->clauses.add(&constraint);
$$ = &constraint;
}
| check_constraint
{
RelationNode::AddConstraintClause* constraint = newNode<RelationNode::AddConstraintClause>();
constraint->constraintType = RelationNode::AddConstraintClause::CTYPE_CHECK;
constraint->check = $1;
$relationNode->clauses.add(constraint);
$$ = 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 DELETE referential_action { $$ = $3;}
;
%type <uintVal> referential_action
referential_action
: CASCADE { $$ = RelationNode::RefActionClause::ACTION_CASCADE; }
| SET DEFAULT { $$ = RelationNode::RefActionClause::ACTION_SET_DEFAULT; }
| SET 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 optional_sql_security_full_alter_clause AS local_declarations_opt full_proc_block
{
$$ = $1;
$$->ssDefiner = $2;
$$->source = makeParseStr(YYPOSNARG(4), YYPOSNARG(5));
$$->localDeclList = $4;
$$->body = $5;
}
;
%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> partial_alter_procedure_clause
partial_alter_procedure_clause
: symbol_procedure_name
{ $$ = newNode<CreateAlterProcedureNode>(*$1); }
optional_sql_security_partial_alter_clause
{
$$ = $2;
$$->ssDefiner = $3;
}
;
%type <createAlterProcedureNode> alter_procedure_clause
alter_procedure_clause
: procedure_clause
{
$$ = $1;
$$->alter = true;
$$->create = false;
}
| partial_alter_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
{
setCollate($1, $2);
$parameters->add(newNode<ParameterClause>($1, $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
{
setCollate($1, $2);
$parameters->add(newNode<ParameterClause>($1));
}
;
%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 optional_sql_security_full_alter_clause AS local_declarations_opt full_proc_block
{
$$ = $1;
$$->ssDefiner = $2;
$$->source = makeParseStr(YYPOSNARG(4), YYPOSNARG(5));
$$->localDeclList = $4;
$$->body = $5;
}
;
%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_clause_opt
{
$$ = $2;
$$->returnType = newNode<ParameterClause>($5);
setCollate($5, $6);
$$->deterministic = $7;
}
;
%type <createAlterFunctionNode> partial_alter_function_clause
partial_alter_function_clause
: symbol_UDF_name
{ $$ = newNode<CreateAlterFunctionNode>(*$1); }
alter_individual_ops($2)
{ $$ = $2; }
;
%type alter_individual_ops(<createAlterFunctionNode>)
alter_individual_ops($createAlterFunctionNode)
: alter_individual_op($createAlterFunctionNode)
| alter_individual_ops alter_individual_op($createAlterFunctionNode)
;
%type alter_individual_op(<createAlterFunctionNode>)
alter_individual_op($createAlterFunctionNode)
: deterministic_clause
{ setClause($createAlterFunctionNode->deterministic, "DETERMINISTIC", $1); }
| optional_sql_security_partial_alter_clause
{ setClause($createAlterFunctionNode->ssDefiner, "SQL SECURITY", $1); }
;
%type <boolVal> deterministic_clause
deterministic_clause
: NOT DETERMINISTIC { $$ = false; }
| DETERMINISTIC { $$ = true; }
;
%type <boolVal> deterministic_clause_opt
deterministic_clause_opt
: { $$ = false; }
| deterministic_clause { $$ = $1; }
;
%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;
}
| partial_alter_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 optional_sql_security_full_alter_clause AS BEGIN package_items_opt END
{
CreateAlterPackageNode* node = newNode<CreateAlterPackageNode>(*$1);
node->ssDefiner = $2;
node->source = makeParseStr(YYPOSNARG(4), YYPOSNARG(6));
node->items = $5;
$$ = node;
}
;
%type <createAlterPackageNode> partial_alter_package_clause
partial_alter_package_clause
: symbol_package_name optional_sql_security_partial_alter_clause
{
CreateAlterPackageNode* node = newNode<CreateAlterPackageNode>(*$1);
node->ssDefiner = $2;
$$ = 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;
}
| partial_alter_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 <ddlNode> replace_package_body_clause
replace_package_body_clause
: package_body_clause
{ $$ = newNode<RecreatePackageBodyNode>($1); }
;
%type <localDeclarationsNode> local_declarations_opt
local_declarations_opt
: local_forward_declarations_opt local_nonforward_declarations_opt
{
LocalDeclarationsNode* forward = $1;
LocalDeclarationsNode* nonForward = $2;
if (!forward)
$$ = nonForward;
else
{
if (nonForward)
forward->statements.add(nonForward->statements.begin(), nonForward->statements.getCount());
$$ = forward;
}
}
;
%type <localDeclarationsNode> local_forward_declarations_opt
local_forward_declarations_opt
: /* nothing */ { $$ = nullptr; }
| local_forward_declarations
;
%type <localDeclarationsNode> local_forward_declarations
local_forward_declarations
: local_forward_declaration
{
$$ = newNode<LocalDeclarationsNode>();
$$->statements.add($1);
}
| local_forward_declarations local_forward_declaration
{
$1->statements.add($2);
$$ = $1;
}
;
%type <stmtNode> local_forward_declaration
local_forward_declaration
: local_declaration_subproc_start ';' { $$ = $1; }
| local_declaration_subfunc_start ';' { $$ = $1; }
;
%type <localDeclarationsNode> local_nonforward_declarations_opt
local_nonforward_declarations_opt
: /* nothing */ { $$ = nullptr; }
| local_nonforward_declarations
;
%type <localDeclarationsNode> local_nonforward_declarations
local_nonforward_declarations
: local_nonforward_declaration
{
$$ = newNode<LocalDeclarationsNode>();
$$->statements.add($1);
}
| local_nonforward_declarations local_nonforward_declaration
{
$1->statements.add($2);
$$ = $1;
}
;
%type <stmtNode> local_nonforward_declaration
local_nonforward_declaration
: DECLARE var_decl_opt local_declaration_item ';'
{
$$ = $3;
$$->line = YYPOSNARG(1).firstLine;
$$->column = YYPOSNARG(1).firstColumn;
}
| local_declaration_subproc_start AS local_declarations_opt full_proc_block
{
DeclareSubProcNode* node = $1;
node->dsqlBlock->localDeclList = $3;
node->dsqlBlock->body = $4;
for (FB_SIZE_T i = 0; i < node->dsqlBlock->parameters.getCount(); ++i)
node->dsqlBlock->parameters[i]->parameterExpr = make_parameter();
$$ = node;
}
| local_declaration_subfunc_start AS local_declarations_opt full_proc_block
{
DeclareSubFuncNode* node = $1;
node->dsqlBlock->localDeclList = $3;
node->dsqlBlock->body = $4;
for (FB_SIZE_T i = 0; i < node->dsqlBlock->parameters.getCount(); ++i)
node->dsqlBlock->parameters[i]->parameterExpr = make_parameter();
$$ = node;
}
;
%type <declareSubProcNode> local_declaration_subproc_start
local_declaration_subproc_start
: DECLARE PROCEDURE symbol_procedure_name
{
$$ = newNode<DeclareSubProcNode>(NOTRIAL(*$3));
$$->dsqlBlock = newNode<ExecBlockNode>();
}
input_parameters(NOTRIAL(&$4->dsqlBlock->parameters))
output_parameters(NOTRIAL(&$4->dsqlBlock->returns))
{ $$ = $4; }
;
%type <declareSubFuncNode> local_declaration_subfunc_start
local_declaration_subfunc_start
: DECLARE FUNCTION symbol_UDF_name
{
$$ = newNode<DeclareSubFuncNode>(NOTRIAL(*$3));
$$->dsqlBlock = newNode<ExecBlockNode>();
}
input_parameters(NOTRIAL(&$4->dsqlBlock->parameters))
RETURNS domain_or_non_array_type collate_clause deterministic_clause_opt
{
$$ = $4;
setCollate($7, $8);
$$->dsqlBlock->returns.add(newNode<ParameterClause>($<legacyField>7));
$$->dsqlDeterministic = $9;
}
;
%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 var_declaration_initializer
{
// Set collate before node allocation to prevent memory leak on throw
setCollate($1, $2);
DeclareVariableNode* node = newNode<DeclareVariableNode>();
node->dsqlDef = newNode<ParameterClause>($1, $3);
$$ = node;
}
;
%type <valueSourceClause> var_declaration_initializer
var_declaration_initializer
: // nothing
{ $$ = nullptr; }
| DEFAULT value
{
const auto clause = newNode<ValueSourceClause>();
clause->value = $2;
clause->source = makeParseStr(YYPOSNARG(1), YYPOSNARG(2));
$$ = clause;
}
| '=' value
{
const auto clause = newNode<ValueSourceClause>();
clause->value = $2;
clause->source = makeParseStr(YYPOSNARG(1), YYPOSNARG(2));
$$ = clause;
}
;
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 ';' [YYVALID;]
{ $$ = newNode<LineColumnNode>(YYPOSNARG(1).firstLine, YYPOSNARG(1).firstColumn, $1); }
| complex_proc_statement [YYVALID;]
{ $$ = newNode<LineColumnNode>(YYPOSNARG(1).firstLine, YYPOSNARG(1).firstColumn, $1); }
;
%type <stmtNode> simple_proc_statement
simple_proc_statement
: assignment_statement
| insert { $$ = $1; }
| merge { $$ = $1; }
| update
| update_or_insert { $$ = $1; }
| delete
| singleton_select
| exec_procedure
| call { $$ = $1; }
| 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); }
| mng_statement { $$ = newNode<SessionManagementWrapperNode>($1, makeParseStr(YYPOSNARG(1), YYPOSNARG(1))); }
;
%type <stmtNode> assignment_statement
assignment_statement
: assignment
| ':' assignment { $$ = $2; }
;
%type <stmtNode> complex_proc_statement
complex_proc_statement
: in_autonomous_transaction
| if_then_else
| while
| for_select { $$ = $1; }
| for_exec_into { $$ = $1; }
;
%type <stmtNode> in_autonomous_transaction
in_autonomous_transaction
: 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 <forNode> for_select
for_select
: label_def_opt FOR select
{
ForNode* node = newNode<ForNode>();
node->dsqlLabelName = $1;
node->dsqlSelect = $3;
$$ = node;
}
for_select_into_cursor($4) DO proc_block
{
ForNode* node = $4;
node->statement = $7;
$$ = node;
}
;
%type for_select_into_cursor(<forNode>)
for_select_into_cursor($forNode)
: into_variable_list cursor_def_opt
{
$forNode->dsqlInto = $1;
$forNode->dsqlCursor = $2;
}
| into_variable_list_opt cursor_def
{
$forNode->dsqlInto = $1;
$forNode->dsqlCursor = $2;
}
;
%type <valueListNode> into_variable_list_opt
into_variable_list_opt
: /* nothing */ { $$ = NULL; }
| into_variable_list
;
%type <valueListNode> into_variable_list
into_variable_list
: INTO variable_list { $$ = $2; }
;
%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_POOL(getPool()) EDS::ParamNames(getPool());
$execStatementNode->inputNames->add($1);
if (!$execStatementNode->inputs)
$execStatementNode->inputs = newNode<ValueListNode>($3);
else
$execStatementNode->inputs->add($3);
}
| EXCESS symbol_variable_name BIND_PARAM value
{
if (!$execStatementNode->inputNames)
$execStatementNode->inputNames = FB_NEW_POOL(getPool()) EDS::ParamNames(getPool());
if (!$execStatementNode->excessInputs)
$execStatementNode->excessInputs = FB_NEW_POOL(getPool()) EDS::ParamNumbers(getPool());
$execStatementNode->excessInputs->add($execStatementNode->inputNames->getCount());
$execStatementNode->inputNames->add($2);
if (!$execStatementNode->inputs)
$execStatementNode->inputs = newNode<ValueListNode>($4);
else
$execStatementNode->inputs->add($4);
}
;
%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
: 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_opt
cursor_def_opt
: /* nothing */ { $$ = NULL; }
| cursor_def
;
%type <declCursorNode> cursor_def
cursor_def
: 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;
}
| SQLSTATE STRING
{
ExceptionItem& item = $exceptionArray->add();
item.type = ExceptionItem::SQL_STATE;
item.name = $2->getString();
}
| 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_opt
{
CursorStmtNode* cursorStmt = $<cursorStmtNode>2;
cursorStmt->dsqlName = *$5;
cursorStmt->dsqlIntoStmt = $6;
$$ = cursorStmt;
}
| FETCH symbol_cursor_name into_variable_list_opt
{ $$ = newNode<CursorStmtNode>(blr_cursor_fetch, *$2, $3); }
;
%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; }
| ABSOLUTE value
{
$cursorStmtNode->scrollOp = blr_scroll_absolute;
$cursorStmtNode->scrollExpr = $2;
}
| 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 ? $4->second : nullptr),
$5,
($4 ? $4->first : nullptr));
}
| EXECUTE PROCEDURE symbol_package_name '.' symbol_procedure_name proc_inputs proc_outputs_opt
{
$$ = newNode<ExecProcedureNode>(
QualifiedName(*$5, *$3),
($6 ? $6->second : nullptr),
$7,
($6 ? $6->first : nullptr));
}
;
%type <namedArguments> proc_inputs
proc_inputs
: /* nothing */ { $$ = nullptr; }
| argument_list { $$ = $1; }
| '(' argument_list ')' { $$ = $2; }
;
%type <valueListNode> proc_outputs_opt
proc_outputs_opt
: /* nothing */ { $$ = NULL; }
| RETURNING_VALUES variable_list { $$ = $2; }
| RETURNING_VALUES '(' variable_list ')' { $$ = $3; }
;
// CALL
%type <stmtNode> call
call
: CALL symbol_procedure_name '(' argument_list_opt ')'
{
auto node = newNode<ExecProcedureNode>(QualifiedName(*$2),
($4 ? $4->second : nullptr),
nullptr,
($4 ? $4->first : nullptr));
node->dsqlCallSyntax = true;
$$ = node;
}
| CALL symbol_package_name '.' symbol_procedure_name '(' argument_list_opt ')'
into_variable_list_opt
{
auto node = newNode<ExecProcedureNode>(QualifiedName(*$4, *$2),
($6 ? $6->second : nullptr),
nullptr,
($6 ? $6->first : nullptr));
node->dsqlCallSyntax = true;
$$ = node;
}
;
// 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_declarations_opt
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
{
setCollate($1, $2);
$parameters->add(newNode<ParameterClause>($1, (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
: create_trigger_start trg_sql_security_clause AS local_declarations_opt full_proc_block
{
$$ = $1;
$$->ssDefiner = $2;
$$->source = makeParseStr(YYPOSNARG(3), YYPOSNARG(5));
$$->localDeclList = $4;
$$->body = $5;
}
| create_trigger_start external_clause external_body_clause_opt
{
$$ = $1;
$$->external = $2;
if ($3)
$$->source = *$3;
}
;
%type <createAlterTriggerNode> create_trigger_start
create_trigger_start
: symbol_trigger_name
{ $$ = newNode<CreateAlterTriggerNode>(*$1); }
create_trigger_common(NOTRIAL($2))
{ $$ = $2; }
;
%type create_trigger_common(<createAlterTriggerNode>)
create_trigger_common($trigger)
: trigger_active trigger_type(NOTRIAL($trigger)) trigger_position
{
$trigger->active = $1;
$trigger->type = $2;
setClause($trigger->position, "POSITION", $3);
}
| FOR symbol_table_name trigger_active table_trigger_type trigger_position
{
$trigger->relationName = *$2;
$trigger->active = $3;
$trigger->type = $4;
setClause($trigger->position, "POSITION", $5);
}
;
%type <createAlterTriggerNode> replace_trigger_clause
replace_trigger_clause
: trigger_clause
{
$$ = $1;
$$->alter = true;
}
;
%type <triState> trigger_active
trigger_active
: ACTIVE
{ $$ = TriState(true); }
| INACTIVE
{ $$ = TriState(false); }
| // nothing
{ $$ = TriState(); }
;
%type <uint64Val> trigger_type(<createAlterTriggerNode>)
trigger_type($trigger)
: table_trigger_type trigger_position ON symbol_table_name
{
$$ = $1;
setClause($trigger->position, "POSITION", $2);
$trigger->relationName = *$4;
}
| ON trigger_db_type
{ $$ = $2; }
| trigger_type_prefix trigger_ddl_type
{ $$ = $1 + $2; }
;
%type <uint64Val> table_trigger_type
table_trigger_type
: trigger_type_prefix trigger_type_suffix { $$ = $1 + $2 - 1; }
;
%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 | DDL_TRIGGER_ANY;
}
;
%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); }
| CREATE MAPPING { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_CREATE_MAPPING); }
| ALTER MAPPING { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_ALTER_MAPPING); }
| DROP MAPPING { $$ = TRIGGER_TYPE_DDL | (1LL << DDL_TRIGGER_DROP_MAPPING); }
| 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); }
| DELETE { $$ = trigger_type_suffix(3, 0, 0); }
| INSERT OR UPDATE { $$ = trigger_type_suffix(1, 2, 0); }
| INSERT OR DELETE { $$ = trigger_type_suffix(1, 3, 0); }
| UPDATE OR INSERT { $$ = trigger_type_suffix(2, 1, 0); }
| UPDATE OR DELETE { $$ = trigger_type_suffix(2, 3, 0); }
| DELETE OR INSERT { $$ = trigger_type_suffix(3, 1, 0); }
| DELETE OR UPDATE { $$ = trigger_type_suffix(3, 2, 0); }
| INSERT OR UPDATE OR DELETE { $$ = trigger_type_suffix(1, 2, 3); }
| INSERT OR DELETE OR UPDATE { $$ = trigger_type_suffix(1, 3, 2); }
| UPDATE OR INSERT OR DELETE { $$ = trigger_type_suffix(2, 1, 3); }
| UPDATE OR DELETE OR INSERT { $$ = trigger_type_suffix(2, 3, 1); }
| DELETE OR INSERT OR UPDATE { $$ = trigger_type_suffix(3, 1, 2); }
| DELETE OR UPDATE OR INSERT { $$ = trigger_type_suffix(3, 2, 1); }
;
%type <nullableIntVal> trigger_position
trigger_position
: /* nothing */ { $$ = std::nullopt; }
| POSITION nonneg_short_integer { $$ = $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; }
| PACKAGE BODY replace_package_body_clause { $$ = $3; }
| 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; }
| MAPPING alter_map_clause(false) { $$ = $2; }
| GLOBAL MAPPING alter_map_clause(true) { $$ = $3; }
| EXTERNAL CONNECTIONS POOL alter_eds_conn_pool_clause { $$ = $4; }
;
%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"); }
| DROP NOT NULL
{ setClause($alterDomainNode->notNullFlag, "{SET | DROP} NOT NULL", false); }
| SET NOT NULL
{ setClause($alterDomainNode->notNullFlag, "{SET | DROP} NOT NULL", true); }
| TO symbol_column_name
{ setClause($alterDomainNode->renameTo, "DOMAIN NAME", *$2); }
| 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 if_exists_opt symbol_column_name drop_behaviour
{
RelationNode::DropColumnClause* clause = newNode<RelationNode::DropColumnClause>();
clause->silent = $2;
clause->name = *$3;
clause->cascade = $4;
$relationNode->clauses.add(clause);
}
| DROP CONSTRAINT if_exists_opt symbol_constraint_name
{
RelationNode::DropConstraintClause* clause = newNode<RelationNode::DropConstraintClause>();
clause->silent = $3;
clause->name = *$4;
$relationNode->clauses.add(clause);
}
| ADD if_not_exists_opt column_def($relationNode)
{
const auto node = $3;
node->createIfNotExistsOnly = $2;
}
| ADD table_constraint($relationNode)
| ADD CONSTRAINT if_not_exists_opt symbol_constraint_name table_constraint($relationNode)
{
const auto node = $5;
node->name = *$4;
node->createIfNotExistsOnly = $3;
}
| 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 DROP NOT NULL
{
RelationNode::AlterColNullClause* clause = newNode<RelationNode::AlterColNullClause>();
clause->name = *$2;
clause->notNullFlag = false;
$relationNode->clauses.add(clause);
}
| col_opt alter_column_name SET NOT NULL
{
RelationNode::AlterColNullClause* clause = newNode<RelationNode::AlterColNullClause>();
clause->name = *$2;
clause->notNullFlag = true;
$relationNode->clauses.add(clause);
}
| col_opt symbol_column_name 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 TYPE non_array_type def_computed
{
RelationNode::AlterColTypeClause* clause = newNode<RelationNode::AlterColTypeClause>();
clause->field = $4;
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
{ $<identityOptions>$ = newNode<RelationNode::IdentityOptions>(); }
alter_identity_clause_spec($<identityOptions>3)
{
RelationNode::AlterColTypeClause* clause = newNode<RelationNode::AlterColTypeClause>();
clause->field = newNode<dsql_fld>();
clause->field->fld_name = *$2;
clause->identityOptions = $<identityOptions>3;
$relationNode->clauses.add(clause);
}
| col_opt symbol_column_name DROP IDENTITY
{
RelationNode::AlterColTypeClause* clause = newNode<RelationNode::AlterColTypeClause>();
clause->field = newNode<dsql_fld>();
clause->field->fld_name = *$2;
clause->dropIdentity = true;
$relationNode->clauses.add(clause);
}
| ALTER SQL SECURITY DEFINER
{
setClause($relationNode->ssDefiner, "SQL SECURITY", true);
RelationNode::Clause* clause =
newNode<RelationNode::Clause>(RelationNode::Clause::TYPE_ALTER_SQL_SECURITY);
$relationNode->clauses.add(clause);
}
| ALTER SQL SECURITY INVOKER
{
setClause($relationNode->ssDefiner, "SQL SECURITY", false);
RelationNode::Clause* clause =
newNode<RelationNode::Clause>(RelationNode::Clause::TYPE_ALTER_SQL_SECURITY);
$relationNode->clauses.add(clause);
}
| DROP SQL SECURITY
{
setClause($relationNode->ssDefiner, "SQL SECURITY", TriState());
RelationNode::Clause* clause =
newNode<RelationNode::Clause>(RelationNode::Clause::TYPE_ALTER_SQL_SECURITY);
$relationNode->clauses.add(clause);
}
| ENABLE PUBLICATION
{
setClause($relationNode->replicationState, "PUBLICATION", true);
RelationNode::Clause* clause =
newNode<RelationNode::Clause>(RelationNode::Clause::TYPE_ALTER_PUBLICATION);
$relationNode->clauses.add(clause);
}
| DISABLE PUBLICATION
{
setClause($relationNode->replicationState, "PUBLICATION", false);
RelationNode::Clause* clause =
newNode<RelationNode::Clause>(RelationNode::Clause::TYPE_ALTER_PUBLICATION);
$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
| LOWER
| OCTET_LENGTH
| TRAILING
| TRIM
| CONNECT // added in FB 2.1
| DISCONNECT
| GLOBAL
| INSENSITIVE
| RECURSIVE
| SENSITIVE
| START
| SIMILAR // added in FB 2.5
| BOOLEAN // added in FB 3.0
| CORR
| COVAR_POP
| COVAR_SAMP
| DELETING
| DETERMINISTIC
| FALSE
| INSERTING
| OFFSET
| OVER
| REGR_AVGX
| REGR_AVGY
| REGR_COUNT
| REGR_INTERCEPT
| REGR_R2
| REGR_SLOPE
| REGR_SXX
| REGR_SXY
| REGR_SYY
| RETURN
| ROW
| SCROLL
| SQLSTATE
| STDDEV_SAMP
| STDDEV_POP
| TRUE
| UNKNOWN
| UPDATING
| VAR_SAMP
| VAR_POP
| BINARY // added in FB 4.0
| DECFLOAT
| INT128
| LATERAL
| LOCAL
| LOCALTIME
| LOCALTIMESTAMP
| PUBLICATION
| RESETTING
| TIMEZONE_HOUR
| TIMEZONE_MINUTE
| UNBOUNDED
| VARBINARY
| WINDOW
| WITHOUT
| BTRIM // added in FB 6.0
| CALL
| LTRIM
| RTRIM
;
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 alter_identity_clause_spec(<identityOptions>)
alter_identity_clause_spec($identityOptions)
: alter_identity_clause_generation($identityOptions) alter_identity_clause_options_opt($identityOptions)
| alter_identity_clause_options($identityOptions)
;
%type alter_identity_clause_generation(<identityOptions>)
alter_identity_clause_generation($identityOptions)
: SET GENERATED ALWAYS { $identityOptions->type = IDENT_TYPE_ALWAYS; }
| SET GENERATED BY DEFAULT { $identityOptions->type = IDENT_TYPE_BY_DEFAULT; }
;
%type alter_identity_clause_options_opt(<identityOptions>)
alter_identity_clause_options_opt($identityOptions)
: // nothing
| alter_identity_clause_options($identityOptions)
;
%type alter_identity_clause_options(<identityOptions>)
alter_identity_clause_options($identityOptions)
: alter_identity_clause_options alter_identity_clause_option($identityOptions)
| alter_identity_clause_option($identityOptions)
;
%type alter_identity_clause_option(<identityOptions>)
alter_identity_clause_option($identityOptions)
: RESTART with_opt
{
setClause($identityOptions->restart, "RESTART");
$identityOptions->startValue = $2;
}
| SET INCREMENT by_noise signed_long_integer
{ setClause($identityOptions->increment, "SET INCREMENT BY", $4); }
;
%type <boolVal> drop_behaviour
drop_behaviour
: { $$ = false; }
| RESTRICT { $$ = false; }
| CASCADE { $$ = true; }
;
%type <ddlNode> alter_index_clause
alter_index_clause
: symbol_index_name index_active
{
$$ = newNode<AlterIndexNode>(*$1, $2);
}
;
%type <boolVal> index_active
index_active
: ACTIVE { $$ = true; }
| INACTIVE { $$ = 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_2X_compatibility
alter_role_2X_compatibility
: symbol_role_name alter_role_enable AUTO ADMIN MAPPING
{
MappingNode* mn = newNode<MappingNode>(MappingNode::MAP_RPL, "AutoAdminImplementationMapping");
mn->op = $2 ? MappingNode::MAP_RPL : MappingNode::MAP_DROP;
mn->from = newNode<IntlString>(FB_DOMAIN_ANY_RID_ADMINS);
mn->fromType = newNode<MetaName>(FB_PREDEFINED_GROUP);
mn->mode = 'P';
mn->plugin = newNode<MetaName>("Win_Sspi");
mn->role = true;
mn->to = $1;
mn->validateAdmin();
$$ = mn;
}
;
%type <ddlNode> alter_role_clause
alter_role_clause
: role_clause { $$ = $1; }
| alter_role_2X_compatibility { $$ = $1; }
;
%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 DIFFERENCE FILE utf_string
{ $alterDatabaseNode->differenceFile = *$4; }
| DROP DIFFERENCE 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 crypt_key_clause($alterDatabaseNode)
{
setClauseFlag($alterDatabaseNode->clauses, AlterDatabaseNode::CLAUSE_CRYPT, "CRYPT");
$alterDatabaseNode->cryptPlugin = *$3;
}
| DECRYPT
{ setClauseFlag($alterDatabaseNode->clauses, AlterDatabaseNode::CLAUSE_CRYPT, "CRYPT"); }
| SET LINGER TO long_integer
{ $alterDatabaseNode->linger = $4; }
| DROP LINGER
{ $alterDatabaseNode->linger = 0; }
| SET DEFAULT sql_security_clause
{ $alterDatabaseNode->ssDefiner = $3; }
| ENABLE PUBLICATION
{ $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_ENABLE_PUB; }
| DISABLE PUBLICATION
{ $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_DISABLE_PUB; }
| INCLUDE pub_table_filter($alterDatabaseNode) TO PUBLICATION
{ $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_PUB_INCL_TABLE; }
| EXCLUDE pub_table_filter($alterDatabaseNode) FROM PUBLICATION
{ $alterDatabaseNode->clauses |= AlterDatabaseNode::CLAUSE_PUB_EXCL_TABLE; }
;
%type crypt_key_clause(<alterDatabaseNode>)
crypt_key_clause($alterDatabaseNode)
: // nothing
| KEY valid_symbol_name { $alterDatabaseNode->keyName = *$2; }
;
%type pub_table_filter(<alterDatabaseNode>)
pub_table_filter($alterDatabaseNode)
: ALL
| TABLE pub_table_list($alterDatabaseNode)
;
%type pub_table_list(<alterDatabaseNode>)
pub_table_list($alterDatabaseNode)
: pub_table_clause($alterDatabaseNode)
| pub_table_list ',' pub_table_clause($alterDatabaseNode)
;
%type pub_table_clause(<alterDatabaseNode>)
pub_table_clause($alterDatabaseNode)
: symbol_table_name
{ $alterDatabaseNode->pubTables.add(*$1); }
;
// ALTER TRIGGER
%type <createAlterTriggerNode> alter_trigger_clause
alter_trigger_clause
: symbol_trigger_name trigger_active trigger_type_opt trigger_position trg_sql_security_clause
AS local_declarations_opt full_proc_block
{
$$ = newNode<CreateAlterTriggerNode>(*$1);
$$->alter = true;
$$->create = false;
$$->active = $2;
$$->type = $3;
$$->position = $4;
$$->ssDefiner = $5;
$$->source = makeParseStr(YYPOSNARG(6), YYPOSNARG(8));
$$->localDeclList = $7;
$$->body = $8;
}
| 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 trg_sql_security_clause
{
$$ = newNode<CreateAlterTriggerNode>(*$1);
$$->alter = true;
$$->create = false;
$$->active = $2;
$$->type = $3;
$$->position = $4;
$$->ssDefiner = $5;
}
;
%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
{ $$ = $1 + $2 - 1; }
|
{ $$ = std::nullopt; }
;
%type <nullableSqlSecurityVal> optional_sql_security_clause
optional_sql_security_clause
: SQL SECURITY DEFINER
{ $$ = SS_DEFINER; }
| SQL SECURITY INVOKER
{ $$ = SS_INVOKER; }
;
%type <nullableSqlSecurityVal> optional_sql_security_full_alter_clause
optional_sql_security_full_alter_clause
: optional_sql_security_clause
{ $$ = $1; }
| // nothing
{ $$ = std::nullopt; }
;
%type <nullableSqlSecurityVal> optional_sql_security_partial_alter_clause
optional_sql_security_partial_alter_clause
: optional_sql_security_clause
{ $$ = $1; }
| DROP SQL SECURITY
{ $$ = SS_DROP; }
;
%type <nullableSqlSecurityVal> trg_sql_security_clause
trg_sql_security_clause
: // nothing
{ $$ = std::nullopt; }
| optional_sql_security_clause
{ $$ = $1; }
| DROP SQL SECURITY
{ $$ = SS_DROP; }
;
// DROP metadata operations
%type <ddlNode> drop
drop
: DROP drop_clause { $$ = $2; }
;
%type <ddlNode> drop_clause
drop_clause
: EXCEPTION if_exists_opt symbol_exception_name
{
const auto node = newNode<DropExceptionNode>(*$3);
node->silent = $2;
$$ = node;
}
| INDEX if_exists_opt symbol_index_name
{
const auto node = newNode<DropIndexNode>(*$3);
node->silent = $2;
$$ = node;
}
| PROCEDURE if_exists_opt symbol_procedure_name
{
const auto node = newNode<DropProcedureNode>(*$3);
node->silent = $2;
$$ = node;
}
| TABLE if_exists_opt symbol_table_name
{
const auto node = newNode<DropRelationNode>(*$3, false);
node->silent = $2;
$$ = node;
}
| TRIGGER if_exists_opt symbol_trigger_name
{
const auto node = newNode<DropTriggerNode>(*$3);
node->silent = $2;
$$ = node;
}
| VIEW if_exists_opt symbol_view_name
{
const auto node = newNode<DropRelationNode>(*$3, true);
node->silent = $2;
$$ = node;
}
| FILTER if_exists_opt symbol_filter_name
{
const auto node = newNode<DropFilterNode>(*$3);
node->silent = $2;
$$ = node;
}
| DOMAIN if_exists_opt symbol_domain_name
{
const auto node = newNode<DropDomainNode>(*$3);
node->silent = $2;
$$ = node;
}
| EXTERNAL FUNCTION if_exists_opt symbol_UDF_name
{
const auto node = newNode<DropFunctionNode>(*$4);
node->silent = $3;
$$ = node;
}
| FUNCTION if_exists_opt symbol_UDF_name
{
const auto node = newNode<DropFunctionNode>(*$3);
node->silent = $2;
$$ = node;
}
| SHADOW if_exists_opt pos_short_integer opt_no_file_delete
{
const auto node = newNode<DropShadowNode>($3, $4);
// DROP SHADOW implicitly has IF EXISTS behavior
$$ = node;
}
| ROLE if_exists_opt symbol_role_name
{
const auto node = newNode<DropRoleNode>(*$3);
node->silent = $2;
$$ = node;
}
| GENERATOR if_exists_opt symbol_generator_name
{
const auto node = newNode<DropSequenceNode>(*$3);
node->silent = $2;
$$ = node;
}
| SEQUENCE if_exists_opt symbol_generator_name
{
const auto node = newNode<DropSequenceNode>(*$3);
node->silent = $2;
$$ = node;
}
| COLLATION if_exists_opt symbol_collation_name
{
const auto node = newNode<DropCollationNode>(*$3);
node->silent = $2;
$$ = node;
}
| USER if_exists_opt symbol_user_name USING PLUGIN valid_symbol_name
{
const auto node = newNode<DropUserNode>(*$3, $6);
node->silent = $2;
$$ = node;
}
| USER if_exists_opt symbol_user_name
{
const auto node = newNode<DropUserNode>(*$3);
node->silent = $2;
$$ = node;
}
| PACKAGE if_exists_opt symbol_package_name
{
const auto node = newNode<DropPackageNode>(*$3);
node->silent = $2;
$$ = node;
}
| PACKAGE BODY if_exists_opt symbol_package_name
{
const auto node = newNode<DropPackageBodyNode>(*$4);
node->silent = $3;
$$ = node;
}
| MAPPING if_exists_opt drop_map_clause(false)
{
const auto node = $3;
node->silentDrop = $2;
$$ = node;
}
| GLOBAL MAPPING if_exists_opt drop_map_clause(true)
{
const auto node = $4;
node->silentDrop = $3;
$$ = node;
}
;
%type <boolVal> if_exists_opt
if_exists_opt
: /* nothing */ { $$ = false; }
| IF EXISTS { $$ = true; }
;
%type <boolVal> if_not_exists_opt
if_not_exists_opt
: /* nothing */ { $$ = false; }
| IF NOT EXISTS { $$ = true; }
;
%type <boolVal> opt_no_file_delete
opt_no_file_delete
: /* nothing */ { $$ = false; }
| PRESERVE FILE { $$ = true; }
| DELETE FILE { $$ = false; }
;
// 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 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
: TYPE OF symbol_column_name
{
$$ = newNode<dsql_fld>();
$$->typeOfName = *$3;
}
| 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 collate_clause
{
$$ = $1;
if ($2)
{
$$->charSet = *$2;
$$->flags |= FLD_has_chset;
}
if ($3)
$$->collate = *$3;
}
;
%type <legacyField> non_charset_simple_type
non_charset_simple_type
: national_character_type collate_clause
{
$$ = $1;
if ($2)
$$->collate = *$2;
}
| binary_character_type
| numeric_type
| float_type
| decfloat_type
| date_time_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);
$$->flags |= FLD_has_prec;
}
| INT128
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_int128;
$$->length = sizeof(Int128);
$$->flags |= FLD_has_prec;
}
| integer_keyword
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_long;
$$->length = sizeof(SLONG);
$$->flags |= FLD_has_prec;
}
| SMALLINT
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_short;
$$->length = sizeof(SSHORT);
$$->flags |= FLD_has_prec;
}
| BOOLEAN
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_boolean;
$$->length = sizeof(UCHAR);
}
;
integer_keyword
: INTEGER
| INT
;
without_time_zone_opt
: // nothing
| WITHOUT TIME ZONE
;
// 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;
$$->flags |= FLD_has_chset;
}
}
| 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;
$$->flags |= FLD_has_sub;
}
| BLOB '(' ',' signed_short_integer ')'
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_blob;
$$->length = sizeof(ISC_QUAD);
$$->segLength = 80;
$$->subType = (USHORT) $4;
$$->flags |= FLD_has_sub;
}
;
%type <uintVal> blob_segsize
blob_segsize
: /* nothing */ { $$ = (USHORT) 80; }
| SEGMENT 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; $field->flags |= FLD_has_sub; }
| SUB_TYPE symbol_blob_subtype_name
{ $field->subTypeName = *$2; $field->flags |= FLD_has_sub; }
;
%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 | FLD_has_len);
}
| 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 | FLD_has_len);
}
;
%type <legacyField> binary_character_type
binary_character_type
: binary_character_keyword '(' pos_short_integer ')'
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_text;
$$->charLength = (USHORT) $3;
$$->length = (USHORT) $3;
$$->textType = ttype_binary;
$$->charSetId = CS_BINARY;
$$->subType = fb_text_subtype_binary;
$$->flags |= (FLD_has_len | FLD_has_chset);
}
| binary_character_keyword
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_text;
$$->charLength = 1;
$$->length = 1;
$$->textType = ttype_binary;
$$->charSetId = CS_BINARY;
$$->subType = fb_text_subtype_binary;
$$->flags |= FLD_has_chset;
}
| varbinary_character_keyword '(' pos_short_integer ')'
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_varying;
$$->charLength = (USHORT) $3;
$$->length = (USHORT) $3 + sizeof(USHORT);
$$->textType = ttype_binary;
$$->charSetId = CS_BINARY;
$$->subType = fb_text_subtype_binary;
$$->flags |= (FLD_has_len | FLD_has_chset);
}
;
%type <legacyField> character_type
character_type
: character_keyword '(' pos_short_integer ')'
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_text;
$$->charLength = (USHORT) $3;
$$->flags |= FLD_has_len;
}
| character_keyword
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_text;
$$->charLength = 1;
}
| varying_keyword '(' pos_short_integer ')'
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_varying;
$$->charLength = (USHORT) $3;
$$->flags |= FLD_has_len;
}
;
varying_keyword
: VARCHAR
| CHARACTER VARYING
| CHAR VARYING
;
character_keyword
: CHARACTER
| CHAR
;
national_character_keyword
: NCHAR
| NATIONAL CHARACTER
| NATIONAL CHAR
;
binary_character_keyword
: BINARY
;
varbinary_character_keyword
: VARBINARY
| BINARY VARYING
;
// numeric type
%type <legacyField> decfloat_type
decfloat_type
: DECFLOAT precision_opt_nz
{
SLONG precision = $2;
if (precision != 0 && precision != 16 && precision != 34)
yyabandon(YYPOSNARG(2), -842, isc_decprecision_err); // DecFloat precision must be 16 or 34.
$$ = newNode<dsql_fld>();
if (precision)
$$->flags |= FLD_has_prec;
$$->precision = precision == 0 ? 34 : (USHORT) precision;
$$->dtype = precision == 16 ? dtype_dec64 : dtype_dec128;
$$->length = precision == 16 ? sizeof(Decimal64) : sizeof(Decimal128);
}
;
%type <legacyField> numeric_type
numeric_type
: NUMERIC prec_scale
{
$$ = $2;
$$->subType = dsc_num_type_numeric;
$$->flags |= FLD_has_sub;
}
| decimal_keyword prec_scale
{
$$ = $2;
$$->subType = dsc_num_type_decimal;
$$->flags |= FLD_has_sub;
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>();
$$->flags |= FLD_has_prec;
if ($2 < 1 || $2 > 38)
yyabandon(YYPOSNARG(2), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(38));
// Precision must be between 1 and 38
if ($2 > 18)
{
$$->dtype = dtype_int128;
$$->length = sizeof(Int128);
}
else 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>();
$$->flags |= (FLD_has_prec | FLD_has_scale);
if ($2 < 1 || $2 > 38)
yyabandon(YYPOSNARG(2), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(38));
// Precision must be between 1 and 38
if ($4 > $2 || $4 < 0)
yyabandon(YYPOSNARG(4), -842, isc_scale_nogt); // Scale must be between 0 and precision
if ($2 > 18)
{
$$->dtype = dtype_int128;
$$->length = sizeof(Int128);
}
else 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
| DEC
;
// floating point type
%type <legacyField> float_type
float_type
: FLOAT precision_opt_nz
{
// Precision is binary digits of the significand: 1-24 for 32 bit single precision, 25-53 for 64 bit double precision
// Precision 0 is the 'no precision specified' case, which defaults to 32 bit single precision
SLONG precision = $2;
if (precision != 0 && (precision < 1 || precision > 53))
yyabandon(YYPOSNARG(2), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(53));
// Precision must be between 1 and 53
$$ = newNode<dsql_fld>();
if (precision > 24)
{
$$->dtype = dtype_double;
$$->length = sizeof(double);
}
else
{
$$->dtype = dtype_real;
$$->length = sizeof(float);
}
}
| LONG FLOAT precision_opt_nz
{
// Precision is binary digits of the significand: 1-53 for 64 bit double precision
// Precision 0 is the 'no precision specified case', which defaults to 64 bit double precision
SLONG precision = $3;
if (precision != 0 && (precision < 1 || precision > 53))
yyabandon(YYPOSNARG(3), -842, Arg::Gds(isc_precision_err2) << Arg::Num(1) << Arg::Num(53));
// Precision must be between 1 and 53
$$ = newNode<dsql_fld>();
$$->dtype = dtype_double;
$$->length = sizeof(double);
}
| REAL
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_real;
$$->length = sizeof(float);
}
| DOUBLE PRECISION
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_double;
$$->length = sizeof(double);
}
;
// optional precision that does not allow zero
%type <int32Val> precision_opt_nz
precision_opt_nz
: /* nothing */ { $$ = 0; }
| '(' pos_short_integer ')' { $$ = $2; }
;
// transaction statements
%type <traNode> savepoint
savepoint
: set_savepoint
| release_savepoint
| undo_savepoint
;
%type <traNode> set_savepoint
set_savepoint
: SAVEPOINT symbol_savepoint_name
{ $$ = newNode<UserSavepointNode>(UserSavepointNode::CMD_SET, *$2); }
;
%type <traNode> release_savepoint
release_savepoint
: RELEASE SAVEPOINT symbol_savepoint_name
{ $$ = newNode<UserSavepointNode>(UserSavepointNode::CMD_RELEASE, *$3); }
| RELEASE SAVEPOINT symbol_savepoint_name ONLY
{ $$ = newNode<UserSavepointNode>(UserSavepointNode::CMD_RELEASE_ONLY, *$3); }
;
%type <traNode> undo_savepoint
undo_savepoint
: ROLLBACK optional_work TO optional_savepoint symbol_savepoint_name
{ $$ = newNode<UserSavepointNode>(UserSavepointNode::CMD_ROLLBACK, *$5); }
;
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 <sessionResetNode> session_reset
session_reset
: ALTER SESSION RESET
{ $$ = newNode<SessionResetNode>(); }
;
%type <setRoleNode> set_role
set_role
: SET ROLE valid_symbol_name
{ $$ = newNode<SetRoleNode>($3); }
| SET TRUSTED ROLE
{ $$ = newNode<SetRoleNode>(); }
;
%type <mngNode> set_debug_option
set_debug_option
: SET DEBUG OPTION valid_symbol_name '=' constant
{ $$ = newNode<SetDebugOptionNode>($4, $6); }
;
%type <setDecFloatRoundNode> set_decfloat_round
set_decfloat_round
: SET DECFLOAT ROUND valid_symbol_name
{ $$ = newNode<SetDecFloatRoundNode>($4); }
;
%type <setDecFloatTrapsNode> set_decfloat_traps
set_decfloat_traps
: SET DECFLOAT TRAPS TO
{ $$ = newNode<SetDecFloatTrapsNode>(); }
decfloat_traps_list_opt($5)
{ $$ = $5; }
;
%type <setBindNode> set_bind
set_bind
: SET BIND OF set_bind_from TO set_bind_to
{ $$ = newNode<SetBindNode>(); $$->from = $4; $$->to = $6; }
;
%type <legacyField> set_bind_from
set_bind_from
: bind_type
| TIME ZONE
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_timestamp_tz;
$$->length = 0;
}
;
%type <legacyField> bind_type
bind_type
: non_array_type
| varying_keyword
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_varying;
$$->charLength = 0;
}
;
%type <legacyField> set_bind_to
set_bind_to
: bind_type
{
$$ = $1;
}
| LEGACY
{
$$ = newNode<dsql_fld>();
$$->flags = FLD_legacy;
}
| NATIVE
{
$$ = newNode<dsql_fld>();
$$->flags = FLD_native;
}
| EXTENDED
{
$$ = newNode<dsql_fld>();
$$->flags = FLD_extended;
}
| EXTENDED TIME WITH TIME ZONE
{
$$ = newNode<dsql_fld>();
checkTimeDialect();
$$->dtype = dtype_ex_time_tz;
$$->length = sizeof(ISC_TIME_TZ_EX);
$$->flags |= FLD_has_prec;
}
| EXTENDED TIMESTAMP WITH TIME ZONE
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_ex_timestamp_tz;
$$->length = sizeof(ISC_TIMESTAMP_TZ_EX);
$$->flags |= FLD_has_prec;
}
;
%type decfloat_traps_list_opt(<setDecFloatTrapsNode>)
decfloat_traps_list_opt($setDecFloatTrapsNode)
: // nothing
| decfloat_traps_list($setDecFloatTrapsNode)
;
%type decfloat_traps_list(<setDecFloatTrapsNode>)
decfloat_traps_list($setDecFloatTrapsNode)
: decfloat_trap($setDecFloatTrapsNode)
| decfloat_traps_list ',' decfloat_trap($setDecFloatTrapsNode)
;
%type decfloat_trap(<setDecFloatTrapsNode>)
decfloat_trap($setDecFloatTrapsNode)
: valid_symbol_name
{ $setDecFloatTrapsNode->trap($1); }
;
%type <mngNode> set_optimize
set_optimize
: SET OPTIMIZE optimize_mode
{ $$ = newNode<SetOptimizeNode>($3); }
| SET OPTIMIZE TO DEFAULT
{ $$ = newNode<SetOptimizeNode>(); }
;
%type <setSessionNode> session_statement
session_statement
: SET SESSION IDLE TIMEOUT long_integer timepart_sesion_idle_tout
{ $$ = newNode<SetSessionNode>(SetSessionNode::TYPE_IDLE_TIMEOUT, $5, $6); }
| SET STATEMENT TIMEOUT long_integer timepart_ses_stmt_tout
{ $$ = newNode<SetSessionNode>(SetSessionNode::TYPE_STMT_TIMEOUT, $4, $5); }
;
%type <blrOp> timepart_sesion_idle_tout
timepart_sesion_idle_tout
: /* nothing */ { $$ = blr_extract_minute; }
| HOUR { $$ = blr_extract_hour; }
| MINUTE { $$ = blr_extract_minute; }
| SECOND { $$ = blr_extract_second; }
;
%type <blrOp> timepart_ses_stmt_tout
timepart_ses_stmt_tout
: /* nothing */ { $$ = blr_extract_second; }
| HOUR { $$ = blr_extract_hour; }
| MINUTE { $$ = blr_extract_minute; }
| SECOND { $$ = blr_extract_second; }
| MILLISECOND { $$ = blr_extract_millisecond; }
;
%type <mngNode> set_time_zone
set_time_zone
: SET TIME ZONE set_time_zone_option { $$ = $4; }
;
%type <mngNode> set_time_zone_option
set_time_zone_option
: sql_string { $$ = newNode<SetTimeZoneNode>($1->getString()); }
| LOCAL { $$ = newNode<SetTimeZoneNode>(); }
;
%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($setTransactionNode)
{ setClause($setTransactionNode->isoLevel, "ISOLATION LEVEL", $1); }
// misc options
| NO AUTO UNDO
{ setClause($setTransactionNode->noAutoUndo, "NO AUTO UNDO", true); }
| IGNORE LIMBO
{ setClause($setTransactionNode->ignoreLimbo, "IGNORE LIMBO", true); }
| RESTART REQUESTS
{ setClause($setTransactionNode->restartRequests, "RESTART REQUESTS", true); }
| AUTO COMMIT
{ setClause($setTransactionNode->autoCommit, "AUTO COMMIT", true); }
| AUTO RELEASE TEMP BLOBID
{ setClause($setTransactionNode->autoReleaseTempBlobID, "AUTO RELEASE TEMP BLOBID", 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(<setTransactionNode>)
isolation_mode($setTransactionNode)
: ISOLATION LEVEL iso_mode($setTransactionNode) { $$ = $3;}
| iso_mode
;
%type <uintVal> iso_mode(<setTransactionNode>)
iso_mode($setTransactionNode)
: snap_shot($setTransactionNode) { $$ = $1; }
| READ UNCOMMITTED version_mode { $$ = $3; }
| READ COMMITTED version_mode { $$ = $3; }
;
%type <uintVal> snap_shot(<setTransactionNode>)
snap_shot($setTransactionNode)
: SNAPSHOT
{ $$ = SetTransactionNode::ISO_LEVEL_CONCURRENCY; }
| SNAPSHOT AT NUMBER snapshot_number
{
setClause($setTransactionNode->atSnapshotNumber, "SNAPSHOT AT NUMBER", (CommitNumber) $4);
$$ = SetTransactionNode::ISO_LEVEL_CONCURRENCY;
}
| SNAPSHOT TABLE
{ $$ = SetTransactionNode::ISO_LEVEL_CONSISTENCY; }
| SNAPSHOT TABLE STABILITY
{ $$ = SetTransactionNode::ISO_LEVEL_CONSISTENCY; }
;
%type <int64Val> snapshot_number
snapshot_number
: NUMBER32BIT { $$ = $1; }
| NUMBER64BIT { $$ = $1.number; }
;
%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; }
| READ CONSISTENCY { $$ = SetTransactionNode::ISO_LEVEL_READ_COMMITTED_READ_CONSISTENCY; }
;
%type <uintVal> lock_type
lock_type
: /* nothing */ { $$ = 0; }
| 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, QualifiedName(""), "", *$5); }
| COMMENT ON ddl_type1 symbol_ddl_name IS ddl_desc
{ $$ = newNode<CommentOnNode>($3, QualifiedName(*$4), "", *$6); }
| COMMENT ON ddl_type2 symbol_ddl_name ddl_subname IS ddl_desc
{ $$ = newNode<CommentOnNode>($3, QualifiedName(*$4), *$5, *$7); }
| COMMENT ON ddl_type3 ddl_qualified_name ddl_subname IS ddl_desc
{ $$ = newNode<CommentOnNode>($3, *$4, *$5, *$7); }
| COMMENT ON ddl_type4 ddl_qualified_name IS ddl_desc
{ $$ = newNode<CommentOnNode>($3, *$4, "", *$6); }
| comment_on_user
{ $$ = $1; }
| comment_on_mapping
{ $$ = $1; }
;
%type <createAlterUserNode> comment_on_user
comment_on_user
: COMMENT ON USER symbol_user_name
{
$$ = newNode<CreateAlterUserNode>(CreateAlterUserNode::USER_MOD, *$4);
}
opt_use_plugin($5) IS ddl_desc
{
CreateAlterUserNode* node = $$ = $5;
node->comment = $8;
}
;
%type opt_use_plugin(<createAlterUserNode>)
opt_use_plugin($node)
: // nothing
| use_plugin($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; }
| TRIGGER { $$ = obj_trigger; }
| 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; }
;
%type <intVal> ddl_type3
ddl_type3
: PARAMETER { $$ = obj_parameter; }
| PROCEDURE PARAMETER { $$ = obj_procedure; }
| FUNCTION PARAMETER { $$ = obj_udf; }
;
%type <intVal> ddl_type4
ddl_type4
: PROCEDURE { $$ = obj_procedure; }
| EXTERNAL FUNCTION { $$ = obj_udf; }
| FUNCTION { $$ = obj_udf; }
;
%type <metaNamePtr> ddl_subname
ddl_subname
: '.' symbol_ddl_name { $$ = $2; }
;
%type <qualifiedNamePtr> ddl_qualified_name
ddl_qualified_name
: symbol_ddl_name { $$ = newNode<QualifiedName>(*$1); }
| symbol_ddl_name '.' symbol_ddl_name { $$ = newNode<QualifiedName>(*$3, *$1); }
;
%type <stringPtr> ddl_desc
ddl_desc
: utf_string { $$ = $1; }
| NULL { $$ = newString(""); }
;
// SELECT statement
%type <selectNode> select
select
: select_expr for_update_clause lock_clause optimize_clause
{
SelectNode* node = newNode<SelectNode>();
node->selectExpr = $1;
node->forUpdate = $2;
node->withLock = $3.first;
node->skipLocked = $3.second;
node->optimizeForFirstRows = $4;
$$ = 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 <boolPair> lock_clause
lock_clause
: /* nothing */ { $$ = {false, false}; }
| WITH LOCK skip_locked_clause_opt { $$ = {true, $3}; }
;
%type <boolVal> skip_locked_clause_opt
skip_locked_clause_opt
: /* nothing */ { $$ = false; }
| SKIP LOCKED { $$ = true; }
;
%type <triState> optimize_clause
optimize_clause
: OPTIMIZE optimize_mode
{ $$ = TriState($2); }
| // nothing
{ $$ = TriState(); }
;
%type <boolVal> optimize_mode
optimize_mode
: FOR FIRST ROWS
{ $$ = true; }
| FOR ALL ROWS
{ $$ = false; }
;
// SELECT expression
%type <selectExprNode> select_expr
select_expr
: with_clause select_expr_body order_clause_opt rows_clause
{
SelectExprNode* node = $$ = newNode<SelectExprNode>();
node->querySpec = $2;
node->orderClause = $3;
node->rowsClause = $4;
node->withClause = $1;
}
| with_clause select_expr_body order_clause_opt result_offset_clause fetch_first_clause
{
SelectExprNode* node = $$ = newNode<SelectExprNode>();
node->querySpec = $2;
node->orderClause = $3;
if ($4 || $5)
{
RowsClause* rowsNode = newNode<RowsClause>();
rowsNode->skip = $4;
rowsNode->length = $5;
node->rowsClause = rowsNode;
}
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_list ',' with_item
{
$$ = $1;
$$->add($3);
}
;
%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 = nodeAs<UnionSourceNode>($1);
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 = nodeAs<UnionSourceNode>($1);
if (node && node->dsqlAll)
node->dsqlClauses->add($4);
else
{
node = newNode<UnionSourceNode>();
node->dsqlAll = true;
node->dsqlClauses = newNode<RecSourceListNode>($1)->add($4);
}
$$ = node;
}
;
%type <recSourceNode> query_term
query_term
: query_primary
;
%type <recSourceNode> query_primary
query_primary
: query_spec
{ $$ = $1; }
| '(' select_expr_body order_clause_opt result_offset_clause fetch_first_clause ')'
{
if ($3 || $4 || $5)
{
const auto selectExpr = newNode<SelectExprNode>();
selectExpr->dsqlFlags |= RecordSourceNode::DFLAG_DERIVED;
selectExpr->querySpec = $2;
selectExpr->orderClause = $3;
if ($4 || $5)
{
const auto rowsNode = newNode<RowsClause>();
rowsNode->skip = $4;
rowsNode->length = $5;
selectExpr->rowsClause = rowsNode;
}
const auto rse = newNode<RseNode>();
rse->dsqlFlags |= RecordSourceNode::DFLAG_BODY_WRAPPER;
rse->dsqlFrom = newNode<RecSourceListNode>(selectExpr);
$$ = rse;
}
else
$$ = $2;
}
;
%type <rseNode> query_spec
query_spec
: SELECT limit_clause
distinct_clause
select_list
from_clause
where_clause
group_clause
having_clause
named_windows_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->items.hasData() ? $4 : nullptr;
rse->dsqlFrom = $5;
rse->dsqlWhere = $6;
rse->dsqlGroup = $7;
rse->dsqlHaving = $8;
rse->dsqlNamedWindows = $9;
rse->rse_plan = $10;
$$ = 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>(0u); }
| all_noise { $$ = NULL; }
;
%type <valueListNode> select_list
select_list
: select_items { $$ = $1; }
| '*' { $$ = newNode<ValueListNode>(0u); }
;
%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; }
| lateral_derived_table { $$ = $1; }
| parenthesized_joined_table { $$ = $1; }
;
%type <recSourceNode> parenthesized_joined_table
parenthesized_joined_table
: '(' parenthesized_joined_table ')' { $$ = $2; }
| '(' joined_table ')' { $$ = $2; }
;
%type <selectExprNode> derived_table
derived_table
: '(' select_expr ')' correlation_name_opt derived_column_list
{
$$ = $2;
$$->dsqlFlags |= RecordSourceNode::DFLAG_DERIVED;
if ($4)
$$->alias = $4->c_str();
$$->columns = $5;
}
;
%type <selectExprNode> lateral_derived_table
lateral_derived_table
: LATERAL derived_table
{
$$ = $2;
$$->dsqlFlags |= RecordSourceNode::DFLAG_LATERAL;
}
;
%type <metaNamePtr> correlation_name_opt
correlation_name_opt
: /* nothing */ { $$ = nullptr; }
| symbol_table_alias_name
| AS symbol_table_alias_name { $$ = $2; }
;
%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
{
const auto node = newNode<ProcedureSourceNode>(QualifiedName(*$1));
node->inputSources = $2 ? $2->second : nullptr;
node->dsqlInputArgNames = $2 ? $2->first : nullptr;
node->alias = $4->c_str();
$$ = node;
}
| symbol_procedure_name table_proc_inputs
{
const auto node = newNode<ProcedureSourceNode>(QualifiedName(*$1));
node->inputSources = $2 ? $2->second : nullptr;
node->dsqlInputArgNames = $2 ? $2->first : nullptr;
$$ = node;
}
| symbol_package_name '.' symbol_procedure_name table_proc_inputs as_noise symbol_table_alias_name
{
const auto node = newNode<ProcedureSourceNode>(
QualifiedName(*$3, *$1));
node->inputSources = $4 ? $4->second : nullptr;
node->dsqlInputArgNames = $4 ? $4->first : nullptr;
node->alias = $6->c_str();
$$ = node;
}
| symbol_package_name '.' symbol_procedure_name table_proc_inputs
{
const auto node = newNode<ProcedureSourceNode>(
QualifiedName(*$3, *$1));
node->inputSources = $4 ? $4->second : nullptr;
node->dsqlInputArgNames = $4 ? $4->first : nullptr;
$$ = node;
}
;
%type <namedArguments> table_proc_inputs
table_proc_inputs
: /* nothing */ { $$ = nullptr; }
| '(' argument_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; }
;
%type <namedWindowsClause> named_windows_clause
named_windows_clause
: /* nothing */ { $$ = NULL; }
| WINDOW window_definition_list { $$ = $2; }
;
%type <namedWindowsClause> window_definition_list
window_definition_list
: window_definition
{
NamedWindowsClause* node = newNode<NamedWindowsClause>();
node->add(*$1);
$$ = node;
}
| window_definition_list ',' window_definition
{
NamedWindowsClause* node = $1;
node->add(*$3);
$$ = node;
}
;
%type <namedWindowClause> window_definition
window_definition
: symbol_window_name AS '(' window_clause ')'
{
$$ = newNode<NamedWindowClause>(*$1, $4);
}
;
%type <metaNamePtr> symbol_window_name_opt
symbol_window_name_opt
: /* nothing */ { $$ = NULL; }
| symbol_window_name
;
// 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.add($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.add();
item.indexName = *$3;
}
;
%type extra_indices_opt(<accessType>)
extra_indices_opt($accessType)
: // nothing
| INDEX '(' index_list($accessType) ')'
;
// ORDER BY clause
%type <valueListNode> order_clause_opt
order_clause_opt
: /* nothing */ { $$ = NULL; }
| order_clause
;
%type <valueListNode> order_clause
order_clause
: 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 - ROWS clause is a non-standard alternative to OFFSET .. FETCH ..
// Non-optional - for use in select_expr (so it doesn't cause conflicts with OFFSET .. FETCH ..)
%type <rowsClause> rows_clause
rows_clause
// 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));
}
;
// Optional - for use in delete_searched and update_searched
%type <rowsClause> rows_clause_optional
rows_clause_optional
: /* nothing */ { $$ = NULL; }
| rows_clause
;
// OFFSET n {ROW | ROWS}
row_noise
: ROW
| ROWS
;
%type <valueExprNode> result_offset_clause
result_offset_clause
: /* nothing */ { $$ = NULL; }
| OFFSET simple_value_spec row_noise { $$ = $2; }
;
// FETCH {FIRST | NEXT} [ n ] {ROW | ROWS} ONLY
first_next_noise
: FIRST
| NEXT
;
%type <valueExprNode> fetch_first_clause
fetch_first_clause
: /* nothing */ { $$ = NULL; }
| FETCH first_next_noise simple_value_spec row_noise ONLY { $$ = $3; }
| FETCH first_next_noise row_noise ONLY { $$ = 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)) override_opt VALUES '(' value_or_default_list ')'
returning_clause
{
StoreNode* node = $$ = $1;
node->overrideClause = $3;
node->dsqlValues = $6;
node->dsqlReturning = $8;
}
| insert_start ins_column_parens_opt(NOTRIAL(&$1->dsqlFields)) override_opt select_expr returning_clause
{
StoreNode* node = $$ = $1;
node->overrideClause = $3;
node->dsqlRse = $4;
node->dsqlReturning = $5;
$$ = 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->target = $3;
$$ = node;
}
;
%type <nullableOverrideClause> override_opt
override_opt
: /* nothing */ { $$ = std::nullopt; }
| OVERRIDING USER VALUE { $$ = OverrideClause::USER_VALUE; }
| OVERRIDING SYSTEM VALUE { $$ = OverrideClause::SYSTEM_VALUE; }
;
%type <valueListNode> value_or_default_list
value_or_default_list
: value_or_default { $$ = newNode<ValueListNode>($1); }
| value_or_default_list ',' value_or_default { $$ = $1->add($3); }
;
%type <valueExprNode> value_or_default
value_or_default
: value
| DEFAULT { $$ = NULL; }
;
// 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)
plan_clause order_clause_opt returning_clause
{
MergeNode* node = $$ = $8;
node->plan = $10;
node->order = $11;
node->returning = $12;
}
;
%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), NOTRIAL(&$mergeNode->relation->dsqlName))
;
%type merge_when_not_matched_clause(<mergeNode>)
merge_when_not_matched_clause($mergeNode)
: WHEN NOT MATCHED by_target_noise
{ $<mergeNotMatchedClause>$ = &$mergeNode->whenNotMatchedByTarget.add(); }
merge_insert_specification(NOTRIAL($<mergeNotMatchedClause>5))
| WHEN NOT MATCHED BY SOURCE
{ $<mergeMatchedClause>$ = &$mergeNode->whenNotMatchedBySource.add(); }
merge_update_specification(NOTRIAL($<mergeMatchedClause>6), NOTRIAL(&$mergeNode->relation->dsqlName))
;
by_target_noise
: // empty
| BY TARGET
;
%type merge_update_specification(<mergeMatchedClause>, <metaNamePtr>)
merge_update_specification($mergeMatchedClause, $relationName)
: THEN UPDATE SET update_assignments(NOTRIAL($relationName))
{ $mergeMatchedClause->assignments = $4; }
| AND search_condition THEN UPDATE SET update_assignments(NOTRIAL($relationName))
{
$mergeMatchedClause->condition = $2;
$mergeMatchedClause->assignments = $6;
}
| THEN DELETE
| AND search_condition THEN DELETE
{ $mergeMatchedClause->condition = $2; }
;
%type merge_insert_specification(<mergeNotMatchedClause>)
merge_insert_specification($mergeNotMatchedClause)
: THEN INSERT ins_column_parens_opt(NOTRIAL(&$mergeNotMatchedClause->fields)) override_opt
VALUES '(' value_or_default_list ')'
{
$mergeNotMatchedClause->overrideClause = $4;
$mergeNotMatchedClause->values = $7;
}
| AND search_condition THEN INSERT ins_column_parens_opt(NOTRIAL(&$mergeNotMatchedClause->fields)) override_opt
VALUES '(' value_or_default_list ')'
{
$mergeNotMatchedClause->overrideClause = $6;
$mergeNotMatchedClause->values = $9;
$mergeNotMatchedClause->condition = $2;
}
;
// DELETE statement
%type <stmtNode> delete
delete
: delete_searched
| delete_positioned
;
%type <stmtNode> delete_searched
delete_searched
: DELETE FROM table_name
where_clause
plan_clause
order_clause_opt
rows_clause_optional
skip_locked_clause_opt
returning_clause
{
const auto node = newNode<EraseNode>();
node->dsqlRelation = $3;
node->dsqlBoolean = $4;
node->dsqlPlan = $5;
node->dsqlOrder = $6;
node->dsqlRows = $7;
node->dsqlSkipLocked = $8;
node->dsqlReturning = $9;
$$ = node;
}
;
%type <stmtNode> delete_positioned
delete_positioned
: 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 update_assignments(NOTRIAL(&$2->dsqlName))
where_clause
plan_clause
order_clause_opt
rows_clause_optional
skip_locked_clause_opt
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->dsqlSkipLocked = $9;
node->dsqlReturning = $10;
$$ = node;
}
;
%type <stmtNode> update_positioned
update_positioned
: UPDATE table_name SET update_assignments(NOTRIAL(&$2->dsqlName)) 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)) override_opt VALUES '(' value_or_default_list ')'
update_or_insert_matching_opt(NOTRIAL(&$6->matching))
plan_clause order_clause_opt rows_clause_optional returning_clause
{
UpdateOrInsertNode* node = $$ = $6;
node->overrideClause = $8;
node->values = $11;
node->plan = $14;
node->order = $15;
node->rows = $16;
node->returning = $17;
}
;
%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 select_list
{
$$ = FB_NEW_POOL(getPool()) ReturningClause(getPool());
$$->first = $2;
}
| RETURNING select_list INTO variable_list
{
$$ = FB_NEW_POOL(getPool()) ReturningClause(getPool());
$$->first = $2;
$$->second = $4;
}
;
%type <metaNamePtr> cursor_clause
cursor_clause
: WHERE CURRENT OF symbol_cursor_name { $$ = newNode<MetaName>(*$4); }
;
// Assignments
%type <stmtNode> assignment
assignment
: update_column_name '=' value
{
AssignmentNode* node = newNode<AssignmentNode>();
node->asgnTo = $1;
node->asgnFrom = $3;
$$ = node;
}
;
%type <compoundStmtNode> update_assignments(<metaNamePtr>)
update_assignments($relationName)
: update_assignment($relationName)
{
$$ = newNode<CompoundStmtNode>();
$$->statements.add($1);
}
| update_assignments ',' update_assignment($relationName)
{
$1->statements.add($3);
$$ = $1;
}
;
%type <stmtNode> update_assignment(<metaNamePtr>)
update_assignment($relationName)
: update_column_name '=' value
{
AssignmentNode* node = newNode<AssignmentNode>();
node->asgnTo = $1;
node->asgnFrom = $3;
$$ = node;
}
| update_column_name '=' DEFAULT
{
AssignmentNode* node = newNode<AssignmentNode>();
node->asgnTo = $1;
node->asgnFrom = newNode<DefaultNode>(*$relationName, $1->dsqlName);
$$ = node;
}
;
%type <stmtNode> exec_function
exec_function
: udf
{
AssignmentNode* node = newNode<AssignmentNode>();
node->asgnTo = NullNode::instance();
node->asgnFrom = $1;
$$ = node;
}
| non_aggregate_function
{
AssignmentNode* node = newNode<AssignmentNode>();
node->asgnTo = NullNode::instance();
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;
}
| ':' symbol_table_alias_name '.' symbol_column_name
{
FieldNode* fieldNode = newNode<FieldNode>();
fieldNode->dsqlQualifier = *$2;
fieldNode->dsqlName = *$4;
fieldNode->dsqlCursorField = true;
$$ = 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
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>(blr_equiv, $1, $3);
node->dsqlCheckBoolean = true;
$$ = node;
}
| value IS NOT boolean_literal
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>(blr_equiv, $1, $4);
node->dsqlCheckBoolean = true;
$$ = 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
| trigger_action_predicate
| session_reset_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 ')'
{ $$ = newNode<ComparativeBoolNode>($2, $1, $3, $5); }
;
%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_special AND value_special %prec BETWEEN
{
$$ = newNode<ComparativeBoolNode>(blr_between, $1, $3, $5);
}
| value NOT BETWEEN value_special AND value_special %prec BETWEEN
{
ComparativeBoolNode* node = newNode<ComparativeBoolNode>(blr_between, $1, $4, $6);
$$ = newNode<NotBoolNode>(node);
}
;
%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 IN in_predicate_value
{
$$ = newNode<ComparativeBoolNode>(blr_eql, $1,
ComparativeBoolNode::DFLAG_ANSI_ANY, $3);
}
| value NOT IN in_predicate_value
{
const auto node = newNode<ComparativeBoolNode>(blr_eql, $1,
ComparativeBoolNode::DFLAG_ANSI_ANY, $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> trigger_action_predicate
trigger_action_predicate
: INSERTING
{
$$ = newNode<ComparativeBoolNode>(blr_eql,
newNode<InternalInfoNode>(MAKE_const_slong(INFO_TYPE_TRIGGER_ACTION)),
MAKE_const_slong(1));
}
| UPDATING
{
$$ = newNode<ComparativeBoolNode>(blr_eql,
newNode<InternalInfoNode>(MAKE_const_slong(INFO_TYPE_TRIGGER_ACTION)),
MAKE_const_slong(2));
}
| DELETING
{
$$ = newNode<ComparativeBoolNode>(blr_eql,
newNode<InternalInfoNode>(MAKE_const_slong(INFO_TYPE_TRIGGER_ACTION)),
MAKE_const_slong(3));
}
;
%type <boolExprNode> session_reset_predicate
session_reset_predicate
: RESETTING
{
$$ = newNode<ComparativeBoolNode>(blr_eql,
newNode<InternalInfoNode>(MAKE_const_slong(INFO_TYPE_SESSION_RESETTING)),
MAKE_const_slong(1));
}
%type <boolExprNode> null_predicate
null_predicate
: value IS NULL
{ $$ = newNode<MissingBoolNode>($1); }
| value IS UNKNOWN
{ $$ = newNode<MissingBoolNode>($1, true); }
| value IS NOT 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
{
$$ = newNode<CreateAlterUserNode>(CreateAlterUserNode::USER_ADD, *$1);
}
user_fixed_list_opt($2)
{
$$ = $2;
}
;
%type <createAlterUserNode> alter_user_clause
alter_user_clause
: symbol_user_name set_noise
{
$$ = newNode<CreateAlterUserNode>(CreateAlterUserNode::USER_MOD, *$1);
}
user_fixed_list_opt($3)
{
$$ = $3;
}
;
%type <createAlterUserNode> alter_cur_user_clause
alter_cur_user_clause
: set_noise
{
$$ = newNode<CreateAlterUserNode>(CreateAlterUserNode::USER_MOD, "");
}
user_fixed_list_opt($2)
{
$$ = $2;
}
;
%type <createAlterUserNode> replace_user_clause
replace_user_clause
: symbol_user_name set_noise
{
$$ = newNode<CreateAlterUserNode>(CreateAlterUserNode::USER_RPL, *$1);
}
user_fixed_list_opt($3)
{
$$ = $3;
}
;
set_noise
: // nothing
| SET
;
%type user_fixed_list_opt(<createAlterUserNode>)
user_fixed_list_opt($node)
: // nothing
| user_fixed_list($node)
;
%type user_fixed_list(<createAlterUserNode>)
user_fixed_list($node)
: user_fixed_option($node)
| user_fixed_list user_fixed_option($node)
;
%type user_fixed_option(<createAlterUserNode>)
user_fixed_option($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); }
| PASSWORD utf_string { setClause($node->password, "PASSWORD", $2); }
| GRANT ADMIN ROLE { setClause($node->adminRole, "ADMIN ROLE", true); }
| REVOKE ADMIN ROLE { setClause($node->adminRole, "ADMIN ROLE", false); }
| ACTIVE { setClause($node->active, "ACTIVE/INACTIVE", true); }
| INACTIVE { setClause($node->active, "ACTIVE/INACTIVE", false); }
| use_plugin($node)
| TAGS '(' user_var_list($node) ')'
;
%type use_plugin(<createAlterUserNode>)
use_plugin($node)
: USING PLUGIN valid_symbol_name
{ setClause($node->plugin, "USING PLUGIN", $3); }
;
%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);
}
;
// logons mapping
%type <mappingNode> create_map_clause(<boolVal>)
create_map_clause($global)
: map_clause(MappingNode::MAP_ADD)
{
$$ = $1;
$$->global = $global;
}
map_to($2)
{
$$ = $2;
}
;
%type <mappingNode> alter_map_clause(<boolVal>)
alter_map_clause($global)
: map_clause(MappingNode::MAP_MOD)
{
$$ = $1;
$$->global = $global;
}
map_to($2)
{
$$ = $2;
}
;
%type <mappingNode> replace_map_clause(<boolVal>)
replace_map_clause($global)
: map_clause(MappingNode::MAP_RPL)
{
$$ = $1;
$$->global = $global;
}
map_to($2)
{
$$ = $2;
}
;
%type <mappingNode> drop_map_clause(<boolVal>)
drop_map_clause($global)
: map_name
{
MappingNode* node = newNode<MappingNode>(MappingNode::MAP_DROP, *$1);
node->global = $global;
$$ = node;
}
;
%type <mappingNode> comment_on_mapping
comment_on_mapping
: COMMENT ON MAPPING map_comment(false)
{
$$ = $4;
}
| COMMENT ON GLOBAL MAPPING map_comment(true)
{
$$ = $5;
}
;
%type <mappingNode> map_comment(<boolVal>)
map_comment($global)
: map_name IS ddl_desc
{
$$ = newNode<MappingNode>(MappingNode::MAP_COMMENT, *$1);
$$->global = $global;
$$->comment = $3;
}
;
%type <mappingNode> map_clause(<mappingOp>)
map_clause($op)
: map_name
{
$$ = newNode<MappingNode>($op, *$1);
}
USING map_using($2)
FROM map_from($2)
{
$$ = $2;
}
;
%type <metaNamePtr> map_name
map_name
: valid_symbol_name
{ $$ = $1; }
;
%type map_from(<mappingNode>)
map_from($node)
: map_from_symbol_name map_logoninfo
{
$node->fromType = $1;
$node->from = $2;
}
| ANY map_from_symbol_name
{
$node->fromType = $2;
$node->from = newNode<IntlString>("*");
}
;
%type <metaNamePtr> map_from_symbol_name
map_from_symbol_name
: valid_symbol_name
| USER { $$ = newNode<MetaName>("USER"); }
| GROUP { $$ = newNode<MetaName>("GROUP"); }
;
%type <intlStringPtr> map_logoninfo
map_logoninfo
: sql_string
| valid_symbol_name { $$ = newIntlString($1->c_str(), metadataCharSet->getName()); }
;
%type map_using(<mappingNode>)
map_using($node)
: PLUGIN valid_symbol_name map_in
{
$node->mode = 'P';
$node->plugin = $2;
$node->db = $3;
}
| ANY PLUGIN map_in
{
$node->mode = 'P';
$node->db = $3;
}
| ANY PLUGIN SERVERWIDE
{
$node->mode = 'S';
}
| MAPPING map_in
{
$node->mode = 'M';
$node->db = $2;
}
| '*' map_in
{
$node->mode = '*';
$node->db = $2;
}
;
%type <metaNamePtr> map_in
map_in
: /* nothing */ { $$ = NULL; }
| IN valid_symbol_name { $$ = $2; }
;
%type map_to(<mappingNode>)
map_to($node)
: TO map_role valid_symbol_name
{
$node->role = $2;
$node->to = $3;
}
| TO map_role
{
$node->role = $2;
}
;
%type <boolVal> map_role
map_role
: ROLE { $$ = true; }
| USER { $$ = false; }
;
// value types
%type <valueExprNode> value
value
: value_primary
| boolean_value_expression
{ $$ = newNode<BoolAsValueNode>($1); }
;
// Used in situations that is not possible to use non-parenthesized boolean expressions.
%type <valueExprNode> value_special
value_special
: value_primary
| '(' boolean_value_expression ')' { $$ = newNode<BoolAsValueNode>($2); }
;
%type <valueExprNode> value_primary
value_primary
: nonparenthesized_value
| '(' value_primary ')' { $$ = $2; }
;
// Matches definition of <simple value specification> in SQL standard
%type <valueExprNode> simple_value_spec
simple_value_spec
: constant
| variable
| parameter
;
%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_special %prec UMINUS
{ $$ = newNode<NegateNode>($2); }
| '+' value_special %prec UPLUS
{ $$ = $2; }
| value_special '+' value_special
{ $$ = newNode<ArithmeticNode>(blr_add, (client_dialect < SQL_DIALECT_V6_TRANSITION), $1, $3); }
| value_special CONCATENATE value_special
{ $$ = newNode<ConcatenateNode>($1, $3); }
| value_special COLLATE symbol_collation_name
{ $$ = newNode<CollateNode>($1, *$3); }
| value_special AT LOCAL %prec AT
{ $$ = newNode<AtNode>($1, nullptr); }
| value_special AT TIME ZONE value_special %prec AT
{ $$ = newNode<AtNode>($1, $5); }
| value_special '-' value_special
{ $$ = newNode<ArithmeticNode>(blr_subtract, (client_dialect < SQL_DIALECT_V6_TRANSITION), $1, $3); }
| value_special '*' value_special
{ $$ = newNode<ArithmeticNode>(blr_multiply, (client_dialect < SQL_DIALECT_V6_TRANSITION), $1, $3); }
| value_special '/' value_special
{ $$ = 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); }
| 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>();
}
| LOCALTIME 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<LocalTimeNode>($2);
}
| 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);
}
| LOCALTIMESTAMP timestamp_precision_opt
{ $$ = newNode<LocalTimeStampNode>($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
| '-' ul_numeric_constant { $$ = newNode<NegateNode>($2); }
| '-' LIMIT64_INT { $$ = MAKE_const_sint64(MIN_SINT64, 0); }
| '-' LIMIT64_NUMBER { $$ = MAKE_const_sint64(MIN_SINT64, $2->getScale()); }
| '-' u_constant_128 { $$ = newNode<NegateNode>($2); }
| boolean_literal
;
%type <valueExprNode> u_numeric_constant
u_numeric_constant
: ul_numeric_constant
{ $$ = $1; }
| LIMIT64_NUMBER
{ $$ = MAKE_constant($1->c_str(), CONSTANT_NUM128, $1->getScale()); }
| LIMIT64_INT
{ $$ = MAKE_constant($1->c_str(), CONSTANT_NUM128); }
| u_constant_128
;
%type <valueExprNode> u_constant_128
u_constant_128
: NUM128
{ $$ = MAKE_constant($1->c_str(), CONSTANT_NUM128, $1->getScale()); }
;
%type <valueExprNode> ul_numeric_constant
ul_numeric_constant
: NUMBER32BIT
{ $$ = MAKE_const_slong($1); }
| FLOAT_NUMBER
{ $$ = MAKE_constant($1->c_str(), CONSTANT_DOUBLE); }
| DECIMAL_NUMBER
{ $$ = MAKE_constant($1->c_str(), CONSTANT_DECIMAL); }
| 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.charSetId); }
| 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
: FALSE { $$ = MAKE_constant("", CONSTANT_BOOLEAN); }
| 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)); }
| RDB_ERROR '(' error_context ')'
{ $$ = newNode<InternalInfoNode>(MAKE_const_slong($3)); }
;
%type <int32Val> error_context
error_context
: GDSCODE { $$ = INFO_TYPE_GDSCODE; }
| SQLCODE { $$ = INFO_TYPE_SQLCODE; }
| SQLSTATE { $$ = INFO_TYPE_SQLSTATE; }
| EXCEPTION { $$ = INFO_TYPE_EXCEPTION; }
| MESSAGE { $$ = INFO_TYPE_ERROR_MSG; }
;
%type <intlStringPtr> sql_string
sql_string
: STRING // string in current charset
| INTRODUCER
[
// feedback for lexer
introducerCharSetName = $1;
]
STRING // string in specific charset
[ introducerCharSetName = nullptr; ]
{
$$ = $3;
$$->setCharSet(*$1);
StrMark* mark = strMarks.get($3);
if (mark) // hex string is not in strMarks
mark->introduced = true;
}
;
%type <stringPtr> utf_string
utf_string
: sql_string
{ $$ = newString($1->toUtf8(scratch->getTransaction())); }
;
%type <int32Val> signed_short_integer
signed_short_integer
: nonneg_short_integer
| '-' neg_short_integer
{ $$ = -$2; }
;
%type <int32Val> nonneg_short_integer
nonneg_short_integer
: NUMBER32BIT
{
if ($1 > SHRT_POS_MAX)
yyabandon(YYPOSNARG(1), -842, isc_expec_short); // Short integer expected
$$ = $1;
}
;
%type <int32Val> neg_short_integer
neg_short_integer
: NUMBER32BIT
{
if ($1 > SHRT_NEG_MAX)
yyabandon(YYPOSNARG(1), -842, isc_expec_short); // Short integer expected
$$ = $1;
}
;
%type <int32Val> pos_short_integer
pos_short_integer
: nonneg_short_integer
{
if ($1 == 0)
yyabandon(YYPOSNARG(1), -842, isc_expec_positive); // Positive number expected
$$ = $1;
}
;
%type <int32Val> unsigned_short_integer
unsigned_short_integer
: NUMBER32BIT
{
if ($1 > SHRT_UNSIGNED_MAX)
yyabandon(YYPOSNARG(1), -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
: NUMBER32BIT { $$ = $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
: aggregate_function_prefix
| aggregate_function_prefix FILTER '(' WHERE search_condition ')'
{
$$ = $1;
if ($$->aggInfo.blr == blr_agg_count2 && !$$->arg) // count(*)
$$->arg = newNode<ValueIfNode>($5, MAKE_const_slong(1), NullNode::instance());
else
{
fb_assert($$->arg);
$$->arg = newNode<ValueIfNode>($5, $$->arg, NullNode::instance());
}
}
;
%type <aggNode> aggregate_function_prefix
aggregate_function_prefix
: 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); }
| STDDEV_SAMP '(' value ')'
{ $$ = newNode<StdDevAggNode>(StdDevAggNode::TYPE_STDDEV_SAMP, $3); }
| STDDEV_POP '(' value ')'
{ $$ = newNode<StdDevAggNode>(StdDevAggNode::TYPE_STDDEV_POP, $3); }
| VAR_SAMP '(' value ')'
{ $$ = newNode<StdDevAggNode>(StdDevAggNode::TYPE_VAR_SAMP, $3); }
| VAR_POP '(' value ')'
{ $$ = newNode<StdDevAggNode>(StdDevAggNode::TYPE_VAR_POP, $3); }
| COVAR_SAMP '(' value ',' value ')'
{ $$ = newNode<CorrAggNode>(CorrAggNode::TYPE_COVAR_SAMP, $3, $5); }
| COVAR_POP '(' value ',' value ')'
{ $$ = newNode<CorrAggNode>(CorrAggNode::TYPE_COVAR_POP, $3, $5); }
| CORR '(' value ',' value ')'
{ $$ = newNode<CorrAggNode>(CorrAggNode::TYPE_CORR, $3, $5); }
| REGR_AVGX '(' value ',' value ')'
{ $$ = newNode<RegrAggNode>(RegrAggNode::TYPE_REGR_AVGX, $3, $5); }
| REGR_AVGY '(' value ',' value ')'
{ $$ = newNode<RegrAggNode>(RegrAggNode::TYPE_REGR_AVGY, $3, $5); }
| REGR_COUNT '(' value ',' value ')'
{ $$ = newNode<RegrCountAggNode>($3, $5); }
| REGR_INTERCEPT '(' value ',' value ')'
{ $$ = newNode<RegrAggNode>(RegrAggNode::TYPE_REGR_INTERCEPT, $3, $5); }
| REGR_R2 '(' value ',' value ')'
{ $$ = newNode<RegrAggNode>(RegrAggNode::TYPE_REGR_R2, $3, $5); }
| REGR_SLOPE '(' value ',' value ')'
{ $$ = newNode<RegrAggNode>(RegrAggNode::TYPE_REGR_SLOPE, $3, $5); }
| REGR_SXX '(' value ',' value ')'
{ $$ = newNode<RegrAggNode>(RegrAggNode::TYPE_REGR_SXX, $3, $5); }
| REGR_SXY '(' value ',' value ')'
{ $$ = newNode<RegrAggNode>(RegrAggNode::TYPE_REGR_SXY, $3, $5); }
| REGR_SYY '(' value ',' value ')'
{ $$ = newNode<RegrAggNode>(RegrAggNode::TYPE_REGR_SYY, $3, $5); }
| ANY_VALUE '(' distinct_noise value ')'
{ $$ = newNode<AnyValueAggNode>($4); }
;
%type <aggNode> window_function
window_function
: DENSE_RANK '(' ')'
{ $$ = newNode<DenseRankWinNode>(); }
| RANK '(' ')'
{ $$ = newNode<RankWinNode>(); }
| PERCENT_RANK '(' ')'
{ $$ = newNode<PercentRankWinNode>(); }
| CUME_DIST '(' ')'
{ $$ = newNode<CumeDistWinNode>(); }
| 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, NullNode::instance()); }
| LAG '(' value ')'
{ $$ = newNode<LagWinNode>($3, MAKE_const_slong(1), NullNode::instance()); }
| LEAD '(' value ',' value ',' value ')'
{ $$ = newNode<LeadWinNode>($3, $5, $7); }
| LEAD '(' value ',' value ')'
{ $$ = newNode<LeadWinNode>($3, $5, NullNode::instance()); }
| LEAD '(' value ')'
{ $$ = newNode<LeadWinNode>($3, MAKE_const_slong(1), NullNode::instance()); }
| NTILE '(' ntile_arg ')'
{ $$ = newNode<NTileWinNode>($3); }
;
%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 <valueExprNode> ntile_arg
ntile_arg
: u_numeric_constant
| variable
| parameter
;
%type <aggNode> aggregate_window_function
aggregate_window_function
: aggregate_function
| window_function
;
%type <valueExprNode> over_clause
over_clause
: aggregate_window_function OVER symbol_window_name
{ $$ = newNode<OverNode>($1, $3); }
| aggregate_window_function OVER '(' window_clause ')'
{ $$ = newNode<OverNode>($1, $4); }
;
%type <windowClause> window_clause
window_clause
: symbol_window_name_opt
window_partition_opt
order_clause_opt
window_frame_extent
window_frame_exclusion_opt
{
$$ = newNode<WindowClause>($1, $2, $3, $4, $5);
}
;
%type <valueListNode> window_partition_opt
window_partition_opt
: /* nothing */ { $$ = NULL; }
| PARTITION BY value_list { $$ = $3; }
;
%type <windowClauseFrameExtent> window_frame_extent
window_frame_extent
: /* nothing */
{ $$ = NULL; }
| RANGE
{ $$ = newNode<WindowClause::FrameExtent>(WindowClause::FrameExtent::Unit::RANGE); }
window_frame($2)
{ $$ = $2; }
| ROWS
{ $$ = newNode<WindowClause::FrameExtent>(WindowClause::FrameExtent::Unit::ROWS); }
window_frame($2)
{ $$ = $2; }
;
%type window_frame(<windowClauseFrameExtent>)
window_frame($frameExtent)
: window_frame_start
{
$frameExtent->frame1 = $1;
$frameExtent->frame2 =
newNode<WindowClause::Frame>(WindowClause::Frame::Bound::CURRENT_ROW);
}
| BETWEEN window_frame_between_bound1 AND window_frame_between_bound2
{
$frameExtent->frame1 = $2;
$frameExtent->frame2 = $4;
}
;
%type <windowClauseFrame> window_frame_start
window_frame_start
: UNBOUNDED PRECEDING
{ $$ = newNode<WindowClause::Frame>(WindowClause::Frame::Bound::PRECEDING); }
| CURRENT ROW
{ $$ = newNode<WindowClause::Frame>(WindowClause::Frame::Bound::CURRENT_ROW); }
| value PRECEDING
{ $$ = newNode<WindowClause::Frame>(WindowClause::Frame::Bound::PRECEDING, $1); }
;
%type <windowClauseFrame> window_frame_between_bound1
window_frame_between_bound1
: UNBOUNDED PRECEDING
{ $$ = newNode<WindowClause::Frame>(WindowClause::Frame::Bound::PRECEDING); }
| CURRENT ROW
{ $$ = newNode<WindowClause::Frame>(WindowClause::Frame::Bound::CURRENT_ROW); }
| value PRECEDING
{ $$ = newNode<WindowClause::Frame>(WindowClause::Frame::Bound::PRECEDING, $1); }
| value FOLLOWING
{ $$ = newNode<WindowClause::Frame>(WindowClause::Frame::Bound::FOLLOWING, $1); }
;
%type <windowClauseFrame> window_frame_between_bound2
window_frame_between_bound2
: UNBOUNDED FOLLOWING
{ $$ = newNode<WindowClause::Frame>(WindowClause::Frame::Bound::FOLLOWING); }
| CURRENT ROW
{ $$ = newNode<WindowClause::Frame>(WindowClause::Frame::Bound::CURRENT_ROW); }
| value PRECEDING
{ $$ = newNode<WindowClause::Frame>(WindowClause::Frame::Bound::PRECEDING, $1); }
| value FOLLOWING
{ $$ = newNode<WindowClause::Frame>(WindowClause::Frame::Bound::FOLLOWING, $1); }
;
%type <windowClauseExclusion> window_frame_exclusion_opt
window_frame_exclusion_opt
: /* nothing */ { $$ = WindowClause::Exclusion::NO_OTHERS; }
| EXCLUDE NO OTHERS { $$ = WindowClause::Exclusion::NO_OTHERS; }
| EXCLUDE CURRENT ROW { $$ = WindowClause::Exclusion::CURRENT_ROW; }
| EXCLUDE GROUP { $$ = WindowClause::Exclusion::GROUP; }
| EXCLUDE TIES { $$ = WindowClause::Exclusion::TIES; }
;
%type <valueExprNode> delimiter_opt
delimiter_opt
: /* nothing */ { $$ = MAKE_str_constant(newIntlString(","), lex.charSetId); }
| ',' 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
| BASE64_DECODE
| BASE64_ENCODE
| BIN_AND
| BIN_NOT
| BIN_OR
| BIN_SHL
| BIN_SHR
| BIN_XOR
| BLOB_APPEND
| CEIL
| CHAR_TO_UUID
| COS
| COSH
| COT
| EXP
| FLOOR
| GEN_UUID
| HEX_DECODE
| HEX_ENCODE
| LEFT
| LN
| LOG
| LOG10
| LPAD
| MAKE_DBKEY
| MAXVALUE
| MINVALUE
| MOD
| PI
| POWER
| RAND
| RDB_GET_CONTEXT
| RDB_GET_TRANSACTION_CN
| RDB_ROLE_IN_USE
| RDB_SET_CONTEXT
| REPLACE
| REVERSE
| RIGHT
| ROUND
| RPAD
| RSA_PRIVATE
| RSA_PUBLIC
| SIGN
| SIN
| SINH
| SQRT
| TAN
| TANH
| TRUNC
| UNICODE_CHAR
| UNICODE_VAL
| UUID_TO_CHAR
| QUANTIZE
| TOTALORDER
| NORMALIZE_DECFLOAT
| COMPARE_DECFLOAT
;
%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;
}
| encrypt_decrypt '(' value USING valid_symbol_name crypt_opt_mode KEY value crypt_opt_iv crypt_opt_counter_type crypt_opt_counter ')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>($3)->add(MAKE_str_constant(newIntlString($5->c_str()), CS_ASCII))->
add(MAKE_str_constant(newIntlString($6->c_str()), CS_ASCII))->add($8)->add($9)->
add(MAKE_str_constant(newIntlString($10->c_str()), CS_ASCII))->add($11));
$$->dsqlSpecialSyntax = true;
}
| FIRST_DAY '(' of_first_last_day_part FROM value ')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>(MAKE_const_slong($3))->add($5));
$$->dsqlSpecialSyntax = true;
}
| HASH '(' value ')'
{ $$ = newNode<SysFuncCallNode>(*$1, newNode<ValueListNode>($3)); }
| hash_func '(' value USING valid_symbol_name ')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>($3)->add(MAKE_str_constant(newIntlString($5->c_str()), CS_ASCII)));
$$->dsqlSpecialSyntax = true;
}
| LAST_DAY '(' of_first_last_day_part FROM value ')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>(MAKE_const_slong($3))->add($5));
$$->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 IN value ')'
{
$$ = newNode<SysFuncCallNode>(*$1, newNode<ValueListNode>($3)->add($5));
$$->dsqlSpecialSyntax = true;
}
| POSITION '(' value_list_opt ')'
{ $$ = newNode<SysFuncCallNode>(*$1, $3); }
| rsa_encrypt_decrypt '(' value KEY value crypt_opt_lparam crypt_opt_hash crypt_opt_pkcs')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>($3)->add($5)->add($6)->
add(MAKE_str_constant(newIntlString($7->c_str()), CS_ASCII))->add($8));
$$->dsqlSpecialSyntax = true;
}
| RSA_SIGN_HASH '(' value KEY value crypt_opt_hash crypt_opt_saltlen crypt_opt_pkcs ')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>($3)->add($5)->
add(MAKE_str_constant(newIntlString($6->c_str()), CS_ASCII))->add($7)->add($8));
$$->dsqlSpecialSyntax = true;
}
| RSA_VERIFY_HASH '(' value SIGNATURE value KEY value crypt_opt_hash crypt_opt_saltlen crypt_opt_pkcs ')'
{
$$ = newNode<SysFuncCallNode>(*$1,
newNode<ValueListNode>($3)->add($5)->add($7)->
add(MAKE_str_constant(newIntlString($8->c_str()), CS_ASCII))->add($9)->add($10));
$$->dsqlSpecialSyntax = true;
}
| RDB_SYSTEM_PRIVILEGE '(' valid_symbol_name ')'
{
ValueExprNode* v = MAKE_system_privilege($3->c_str());
$$ = newNode<SysFuncCallNode>(*$1, newNode<ValueListNode>(v));
}
;
%type <metaNamePtr> hash_func
hash_func
: HASH | CRYPT_HASH
;
%type <metaNamePtr> rsa_encrypt_decrypt
rsa_encrypt_decrypt
: RSA_DECRYPT | RSA_ENCRYPT
;
%type <valueExprNode> crypt_opt_lparam
crypt_opt_lparam
: // nothing
{ $$ = MAKE_str_constant(newIntlString(""), CS_ASCII); }
| LPARAM value
{ $$ = $2; }
;
%type <valueExprNode> crypt_opt_pkcs
crypt_opt_pkcs
: // nothing
{ $$ = MAKE_const_slong(0); }
| PKCS_1_5
{ $$ = MAKE_const_slong(1); }
;
%type <metaNamePtr> crypt_opt_hash
crypt_opt_hash
: // nothing
{ $$ = newNode<MetaName>(""); }
| HASH valid_symbol_name
{ $$ = $2; }
;
%type <valueExprNode> crypt_opt_saltlen
crypt_opt_saltlen
: // nothing
{ $$ = MAKE_str_constant(newIntlString(""), CS_ASCII); }
| SALT_LENGTH value
{ $$ = $2; }
;
%type <metaNamePtr> crypt_opt_mode
crypt_opt_mode
: // nothing
{ $$ = newNode<MetaName>(""); }
| MODE valid_symbol_name
{ $$ = $2; }
;
%type <valueExprNode> crypt_opt_iv
crypt_opt_iv
: // nothing
{ $$ = MAKE_str_constant(newIntlString(""), CS_ASCII); }
| IV value
{ $$ = $2; }
;
%type <metaNamePtr> crypt_opt_counter_type
crypt_opt_counter_type
: // nothing
{ $$ = newNode<MetaName>(""); }
| crypt_counter_type
{ $$ = $1; }
;
%type <metaNamePtr> crypt_counter_type
crypt_counter_type
: CTR_BIG_ENDIAN | CTR_LITTLE_ENDIAN
;
%type <valueExprNode> crypt_opt_counter
crypt_opt_counter
: // nothing
{ $$ = MAKE_str_constant(newIntlString(""), CS_ASCII); }
| crypt_counter_name value
{ $$ = $2; }
;
%type <metaNamePtr> crypt_counter_name
crypt_counter_name
: COUNTER | CTR_LENGTH
;
%type <metaNamePtr> encrypt_decrypt
encrypt_decrypt
: ENCRYPT | DECRYPT
;
%type <blrOp> of_first_last_day_part
of_first_last_day_part
: OF YEAR { $$ = blr_extract_year; }
| OF QUARTER { $$ = blr_extract_quarter; }
| OF MONTH { $$ = blr_extract_month; }
| OF WEEK { $$ = blr_extract_week; }
;
%type <valueExprNode> string_value_function
string_value_function
: substring_function
| trim_function
| btrim_function
| ltrim_function
| rtrim_function
| UPPER '(' value ')'
{ $$ = newNode<StrCaseNode>(blr_upcase, $3); }
| 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, blr_trim_characters, $6, $4); }
| TRIM '(' value FROM value ')'
{ $$ = newNode<TrimNode>(blr_trim_both, blr_trim_characters, $5, $3); }
| TRIM '(' trim_specification FROM value ')'
{ $$ = newNode<TrimNode>($3, blr_trim_spaces, $5); }
| TRIM '(' value ')'
{ $$ = newNode<TrimNode>(blr_trim_both, blr_trim_spaces, $3); }
;
%type <blrOp> trim_specification
trim_specification
: BOTH { $$ = blr_trim_both; }
| TRAILING { $$ = blr_trim_trailing; }
| LEADING { $$ = blr_trim_leading; }
;
%type <valueExprNode> btrim_function
btrim_function
: BTRIM '(' value ',' value ')'
{ $$ = newNode<TrimNode>(blr_trim_both, blr_trim_multi_characters, $3, $5); }
| BTRIM '(' value ')'
{ $$ = newNode<TrimNode>(blr_trim_both, blr_trim_spaces, $3); }
;
%type <valueExprNode> ltrim_function
ltrim_function
: LTRIM '(' value ',' value ')'
{ $$ = newNode<TrimNode>(blr_trim_leading, blr_trim_multi_characters, $3, $5); }
| LTRIM '(' value ')'
{ $$ = newNode<TrimNode>(blr_trim_leading, blr_trim_spaces, $3); }
;
%type <valueExprNode> rtrim_function
rtrim_function
: RTRIM '(' value ',' value ')'
{ $$ = newNode<TrimNode>(blr_trim_trailing, blr_trim_multi_characters, $3, $5); }
| RTRIM '(' value ')'
{ $$ = newNode<TrimNode>(blr_trim_trailing, blr_trim_spaces, $3); }
;
%type <valueExprNode> udf
udf
: symbol_UDF_call_name '(' argument_list_opt ')'
{ $$ = newNode<UdfCallNode>(QualifiedName(*$1, ""), $3->second, $3->first); }
| symbol_package_name '.' symbol_UDF_name '(' argument_list_opt ')'
{ $$ = newNode<UdfCallNode>(QualifiedName(*$3, *$1), $5->second, $5->first); }
;
%type <namedArguments> argument_list_opt
argument_list_opt
: // nothing
{
$$ = newNode<NonPooledPair<ObjectsArray<MetaName>*, ValueListNode*>>();
$$->second = newNode<ValueListNode>();
}
| argument_list
;
%type <namedArguments> argument_list
argument_list
: named_argument_list
| value_or_default_list
{
$$ = newNode<NonPooledPair<ObjectsArray<MetaName>*, ValueListNode*>>();
$$->second = $1;
}
| value_or_default_list ',' named_argument_list
{
$$ = $3;
for (auto item : $$->second->items)
$1->add(item);
delete $$->second;
$$->second = $1;
}
;
%type <namedArguments> named_argument_list
named_argument_list
: named_argument
{
$$ = newNode<NonPooledPair<ObjectsArray<MetaName>*, ValueListNode*>>();
$$->first = newNode<ObjectsArray<MetaName>>();
$$->first->add(*$1->first);
$$->second = newNode<ValueListNode>();
$$->second->add($1->second);
}
| named_argument_list ',' named_argument
{
$$ = $1;
$$->first->add(*$3->first);
$$->second->add($3->second);
}
;
%type <namedArgument> named_argument
named_argument
: symbol_column_name NAMED_ARG_ASSIGN value_or_default
{ $$ = newNode<NonPooledPair<MetaName*, ValueExprNode*>>($1, $3); }
;
%type <valueExprNode> cast_specification
cast_specification
: CAST '(' value AS data_type_descriptor ')'
{ $$ = newNode<CastNode>($3, $5); }
| CAST '(' value AS cast_format_type cast_format_clause utf_string ')'
{ $$ = newNode<CastNode>($3, $5, *$7); }
;
%type <metaNamePtr> cast_format_clause
cast_format_clause
: FORMAT
;
%type <legacyField> date_time_type
date_time_type
: 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(YYPOSNARG(1), -104, isc_transitional_date);
else
{
$$->dtype = dtype_sql_date;
$$->length = sizeof(ULONG);
}
$$->flags |= FLD_has_prec;
}
| TIME without_time_zone_opt
{
$$ = newNode<dsql_fld>();
checkTimeDialect();
$$->dtype = dtype_sql_time;
$$->length = sizeof(SLONG);
$$->flags |= FLD_has_prec;
}
| TIME WITH TIME ZONE
{
$$ = newNode<dsql_fld>();
checkTimeDialect();
$$->dtype = dtype_sql_time_tz;
$$->length = sizeof(ISC_TIME_TZ);
$$->flags |= FLD_has_prec;
}
| TIMESTAMP without_time_zone_opt
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_timestamp;
$$->length = sizeof(GDS_TIMESTAMP);
$$->flags |= FLD_has_prec;
}
| TIMESTAMP WITH TIME ZONE
{
$$ = newNode<dsql_fld>();
$$->dtype = dtype_timestamp_tz;
$$->length = sizeof(ISC_TIMESTAMP_TZ);
$$->flags |= FLD_has_prec;
}
;
%type <legacyField> cast_format_type
cast_format_type
: character_type
| date_time_type
;
// 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, NullNode::instance(), $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 (FB_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 (FB_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 = nodeAs<ValueIfNode>(last->falseValue)))
last = next;
fb_assert(nodeIs<NullNode>(last->falseValue));
last->falseValue = $4;
$$ = $2;
}
;
%type <valueIfNode> searched_when_clause
searched_when_clause
: WHEN search_condition THEN case_result
{ $$ = newNode<ValueIfNode>($2, $4, NullNode::instance()); }
| searched_when_clause WHEN search_condition THEN case_result
{
ValueIfNode* cond = newNode<ValueIfNode>($3, $5, NullNode::instance());
cond->dsqlGenCast = false;
ValueIfNode* last = $1;
ValueIfNode* next;
while ((next = nodeAs<ValueIfNode>(last->falseValue)))
last = next;
fb_assert(nodeIs<NullNode>(last->falseValue));
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 VALUE FOR symbol_generator_name
{
$$ = newNode<GenIdNode>((client_dialect < SQL_DIALECT_V6_TRANSITION),
*$4, ((Jrd::ValueExprNode*) NULL), true, false);
}
| GEN_ID '(' symbol_generator_name ',' value ')'
{
$$ = newNode<GenIdNode>((client_dialect < SQL_DIALECT_V6_TRANSITION),
*$3, $5, false, false);
}
;
%type <blrOp> timestamp_part
timestamp_part
: YEAR { $$ = blr_extract_year; }
| QUARTER { $$ = blr_extract_quarter; }
| MONTH { $$ = blr_extract_month; }
| DAY { $$ = blr_extract_day; }
| HOUR { $$ = blr_extract_hour; }
| MINUTE { $$ = blr_extract_minute; }
| SECOND { $$ = blr_extract_second; }
| MILLISECOND { $$ = blr_extract_millisecond; }
| TIMEZONE_HOUR { $$ = blr_extract_timezone_hour; }
| TIMEZONE_MINUTE { $$ = blr_extract_timezone_minute; }
| TIMEZONE_NAME { $$ = blr_extract_timezone_name; }
| WEEK { $$ = blr_extract_week; }
| WEEKDAY { $$ = blr_extract_weekday; }
| YEARDAY { $$ = blr_extract_yearday; }
;
all_noise
:
| ALL
;
distinct_noise
:
| DISTINCT
;
%type <valueExprNode> null_value
null_value
: NULL
{ $$ = NullNode::instance(); }
| UNKNOWN
{
dsql_fld* field = newNode<dsql_fld>();
field->dtype = dtype_boolean;
field->length = sizeof(UCHAR);
CastNode* castNode = newNode<CastNode>(NullNode::instance(), 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
| BINARY
;
%type <metaNamePtr> symbol_character_set_name
symbol_character_set_name
: valid_symbol_name
| BINARY
;
%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
;
%type <metaNamePtr> symbol_window_name
symbol_window_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
| TYPE // added in IB 6.0
| BREAK // added in FB 1.0
| DESCRIPTOR
| SUBSTRING
| COALESCE // added in FB 1.5
| LAST
| LEAVE
| LOCK
| NULLIF
| NULLS
| STATEMENT
| FIRST
| SKIP
| BLOCK // added in FB 2.0
| BACKUP
| DIFFERENCE
| IIF
| SCALAR_ARRAY
| WEEKDAY
| YEARDAY
| SEQUENCE
| NEXT
| RESTART
| COLLATION
| RETURNING
| 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
| 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
| DESC
| DO
| DOMAIN
| ENTRY_POINT
| EXCEPTION
| EXIT
| FILE
// | GDSCODE
| GENERATOR
| GEN_ID
| IF
| INACTIVE
// | INDEX
| INPUT_TYPE
| ISOLATION
| KEY
| LENGTH
| LEVEL
// | LONG
| MANUAL
| MODULE_NAME
| NAMES
| OPTION
| OUTPUT_TYPE
| OVERFLOW
| PAGE
| PAGES
| PAGE_SIZE
| PASSWORD
// | PLAN
// | POST_EVENT
| PRIVILEGES
| PROTECTED
| READ
| RESERVING
| RETAIN
// | RETURNING_VALUES
| SEGMENT
| SHADOW
| SHARED
| SINGULAR
| 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
| ABSOLUTE // added in FB 3.0
| ACOSH
| ASINH
| ATANH
| BODY
| CONTINUE
| DDL
| DECRYPT
| ENCRYPT
| ENGINE
| IDENTITY
| NAME
| PACKAGE
| PARTITION
| PRIOR
| RELATIVE
| DENSE_RANK
| FIRST_VALUE
| NTH_VALUE
| LAST_VALUE
| LAG
| LEAD
| RANK
| ROW_NUMBER
| USAGE
| LINGER
| TAGS
| PLUGIN
| SERVERWIDE
| INCREMENT
| TRUSTED
// added in FB 4.0
| BASE64_DECODE
| BASE64_ENCODE
| BIND
| CLEAR
| COUNTER
| COMPARE_DECFLOAT
| CONNECTIONS
| CONSISTENCY
| CRYPT_HASH
| CTR_BIG_ENDIAN
| CTR_LENGTH
| CTR_LITTLE_ENDIAN
| CUME_DIST
| DEFINER
| DISABLE
| ENABLE
| EXCESS
| EXCLUDE
| EXTENDED
| FIRST_DAY
| FOLLOWING
| HEX_DECODE
| HEX_ENCODE
| IDLE
| INCLUDE
| INVOKER
| IV
| LAST_DAY
| LEGACY
| LIFETIME
| LPARAM
| MAKE_DBKEY
| MESSAGE
| MODE
| NATIVE
| NORMALIZE_DECFLOAT
| NTILE
| NUMBER
| OLDEST
| OTHERS
| OVERRIDING
| PERCENT_RANK
| POOL
| PRECEDING
| PRIVILEGE
| QUANTIZE
| RANGE
| RESET
| RSA_DECRYPT
| RSA_ENCRYPT
| RSA_PRIVATE
| RSA_PUBLIC
| RSA_SIGN_HASH
| RSA_VERIFY_HASH
| SALT_LENGTH
| SECURITY
| SESSION
| SIGNATURE
| SQL
| SYSTEM
| TIES
| TOTALORDER
| TRAPS
| ZONE
// added in FB 4.0.1
| DEBUG
| PKCS_1_5
// added in FB 4.0.2
| BLOB_APPEND
// added in FB 5.0
| BLOBID
| LOCKED
| OPTIMIZE
| QUARTER
| TARGET
| TEMP
| TIMEZONE_NAME
| UNICODE_CHAR
| UNICODE_VAL
// added in FB 6.0
| ANY_VALUE
| FORMAT
| OWNER
;
%%