15975 lines
367 KiB
Plaintext
15975 lines
367 KiB
Plaintext
%{
|
|
// Copyright 2013 The ql Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSES/QL-LICENSE file.
|
|
|
|
// Copyright 2015 PingCAP, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Initial yacc source generated by ebnf2y[1]
|
|
// at 2013-10-04 23:10:47.861401015 +0200 CEST
|
|
//
|
|
// $ ebnf2y -o ql.y -oe ql.ebnf -start StatementList -pkg ql -p _
|
|
//
|
|
// [1]: http://github.com/cznic/ebnf2y
|
|
|
|
package parser
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/pingcap/tidb/parser/mysql"
|
|
"github.com/pingcap/tidb/parser/ast"
|
|
"github.com/pingcap/tidb/parser/model"
|
|
"github.com/pingcap/tidb/parser/opcode"
|
|
"github.com/pingcap/tidb/parser/auth"
|
|
"github.com/pingcap/tidb/parser/charset"
|
|
"github.com/pingcap/tidb/parser/types"
|
|
"github.com/pingcap/tidb/parser/duration"
|
|
)
|
|
|
|
%}
|
|
|
|
%union {
|
|
offset int // offset
|
|
item interface{}
|
|
ident string
|
|
expr ast.ExprNode
|
|
statement ast.StmtNode
|
|
}
|
|
|
|
%token <ident>
|
|
|
|
/*yy:token "%c" */
|
|
identifier "identifier"
|
|
asof "AS OF"
|
|
toTimestamp "TO TIMESTAMP"
|
|
memberof "MEMBER OF"
|
|
optionallyEnclosedBy "OPTIONALLY ENCLOSED BY"
|
|
|
|
/*yy:token "_%c" */
|
|
underscoreCS "UNDERSCORE_CHARSET"
|
|
|
|
/*yy:token "\"%c\"" */
|
|
stringLit "string literal"
|
|
singleAtIdentifier "identifier with single leading at"
|
|
doubleAtIdentifier "identifier with double leading at"
|
|
invalid "a special token never used by parser, used by lexer to indicate error"
|
|
hintComment "an optimizer hint"
|
|
andand "&&"
|
|
pipes "||"
|
|
|
|
/* The following tokens belong to ODBCDateTimeType. */
|
|
odbcDateType "d"
|
|
odbcTimeType "t"
|
|
odbcTimestampType "ts"
|
|
|
|
/* The following tokens belong to ReservedKeyword. Notice: make sure these tokens are contained in ReservedKeyword. */
|
|
add "ADD"
|
|
all "ALL"
|
|
alter "ALTER"
|
|
analyze "ANALYZE"
|
|
and "AND"
|
|
array "ARRAY"
|
|
as "AS"
|
|
asc "ASC"
|
|
between "BETWEEN"
|
|
bigIntType "BIGINT"
|
|
binaryType "BINARY"
|
|
blobType "BLOB"
|
|
both "BOTH"
|
|
by "BY"
|
|
call "CALL"
|
|
cascade "CASCADE"
|
|
caseKwd "CASE"
|
|
change "CHANGE"
|
|
character "CHARACTER"
|
|
charType "CHAR"
|
|
check "CHECK"
|
|
collate "COLLATE"
|
|
column "COLUMN"
|
|
constraint "CONSTRAINT"
|
|
continueKwd "CONTINUE"
|
|
convert "CONVERT"
|
|
create "CREATE"
|
|
cross "CROSS"
|
|
cumeDist "CUME_DIST"
|
|
currentDate "CURRENT_DATE"
|
|
currentTime "CURRENT_TIME"
|
|
currentTs "CURRENT_TIMESTAMP"
|
|
currentUser "CURRENT_USER"
|
|
currentRole "CURRENT_ROLE"
|
|
cursor "CURSOR"
|
|
database "DATABASE"
|
|
databases "DATABASES"
|
|
dayHour "DAY_HOUR"
|
|
dayMicrosecond "DAY_MICROSECOND"
|
|
dayMinute "DAY_MINUTE"
|
|
daySecond "DAY_SECOND"
|
|
decimalType "DECIMAL"
|
|
defaultKwd "DEFAULT"
|
|
delayed "DELAYED"
|
|
deleteKwd "DELETE"
|
|
denseRank "DENSE_RANK"
|
|
desc "DESC"
|
|
describe "DESCRIBE"
|
|
distinct "DISTINCT"
|
|
distinctRow "DISTINCTROW"
|
|
div "DIV"
|
|
doubleType "DOUBLE"
|
|
drop "DROP"
|
|
dual "DUAL"
|
|
elseIfKwd "ELSEIF"
|
|
elseKwd "ELSE"
|
|
enclosed "ENCLOSED"
|
|
escaped "ESCAPED"
|
|
exists "EXISTS"
|
|
exit "EXIT"
|
|
explain "EXPLAIN"
|
|
except "EXCEPT"
|
|
falseKwd "FALSE"
|
|
fetch "FETCH"
|
|
firstValue "FIRST_VALUE"
|
|
floatType "FLOAT"
|
|
float4Type "FLOAT4"
|
|
float8Type "FLOAT8"
|
|
forKwd "FOR"
|
|
force "FORCE"
|
|
foreign "FOREIGN"
|
|
from "FROM"
|
|
fulltext "FULLTEXT"
|
|
generated "GENERATED"
|
|
grant "GRANT"
|
|
group "GROUP"
|
|
groups "GROUPS"
|
|
having "HAVING"
|
|
highPriority "HIGH_PRIORITY"
|
|
hourMicrosecond "HOUR_MICROSECOND"
|
|
hourMinute "HOUR_MINUTE"
|
|
hourSecond "HOUR_SECOND"
|
|
ifKwd "IF"
|
|
ignore "IGNORE"
|
|
in "IN"
|
|
index "INDEX"
|
|
infile "INFILE"
|
|
inner "INNER"
|
|
inout "INOUT"
|
|
integerType "INTEGER"
|
|
intersect "INTERSECT"
|
|
interval "INTERVAL"
|
|
into "INTO"
|
|
outfile "OUTFILE"
|
|
is "IS"
|
|
insert "INSERT"
|
|
intType "INT"
|
|
int1Type "INT1"
|
|
int2Type "INT2"
|
|
int3Type "INT3"
|
|
int4Type "INT4"
|
|
int8Type "INT8"
|
|
iterate "ITERATE"
|
|
join "JOIN"
|
|
key "KEY"
|
|
keys "KEYS"
|
|
kill "KILL"
|
|
lag "LAG"
|
|
lastValue "LAST_VALUE"
|
|
lead "LEAD"
|
|
leading "LEADING"
|
|
leave "LEAVE"
|
|
left "LEFT"
|
|
like "LIKE"
|
|
ilike "ILIKE"
|
|
limit "LIMIT"
|
|
lines "LINES"
|
|
linear "LINEAR"
|
|
load "LOAD"
|
|
localTime "LOCALTIME"
|
|
localTs "LOCALTIMESTAMP"
|
|
lock "LOCK"
|
|
longblobType "LONGBLOB"
|
|
longtextType "LONGTEXT"
|
|
lowPriority "LOW_PRIORITY"
|
|
match "MATCH"
|
|
maxValue "MAXVALUE"
|
|
mediumblobType "MEDIUMBLOB"
|
|
mediumIntType "MEDIUMINT"
|
|
mediumtextType "MEDIUMTEXT"
|
|
middleIntType "MIDDLEINT"
|
|
minuteMicrosecond "MINUTE_MICROSECOND"
|
|
minuteSecond "MINUTE_SECOND"
|
|
mod "MOD"
|
|
not "NOT"
|
|
noWriteToBinLog "NO_WRITE_TO_BINLOG"
|
|
nthValue "NTH_VALUE"
|
|
ntile "NTILE"
|
|
null "NULL"
|
|
numericType "NUMERIC"
|
|
of "OF"
|
|
on "ON"
|
|
optimize "OPTIMIZE"
|
|
option "OPTION"
|
|
optionally "OPTIONALLY"
|
|
or "OR"
|
|
order "ORDER"
|
|
out "OUT"
|
|
outer "OUTER"
|
|
over "OVER"
|
|
partition "PARTITION"
|
|
percentRank "PERCENT_RANK"
|
|
precisionType "PRECISION"
|
|
primary "PRIMARY"
|
|
procedure "PROCEDURE"
|
|
rangeKwd "RANGE"
|
|
rank "RANK"
|
|
read "READ"
|
|
realType "REAL"
|
|
recursive "RECURSIVE"
|
|
references "REFERENCES"
|
|
regexpKwd "REGEXP"
|
|
release "RELEASE"
|
|
rename "RENAME"
|
|
repeat "REPEAT"
|
|
replace "REPLACE"
|
|
require "REQUIRE"
|
|
restrict "RESTRICT"
|
|
revoke "REVOKE"
|
|
right "RIGHT"
|
|
rlike "RLIKE"
|
|
row "ROW"
|
|
rows "ROWS"
|
|
rowNumber "ROW_NUMBER"
|
|
secondMicrosecond "SECOND_MICROSECOND"
|
|
selectKwd "SELECT"
|
|
set "SET"
|
|
show "SHOW"
|
|
smallIntType "SMALLINT"
|
|
spatial "SPATIAL"
|
|
sql "SQL"
|
|
sqlBigResult "SQL_BIG_RESULT"
|
|
sqlCalcFoundRows "SQL_CALC_FOUND_ROWS"
|
|
sqlSmallResult "SQL_SMALL_RESULT"
|
|
sqlexception "SQLEXCEPTION"
|
|
sqlstate "SQLSTATE"
|
|
sqlwarning "SQLWARNING"
|
|
ssl "SSL"
|
|
starting "STARTING"
|
|
statsExtended "STATS_EXTENDED"
|
|
straightJoin "STRAIGHT_JOIN"
|
|
tidbCurrentTSO "TiDB_CURRENT_TSO"
|
|
tableKwd "TABLE"
|
|
tableSample "TABLESAMPLE"
|
|
stored "STORED"
|
|
terminated "TERMINATED"
|
|
then "THEN"
|
|
tinyblobType "TINYBLOB"
|
|
tinyIntType "TINYINT"
|
|
tinytextType "TINYTEXT"
|
|
to "TO"
|
|
trailing "TRAILING"
|
|
trigger "TRIGGER"
|
|
trueKwd "TRUE"
|
|
unique "UNIQUE"
|
|
union "UNION"
|
|
unlock "UNLOCK"
|
|
unsigned "UNSIGNED"
|
|
until "UNTIL"
|
|
update "UPDATE"
|
|
usage "USAGE"
|
|
use "USE"
|
|
using "USING"
|
|
utcDate "UTC_DATE"
|
|
utcTimestamp "UTC_TIMESTAMP"
|
|
utcTime "UTC_TIME"
|
|
values "VALUES"
|
|
long "LONG"
|
|
varcharType "VARCHAR"
|
|
varcharacter "VARCHARACTER"
|
|
varbinaryType "VARBINARY"
|
|
varying "VARYING"
|
|
virtual "VIRTUAL"
|
|
when "WHEN"
|
|
where "WHERE"
|
|
while "WHILE"
|
|
write "WRITE"
|
|
window "WINDOW"
|
|
with "WITH"
|
|
xor "XOR"
|
|
yearMonth "YEAR_MONTH"
|
|
zerofill "ZEROFILL"
|
|
natural "NATURAL"
|
|
|
|
/* The following tokens belong to UnReservedKeyword. Notice: make sure these tokens are contained in UnReservedKeyword. */
|
|
account "ACCOUNT"
|
|
action "ACTION"
|
|
advise "ADVISE"
|
|
after "AFTER"
|
|
against "AGAINST"
|
|
ago "AGO"
|
|
algorithm "ALGORITHM"
|
|
always "ALWAYS"
|
|
any "ANY"
|
|
ascii "ASCII"
|
|
attribute "ATTRIBUTE"
|
|
attributes "ATTRIBUTES"
|
|
statsOptions "STATS_OPTIONS"
|
|
statsSampleRate "STATS_SAMPLE_RATE"
|
|
statsColChoice "STATS_COL_CHOICE"
|
|
statsColList "STATS_COL_LIST"
|
|
autoIdCache "AUTO_ID_CACHE"
|
|
autoIncrement "AUTO_INCREMENT"
|
|
autoRandom "AUTO_RANDOM"
|
|
autoRandomBase "AUTO_RANDOM_BASE"
|
|
avg "AVG"
|
|
avgRowLength "AVG_ROW_LENGTH"
|
|
backend "BACKEND"
|
|
backup "BACKUP"
|
|
backups "BACKUPS"
|
|
begin "BEGIN"
|
|
bernoulli "BERNOULLI"
|
|
binding "BINDING"
|
|
bindingCache "BINDING_CACHE"
|
|
bindings "BINDINGS"
|
|
binlog "BINLOG"
|
|
bitType "BIT"
|
|
block "BLOCK"
|
|
booleanType "BOOLEAN"
|
|
boolType "BOOL"
|
|
btree "BTREE"
|
|
byteType "BYTE"
|
|
cache "CACHE"
|
|
calibrate "CALIBRATE"
|
|
capture "CAPTURE"
|
|
cascaded "CASCADED"
|
|
causal "CAUSAL"
|
|
chain "CHAIN"
|
|
charsetKwd "CHARSET"
|
|
checkpoint "CHECKPOINT"
|
|
checksum "CHECKSUM"
|
|
cipher "CIPHER"
|
|
cleanup "CLEANUP"
|
|
client "CLIENT"
|
|
clientErrorsSummary "CLIENT_ERRORS_SUMMARY"
|
|
coalesce "COALESCE"
|
|
collation "COLLATION"
|
|
columnFormat "COLUMN_FORMAT"
|
|
columns "COLUMNS"
|
|
config "CONFIG"
|
|
comment "COMMENT"
|
|
commit "COMMIT"
|
|
committed "COMMITTED"
|
|
compact "COMPACT"
|
|
compressed "COMPRESSED"
|
|
compression "COMPRESSION"
|
|
concurrency "CONCURRENCY"
|
|
connection "CONNECTION"
|
|
consistency "CONSISTENCY"
|
|
consistent "CONSISTENT"
|
|
context "CONTEXT"
|
|
cpu "CPU"
|
|
csvBackslashEscape "CSV_BACKSLASH_ESCAPE"
|
|
csvDelimiter "CSV_DELIMITER"
|
|
csvHeader "CSV_HEADER"
|
|
csvNotNull "CSV_NOT_NULL"
|
|
csvNull "CSV_NULL"
|
|
csvSeparator "CSV_SEPARATOR"
|
|
csvTrimLastSeparators "CSV_TRIM_LAST_SEPARATORS"
|
|
current "CURRENT"
|
|
close "CLOSE"
|
|
cluster "CLUSTER"
|
|
clustered "CLUSTERED"
|
|
cycle "CYCLE"
|
|
data "DATA"
|
|
datetimeType "DATETIME"
|
|
dateType "DATE"
|
|
day "DAY"
|
|
deallocate "DEALLOCATE"
|
|
declare "DECLARE"
|
|
definer "DEFINER"
|
|
delayKeyWrite "DELAY_KEY_WRITE"
|
|
digest "DIGEST"
|
|
directory "DIRECTORY"
|
|
disable "DISABLE"
|
|
disabled "DISABLED"
|
|
discard "DISCARD"
|
|
disk "DISK"
|
|
do "DO"
|
|
duplicate "DUPLICATE"
|
|
dynamic "DYNAMIC"
|
|
enable "ENABLE"
|
|
enabled "ENABLED"
|
|
encryption "ENCRYPTION"
|
|
end "END"
|
|
enforced "ENFORCED"
|
|
engine "ENGINE"
|
|
engines "ENGINES"
|
|
enum "ENUM"
|
|
errorKwd "ERROR"
|
|
escape "ESCAPE"
|
|
event "EVENT"
|
|
events "EVENTS"
|
|
evolve "EVOLVE"
|
|
exchange "EXCHANGE"
|
|
exclusive "EXCLUSIVE"
|
|
execute "EXECUTE"
|
|
expansion "EXPANSION"
|
|
expire "EXPIRE"
|
|
extended "EXTENDED"
|
|
faultsSym "FAULTS"
|
|
fields "FIELDS"
|
|
file "FILE"
|
|
first "FIRST"
|
|
fixed "FIXED"
|
|
flush "FLUSH"
|
|
found "FOUND"
|
|
following "FOLLOWING"
|
|
format "FORMAT"
|
|
full "FULL"
|
|
function "FUNCTION"
|
|
general "GENERAL"
|
|
global "GLOBAL"
|
|
grants "GRANTS"
|
|
handler "HANDLER"
|
|
hash "HASH"
|
|
help "HELP"
|
|
histogram "HISTOGRAM"
|
|
history "HISTORY"
|
|
hosts "HOSTS"
|
|
hour "HOUR"
|
|
identified "IDENTIFIED"
|
|
identSQLErrors "ERRORS"
|
|
importKwd "IMPORT"
|
|
imports "IMPORTS"
|
|
increment "INCREMENT"
|
|
incremental "INCREMENTAL"
|
|
indexes "INDEXES"
|
|
insertMethod "INSERT_METHOD"
|
|
instance "INSTANCE"
|
|
invisible "INVISIBLE"
|
|
invoker "INVOKER"
|
|
io "IO"
|
|
ipc "IPC"
|
|
isolation "ISOLATION"
|
|
issuer "ISSUER"
|
|
jsonType "JSON"
|
|
keyBlockSize "KEY_BLOCK_SIZE"
|
|
labels "LABELS"
|
|
language "LANGUAGE"
|
|
last "LAST"
|
|
lastBackup "LAST_BACKUP"
|
|
lastval "LASTVAL"
|
|
less "LESS"
|
|
level "LEVEL"
|
|
list "LIST"
|
|
local "LOCAL"
|
|
locked "LOCKED"
|
|
location "LOCATION"
|
|
logs "LOGS"
|
|
master "MASTER"
|
|
max_idxnum "MAX_IDXNUM"
|
|
max_minutes "MAX_MINUTES"
|
|
maxConnectionsPerHour "MAX_CONNECTIONS_PER_HOUR"
|
|
maxQueriesPerHour "MAX_QUERIES_PER_HOUR"
|
|
maxRows "MAX_ROWS"
|
|
maxUpdatesPerHour "MAX_UPDATES_PER_HOUR"
|
|
maxUserConnections "MAX_USER_CONNECTIONS"
|
|
mb "MB"
|
|
member "MEMBER"
|
|
memory "MEMORY"
|
|
merge "MERGE"
|
|
microsecond "MICROSECOND"
|
|
minRows "MIN_ROWS"
|
|
minute "MINUTE"
|
|
minValue "MINVALUE"
|
|
mode "MODE"
|
|
modify "MODIFY"
|
|
month "MONTH"
|
|
names "NAMES"
|
|
national "NATIONAL"
|
|
ncharType "NCHAR"
|
|
never "NEVER"
|
|
next "NEXT"
|
|
nextval "NEXTVAL"
|
|
no "NO"
|
|
nocache "NOCACHE"
|
|
nocycle "NOCYCLE"
|
|
nodegroup "NODEGROUP"
|
|
nomaxvalue "NOMAXVALUE"
|
|
nominvalue "NOMINVALUE"
|
|
nonclustered "NONCLUSTERED"
|
|
none "NONE"
|
|
nowait "NOWAIT"
|
|
nvarcharType "NVARCHAR"
|
|
nulls "NULLS"
|
|
off "OFF"
|
|
offset "OFFSET"
|
|
oltpReadOnly "OLTP_READ_ONLY"
|
|
oltpReadWrite "OLTP_READ_WRITE"
|
|
oltpWriteOnly "OLTP_WRITE_ONLY"
|
|
onDuplicate "ON_DUPLICATE"
|
|
online "ONLINE"
|
|
only "ONLY"
|
|
open "OPEN"
|
|
optional "OPTIONAL"
|
|
packKeys "PACK_KEYS"
|
|
pageSym "PAGE"
|
|
parser "PARSER"
|
|
partial "PARTIAL"
|
|
partitioning "PARTITIONING"
|
|
partitions "PARTITIONS"
|
|
password "PASSWORD"
|
|
pause "PAUSE"
|
|
percent "PERCENT"
|
|
per_db "PER_DB"
|
|
per_table "PER_TABLE"
|
|
pipesAsOr
|
|
plugins "PLUGINS"
|
|
point "POINT"
|
|
policy "POLICY"
|
|
preSplitRegions "PRE_SPLIT_REGIONS"
|
|
preceding "PRECEDING"
|
|
prepare "PREPARE"
|
|
preserve "PRESERVE"
|
|
privileges "PRIVILEGES"
|
|
process "PROCESS"
|
|
processlist "PROCESSLIST"
|
|
profile "PROFILE"
|
|
profiles "PROFILES"
|
|
proxy "PROXY"
|
|
purge "PURGE"
|
|
quarter "QUARTER"
|
|
queries "QUERIES"
|
|
query "QUERY"
|
|
quick "QUICK"
|
|
rateLimit "RATE_LIMIT"
|
|
rebuild "REBUILD"
|
|
recover "RECOVER"
|
|
redundant "REDUNDANT"
|
|
reload "RELOAD"
|
|
remove "REMOVE"
|
|
reorganize "REORGANIZE"
|
|
repair "REPAIR"
|
|
repeatable "REPEATABLE"
|
|
replica "REPLICA"
|
|
replicas "REPLICAS"
|
|
replication "REPLICATION"
|
|
required "REQUIRED"
|
|
resource "RESOURCE"
|
|
respect "RESPECT"
|
|
restart "RESTART"
|
|
restore "RESTORE"
|
|
restores "RESTORES"
|
|
resume "RESUME"
|
|
reuse "REUSE"
|
|
reverse "REVERSE"
|
|
role "ROLE"
|
|
rollback "ROLLBACK"
|
|
rollup "ROLLUP"
|
|
routine "ROUTINE"
|
|
rowCount "ROW_COUNT"
|
|
rowFormat "ROW_FORMAT"
|
|
rtree "RTREE"
|
|
hypo "HYPO"
|
|
san "SAN"
|
|
savepoint "SAVEPOINT"
|
|
second "SECOND"
|
|
secondaryEngine "SECONDARY_ENGINE"
|
|
secondaryLoad "SECONDARY_LOAD"
|
|
secondaryUnload "SECONDARY_UNLOAD"
|
|
security "SECURITY"
|
|
sendCredentialsToTiKV "SEND_CREDENTIALS_TO_TIKV"
|
|
separator "SEPARATOR"
|
|
sequence "SEQUENCE"
|
|
serial "SERIAL"
|
|
serializable "SERIALIZABLE"
|
|
session "SESSION"
|
|
setval "SETVAL"
|
|
shardRowIDBits "SHARD_ROW_ID_BITS"
|
|
share "SHARE"
|
|
shared "SHARED"
|
|
shutdown "SHUTDOWN"
|
|
signed "SIGNED"
|
|
simple "SIMPLE"
|
|
skip "SKIP"
|
|
skipSchemaFiles "SKIP_SCHEMA_FILES"
|
|
slave "SLAVE"
|
|
slow "SLOW"
|
|
snapshot "SNAPSHOT"
|
|
some "SOME"
|
|
source "SOURCE"
|
|
sqlBufferResult "SQL_BUFFER_RESULT"
|
|
sqlCache "SQL_CACHE"
|
|
sqlNoCache "SQL_NO_CACHE"
|
|
sqlTsiDay "SQL_TSI_DAY"
|
|
sqlTsiHour "SQL_TSI_HOUR"
|
|
sqlTsiMinute "SQL_TSI_MINUTE"
|
|
sqlTsiMonth "SQL_TSI_MONTH"
|
|
sqlTsiQuarter "SQL_TSI_QUARTER"
|
|
sqlTsiSecond "SQL_TSI_SECOND"
|
|
sqlTsiWeek "SQL_TSI_WEEK"
|
|
sqlTsiYear "SQL_TSI_YEAR"
|
|
start "START"
|
|
statsAutoRecalc "STATS_AUTO_RECALC"
|
|
statsPersistent "STATS_PERSISTENT"
|
|
statsSamplePages "STATS_SAMPLE_PAGES"
|
|
status "STATUS"
|
|
storage "STORAGE"
|
|
strictFormat "STRICT_FORMAT"
|
|
subject "SUBJECT"
|
|
subpartition "SUBPARTITION"
|
|
subpartitions "SUBPARTITIONS"
|
|
super "SUPER"
|
|
swaps "SWAPS"
|
|
switchesSym "SWITCHES"
|
|
system "SYSTEM"
|
|
systemTime "SYSTEM_TIME"
|
|
tableChecksum "TABLE_CHECKSUM"
|
|
tables "TABLES"
|
|
tablespace "TABLESPACE"
|
|
temporary "TEMPORARY"
|
|
temptable "TEMPTABLE"
|
|
textType "TEXT"
|
|
than "THAN"
|
|
tikvImporter "TIKV_IMPORTER"
|
|
timestampType "TIMESTAMP"
|
|
timeType "TIME"
|
|
tokenIssuer "TOKEN_ISSUER"
|
|
tp "TYPE"
|
|
tpcc "TPCC"
|
|
trace "TRACE"
|
|
traditional "TRADITIONAL"
|
|
transaction "TRANSACTION"
|
|
triggers "TRIGGERS"
|
|
truncate "TRUNCATE"
|
|
ttl "TTL"
|
|
ttlEnable "TTL_ENABLE"
|
|
ttlJobInterval "TTL_JOB_INTERVAL"
|
|
unbounded "UNBOUNDED"
|
|
uncommitted "UNCOMMITTED"
|
|
undefined "UNDEFINED"
|
|
unicodeSym "UNICODE"
|
|
unknown "UNKNOWN"
|
|
user "USER"
|
|
validation "VALIDATION"
|
|
value "VALUE"
|
|
variables "VARIABLES"
|
|
view "VIEW"
|
|
visible "VISIBLE"
|
|
warnings "WARNINGS"
|
|
week "WEEK"
|
|
weightString "WEIGHT_STRING"
|
|
without "WITHOUT"
|
|
workload "WORKLOAD"
|
|
x509 "X509"
|
|
yearType "YEAR"
|
|
wait "WAIT"
|
|
failedLoginAttempts "FAILED_LOGIN_ATTEMPTS"
|
|
passwordLockTime "PASSWORD_LOCK_TIME"
|
|
|
|
/* The following tokens belong to NotKeywordToken. Notice: make sure these tokens are contained in NotKeywordToken. */
|
|
addDate "ADDDATE"
|
|
approxCountDistinct "APPROX_COUNT_DISTINCT"
|
|
approxPercentile "APPROX_PERCENTILE"
|
|
bitAnd "BIT_AND"
|
|
bitOr "BIT_OR"
|
|
bitXor "BIT_XOR"
|
|
bound "BOUND"
|
|
br "BR"
|
|
briefType "BRIEF"
|
|
burstable "BURSTABLE"
|
|
cast "CAST"
|
|
copyKwd "COPY"
|
|
constraints "CONSTRAINTS"
|
|
curTime "CURTIME"
|
|
curDate "CURDATE"
|
|
dateAdd "DATE_ADD"
|
|
dateSub "DATE_SUB"
|
|
defined "DEFINED"
|
|
dotType "DOT"
|
|
dump "DUMP"
|
|
timeDuration "DURATION"
|
|
endTime "END_TIME"
|
|
exact "EXACT"
|
|
exprPushdownBlacklist "EXPR_PUSHDOWN_BLACKLIST"
|
|
extract "EXTRACT"
|
|
flashback "FLASHBACK"
|
|
follower "FOLLOWER"
|
|
followerConstraints "FOLLOWER_CONSTRAINTS"
|
|
followers "FOLLOWERS"
|
|
fullBackupStorage "FULL_BACKUP_STORAGE"
|
|
getFormat "GET_FORMAT"
|
|
gcTTL "GC_TTL"
|
|
groupConcat "GROUP_CONCAT"
|
|
next_row_id "NEXT_ROW_ID"
|
|
inplace "INPLACE"
|
|
instant "INSTANT"
|
|
internal "INTERNAL"
|
|
jsonArrayagg "JSON_ARRAYAGG"
|
|
jsonObjectAgg "JSON_OBJECTAGG"
|
|
leader "LEADER"
|
|
leaderConstraints "LEADER_CONSTRAINTS"
|
|
learner "LEARNER"
|
|
learnerConstraints "LEARNER_CONSTRAINTS"
|
|
learners "LEARNERS"
|
|
min "MIN"
|
|
max "MAX"
|
|
metadata "METADATA"
|
|
now "NOW"
|
|
optRuleBlacklist "OPT_RULE_BLACKLIST"
|
|
placement "PLACEMENT"
|
|
plan "PLAN"
|
|
planCache "PLAN_CACHE"
|
|
position "POSITION"
|
|
predicate "PREDICATE"
|
|
primaryRegion "PRIMARY_REGION"
|
|
recent "RECENT"
|
|
replayer "REPLAYER"
|
|
restoredTS "RESTORED_TS"
|
|
running "RUNNING"
|
|
s3 "S3"
|
|
schedule "SCHEDULE"
|
|
staleness "STALENESS"
|
|
startTime "START_TIME"
|
|
startTS "START_TS"
|
|
std "STD"
|
|
stddev "STDDEV"
|
|
stddevPop "STDDEV_POP"
|
|
stddevSamp "STDDEV_SAMP"
|
|
stop "STOP"
|
|
strict "STRICT"
|
|
strong "STRONG"
|
|
subDate "SUBDATE"
|
|
sum "SUM"
|
|
substring "SUBSTRING"
|
|
survivalPreferences "SURVIVAL_PREFERENCES"
|
|
target "TARGET"
|
|
taskTypes "TASK_TYPES"
|
|
tidbJson "TIDB_JSON"
|
|
timestampAdd "TIMESTAMPADD"
|
|
timestampDiff "TIMESTAMPDIFF"
|
|
tls "TLS"
|
|
tokudbDefault "TOKUDB_DEFAULT"
|
|
tokudbFast "TOKUDB_FAST"
|
|
tokudbLzma "TOKUDB_LZMA"
|
|
tokudbQuickLZ "TOKUDB_QUICKLZ"
|
|
tokudbSnappy "TOKUDB_SNAPPY"
|
|
tokudbSmall "TOKUDB_SMALL"
|
|
tokudbUncompressed "TOKUDB_UNCOMPRESSED"
|
|
tokudbZlib "TOKUDB_ZLIB"
|
|
tokudbZstd "TOKUDB_ZSTD"
|
|
top "TOP"
|
|
trim "TRIM"
|
|
untilTS "UNTIL_TS"
|
|
variance "VARIANCE"
|
|
varPop "VAR_POP"
|
|
varSamp "VAR_SAMP"
|
|
verboseType "VERBOSE"
|
|
trueCardCost "TRUE_CARD_COST"
|
|
voter "VOTER"
|
|
voterConstraints "VOTER_CONSTRAINTS"
|
|
voters "VOTERS"
|
|
ruRate "RU_PER_SEC"
|
|
priority "PRIORITY"
|
|
high "HIGH"
|
|
medium "MEDIUM"
|
|
low "LOW"
|
|
ioReadBandwidth "IO_READ_BANDWIDTH"
|
|
ioWriteBandwidth "IO_WRITE_BANDWIDTH"
|
|
execElapsed "EXEC_ELAPSED"
|
|
dryRun "DRYRUN"
|
|
cooldown "COOLDOWN"
|
|
watch "WATCH"
|
|
similar "SIMILAR"
|
|
queryLimit "QUERY_LIMIT"
|
|
background "BACKGROUND"
|
|
unlimited "UNLIMITED"
|
|
|
|
/* The following tokens belong to TiDBKeyword. Notice: make sure these tokens are contained in TiDBKeyword. */
|
|
admin "ADMIN"
|
|
batch "BATCH"
|
|
buckets "BUCKETS"
|
|
builtins "BUILTINS"
|
|
cancel "CANCEL"
|
|
cardinality "CARDINALITY"
|
|
cmSketch "CMSKETCH"
|
|
columnStatsUsage "COLUMN_STATS_USAGE"
|
|
correlation "CORRELATION"
|
|
ddl "DDL"
|
|
dependency "DEPENDENCY"
|
|
depth "DEPTH"
|
|
drainer "DRAINER"
|
|
dry "DRY"
|
|
jobs "JOBS"
|
|
job "JOB"
|
|
nodeID "NODE_ID"
|
|
nodeState "NODE_STATE"
|
|
optimistic "OPTIMISTIC"
|
|
pessimistic "PESSIMISTIC"
|
|
pump "PUMP"
|
|
run "RUN"
|
|
samples "SAMPLES"
|
|
sampleRate "SAMPLERATE"
|
|
sessionStates "SESSION_STATES"
|
|
statistics "STATISTICS"
|
|
stats "STATS"
|
|
statsMeta "STATS_META"
|
|
statsHistograms "STATS_HISTOGRAMS"
|
|
statsBuckets "STATS_BUCKETS"
|
|
statsHealthy "STATS_HEALTHY"
|
|
statsTopN "STATS_TOPN"
|
|
statsLocked "STATS_LOCKED"
|
|
histogramsInFlight "HISTOGRAMS_IN_FLIGHT"
|
|
telemetry "TELEMETRY"
|
|
telemetryID "TELEMETRY_ID"
|
|
tidb "TIDB"
|
|
tiFlash "TIFLASH"
|
|
topn "TOPN"
|
|
split "SPLIT"
|
|
width "WIDTH"
|
|
reset "RESET"
|
|
regions "REGIONS"
|
|
region "REGION"
|
|
builtinBitAnd
|
|
builtinBitOr
|
|
builtinBitXor
|
|
builtinCast
|
|
builtinCount
|
|
builtinApproxCountDistinct
|
|
builtinApproxPercentile
|
|
builtinCurDate
|
|
builtinCurTime
|
|
builtinDateAdd
|
|
builtinDateSub
|
|
builtinExtract
|
|
builtinGroupConcat
|
|
builtinMax
|
|
builtinMin
|
|
builtinNow
|
|
builtinPosition
|
|
builtinSubstring
|
|
builtinSum
|
|
builtinSysDate
|
|
builtinStddevPop
|
|
builtinStddevSamp
|
|
builtinTranslate
|
|
builtinTrim
|
|
builtinUser
|
|
builtinVarPop
|
|
builtinVarSamp
|
|
|
|
%token <item>
|
|
|
|
/*yy:token "1.%d" */
|
|
floatLit "floating-point literal"
|
|
|
|
/*yy:token "1.%d" */
|
|
decLit "decimal literal"
|
|
|
|
/*yy:token "%d" */
|
|
intLit "integer literal"
|
|
|
|
/*yy:token "%x" */
|
|
hexLit "hexadecimal literal"
|
|
|
|
/*yy:token "%b" */
|
|
bitLit "bit literal"
|
|
andnot "&^"
|
|
assignmentEq ":="
|
|
eq "="
|
|
ge ">="
|
|
le "<="
|
|
jss "->"
|
|
juss "->>"
|
|
lsh "<<"
|
|
neq "!="
|
|
neqSynonym "<>"
|
|
nulleq "<=>"
|
|
paramMarker "?"
|
|
rsh ">>"
|
|
|
|
%token not2
|
|
%type <expr>
|
|
Expression "expression"
|
|
MaxValueOrExpression "maxvalue or expression"
|
|
DefaultOrExpression "default or expression"
|
|
BoolPri "boolean primary expression"
|
|
ExprOrDefault "expression or default"
|
|
PredicateExpr "Predicate expression factor"
|
|
SetExpr "Set variable statement value's expression"
|
|
BitExpr "bit expression"
|
|
SimpleExpr "simple expression"
|
|
SimpleIdent "Simple Identifier expression"
|
|
SumExpr "aggregate functions"
|
|
FunctionCallGeneric "Function call with Identifier"
|
|
FunctionCallKeyword "Function call with keyword as function name"
|
|
FunctionCallNonKeyword "Function call with nonkeyword as function name"
|
|
Literal "literal value"
|
|
Variable "User or system variable"
|
|
SystemVariable "System defined variable name"
|
|
UserVariable "User defined variable name"
|
|
SubSelect "Sub Select"
|
|
StringLiteral "text literal"
|
|
ExpressionOpt "Optional expression"
|
|
SignedLiteral "Literal or NumLiteral with sign"
|
|
DefaultValueExpr "DefaultValueExpr(Now or Signed Literal)"
|
|
NowSymOptionFraction "NowSym with optional fraction part"
|
|
NowSymOptionFractionParentheses "NowSym with optional fraction part within potential parentheses"
|
|
CharsetNameOrDefault "Character set name or default"
|
|
NextValueForSequence "Default nextval expression"
|
|
BuiltinFunction "Default builtin functions for columns"
|
|
FunctionNameSequence "Function with sequence function call"
|
|
WindowFuncCall "WINDOW function call"
|
|
RepeatableOpt "Repeatable optional in sample clause"
|
|
ProcedureCall "Procedure call with Identifier or identifier"
|
|
|
|
%type <statement>
|
|
AdminStmt "Check table statement or show ddl statement"
|
|
AlterDatabaseStmt "Alter database statement"
|
|
AlterTableStmt "Alter table statement"
|
|
AlterUserStmt "Alter user statement"
|
|
AlterInstanceStmt "Alter instance statement"
|
|
AlterPolicyStmt "Alter Placement Policy statement"
|
|
AlterResourceGroupStmt "Alter Resource Group statement"
|
|
AlterSequenceStmt "Alter sequence statement"
|
|
AnalyzeTableStmt "Analyze table statement"
|
|
BeginTransactionStmt "BEGIN TRANSACTION statement"
|
|
BinlogStmt "Binlog base64 statement"
|
|
BRIEStmt "BACKUP or RESTORE statement"
|
|
CalibrateResourceStmt "CALIBRATE RESOURCE statement"
|
|
CommitStmt "COMMIT statement"
|
|
CreateTableStmt "CREATE TABLE statement"
|
|
CreateViewStmt "CREATE VIEW statement"
|
|
CreateUserStmt "CREATE User statement"
|
|
CreateRoleStmt "CREATE Role statement"
|
|
CreateDatabaseStmt "Create Database Statement"
|
|
CreateIndexStmt "CREATE INDEX statement"
|
|
CreateBindingStmt "CREATE BINDING statement"
|
|
CreatePolicyStmt "CREATE PLACEMENT POLICY statement"
|
|
CreateProcedureStmt "CREATE PROCEDURE statement"
|
|
AddQueryWatchStmt "ADD QUERY WATCH statement"
|
|
CreateResourceGroupStmt "CREATE RESOURCE GROUP statement"
|
|
CreateSequenceStmt "CREATE SEQUENCE statement"
|
|
CreateStatisticsStmt "CREATE STATISTICS statement"
|
|
DoStmt "Do statement"
|
|
DropDatabaseStmt "DROP DATABASE statement"
|
|
DropIndexStmt "DROP INDEX statement"
|
|
DropProcedureStmt "DROP PROCEDURE statement"
|
|
DropQueryWatchStmt "DROP QUERY WATCH statement"
|
|
DropResourceGroupStmt "DROP RESOURCE GROUP statement"
|
|
DropStatisticsStmt "DROP STATISTICS statement"
|
|
DropStatsStmt "DROP STATS statement"
|
|
DropTableStmt "DROP TABLE statement"
|
|
DropSequenceStmt "DROP SEQUENCE statement"
|
|
DropUserStmt "DROP USER"
|
|
DropRoleStmt "DROP ROLE"
|
|
DropViewStmt "DROP VIEW statement"
|
|
DropBindingStmt "DROP BINDING statement"
|
|
DropPolicyStmt "DROP PLACEMENT POLICY statement"
|
|
DeallocateStmt "Deallocate prepared statement"
|
|
DeleteFromStmt "DELETE FROM statement"
|
|
DeleteWithoutUsingStmt "Normal DELETE statement"
|
|
DeleteWithUsingStmt "DELETE USING statement"
|
|
EmptyStmt "empty statement"
|
|
ExecuteStmt "Execute statement"
|
|
ExplainStmt "EXPLAIN statement"
|
|
ExplainableStmt "explainable statement"
|
|
FlushStmt "Flush statement"
|
|
FlashbackTableStmt "Flashback table statement"
|
|
FlashbackToTimestampStmt "Flashback cluster statement"
|
|
FlashbackDatabaseStmt "Flashback Database statement"
|
|
GrantStmt "Grant statement"
|
|
GrantProxyStmt "Grant proxy statement"
|
|
GrantRoleStmt "Grant role statement"
|
|
InsertIntoStmt "INSERT INTO statement"
|
|
CallStmt "CALL statement"
|
|
IndexAdviseStmt "INDEX ADVISE statement"
|
|
ImportIntoStmt "IMPORT INTO statement"
|
|
KillStmt "Kill statement"
|
|
LoadDataStmt "Load data statement"
|
|
LoadStatsStmt "Load statistic statement"
|
|
LockStatsStmt "Lock statistic statement"
|
|
UnlockStatsStmt "Unlock statistic statement"
|
|
LockTablesStmt "Lock tables statement"
|
|
NonTransactionalDMLStmt "Non-transactional DML statement"
|
|
PlanReplayerStmt "Plan replayer statement"
|
|
PreparedStmt "PreparedStmt"
|
|
ProcedureProcStmt "The entrance of procedure statements which contains all kinds of statements in procedure"
|
|
ProcedureStatementStmt "The normal statements in procedure, such as dml, select, set ..."
|
|
SelectStmt "SELECT statement"
|
|
SelectStmtWithClause "common table expression SELECT statement"
|
|
RenameTableStmt "rename table statement"
|
|
RenameUserStmt "rename user statement"
|
|
ReplaceIntoStmt "REPLACE INTO statement"
|
|
RecoverTableStmt "recover table statement"
|
|
RevokeStmt "Revoke statement"
|
|
RevokeRoleStmt "Revoke role statement"
|
|
RollbackStmt "ROLLBACK statement"
|
|
ReleaseSavepointStmt "RELEASE SAVEPOINT statement"
|
|
SavepointStmt "SAVEPOINT statement"
|
|
SplitRegionStmt "Split index region statement"
|
|
SetStmt "Set variable statement"
|
|
ChangeStmt "Change statement"
|
|
SetBindingStmt "Set binding statement"
|
|
SetRoleStmt "Set active role statement"
|
|
SetDefaultRoleStmt "Set default statement for some user"
|
|
ShowStmt "Show engines/databases/tables/user/columns/warnings/status statement"
|
|
Statement "statement"
|
|
TraceStmt "TRACE statement"
|
|
TraceableStmt "traceable statement"
|
|
TruncateTableStmt "TRUNCATE TABLE statement"
|
|
UnlockTablesStmt "Unlock tables statement"
|
|
UpdateStmt "UPDATE statement"
|
|
SetOprStmt "Union/Except/Intersect select statement"
|
|
SetOprStmtWithLimitOrderBy "Union/Except/Intersect select statement with limit and order by"
|
|
SetOprStmtWoutLimitOrderBy "Union/Except/Intersect select statement without limit and order by"
|
|
UseStmt "USE statement"
|
|
ShutdownStmt "SHUTDOWN statement"
|
|
RestartStmt "RESTART statement"
|
|
CreateViewSelectOpt "Select/Union/Except/Intersect statement in CREATE VIEW ... AS SELECT"
|
|
BindableStmt "Statement that can be created binding on"
|
|
UpdateStmtNoWith "Update statement without CTE clause"
|
|
HelpStmt "HELP statement"
|
|
ShardableStmt "Shardable statement that can be used in non-transactional DMLs"
|
|
PauseLoadDataStmt "PAUSE LOAD DATA JOB statement"
|
|
ResumeLoadDataStmt "RESUME LOAD DATA JOB statement"
|
|
CancelImportStmt "CANCEL IMPORT JOB statement"
|
|
DropLoadDataStmt "DROP LOAD DATA JOB statement"
|
|
ProcedureUnlabeledBlock "The statement block without label in procedure"
|
|
ProcedureBlockContent "The statement block in procedure expressed with 'Begin ... End'"
|
|
SimpleWhenThen "Procedure case when then"
|
|
SearchWhenThen "Procedure search when then"
|
|
ProcedureIfstmt "The if statement in procedure, expressed by if ... elseif .. else ... end if"
|
|
procedurceElseIfs "The else block in procedure, expressed by elseif or else or nil"
|
|
ProcedureIf "The if block in procedure, expressed by expr then statement procedurceElseIfs"
|
|
ProcedureUnlabelLoopBlock "The loop block without label in procedure "
|
|
ProcedureUnlabelLoopStmt "The loop statement in procedure, expressed by repeat/do while/loop"
|
|
ProcedureCaseStmt "Case statement in procedure, expressed by `case ... when.. then ..`"
|
|
ProcedureSimpleCase "The simpe case statement in procedure, expressed by `case expr when expr then statement ... end case`"
|
|
ProcedureSearchedCase "The searched case statement in procedure, expressed by `case when expr then statement ... end case`"
|
|
ProcedureCursorSelectStmt "The select stmt can used in procedure cursor."
|
|
ProcedureOpenCur "The open cursor statement in procedure, expressed by `open ...`"
|
|
ProcedureCloseCur "The close cursor statement in procedure, expressed by `close ...`"
|
|
ProcedureFetchInto "The fetch into statement in procedure, expressed by `fetch ... into ...`"
|
|
ProcedureHcond "The handler value statement in procedure, expressed by condition_value"
|
|
ProcedurceCond "The handler code statement in procedure, expressed by code error num or `sqlstate ...`"
|
|
ProcedureLabeledBlock "The statement block with label in procedure"
|
|
ProcedurelabeledLoopStmt "The loop block with label in procedure"
|
|
ProcedureIterate "The iterate statement in procedure, expressed by `iterate ...`"
|
|
ProcedureLeave "The leave statement in procedure, expressed by `leave ...`"
|
|
|
|
%type <item>
|
|
AdminShowSlow "Admin Show Slow statement"
|
|
AdminStmtLimitOpt "Admin show ddl jobs limit option"
|
|
AllOrPartitionNameList "All or partition name list"
|
|
AlgorithmClause "Alter table algorithm"
|
|
AlterTableSpecSingleOpt "Alter table single option"
|
|
AlterTableSpec "Alter table specification"
|
|
AlterTableSpecList "Alter table specification list"
|
|
AlterTableSpecListOpt "Alter table specification list optional"
|
|
AlterSequenceOption "Alter sequence option"
|
|
AlterSequenceOptionList "Alter sequence option list"
|
|
ArrayKwdOpt "Array options"
|
|
AnalyzeOption "Analyze option"
|
|
AnalyzeOptionList "Analyze option list"
|
|
AnalyzeOptionListOpt "Optional analyze option list"
|
|
AnyOrAll "Any or All for subquery"
|
|
Assignment "assignment"
|
|
AssignmentList "assignment list"
|
|
AssignmentListOpt "assignment list opt"
|
|
AuthOption "User auth option"
|
|
AutoRandomOpt "Auto random option"
|
|
Boolean "Boolean (0, 1, false, true)"
|
|
OptionalBraces "optional braces"
|
|
CastType "Cast function target type"
|
|
CharsetOpt "CHARACTER SET option in LOAD DATA"
|
|
ColumnDef "table column definition"
|
|
ColumnDefList "table column definition list"
|
|
ColumnName "column name"
|
|
ColumnNameOrUserVariable "column name or user variable"
|
|
ColumnNameList "column name list"
|
|
ColumnNameOrUserVariableList "column name or user variable list"
|
|
ColumnList "column list"
|
|
ColumnNameListOpt "column name list opt"
|
|
IdentList "identifier list"
|
|
IdentListWithParenOpt "column name list opt with parentheses"
|
|
ColumnNameOrUserVarListOpt "column name or user vairiabe list opt"
|
|
ColumnNameOrUserVarListOptWithBrackets "column name or user variable list opt with brackets"
|
|
ColumnSetValueList "insert statement set value by column name list"
|
|
CompareOp "Compare opcode"
|
|
ColumnOption "column definition option"
|
|
ColumnOptionList "column definition option list"
|
|
VirtualOrStored "indicate generated column is stored or not"
|
|
ColumnOptionListOpt "optional column definition option list"
|
|
CommonTableExpr "Common table expression"
|
|
CompletionTypeWithinTransaction "overwrite system variable completion_type within current transaction"
|
|
ConnectionOption "single connection options"
|
|
ConnectionOptionList "connection options for CREATE USER statement"
|
|
ConnectionOptions "optional connection options for CREATE USER statement"
|
|
Constraint "table constraint"
|
|
ConstraintElem "table constraint element"
|
|
ConstraintKeywordOpt "Constraint Keyword or empty"
|
|
CreateSequenceOptionListOpt "create sequence list opt"
|
|
CreateTableOptionListOpt "create table option list opt"
|
|
CreateTableSelectOpt "Select/Union statement in CREATE TABLE ... SELECT"
|
|
DatabaseOption "CREATE Database specification"
|
|
DatabaseOptionList "CREATE Database specification list"
|
|
DatabaseOptionListOpt "CREATE Database specification list opt"
|
|
DistinctOpt "Explicit distinct option"
|
|
DefaultFalseDistinctOpt "Distinct option which defaults to false"
|
|
DefaultTrueDistinctOpt "Distinct option which defaults to true"
|
|
BuggyDefaultFalseDistinctOpt "Distinct option which accepts DISTINCT ALL and defaults to false"
|
|
RequireClause "Encrypted connections options"
|
|
RequireClauseOpt "optional Encrypted connections options"
|
|
EqOpt "= or empty"
|
|
EscapedTableRef "escaped table reference"
|
|
ExpressionList "expression list"
|
|
ExtendedPriv "Extended privileges like LOAD FROM S3 or dynamic privileges"
|
|
MaxValueOrExpressionList "maxvalue or expression list"
|
|
DefaultOrExpressionList "default or expression list"
|
|
ExpressionListOpt "expression list opt"
|
|
FetchFirstOpt "Fetch First/Next Option"
|
|
FuncDatetimePrecListOpt "Function datetime precision list opt"
|
|
FuncDatetimePrecList "Function datetime precision list"
|
|
Field "field expression"
|
|
Fields "Fields clause"
|
|
FieldList "field expression list"
|
|
FlushOption "Flush option"
|
|
ForceOpt "Force opt"
|
|
InstanceOption "Instance option"
|
|
FulltextSearchModifierOpt "Fulltext modifier"
|
|
PluginNameList "Plugin Name List"
|
|
TableRefsClause "Table references clause"
|
|
FieldItem "Field item for load data clause"
|
|
FieldItemList "Field items for load data clause"
|
|
FirstAndLastPartOpt "First and Last partition option"
|
|
FuncDatetimePrec "Function datetime precision"
|
|
GetFormatSelector "{DATE|DATETIME|TIME|TIMESTAMP}"
|
|
GlobalScope "The scope of variable"
|
|
StatementScope "The scope of statement"
|
|
GroupByClause "GROUP BY clause"
|
|
HavingClause "HAVING clause"
|
|
AsOfClause "AS OF clause"
|
|
AsOfClauseOpt "AS OF clause optional"
|
|
HandleRange "handle range"
|
|
HandleRangeList "handle range list"
|
|
IfExists "If Exists"
|
|
IfNotExists "If Not Exists"
|
|
IgnoreOptional "IGNORE or empty"
|
|
IndexHint "index hint"
|
|
IndexHintList "index hint list"
|
|
IndexHintListOpt "index hint list opt"
|
|
IndexHintScope "index hint scope"
|
|
IndexHintType "index hint type"
|
|
IndexInvisible "index visible/invisible"
|
|
IndexKeyTypeOpt "index key type"
|
|
IndexLockAndAlgorithmOpt "index lock and algorithm"
|
|
IndexNameAndTypeOpt "index name and index type"
|
|
IndexNameList "index name list"
|
|
IndexOption "Index Option"
|
|
IndexOptionList "Index Option List or empty"
|
|
IndexType "index type"
|
|
IndexName "index name"
|
|
IndexTypeName "index type name"
|
|
IndexTypeOpt "optional index type"
|
|
IndexPartSpecification "Index column name or expression"
|
|
IndexPartSpecificationList "List of index column name or expression"
|
|
IndexPartSpecificationListOpt "Optional list of index column name or expression"
|
|
InsertValues "Rest part of INSERT/REPLACE INTO statement"
|
|
IntervalExpr "Interval expression"
|
|
JoinTable "join table"
|
|
JoinType "join type"
|
|
KillOrKillTiDB "Kill or Kill TiDB"
|
|
LocationLabelList "location label name list"
|
|
LikeTableWithOrWithoutParen "LIKE table_name or ( LIKE table_name )"
|
|
LimitClause "LIMIT clause"
|
|
LimitOption "Limit option could be integer or parameter marker."
|
|
Lines "Lines clause"
|
|
LinesTerminated "Lines terminated by"
|
|
LoadDataSetSpecOpt "Optional load data specification"
|
|
LoadDataOptionListOpt "Optional load data option list"
|
|
LoadDataOptionList "Load data option list"
|
|
LoadDataOption "Load data option"
|
|
LoadDataSetList "Load data specifications"
|
|
LoadDataSetItem "Single load data specification"
|
|
LocalOpt "Local opt"
|
|
LockClause "Alter table lock clause"
|
|
LogTypeOpt "Optional log type used in FLUSH statements"
|
|
MaxValPartOpt "MAXVALUE partition option"
|
|
NullPartOpt "NULL Partition option"
|
|
NumLiteral "Num/Int/Float/Decimal Literal"
|
|
NoWriteToBinLogAliasOpt "NO_WRITE_TO_BINLOG alias LOCAL or empty"
|
|
ObjectType "Grant statement object type"
|
|
OnDuplicateKeyUpdate "ON DUPLICATE KEY UPDATE value list"
|
|
OnCommitOpt "ON COMMIT DELETE |PRESERVE ROWS"
|
|
DuplicateOpt "[IGNORE|REPLACE] in CREATE TABLE ... SELECT statement or LOAD DATA statement"
|
|
FormatOpt "FORMAT 'SQL FILE'..."
|
|
OfTablesOpt "OF table_name [, ...]"
|
|
OptFull "Full or empty"
|
|
OptTemporary "TEMPORARY or empty"
|
|
OptOrder "Optional ordering keyword: ASC/DESC. Default to ASC"
|
|
Order "Ordering keyword: ASC or DESC"
|
|
OptionLevel "3 levels used by lightning config"
|
|
OrderBy "ORDER BY clause"
|
|
OrReplace "or replace"
|
|
ByItem "BY item"
|
|
OrderByOptional "Optional ORDER BY clause optional"
|
|
ByList "BY list"
|
|
AlterOrderItem "Alter Order item"
|
|
AlterOrderList "Alter Order list"
|
|
QuickOptional "QUICK or empty"
|
|
PartitionDefinition "Partition definition"
|
|
PartitionDefinitionList "Partition definition list"
|
|
PartitionDefinitionListOpt "Partition definition list option"
|
|
PartitionIntervalOpt "Partition interval option"
|
|
PartitionKeyAlgorithmOpt "ALGORITHM = n option for KEY partition"
|
|
PartitionMethod "Partition method"
|
|
PartitionOpt "Partition option"
|
|
PartitionNameList "Partition name list"
|
|
PartitionNameListOpt "table partition names list optional"
|
|
PartitionNumOpt "PARTITION NUM option"
|
|
PartDefValuesOpt "VALUES {LESS THAN {(expr | value_list) | MAXVALUE} | IN {value_list}"
|
|
PartDefOptionList "PartDefOption list"
|
|
PartDefOption "COMMENT [=] xxx | TABLESPACE [=] tablespace_name | ENGINE [=] xxx"
|
|
PasswordOrLockOption "Single password or lock option for create user statement"
|
|
PasswordOrLockOptionList "Password or lock options for create user statement"
|
|
PasswordOrLockOptions "Optional password or lock options for create user statement"
|
|
PlanReplayerDumpOpt "Plan Replayer Dump option"
|
|
CommentOrAttributeOption "Optional comment or attribute option for CREATE/ALTER USER statements"
|
|
ColumnPosition "Column position [First|After ColumnName]"
|
|
PrepareSQL "Prepare statement sql string"
|
|
Priority "Statement priority"
|
|
PriorityOpt "Statement priority option"
|
|
PrivElem "Privilege element"
|
|
PrivLevel "Privilege scope"
|
|
PrivType "Privilege type"
|
|
ReferDef "Reference definition"
|
|
OnDelete "ON DELETE clause"
|
|
OnUpdate "ON UPDATE clause"
|
|
OnDeleteUpdateOpt "optional ON DELETE and UPDATE clause"
|
|
OptGConcatSeparator "optional GROUP_CONCAT SEPARATOR"
|
|
ReferOpt "reference option"
|
|
ReorganizePartitionRuleOpt "optional reorganize partition partition list and definitions"
|
|
RequireList "require list for tls options"
|
|
RequireListElement "require list element for tls option"
|
|
ResourceGroupNameOption "resource group name for user"
|
|
Rolename "Rolename"
|
|
RolenameComposed "Rolename that composed with more than 1 symbol"
|
|
RolenameList "RolenameList"
|
|
RolenameWithoutIdent "Rolename except identifier"
|
|
RoleOrPrivElem "Element that may be a Rolename or PrivElem"
|
|
RoleOrPrivElemList "RoleOrPrivElem list"
|
|
RoleSpec "Rolename and auth option"
|
|
RoleSpecList "Rolename and auth option list"
|
|
RowFormat "Row format option"
|
|
RowValue "Row value"
|
|
RowStmt "Row constructor"
|
|
SelectLockOpt "SELECT lock options"
|
|
SelectStmtSQLCache "SELECT statement optional SQL_CAHCE/SQL_NO_CACHE"
|
|
SelectStmtFieldList "SELECT statement field list"
|
|
SelectStmtLimit "SELECT statement LIMIT clause"
|
|
SelectStmtLimitOpt "SELECT statement optional LIMIT clause"
|
|
SelectStmtOpt "Select statement option"
|
|
SelectStmtOpts "Select statement options"
|
|
SelectStmtOptsList "Select statement options list"
|
|
SelectStmtBasic "SELECT statement from constant value"
|
|
SelectStmtFromDualTable "SELECT statement from dual table"
|
|
SelectStmtFromTable "SELECT statement from table"
|
|
SelectStmtGroup "SELECT statement optional GROUP BY clause"
|
|
SelectStmtIntoOption "SELECT statement into clause"
|
|
SequenceOption "Create sequence option"
|
|
SequenceOptionList "Create sequence option list"
|
|
SetRoleOpt "Set role options"
|
|
SetDefaultRoleOpt "Set default role options"
|
|
SetOpr "Set operator contain UNION, EXCEPT and INTERSECT"
|
|
SetOprClause "Union/Except/Intersect select clause"
|
|
SetOprClauseList "Union/Except/Intersect select clause list"
|
|
ShowTargetFilterable "Show target that can be filtered by WHERE or LIKE"
|
|
ShowTableAliasOpt "Show table alias option"
|
|
ShowLikeOrWhereOpt "Show like or where clause option"
|
|
ShowPlacementTarget "Show placement target"
|
|
ShowProfileArgsOpt "Show profile args option"
|
|
ShowProfileTypesOpt "Show profile types option"
|
|
ShowProfileType "Show profile type"
|
|
ShowProfileTypes "Show profile types"
|
|
SplitOption "Split Option"
|
|
SplitSyntaxOption "Split syntax Option"
|
|
Starting "Starting by"
|
|
StatementList "statement list"
|
|
StatsPersistentVal "stats_persistent value"
|
|
StatsType "stats type value"
|
|
BindingStatusType "binding status type value"
|
|
StringList "string list"
|
|
SubPartDefinition "SubPartition definition"
|
|
SubPartDefinitionList "SubPartition definition list"
|
|
SubPartDefinitionListOpt "SubPartition definition list optional"
|
|
SubPartitionMethod "SubPartition method"
|
|
SubPartitionOpt "SubPartition option"
|
|
SubPartitionNumOpt "SubPartition NUM option"
|
|
TableAliasRefList "table alias reference list"
|
|
TableAsName "table alias name"
|
|
TableAsNameOpt "table alias name optional"
|
|
TableElement "table definition element"
|
|
TableElementList "table definition element list"
|
|
TableElementListOpt "table definition element list optional"
|
|
TableFactor "table factor"
|
|
TableLock "Table name and lock type"
|
|
TableLockList "Table lock list"
|
|
TableName "Table name"
|
|
TableNameOptWild "Table name with optional wildcard"
|
|
TableNameList "Table name list"
|
|
TableNameListOpt "Table name list opt"
|
|
TableNameListOpt2 "Optional table name list with a preceding TABLE"
|
|
TableOption "create table option"
|
|
TableOptionList "create table option list"
|
|
TableRef "table reference"
|
|
TableRefs "table references"
|
|
TableSampleOpt "table sample clause optional"
|
|
TableSampleMethodOpt "table sample method optional"
|
|
TableSampleUnitOpt "table sample unit optional"
|
|
TableToTable "rename table to table"
|
|
TableToTableList "rename table to table by list"
|
|
TextString "text string item"
|
|
TextStringList "text string list"
|
|
TimeUnit "Time unit for 'DATE_ADD', 'DATE_SUB', 'ADDDATE', 'SUBDATE', 'EXTRACT'"
|
|
TimestampUnit "Time unit for 'TIMESTAMPADD' and 'TIMESTAMPDIFF'"
|
|
LockType "Table locks type"
|
|
TransactionChar "Transaction characteristic"
|
|
TransactionChars "Transaction characteristic list"
|
|
TrimDirection "Trim string direction"
|
|
SetOprOpt "Union/Except/Intersect Option(empty/ALL/DISTINCT)"
|
|
Username "Username"
|
|
UsernameList "UsernameList"
|
|
UserSpec "Username and auth option"
|
|
UserSpecList "Username and auth option list"
|
|
UserVariableList "User defined variable name list"
|
|
UserToUser "rename user to user"
|
|
UserToUserList "rename user to user by list"
|
|
UsingRoles "UsingRoles is role option for SHOW GRANT"
|
|
Values "values"
|
|
ValuesList "values list"
|
|
ValuesOpt "values optional"
|
|
ValuesStmtList "VALUES statement field list"
|
|
VariableAssignment "set variable value"
|
|
VariableAssignmentList "set variable value list"
|
|
ViewAlgorithm "view algorithm"
|
|
ViewCheckOption "view check option"
|
|
ViewDefiner "view definer"
|
|
ViewName "view name"
|
|
ViewFieldList "create view statement field list"
|
|
ViewSQLSecurity "view sql security"
|
|
WhereClause "WHERE clause"
|
|
WhereClauseOptional "Optional WHERE clause"
|
|
WhenClause "When clause"
|
|
WhenClauseList "When clause list"
|
|
WithClustered "With Clustered Index Enabled"
|
|
WithClause "With Clause"
|
|
WithList "With list"
|
|
WithReadLockOpt "With Read Lock opt"
|
|
WithGrantOptionOpt "With Grant Option opt"
|
|
WithValidation "with validation"
|
|
WithValidationOpt "optional with validation"
|
|
Writeable "Table writeable status"
|
|
ElseOpt "Optional else clause"
|
|
Type "Types"
|
|
OptExistingWindowName "Optional existing WINDOW name"
|
|
OptFromFirstLast "Optional FROM FIRST/LAST"
|
|
OptLLDefault "Optional LEAD/LAG default"
|
|
OptLeadLagInfo "Optional LEAD/LAG info"
|
|
OptNullTreatment "Optional NULL treatment"
|
|
OptPartitionClause "Optional PARTITION clause"
|
|
OptWild "Optional Wildcard"
|
|
OptWindowOrderByClause "Optional ORDER BY clause in WINDOW"
|
|
OptWindowFrameClause "Optional FRAME clause in WINDOW"
|
|
OptWindowingClause "Optional OVER clause"
|
|
WindowingClause "OVER clause"
|
|
WindowClauseOptional "Optional WINDOW clause"
|
|
WindowDefinitionList "WINDOW definition list"
|
|
WindowDefinition "WINDOW definition"
|
|
WindowFrameUnits "WINDOW frame units"
|
|
WindowFrameBetween "WINDOW frame between"
|
|
WindowFrameBound "WINDOW frame bound"
|
|
WindowFrameExtent "WINDOW frame extent"
|
|
WindowFrameStart "WINDOW frame start"
|
|
WindowName "WINDOW name"
|
|
WindowNameOrSpec "WINDOW name or spec"
|
|
WindowSpec "WINDOW spec"
|
|
WindowSpecDetails "WINDOW spec details"
|
|
WithRollupClause "With rollup clause"
|
|
BetweenOrNotOp "Between predicate"
|
|
IsOrNotOp "Is predicate"
|
|
InOrNotOp "In predicate"
|
|
LikeOrNotOp "Like predicate"
|
|
IlikeOrNotOp "Ilike predicate"
|
|
RegexpOrNotOp "Regexp predicate"
|
|
NumericType "Numeric types"
|
|
IntegerType "Integer Types types"
|
|
BooleanType "Boolean Types types"
|
|
FixedPointType "Exact value types"
|
|
FloatingPointType "Approximate value types"
|
|
BitValueType "bit value types"
|
|
StringType "String types"
|
|
BlobType "Blob types"
|
|
TextType "Text types"
|
|
DateAndTimeType "Date and Time types"
|
|
OptFieldLen "Field length or empty"
|
|
FieldLen "Field length"
|
|
FieldOpts "Field type definition option list"
|
|
FieldOpt "Field type definition option"
|
|
FloatOpt "Floating-point type option"
|
|
Precision "Floating-point precision option"
|
|
OptBinary "Optional BINARY"
|
|
OptBinMod "Optional BINARY mode"
|
|
OptCharsetWithOptBinary "Optional BINARY or ASCII or UNICODE or BYTE"
|
|
IgnoreLines "Ignore num(int) lines"
|
|
Int64Num "a number that can be safely converted to int64"
|
|
NUM "A number"
|
|
NumList "Some numbers"
|
|
LengthNum "Field length num(uint64)"
|
|
SignedNum "Signed num(int64)"
|
|
TableOptimizerHints "Table level optimizer hints"
|
|
TableOptimizerHintsOpt "Table level optimizer hints option"
|
|
EnforcedOrNot "{ENFORCED|NOT ENFORCED}"
|
|
EnforcedOrNotOpt "Optional {ENFORCED|NOT ENFORCED}"
|
|
EnforcedOrNotOrNotNullOpt "{[ENFORCED|NOT ENFORCED|NOT NULL]}"
|
|
Match "[MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]"
|
|
MatchOpt "optional MATCH clause"
|
|
MaxMinutesOpt "MAX_MINUTES num(int)"
|
|
MaxIndexNumOpt "MAX_IDXNUM clause"
|
|
PerTable "Max index number PER_TABLE"
|
|
PerDB "Max index number PER_DB"
|
|
BRIETables "List of tables or databases for BRIE statements"
|
|
DBNameList "List of database names"
|
|
BRIEOption "Single BRIE option"
|
|
BRIEOptions "List of BRIE options"
|
|
BRIEIntegerOptionName "Name of a BRIE option which takes an integer as input"
|
|
BRIEBooleanOptionName "Name of a BRIE option which takes a boolean as input"
|
|
BRIEStringOptionName "Name of a BRIE option which takes a string as input"
|
|
BRIEKeywordOptionName "Name of a BRIE option which takes a case-insensitive string as input"
|
|
PlacementPolicyOption "Anonymous or placement policy option"
|
|
DirectPlacementOption "Subset of anonymous or direct placement option"
|
|
PlacementOptionList "Anomymous or direct placement option list"
|
|
DirectResourceGroupBackgroundOption "Subset of direct resource group background option"
|
|
DirectResourceGroupRunawayOption "Subset of anonymous or direct resource group runaway option"
|
|
ResourceGroupBackgroundOptionList "Direct resource group background option list"
|
|
ResourceGroupRunawayActionOption "Resource group runaway action option"
|
|
ResourceGroupRunawayWatchOption "Resource group runaway watch option"
|
|
ResourceGroupRunawayOptionList "Anomymous or direct resource group runaway option list"
|
|
WatchDurationOption "Runaway watch duration option"
|
|
DirectResourceGroupOption "Subset of anonymous or direct resource group option"
|
|
ResourceGroupOptionList "Anomymous or direct resource group option list"
|
|
ResourceGroupPriorityOption "Resource group priority option"
|
|
DynamicCalibrateResourceOption "Dynamic resource calibrate option"
|
|
CalibrateOption "Dynamic or static calibrate option"
|
|
DynamicCalibrateOptionList "Anomymous or direct dynamic resource calibrate option list"
|
|
CalibrateResourceWorkloadOption "Calibrate Resource workload option"
|
|
QueryWatchOptionList "Query watch option list"
|
|
QueryWatchOption "Query watch option"
|
|
QueryWatchTextOption "Query watch text option"
|
|
AttributesOpt "Attributes options"
|
|
AllColumnsOrPredicateColumnsOpt "all columns or predicate columns option"
|
|
StatsOptionsOpt "Stats options"
|
|
DryRunOptions "Dry run options"
|
|
OptionalShardColumn "Optional shard column"
|
|
SpOptInout "Optional procedure param type"
|
|
OptSpPdparams "Optional procedure param list"
|
|
SpPdparams "Procedure params"
|
|
SpPdparam "Procedure param"
|
|
ProcedureOptDefault "Optional procedure variable default value"
|
|
ProcedureProcStmts "Procedure statement list"
|
|
ProcedureProcStmt1s "One more procedure statement"
|
|
ProcedureDecl "Procedure variable statement"
|
|
ProcedureDecls "Procedure variable statements"
|
|
ProcedureDeclsOpt "Optional procedure variable statements"
|
|
ProcedureDeclIdents "Procedure variable name identifiers"
|
|
SimpleWhenThenList "Procedure case WhenThen list"
|
|
SearchedWhenThenList "Procedure search WhenThen list"
|
|
ElseCaseOpt "Optional procedure else statement, expressed by `else .../nil`"
|
|
ProcedureFetchList "Procedure fetch into variables"
|
|
ProcedureHandlerType "Procedure handler operation type"
|
|
ProcedureHcondList "Procedure handler condition value list"
|
|
|
|
%type <ident>
|
|
AsOpt "AS or EmptyString"
|
|
KeyOrIndex "{KEY|INDEX}"
|
|
ColumnKeywordOpt "Column keyword or empty"
|
|
PrimaryOpt "Optional primary keyword"
|
|
NowSym "CURRENT_TIMESTAMP/LOCALTIME/LOCALTIMESTAMP"
|
|
NowSymFunc "CURRENT_TIMESTAMP/LOCALTIME/LOCALTIMESTAMP/NOW"
|
|
CurdateSym "CURDATE or CURRENT_DATE"
|
|
DefaultKwdOpt "optional DEFAULT keyword"
|
|
DatabaseSym "DATABASE or SCHEMA"
|
|
ExplainSym "EXPLAIN or DESCRIBE or DESC"
|
|
RegexpSym "REGEXP or RLIKE"
|
|
IntoOpt "INTO or EmptyString"
|
|
ValueSym "Value or Values"
|
|
NotSym "Not token"
|
|
Char "{CHAR|CHARACTER}"
|
|
NChar "{NCHAR|NATIONAL CHARACTER|NATIONAL CHAR}"
|
|
Varchar "{VARCHAR|VARCHARACTER|CHARACTER VARYING|CHAR VARYING}"
|
|
NVarchar "{NATIONAL VARCHAR|NATIONAL VARCHARACTER|NVARCHAR|NCHAR VARCHAR|NATIONAL CHARACTER VARYING|NATIONAL CHAR VARYING|NCHAR VARYING}"
|
|
Year "{YEAR|SQL_TSI_YEAR}"
|
|
DeallocateSym "Deallocate or drop"
|
|
OuterOpt "optional OUTER clause"
|
|
CrossOpt "Cross join option"
|
|
TablesTerminalSym "{TABLE|TABLES}"
|
|
IsolationLevel "Isolation level"
|
|
ShowIndexKwd "Show index/indexs/key keyword"
|
|
DistinctKwd "DISTINCT/DISTINCTROW keyword"
|
|
FromOrIn "From or In"
|
|
OptTable "Optional table keyword"
|
|
OptInteger "Optional Integer keyword"
|
|
CharsetKw "charset or charater set"
|
|
CommaOpt "optional comma"
|
|
logAnd "logical and operator"
|
|
logOr "logical or operator"
|
|
LinearOpt "linear or empty"
|
|
FieldsOrColumns "Fields or columns"
|
|
StorageMedia "{DISK|MEMORY|DEFAULT}"
|
|
EncryptionOpt "Encryption option 'Y' or 'N'"
|
|
FirstOrNext "FIRST or NEXT"
|
|
RowOrRows "ROW or ROWS"
|
|
|
|
%type <ident>
|
|
Identifier "identifier or unreserved keyword"
|
|
NotKeywordToken "Tokens not mysql keyword but treated specially"
|
|
UnReservedKeyword "MySQL unreserved keywords"
|
|
TiDBKeyword "TiDB added keywords"
|
|
FunctionNameConflict "Built-in function call names which are conflict with keywords"
|
|
FunctionNameOptionalBraces "Function with optional braces, all of them are reserved keywords."
|
|
FunctionNameDatetimePrecision "Function with optional datetime precision, all of them are reserved keywords."
|
|
FunctionNameDateArith "Date arith function call names (date_add or date_sub)"
|
|
FunctionNameDateArithMultiForms "Date arith function call names (adddate or subdate)"
|
|
VariableName "A simple Identifier like xx or the xx.xx form"
|
|
ConfigItemName "A config item like aa or aa.bb or aa.bb-cc.dd"
|
|
AuthString "Password string value"
|
|
AuthPlugin "Authentication plugin name"
|
|
CharsetName "Character set name"
|
|
CollationName "Collation name"
|
|
ColumnFormat "Column format"
|
|
DBName "Database Name"
|
|
PolicyName "Placement Policy Name"
|
|
ResourceGroupName "Resource Group Name"
|
|
ExplainFormatType "explain format type"
|
|
FieldAsName "Field alias name"
|
|
FieldAsNameOpt "Field alias name opt"
|
|
FieldTerminator "Field terminator"
|
|
FlashbackToNewName "Flashback to new name"
|
|
HashString "Hashed string"
|
|
LikeOrIlikeEscapeOpt "like or ilike escape option"
|
|
OptCharset "Optional Character setting"
|
|
OptCollate "Optional Collate setting"
|
|
PasswordOpt "Password option"
|
|
RoleNameString "role name string"
|
|
ShowDatabaseNameOpt "Show tables/columns statement database name option"
|
|
StringName "string literal or identifier"
|
|
StringNameOrBRIEOptionKeyword "string literal or identifier or keyword used for BRIE options"
|
|
Symbol "Constraint Symbol"
|
|
ProcedurceLabelOpt "Optional Procedure label name"
|
|
|
|
%precedence empty
|
|
%precedence as
|
|
%precedence placement
|
|
%precedence lowerThanSelectOpt
|
|
%precedence sqlBufferResult
|
|
%precedence sqlBigResult
|
|
%precedence sqlSmallResult
|
|
%precedence sqlCache sqlNoCache
|
|
%precedence next
|
|
%precedence lowerThanValueKeyword
|
|
%precedence value
|
|
%precedence lowerThanWith
|
|
%precedence with
|
|
%precedence lowerThanStringLitToken
|
|
%precedence stringLit
|
|
%precedence lowerThanSetKeyword
|
|
%precedence set
|
|
%precedence selectKwd
|
|
%precedence lowerThanSelectStmt
|
|
%precedence lowerThanInsertValues
|
|
%precedence insertValues
|
|
%precedence lowerThanCreateTableSelect
|
|
%precedence createTableSelect
|
|
%precedence lowerThanCharsetKwd
|
|
%precedence charsetKwd
|
|
%precedence lowerThanKey
|
|
%precedence key
|
|
%precedence lowerThanLocal
|
|
%precedence local
|
|
%precedence lowerThanRemove
|
|
%precedence remove
|
|
%precedence lowerThenOrder
|
|
%precedence order
|
|
%precedence lowerThanFunction
|
|
%precedence function
|
|
|
|
/* A dummy token to force the priority of TableRef production in a join. */
|
|
%left tableRefPriority
|
|
%precedence lowerThanParenthese
|
|
%right '('
|
|
%left ')'
|
|
%precedence higherThanParenthese
|
|
%left join straightJoin inner cross left right full natural
|
|
%precedence lowerThanOn
|
|
%precedence on using
|
|
%right assignmentEq
|
|
%left pipes or pipesAsOr
|
|
%left xor
|
|
%left andand and
|
|
%left between
|
|
%precedence lowerThanEq
|
|
%left eq ge le neq neqSynonym '>' '<' is like ilike in
|
|
%left '|'
|
|
%left '&'
|
|
%left rsh lsh
|
|
%left '-' '+'
|
|
%left '*' '/' '%' div mod
|
|
%left '^'
|
|
%left '~' neg
|
|
%precedence lowerThanNot
|
|
%right not not2
|
|
%right collate
|
|
%left interval
|
|
%right encryption
|
|
%left labels
|
|
%precedence quick
|
|
%precedence escape
|
|
%precedence lowerThanComma
|
|
%precedence ','
|
|
%precedence higherThanComma
|
|
|
|
%start Start
|
|
|
|
%%
|
|
|
|
Start:
|
|
StatementList
|
|
|
|
/**************************************AlterTableStmt***************************************
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/alter-table.html
|
|
*******************************************************************************************/
|
|
AlterTableStmt:
|
|
"ALTER" IgnoreOptional "TABLE" TableName AlterTableSpecListOpt AlterTableSpecSingleOpt
|
|
{
|
|
specs := $5.([]*ast.AlterTableSpec)
|
|
if $6 != nil {
|
|
specs = append(specs, $6.(*ast.AlterTableSpec))
|
|
}
|
|
$$ = &ast.AlterTableStmt{
|
|
Table: $4.(*ast.TableName),
|
|
Specs: specs,
|
|
}
|
|
}
|
|
| "ALTER" IgnoreOptional "TABLE" TableName "ANALYZE" "PARTITION" PartitionNameList AnalyzeOptionListOpt
|
|
{
|
|
$$ = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{$4.(*ast.TableName)}, PartitionNames: $7.([]model.CIStr), AnalyzeOpts: $8.([]ast.AnalyzeOpt)}
|
|
}
|
|
| "ALTER" IgnoreOptional "TABLE" TableName "ANALYZE" "PARTITION" PartitionNameList "INDEX" IndexNameList AnalyzeOptionListOpt
|
|
{
|
|
$$ = &ast.AnalyzeTableStmt{
|
|
TableNames: []*ast.TableName{$4.(*ast.TableName)},
|
|
PartitionNames: $7.([]model.CIStr),
|
|
IndexNames: $9.([]model.CIStr),
|
|
IndexFlag: true,
|
|
AnalyzeOpts: $10.([]ast.AnalyzeOpt),
|
|
}
|
|
}
|
|
| "ALTER" IgnoreOptional "TABLE" TableName "COMPACT"
|
|
{
|
|
$$ = &ast.CompactTableStmt{
|
|
Table: $4.(*ast.TableName),
|
|
ReplicaKind: ast.CompactReplicaKindAll,
|
|
}
|
|
}
|
|
| "ALTER" IgnoreOptional "TABLE" TableName "COMPACT" "TIFLASH" "REPLICA"
|
|
{
|
|
$$ = &ast.CompactTableStmt{
|
|
Table: $4.(*ast.TableName),
|
|
ReplicaKind: ast.CompactReplicaKindTiFlash,
|
|
}
|
|
}
|
|
| "ALTER" IgnoreOptional "TABLE" TableName "COMPACT" "PARTITION" PartitionNameList
|
|
{
|
|
$$ = &ast.CompactTableStmt{
|
|
Table: $4.(*ast.TableName),
|
|
PartitionNames: $7.([]model.CIStr),
|
|
ReplicaKind: ast.CompactReplicaKindAll,
|
|
}
|
|
}
|
|
| "ALTER" IgnoreOptional "TABLE" TableName "COMPACT" "PARTITION" PartitionNameList "TIFLASH" "REPLICA"
|
|
{
|
|
$$ = &ast.CompactTableStmt{
|
|
Table: $4.(*ast.TableName),
|
|
PartitionNames: $7.([]model.CIStr),
|
|
ReplicaKind: ast.CompactReplicaKindTiFlash,
|
|
}
|
|
}
|
|
|
|
ResourceGroupOptionList:
|
|
DirectResourceGroupOption
|
|
{
|
|
$$ = []*ast.ResourceGroupOption{$1.(*ast.ResourceGroupOption)}
|
|
}
|
|
| ResourceGroupOptionList DirectResourceGroupOption
|
|
{
|
|
if !ast.CheckAppend($1.([]*ast.ResourceGroupOption), $2.(*ast.ResourceGroupOption)) {
|
|
yylex.AppendError(yylex.Errorf("Dupliated options specified"))
|
|
return 1
|
|
}
|
|
$$ = append($1.([]*ast.ResourceGroupOption), $2.(*ast.ResourceGroupOption))
|
|
}
|
|
| ResourceGroupOptionList ',' DirectResourceGroupOption
|
|
{
|
|
if !ast.CheckAppend($1.([]*ast.ResourceGroupOption), $3.(*ast.ResourceGroupOption)) {
|
|
yylex.AppendError(yylex.Errorf("Dupliated options specified"))
|
|
return 1
|
|
}
|
|
$$ = append($1.([]*ast.ResourceGroupOption), $3.(*ast.ResourceGroupOption))
|
|
}
|
|
|
|
ResourceGroupPriorityOption:
|
|
"LOW"
|
|
{
|
|
$$ = uint64(1)
|
|
}
|
|
| "MEDIUM"
|
|
{
|
|
$$ = uint64(8)
|
|
}
|
|
| "HIGH"
|
|
{
|
|
$$ = uint64(16)
|
|
}
|
|
|
|
ResourceGroupRunawayOptionList:
|
|
DirectResourceGroupRunawayOption
|
|
{
|
|
$$ = []*ast.ResourceGroupRunawayOption{$1.(*ast.ResourceGroupRunawayOption)}
|
|
}
|
|
| ResourceGroupRunawayOptionList DirectResourceGroupRunawayOption
|
|
{
|
|
if !ast.CheckRunawayAppend($1.([]*ast.ResourceGroupRunawayOption), $2.(*ast.ResourceGroupRunawayOption)) {
|
|
yylex.AppendError(yylex.Errorf("Dupliated runaway options specified"))
|
|
return 1
|
|
}
|
|
$$ = append($1.([]*ast.ResourceGroupRunawayOption), $2.(*ast.ResourceGroupRunawayOption))
|
|
}
|
|
| ResourceGroupRunawayOptionList ',' DirectResourceGroupRunawayOption
|
|
{
|
|
if !ast.CheckRunawayAppend($1.([]*ast.ResourceGroupRunawayOption), $3.(*ast.ResourceGroupRunawayOption)) {
|
|
yylex.AppendError(yylex.Errorf("Dupliated runaway options specified"))
|
|
return 1
|
|
}
|
|
$$ = append($1.([]*ast.ResourceGroupRunawayOption), $3.(*ast.ResourceGroupRunawayOption))
|
|
}
|
|
|
|
ResourceGroupRunawayWatchOption:
|
|
"EXACT"
|
|
{
|
|
$$ = int32(model.WatchExact)
|
|
}
|
|
| "SIMILAR"
|
|
{
|
|
$$ = int32(model.WatchSimilar)
|
|
}
|
|
| "PLAN"
|
|
{
|
|
$$ = int32(model.WatchPlan)
|
|
}
|
|
|
|
ResourceGroupRunawayActionOption:
|
|
"DRYRUN"
|
|
{
|
|
$$ = int32(model.RunawayActionDryRun)
|
|
}
|
|
| "COOLDOWN"
|
|
{
|
|
$$ = int32(model.RunawayActionCooldown)
|
|
}
|
|
| "KILL"
|
|
{
|
|
$$ = int32(model.RunawayActionKill)
|
|
}
|
|
|
|
DirectResourceGroupRunawayOption:
|
|
"EXEC_ELAPSED" EqOpt stringLit
|
|
{
|
|
_, err := time.ParseDuration($3)
|
|
if err != nil {
|
|
yylex.AppendError(yylex.Errorf("The EXEC_ELAPSED option is not a valid duration: %s", err.Error()))
|
|
return 1
|
|
}
|
|
$$ = &ast.ResourceGroupRunawayOption{Tp: ast.RunawayRule, StrValue: $3}
|
|
}
|
|
| "ACTION" EqOpt ResourceGroupRunawayActionOption
|
|
{
|
|
$$ = &ast.ResourceGroupRunawayOption{Tp: ast.RunawayAction, IntValue: $3.(int32)}
|
|
}
|
|
| "WATCH" EqOpt ResourceGroupRunawayWatchOption WatchDurationOption
|
|
{
|
|
dur := strings.ToLower($4.(string))
|
|
if dur == "unlimited" {
|
|
dur = ""
|
|
}
|
|
if len(dur) > 0 {
|
|
_, err := time.ParseDuration(dur)
|
|
if err != nil {
|
|
yylex.AppendError(yylex.Errorf("The WATCH DURATION option is not a valid duration: %s", err.Error()))
|
|
return 1
|
|
}
|
|
}
|
|
$$ = &ast.ResourceGroupRunawayOption{Tp: ast.RunawayWatch, StrValue: dur, IntValue: $3.(int32)}
|
|
}
|
|
|
|
WatchDurationOption:
|
|
{
|
|
$$ = ""
|
|
}
|
|
| "DURATION" EqOpt stringLit
|
|
{
|
|
$$ = $3
|
|
}
|
|
| "DURATION" EqOpt "UNLIMITED"
|
|
{
|
|
$$ = ""
|
|
}
|
|
|
|
DirectResourceGroupOption:
|
|
"RU_PER_SEC" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.ResourceGroupOption{Tp: ast.ResourceRURate, UintValue: $3.(uint64)}
|
|
}
|
|
| "PRIORITY" EqOpt ResourceGroupPriorityOption
|
|
{
|
|
$$ = &ast.ResourceGroupOption{Tp: ast.ResourcePriority, UintValue: $3.(uint64)}
|
|
}
|
|
| "BURSTABLE"
|
|
{
|
|
$$ = &ast.ResourceGroupOption{Tp: ast.ResourceBurstableOpiton, BoolValue: true}
|
|
}
|
|
| "BURSTABLE" EqOpt Boolean
|
|
{
|
|
$$ = &ast.ResourceGroupOption{Tp: ast.ResourceBurstableOpiton, BoolValue: $3.(bool)}
|
|
}
|
|
| "QUERY_LIMIT" EqOpt '(' ResourceGroupRunawayOptionList ')'
|
|
{
|
|
$$ = &ast.ResourceGroupOption{Tp: ast.ResourceGroupRunaway, RunawayOptionList: $4.([]*ast.ResourceGroupRunawayOption)}
|
|
}
|
|
| "QUERY_LIMIT" EqOpt '(' ')'
|
|
{
|
|
$$ = &ast.ResourceGroupOption{Tp: ast.ResourceGroupRunaway, RunawayOptionList: nil}
|
|
}
|
|
| "QUERY_LIMIT" EqOpt "NULL"
|
|
{
|
|
$$ = &ast.ResourceGroupOption{Tp: ast.ResourceGroupRunaway, RunawayOptionList: nil}
|
|
}
|
|
| "BACKGROUND" EqOpt '(' ResourceGroupBackgroundOptionList ')'
|
|
{
|
|
$$ = &ast.ResourceGroupOption{Tp: ast.ResourceGroupBackground, BackgroundOptions: $4.([]*ast.ResourceGroupBackgroundOption)}
|
|
}
|
|
| "BACKGROUND" EqOpt '(' ')'
|
|
{
|
|
$$ = &ast.ResourceGroupOption{Tp: ast.ResourceGroupBackground, BackgroundOptions: nil}
|
|
}
|
|
| "BACKGROUND" EqOpt "NULL"
|
|
{
|
|
$$ = &ast.ResourceGroupOption{Tp: ast.ResourceGroupBackground, BackgroundOptions: nil}
|
|
}
|
|
|
|
ResourceGroupBackgroundOptionList:
|
|
DirectResourceGroupBackgroundOption
|
|
{
|
|
$$ = []*ast.ResourceGroupBackgroundOption{$1.(*ast.ResourceGroupBackgroundOption)}
|
|
}
|
|
| ResourceGroupBackgroundOptionList DirectResourceGroupBackgroundOption
|
|
{
|
|
if !ast.CheckBackgroundAppend($1.([]*ast.ResourceGroupBackgroundOption), $2.(*ast.ResourceGroupBackgroundOption)) {
|
|
yylex.AppendError(yylex.Errorf("Dupliated background options specified"))
|
|
return 1
|
|
}
|
|
$$ = append($1.([]*ast.ResourceGroupBackgroundOption), $2.(*ast.ResourceGroupBackgroundOption))
|
|
}
|
|
| ResourceGroupBackgroundOptionList ',' DirectResourceGroupBackgroundOption
|
|
{
|
|
if !ast.CheckBackgroundAppend($1.([]*ast.ResourceGroupBackgroundOption), $3.(*ast.ResourceGroupBackgroundOption)) {
|
|
yylex.AppendError(yylex.Errorf("Dupliated background options specified"))
|
|
return 1
|
|
}
|
|
$$ = append($1.([]*ast.ResourceGroupBackgroundOption), $3.(*ast.ResourceGroupBackgroundOption))
|
|
}
|
|
|
|
DirectResourceGroupBackgroundOption:
|
|
"TASK_TYPES" EqOpt stringLit
|
|
{
|
|
$$ = &ast.ResourceGroupBackgroundOption{Type: ast.BackgroundOptionTaskNames, StrValue: $3}
|
|
}
|
|
|
|
PlacementOptionList:
|
|
DirectPlacementOption
|
|
{
|
|
$$ = []*ast.PlacementOption{$1.(*ast.PlacementOption)}
|
|
}
|
|
| PlacementOptionList DirectPlacementOption
|
|
{
|
|
$$ = append($1.([]*ast.PlacementOption), $2.(*ast.PlacementOption))
|
|
}
|
|
| PlacementOptionList ',' DirectPlacementOption
|
|
{
|
|
$$ = append($1.([]*ast.PlacementOption), $3.(*ast.PlacementOption))
|
|
}
|
|
|
|
DirectPlacementOption:
|
|
"PRIMARY_REGION" EqOpt stringLit
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionPrimaryRegion, StrValue: $3}
|
|
}
|
|
| "REGIONS" EqOpt stringLit
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionRegions, StrValue: $3}
|
|
}
|
|
| "FOLLOWERS" EqOpt LengthNum
|
|
{
|
|
cnt := $3.(uint64)
|
|
if cnt == 0 {
|
|
yylex.AppendError(yylex.Errorf("FOLLOWERS must be positive"))
|
|
return 1
|
|
}
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionFollowerCount, UintValue: cnt}
|
|
}
|
|
| "VOTERS" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionVoterCount, UintValue: $3.(uint64)}
|
|
}
|
|
| "LEARNERS" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionLearnerCount, UintValue: $3.(uint64)}
|
|
}
|
|
| "SCHEDULE" EqOpt stringLit
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionSchedule, StrValue: $3}
|
|
}
|
|
| "CONSTRAINTS" EqOpt stringLit
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionConstraints, StrValue: $3}
|
|
}
|
|
| "LEADER_CONSTRAINTS" EqOpt stringLit
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionLeaderConstraints, StrValue: $3}
|
|
}
|
|
| "FOLLOWER_CONSTRAINTS" EqOpt stringLit
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionFollowerConstraints, StrValue: $3}
|
|
}
|
|
| "VOTER_CONSTRAINTS" EqOpt stringLit
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionVoterConstraints, StrValue: $3}
|
|
}
|
|
| "LEARNER_CONSTRAINTS" EqOpt stringLit
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionLearnerConstraints, StrValue: $3}
|
|
}
|
|
| "SURVIVAL_PREFERENCES" EqOpt stringLit
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionSurvivalPreferences, StrValue: $3}
|
|
}
|
|
|
|
PlacementPolicyOption:
|
|
"PLACEMENT" "POLICY" EqOpt stringLit
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionPolicy, StrValue: $4}
|
|
}
|
|
| "PLACEMENT" "POLICY" EqOpt PolicyName
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionPolicy, StrValue: $4}
|
|
}
|
|
| "PLACEMENT" "POLICY" EqOpt "DEFAULT"
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionPolicy, StrValue: $4}
|
|
}
|
|
| "PLACEMENT" "POLICY" "SET" "DEFAULT"
|
|
{
|
|
$$ = &ast.PlacementOption{Tp: ast.PlacementOptionPolicy, StrValue: $4}
|
|
}
|
|
|
|
AttributesOpt:
|
|
"ATTRIBUTES" EqOpt "DEFAULT"
|
|
{
|
|
$$ = &ast.AttributesSpec{Default: true}
|
|
}
|
|
| "ATTRIBUTES" EqOpt stringLit
|
|
{
|
|
$$ = &ast.AttributesSpec{Default: false, Attributes: $3}
|
|
}
|
|
|
|
StatsOptionsOpt:
|
|
"STATS_OPTIONS" EqOpt "DEFAULT"
|
|
{
|
|
$$ = &ast.StatsOptionsSpec{Default: true}
|
|
}
|
|
| "STATS_OPTIONS" EqOpt stringLit
|
|
{
|
|
$$ = &ast.StatsOptionsSpec{Default: false, StatsOptions: $3}
|
|
}
|
|
|
|
// Some spec can only have one, but not in a list
|
|
AlterTableSpecSingleOpt:
|
|
PartitionOpt
|
|
{
|
|
if $1 != nil {
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTablePartition,
|
|
Partition: $1.(*ast.PartitionOptions),
|
|
}
|
|
} else {
|
|
$$ = nil
|
|
}
|
|
}
|
|
| "REMOVE" "PARTITIONING"
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableRemovePartitioning,
|
|
}
|
|
}
|
|
| "REORGANIZE" "PARTITION" NoWriteToBinLogAliasOpt ReorganizePartitionRuleOpt
|
|
{
|
|
ret := $4.(*ast.AlterTableSpec)
|
|
ret.NoWriteToBinlog = $3.(bool)
|
|
$$ = ret
|
|
}
|
|
| "SPLIT" "MAXVALUE" "PARTITION" "LESS" "THAN" '(' BitExpr ')'
|
|
{
|
|
partitionMethod := ast.PartitionMethod{Expr: $7}
|
|
startOffset := parser.yyVAL.offset
|
|
endOffset := parser.yylval.offset
|
|
partitionMethod.SetText(parser.lexer.client, parser.src[startOffset:endOffset])
|
|
partitionMethod.SetOriginTextPosition(startOffset)
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableReorganizeLastPartition,
|
|
Partition: &ast.PartitionOptions{PartitionMethod: partitionMethod},
|
|
}
|
|
}
|
|
| "MERGE" "FIRST" "PARTITION" "LESS" "THAN" '(' BitExpr ')'
|
|
{
|
|
partitionMethod := ast.PartitionMethod{Expr: $7}
|
|
startOffset := parser.yyVAL.offset
|
|
endOffset := parser.yylval.offset
|
|
partitionMethod.SetText(parser.lexer.client, parser.src[startOffset:endOffset])
|
|
// Needed for replacing syntactic sugar with generated partitioning definition string
|
|
partitionMethod.SetOriginTextPosition(startOffset)
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableReorganizeFirstPartition,
|
|
Partition: &ast.PartitionOptions{PartitionMethod: partitionMethod},
|
|
}
|
|
}
|
|
| "PARTITION" Identifier AttributesOpt
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTablePartitionAttributes,
|
|
PartitionNames: []model.CIStr{model.NewCIStr($2)},
|
|
AttributesSpec: $3.(*ast.AttributesSpec),
|
|
}
|
|
}
|
|
| "PARTITION" Identifier PartDefOptionList
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTablePartitionOptions,
|
|
PartitionNames: []model.CIStr{model.NewCIStr($2)},
|
|
Options: $3.([]*ast.TableOption),
|
|
}
|
|
}
|
|
| "REMOVE" "TTL"
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableRemoveTTL,
|
|
}
|
|
}
|
|
|
|
LocationLabelList:
|
|
{
|
|
$$ = []string{}
|
|
}
|
|
| "LOCATION" "LABELS" StringList
|
|
{
|
|
$$ = $3
|
|
}
|
|
|
|
AlterTableSpec:
|
|
TableOptionList %prec higherThanComma
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableOption,
|
|
Options: $1.([]*ast.TableOption),
|
|
}
|
|
}
|
|
| "SET" "TIFLASH" "REPLICA" LengthNum LocationLabelList
|
|
{
|
|
tiflashReplicaSpec := &ast.TiFlashReplicaSpec{
|
|
Count: $4.(uint64),
|
|
Labels: $5.([]string),
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableSetTiFlashReplica,
|
|
TiFlashReplica: tiflashReplicaSpec,
|
|
}
|
|
}
|
|
| "SET" "HYPO" "TIFLASH" "REPLICA" LengthNum LocationLabelList
|
|
{
|
|
tiflashReplicaSpec := &ast.TiFlashReplicaSpec{
|
|
Count: $5.(uint64),
|
|
Labels: $6.([]string),
|
|
Hypo: true,
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableSetTiFlashReplica,
|
|
TiFlashReplica: tiflashReplicaSpec,
|
|
}
|
|
}
|
|
| "CONVERT" "TO" CharsetKw CharsetName OptCollate
|
|
{
|
|
op := &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableOption,
|
|
Options: []*ast.TableOption{{Tp: ast.TableOptionCharset, StrValue: $4,
|
|
UintValue: ast.TableOptionCharsetWithConvertTo}},
|
|
}
|
|
if $5 != "" {
|
|
op.Options = append(op.Options, &ast.TableOption{Tp: ast.TableOptionCollate, StrValue: $5})
|
|
}
|
|
$$ = op
|
|
}
|
|
| "CONVERT" "TO" CharsetKw "DEFAULT" OptCollate
|
|
{
|
|
op := &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableOption,
|
|
Options: []*ast.TableOption{{Tp: ast.TableOptionCharset, Default: true,
|
|
UintValue: ast.TableOptionCharsetWithConvertTo}},
|
|
}
|
|
if $5 != "" {
|
|
op.Options = append(op.Options, &ast.TableOption{Tp: ast.TableOptionCollate, StrValue: $5})
|
|
}
|
|
$$ = op
|
|
}
|
|
| "ADD" ColumnKeywordOpt IfNotExists ColumnDef ColumnPosition
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
IfNotExists: $3.(bool),
|
|
Tp: ast.AlterTableAddColumns,
|
|
NewColumns: []*ast.ColumnDef{$4.(*ast.ColumnDef)},
|
|
Position: $5.(*ast.ColumnPosition),
|
|
}
|
|
}
|
|
| "ADD" ColumnKeywordOpt IfNotExists '(' TableElementList ')'
|
|
{
|
|
tes := $5.([]interface{})
|
|
var columnDefs []*ast.ColumnDef
|
|
var constraints []*ast.Constraint
|
|
for _, te := range tes {
|
|
switch te := te.(type) {
|
|
case *ast.ColumnDef:
|
|
columnDefs = append(columnDefs, te)
|
|
case *ast.Constraint:
|
|
constraints = append(constraints, te)
|
|
}
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
IfNotExists: $3.(bool),
|
|
Tp: ast.AlterTableAddColumns,
|
|
NewColumns: columnDefs,
|
|
NewConstraints: constraints,
|
|
}
|
|
}
|
|
| "ADD" Constraint
|
|
{
|
|
constraint := $2.(*ast.Constraint)
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableAddConstraint,
|
|
Constraint: constraint,
|
|
}
|
|
}
|
|
| "ADD" "PARTITION" IfNotExists NoWriteToBinLogAliasOpt PartitionDefinitionListOpt
|
|
{
|
|
var defs []*ast.PartitionDefinition
|
|
if $5 != nil {
|
|
defs = $5.([]*ast.PartitionDefinition)
|
|
}
|
|
noWriteToBinlog := $4.(bool)
|
|
if noWriteToBinlog {
|
|
yylex.AppendError(yylex.Errorf("The NO_WRITE_TO_BINLOG option is parsed but ignored for now."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
IfNotExists: $3.(bool),
|
|
NoWriteToBinlog: noWriteToBinlog,
|
|
Tp: ast.AlterTableAddPartitions,
|
|
PartDefinitions: defs,
|
|
}
|
|
}
|
|
| "ADD" "PARTITION" IfNotExists NoWriteToBinLogAliasOpt "PARTITIONS" NUM
|
|
{
|
|
noWriteToBinlog := $4.(bool)
|
|
if noWriteToBinlog {
|
|
yylex.AppendError(yylex.Errorf("The NO_WRITE_TO_BINLOG option is parsed but ignored for now."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
IfNotExists: $3.(bool),
|
|
NoWriteToBinlog: noWriteToBinlog,
|
|
Tp: ast.AlterTableAddPartitions,
|
|
Num: getUint64FromNUM($6),
|
|
}
|
|
}
|
|
| "LAST" "PARTITION" "LESS" "THAN" '(' BitExpr ')' NoWriteToBinLogAliasOpt
|
|
{
|
|
noWriteToBinlog := $8.(bool)
|
|
if noWriteToBinlog {
|
|
yylex.AppendError(yylex.Errorf("The NO_WRITE_TO_BINLOG option is parsed but ignored for now."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
partitionMethod := ast.PartitionMethod{Expr: $6}
|
|
startOffset := parser.yyVAL.offset
|
|
endOffset := parser.yylval.offset
|
|
partitionMethod.SetText(parser.lexer.client, parser.src[startOffset:endOffset])
|
|
// Needed for replacing syntactic sugar with generated partitioning definition string
|
|
partitionMethod.SetOriginTextPosition(startOffset)
|
|
$$ = &ast.AlterTableSpec{
|
|
NoWriteToBinlog: noWriteToBinlog,
|
|
Tp: ast.AlterTableAddLastPartition,
|
|
Partition: &ast.PartitionOptions{PartitionMethod: partitionMethod},
|
|
}
|
|
}
|
|
| "ADD" "STATS_EXTENDED" IfNotExists Identifier StatsType '(' ColumnNameList ')'
|
|
{
|
|
statsSpec := &ast.StatisticsSpec{
|
|
StatsName: $4,
|
|
StatsType: $5.(uint8),
|
|
Columns: $7.([]*ast.ColumnName),
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableAddStatistics,
|
|
IfNotExists: $3.(bool),
|
|
Statistics: statsSpec,
|
|
}
|
|
}
|
|
| AttributesOpt
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableAttributes,
|
|
AttributesSpec: $1.(*ast.AttributesSpec),
|
|
}
|
|
}
|
|
| StatsOptionsOpt
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableStatsOptions,
|
|
StatsOptionsSpec: $1.(*ast.StatsOptionsSpec),
|
|
}
|
|
}
|
|
| "CHECK" "PARTITION" AllOrPartitionNameList
|
|
{
|
|
yylex.AppendError(yylex.Errorf("The CHECK PARTITIONING clause is parsed but not implement yet."))
|
|
parser.lastErrorAsWarn()
|
|
ret := &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableCheckPartitions,
|
|
}
|
|
if $3 == nil {
|
|
ret.OnAllPartitions = true
|
|
} else {
|
|
ret.PartitionNames = $3.([]model.CIStr)
|
|
}
|
|
$$ = ret
|
|
}
|
|
| "COALESCE" "PARTITION" NoWriteToBinLogAliasOpt NUM
|
|
{
|
|
noWriteToBinlog := $3.(bool)
|
|
if noWriteToBinlog {
|
|
yylex.AppendError(yylex.Errorf("The NO_WRITE_TO_BINLOG option is parsed but ignored for now."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableCoalescePartitions,
|
|
NoWriteToBinlog: noWriteToBinlog,
|
|
Num: getUint64FromNUM($4),
|
|
}
|
|
}
|
|
| "DROP" ColumnKeywordOpt IfExists ColumnName RestrictOrCascadeOpt
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
IfExists: $3.(bool),
|
|
Tp: ast.AlterTableDropColumn,
|
|
OldColumnName: $4.(*ast.ColumnName),
|
|
}
|
|
}
|
|
| "DROP" "PRIMARY" "KEY"
|
|
{
|
|
$$ = &ast.AlterTableSpec{Tp: ast.AlterTableDropPrimaryKey}
|
|
}
|
|
| "DROP" "PARTITION" IfExists PartitionNameList %prec lowerThanComma
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
IfExists: $3.(bool),
|
|
Tp: ast.AlterTableDropPartition,
|
|
PartitionNames: $4.([]model.CIStr),
|
|
}
|
|
}
|
|
| "FIRST" "PARTITION" "LESS" "THAN" '(' BitExpr ')' IfExists
|
|
{
|
|
partitionMethod := ast.PartitionMethod{Expr: $6}
|
|
startOffset := parser.yyVAL.offset
|
|
endOffset := parser.yylval.offset
|
|
partitionMethod.SetText(parser.lexer.client, parser.src[startOffset:endOffset])
|
|
// Needed for replacing syntactic sugar with generated partitioning definition string
|
|
partitionMethod.SetOriginTextPosition(startOffset)
|
|
$$ = &ast.AlterTableSpec{
|
|
IfExists: $8.(bool),
|
|
Tp: ast.AlterTableDropFirstPartition,
|
|
Partition: &ast.PartitionOptions{PartitionMethod: partitionMethod},
|
|
}
|
|
}
|
|
| "DROP" "STATS_EXTENDED" IfExists Identifier
|
|
{
|
|
statsSpec := &ast.StatisticsSpec{
|
|
StatsName: $4,
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableDropStatistics,
|
|
IfExists: $3.(bool),
|
|
Statistics: statsSpec,
|
|
}
|
|
}
|
|
| "EXCHANGE" "PARTITION" Identifier "WITH" "TABLE" TableName WithValidationOpt
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableExchangePartition,
|
|
PartitionNames: []model.CIStr{model.NewCIStr($3)},
|
|
NewTable: $6.(*ast.TableName),
|
|
WithValidation: $7.(bool),
|
|
}
|
|
}
|
|
| "TRUNCATE" "PARTITION" AllOrPartitionNameList
|
|
{
|
|
ret := &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableTruncatePartition,
|
|
}
|
|
if $3 == nil {
|
|
ret.OnAllPartitions = true
|
|
} else {
|
|
ret.PartitionNames = $3.([]model.CIStr)
|
|
}
|
|
$$ = ret
|
|
}
|
|
| "OPTIMIZE" "PARTITION" NoWriteToBinLogAliasOpt AllOrPartitionNameList
|
|
{
|
|
ret := &ast.AlterTableSpec{
|
|
NoWriteToBinlog: $3.(bool),
|
|
Tp: ast.AlterTableOptimizePartition,
|
|
}
|
|
if $4 == nil {
|
|
ret.OnAllPartitions = true
|
|
} else {
|
|
ret.PartitionNames = $4.([]model.CIStr)
|
|
}
|
|
$$ = ret
|
|
}
|
|
| "REPAIR" "PARTITION" NoWriteToBinLogAliasOpt AllOrPartitionNameList
|
|
{
|
|
ret := &ast.AlterTableSpec{
|
|
NoWriteToBinlog: $3.(bool),
|
|
Tp: ast.AlterTableRepairPartition,
|
|
}
|
|
if $4 == nil {
|
|
ret.OnAllPartitions = true
|
|
} else {
|
|
ret.PartitionNames = $4.([]model.CIStr)
|
|
}
|
|
$$ = ret
|
|
}
|
|
| "IMPORT" "PARTITION" AllOrPartitionNameList "TABLESPACE"
|
|
{
|
|
ret := &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableImportPartitionTablespace,
|
|
}
|
|
if $3 == nil {
|
|
ret.OnAllPartitions = true
|
|
} else {
|
|
ret.PartitionNames = $3.([]model.CIStr)
|
|
}
|
|
$$ = ret
|
|
yylex.AppendError(yylex.Errorf("The IMPORT PARTITION TABLESPACE clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "DISCARD" "PARTITION" AllOrPartitionNameList "TABLESPACE"
|
|
{
|
|
ret := &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableDiscardPartitionTablespace,
|
|
}
|
|
if $3 == nil {
|
|
ret.OnAllPartitions = true
|
|
} else {
|
|
ret.PartitionNames = $3.([]model.CIStr)
|
|
}
|
|
$$ = ret
|
|
yylex.AppendError(yylex.Errorf("The DISCARD PARTITION TABLESPACE clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "IMPORT" "TABLESPACE"
|
|
{
|
|
ret := &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableImportTablespace,
|
|
}
|
|
$$ = ret
|
|
yylex.AppendError(yylex.Errorf("The IMPORT TABLESPACE clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "DISCARD" "TABLESPACE"
|
|
{
|
|
ret := &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableDiscardTablespace,
|
|
}
|
|
$$ = ret
|
|
yylex.AppendError(yylex.Errorf("The DISCARD TABLESPACE clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "REBUILD" "PARTITION" NoWriteToBinLogAliasOpt AllOrPartitionNameList
|
|
{
|
|
ret := &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableRebuildPartition,
|
|
NoWriteToBinlog: $3.(bool),
|
|
}
|
|
if $4 == nil {
|
|
ret.OnAllPartitions = true
|
|
} else {
|
|
ret.PartitionNames = $4.([]model.CIStr)
|
|
}
|
|
$$ = ret
|
|
}
|
|
| "DROP" KeyOrIndex IfExists Identifier
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
IfExists: $3.(bool),
|
|
Tp: ast.AlterTableDropIndex,
|
|
Name: $4,
|
|
}
|
|
}
|
|
| "DROP" "FOREIGN" "KEY" IfExists Symbol
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
IfExists: $4.(bool),
|
|
Tp: ast.AlterTableDropForeignKey,
|
|
Name: $5,
|
|
}
|
|
}
|
|
| "ORDER" "BY" AlterOrderList %prec lowerThenOrder
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableOrderByColumns,
|
|
OrderByList: $3.([]*ast.AlterOrderItem),
|
|
}
|
|
}
|
|
| "DISABLE" "KEYS"
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableDisableKeys,
|
|
}
|
|
}
|
|
| "ENABLE" "KEYS"
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableEnableKeys,
|
|
}
|
|
}
|
|
| "MODIFY" ColumnKeywordOpt IfExists ColumnDef ColumnPosition
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
IfExists: $3.(bool),
|
|
Tp: ast.AlterTableModifyColumn,
|
|
NewColumns: []*ast.ColumnDef{$4.(*ast.ColumnDef)},
|
|
Position: $5.(*ast.ColumnPosition),
|
|
}
|
|
}
|
|
| "CHANGE" ColumnKeywordOpt IfExists ColumnName ColumnDef ColumnPosition
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
IfExists: $3.(bool),
|
|
Tp: ast.AlterTableChangeColumn,
|
|
OldColumnName: $4.(*ast.ColumnName),
|
|
NewColumns: []*ast.ColumnDef{$5.(*ast.ColumnDef)},
|
|
Position: $6.(*ast.ColumnPosition),
|
|
}
|
|
}
|
|
| "ALTER" ColumnKeywordOpt ColumnName "SET" "DEFAULT" SignedLiteral
|
|
{
|
|
option := &ast.ColumnOption{Expr: $6}
|
|
colDef := &ast.ColumnDef{
|
|
Name: $3.(*ast.ColumnName),
|
|
Options: []*ast.ColumnOption{option},
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableAlterColumn,
|
|
NewColumns: []*ast.ColumnDef{colDef},
|
|
}
|
|
}
|
|
| "ALTER" ColumnKeywordOpt ColumnName "SET" "DEFAULT" '(' Expression ')'
|
|
{
|
|
option := &ast.ColumnOption{Expr: $7}
|
|
colDef := &ast.ColumnDef{
|
|
Name: $3.(*ast.ColumnName),
|
|
Options: []*ast.ColumnOption{option},
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableAlterColumn,
|
|
NewColumns: []*ast.ColumnDef{colDef},
|
|
}
|
|
}
|
|
| "ALTER" ColumnKeywordOpt ColumnName "DROP" "DEFAULT"
|
|
{
|
|
colDef := &ast.ColumnDef{
|
|
Name: $3.(*ast.ColumnName),
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableAlterColumn,
|
|
NewColumns: []*ast.ColumnDef{colDef},
|
|
}
|
|
}
|
|
| "RENAME" "COLUMN" Identifier "TO" Identifier
|
|
{
|
|
oldColName := &ast.ColumnName{Name: model.NewCIStr($3)}
|
|
newColName := &ast.ColumnName{Name: model.NewCIStr($5)}
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableRenameColumn,
|
|
OldColumnName: oldColName,
|
|
NewColumnName: newColName,
|
|
}
|
|
}
|
|
| "RENAME" "TO" TableName
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableRenameTable,
|
|
NewTable: $3.(*ast.TableName),
|
|
}
|
|
}
|
|
| "RENAME" EqOpt TableName
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableRenameTable,
|
|
NewTable: $3.(*ast.TableName),
|
|
}
|
|
}
|
|
| "RENAME" "AS" TableName
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableRenameTable,
|
|
NewTable: $3.(*ast.TableName),
|
|
}
|
|
}
|
|
| "RENAME" KeyOrIndex Identifier "TO" Identifier
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableRenameIndex,
|
|
FromKey: model.NewCIStr($3),
|
|
ToKey: model.NewCIStr($5),
|
|
}
|
|
}
|
|
| LockClause
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableLock,
|
|
LockType: $1.(ast.LockType),
|
|
}
|
|
}
|
|
| Writeable
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableWriteable,
|
|
Writeable: $1.(bool),
|
|
}
|
|
}
|
|
| AlgorithmClause
|
|
{
|
|
// Parse it and ignore it. Just for compatibility.
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableAlgorithm,
|
|
Algorithm: $1.(ast.AlgorithmType),
|
|
}
|
|
}
|
|
| "FORCE"
|
|
{
|
|
// Parse it and ignore it. Just for compatibility.
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableForce,
|
|
}
|
|
}
|
|
| "WITH" "VALIDATION"
|
|
{
|
|
// Parse it and ignore it. Just for compatibility.
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableWithValidation,
|
|
}
|
|
}
|
|
| "WITHOUT" "VALIDATION"
|
|
{
|
|
// Parse it and ignore it. Just for compatibility.
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableWithoutValidation,
|
|
}
|
|
}
|
|
// Added in MySQL 8.0.13, see: https://dev.mysql.com/doc/refman/8.0/en/keywords.html for details
|
|
| "SECONDARY_LOAD"
|
|
{
|
|
// Parse it and ignore it. Just for compatibility.
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableSecondaryLoad,
|
|
}
|
|
yylex.AppendError(yylex.Errorf("The SECONDARY_LOAD clause is parsed but not implement yet."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
// Added in MySQL 8.0.13, see: https://dev.mysql.com/doc/refman/8.0/en/keywords.html for details
|
|
| "SECONDARY_UNLOAD"
|
|
{
|
|
// Parse it and ignore it. Just for compatibility.
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableSecondaryUnload,
|
|
}
|
|
yylex.AppendError(yylex.Errorf("The SECONDARY_UNLOAD VALIDATION clause is parsed but not implement yet."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "ALTER" CheckConstraintKeyword Identifier EnforcedOrNot
|
|
{
|
|
c := &ast.Constraint{
|
|
Name: $3,
|
|
Enforced: $4.(bool),
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableAlterCheck,
|
|
Constraint: c,
|
|
}
|
|
}
|
|
| "DROP" CheckConstraintKeyword Identifier
|
|
{
|
|
// Parse it and ignore it. Just for compatibility.
|
|
c := &ast.Constraint{
|
|
Name: $3,
|
|
}
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableDropCheck,
|
|
Constraint: c,
|
|
}
|
|
}
|
|
| "ALTER" "INDEX" Identifier IndexInvisible
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableIndexInvisible,
|
|
IndexName: model.NewCIStr($3),
|
|
Visibility: $4.(ast.IndexVisibility),
|
|
}
|
|
}
|
|
// Support caching or non-caching a table in memory for tidb, It can be found in the official Oracle document, see: https://docs.oracle.com/database/121/SQLRF/statements_3001.htm
|
|
| "CACHE"
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableCache,
|
|
}
|
|
}
|
|
| "NOCACHE"
|
|
{
|
|
$$ = &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableNoCache,
|
|
}
|
|
}
|
|
|
|
ReorganizePartitionRuleOpt:
|
|
/* empty */ %prec lowerThanRemove
|
|
{
|
|
ret := &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableReorganizePartition,
|
|
OnAllPartitions: true,
|
|
}
|
|
$$ = ret
|
|
}
|
|
| PartitionNameList "INTO" '(' PartitionDefinitionList ')'
|
|
{
|
|
ret := &ast.AlterTableSpec{
|
|
Tp: ast.AlterTableReorganizePartition,
|
|
PartitionNames: $1.([]model.CIStr),
|
|
PartDefinitions: $4.([]*ast.PartitionDefinition),
|
|
}
|
|
$$ = ret
|
|
}
|
|
|
|
AllOrPartitionNameList:
|
|
"ALL"
|
|
{
|
|
$$ = nil
|
|
}
|
|
| PartitionNameList %prec lowerThanComma
|
|
|
|
WithValidationOpt:
|
|
{
|
|
$$ = true
|
|
}
|
|
| WithValidation
|
|
|
|
WithValidation:
|
|
"WITH" "VALIDATION"
|
|
{
|
|
$$ = true
|
|
}
|
|
| "WITHOUT" "VALIDATION"
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
WithClustered:
|
|
"CLUSTERED"
|
|
{
|
|
$$ = model.PrimaryKeyTypeClustered
|
|
}
|
|
| "NONCLUSTERED"
|
|
{
|
|
$$ = model.PrimaryKeyTypeNonClustered
|
|
}
|
|
|
|
AlgorithmClause:
|
|
"ALGORITHM" EqOpt "DEFAULT"
|
|
{
|
|
$$ = ast.AlgorithmTypeDefault
|
|
}
|
|
| "ALGORITHM" EqOpt "COPY"
|
|
{
|
|
$$ = ast.AlgorithmTypeCopy
|
|
}
|
|
| "ALGORITHM" EqOpt "INPLACE"
|
|
{
|
|
$$ = ast.AlgorithmTypeInplace
|
|
}
|
|
| "ALGORITHM" EqOpt "INSTANT"
|
|
{
|
|
$$ = ast.AlgorithmTypeInstant
|
|
}
|
|
| "ALGORITHM" EqOpt identifier
|
|
{
|
|
yylex.AppendError(ErrUnknownAlterAlgorithm.GenWithStackByArgs($1))
|
|
return 1
|
|
}
|
|
|
|
LockClause:
|
|
"LOCK" EqOpt "DEFAULT"
|
|
{
|
|
$$ = ast.LockTypeDefault
|
|
}
|
|
| "LOCK" EqOpt Identifier
|
|
{
|
|
id := strings.ToUpper($3)
|
|
|
|
if id == "NONE" {
|
|
$$ = ast.LockTypeNone
|
|
} else if id == "SHARED" {
|
|
$$ = ast.LockTypeShared
|
|
} else if id == "EXCLUSIVE" {
|
|
$$ = ast.LockTypeExclusive
|
|
} else {
|
|
yylex.AppendError(ErrUnknownAlterLock.GenWithStackByArgs($3))
|
|
return 1
|
|
}
|
|
}
|
|
|
|
Writeable:
|
|
"READ" "WRITE"
|
|
{
|
|
$$ = true
|
|
}
|
|
| "READ" "ONLY"
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
KeyOrIndex:
|
|
"KEY"
|
|
| "INDEX"
|
|
|
|
KeyOrIndexOpt:
|
|
{}
|
|
| KeyOrIndex
|
|
|
|
ColumnKeywordOpt:
|
|
/* empty */ %prec empty
|
|
{}
|
|
| "COLUMN"
|
|
|
|
ColumnPosition:
|
|
{
|
|
$$ = &ast.ColumnPosition{Tp: ast.ColumnPositionNone}
|
|
}
|
|
| "FIRST"
|
|
{
|
|
$$ = &ast.ColumnPosition{Tp: ast.ColumnPositionFirst}
|
|
}
|
|
| "AFTER" ColumnName
|
|
{
|
|
$$ = &ast.ColumnPosition{
|
|
Tp: ast.ColumnPositionAfter,
|
|
RelativeColumn: $2.(*ast.ColumnName),
|
|
}
|
|
}
|
|
|
|
AlterTableSpecListOpt:
|
|
/* empty */
|
|
{
|
|
$$ = make([]*ast.AlterTableSpec, 0, 1)
|
|
}
|
|
| AlterTableSpecList
|
|
|
|
AlterTableSpecList:
|
|
AlterTableSpec
|
|
{
|
|
$$ = []*ast.AlterTableSpec{$1.(*ast.AlterTableSpec)}
|
|
}
|
|
| AlterTableSpecList ',' AlterTableSpec
|
|
{
|
|
$$ = append($1.([]*ast.AlterTableSpec), $3.(*ast.AlterTableSpec))
|
|
}
|
|
|
|
PartitionNameList:
|
|
Identifier
|
|
{
|
|
$$ = []model.CIStr{model.NewCIStr($1)}
|
|
}
|
|
| PartitionNameList ',' Identifier
|
|
{
|
|
$$ = append($1.([]model.CIStr), model.NewCIStr($3))
|
|
}
|
|
|
|
ConstraintKeywordOpt:
|
|
/* empty */ %prec empty
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "CONSTRAINT"
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "CONSTRAINT" Symbol
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
Symbol:
|
|
Identifier
|
|
|
|
/**************************************RenameTableStmt***************************************
|
|
* See http://dev.mysql.com/doc/refman/5.7/en/rename-table.html
|
|
*
|
|
* RENAME TABLE
|
|
* tbl_name TO new_tbl_name
|
|
* [, tbl_name2 TO new_tbl_name2] ...
|
|
*******************************************************************************************/
|
|
RenameTableStmt:
|
|
"RENAME" "TABLE" TableToTableList
|
|
{
|
|
$$ = &ast.RenameTableStmt{
|
|
TableToTables: $3.([]*ast.TableToTable),
|
|
}
|
|
}
|
|
|
|
TableToTableList:
|
|
TableToTable
|
|
{
|
|
$$ = []*ast.TableToTable{$1.(*ast.TableToTable)}
|
|
}
|
|
| TableToTableList ',' TableToTable
|
|
{
|
|
$$ = append($1.([]*ast.TableToTable), $3.(*ast.TableToTable))
|
|
}
|
|
|
|
TableToTable:
|
|
TableName "TO" TableName
|
|
{
|
|
$$ = &ast.TableToTable{
|
|
OldTable: $1.(*ast.TableName),
|
|
NewTable: $3.(*ast.TableName),
|
|
}
|
|
}
|
|
|
|
/**************************************RenameUserStmt***************************************
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/rename-user.html
|
|
*
|
|
* RENAME USER
|
|
* old_user TO new_user
|
|
* [, old_user2 TO new_user2] ...
|
|
*******************************************************************************************/
|
|
RenameUserStmt:
|
|
"RENAME" "USER" UserToUserList
|
|
{
|
|
$$ = &ast.RenameUserStmt{
|
|
UserToUsers: $3.([]*ast.UserToUser),
|
|
}
|
|
}
|
|
|
|
UserToUserList:
|
|
UserToUser
|
|
{
|
|
$$ = []*ast.UserToUser{$1.(*ast.UserToUser)}
|
|
}
|
|
| UserToUserList ',' UserToUser
|
|
{
|
|
$$ = append($1.([]*ast.UserToUser), $3.(*ast.UserToUser))
|
|
}
|
|
|
|
UserToUser:
|
|
Username "TO" Username
|
|
{
|
|
$$ = &ast.UserToUser{
|
|
OldUser: $1.(*auth.UserIdentity),
|
|
NewUser: $3.(*auth.UserIdentity),
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Recover Table Statement
|
|
*
|
|
* Example:
|
|
* RECOVER TABLE t1;
|
|
* RECOVER TABLE BY JOB 100;
|
|
*
|
|
*******************************************************************/
|
|
RecoverTableStmt:
|
|
"RECOVER" "TABLE" "BY" "JOB" Int64Num
|
|
{
|
|
$$ = &ast.RecoverTableStmt{
|
|
JobID: $5.(int64),
|
|
}
|
|
}
|
|
| "RECOVER" "TABLE" TableName
|
|
{
|
|
$$ = &ast.RecoverTableStmt{
|
|
Table: $3.(*ast.TableName),
|
|
}
|
|
}
|
|
| "RECOVER" "TABLE" TableName Int64Num
|
|
{
|
|
$$ = &ast.RecoverTableStmt{
|
|
Table: $3.(*ast.TableName),
|
|
JobNum: $4.(int64),
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
*
|
|
* FLASHBACK [CLUSTER | DATABASE | TABLE] TO TIMESTAMP
|
|
*
|
|
* Example:
|
|
*
|
|
*******************************************************************/
|
|
FlashbackToTimestampStmt:
|
|
"FLASHBACK" "CLUSTER" toTimestamp stringLit
|
|
{
|
|
$$ = &ast.FlashBackToTimestampStmt{
|
|
FlashbackTS: ast.NewValueExpr($4, "", ""),
|
|
}
|
|
}
|
|
| "FLASHBACK" "TABLE" TableNameList toTimestamp stringLit
|
|
{
|
|
$$ = &ast.FlashBackToTimestampStmt{
|
|
Tables: $3.([]*ast.TableName),
|
|
FlashbackTS: ast.NewValueExpr($5, "", ""),
|
|
}
|
|
}
|
|
| "FLASHBACK" DatabaseSym DBName toTimestamp stringLit
|
|
{
|
|
$$ = &ast.FlashBackToTimestampStmt{
|
|
DBName: model.NewCIStr($3),
|
|
FlashbackTS: ast.NewValueExpr($5, "", ""),
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Flush Back Table Statement
|
|
*
|
|
* Example:
|
|
*
|
|
*******************************************************************/
|
|
FlashbackTableStmt:
|
|
"FLASHBACK" "TABLE" TableName FlashbackToNewName
|
|
{
|
|
$$ = &ast.FlashBackTableStmt{
|
|
Table: $3.(*ast.TableName),
|
|
NewName: $4,
|
|
}
|
|
}
|
|
|
|
FlashbackToNewName:
|
|
{
|
|
$$ = ""
|
|
}
|
|
| "TO" Identifier
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Flush Back Database Statement
|
|
*
|
|
* Example:
|
|
* FLASHBACK DATABASE/SCHEMA DBName TO newDBName
|
|
*
|
|
*******************************************************************/
|
|
FlashbackDatabaseStmt:
|
|
"FLASHBACK" DatabaseSym DBName FlashbackToNewName
|
|
{
|
|
$$ = &ast.FlashBackDatabaseStmt{
|
|
DBName: model.NewCIStr($3),
|
|
NewName: $4,
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Split index region statement
|
|
*
|
|
* Example:
|
|
* SPLIT TABLE table_name INDEX index_name BY (val1...),(val2...)...
|
|
*
|
|
*******************************************************************/
|
|
SplitRegionStmt:
|
|
"SPLIT" SplitSyntaxOption "TABLE" TableName PartitionNameListOpt SplitOption
|
|
{
|
|
$$ = &ast.SplitRegionStmt{
|
|
SplitSyntaxOpt: $2.(*ast.SplitSyntaxOption),
|
|
Table: $4.(*ast.TableName),
|
|
PartitionNames: $5.([]model.CIStr),
|
|
SplitOpt: $6.(*ast.SplitOption),
|
|
}
|
|
}
|
|
| "SPLIT" SplitSyntaxOption "TABLE" TableName PartitionNameListOpt "INDEX" Identifier SplitOption
|
|
{
|
|
$$ = &ast.SplitRegionStmt{
|
|
SplitSyntaxOpt: $2.(*ast.SplitSyntaxOption),
|
|
Table: $4.(*ast.TableName),
|
|
PartitionNames: $5.([]model.CIStr),
|
|
IndexName: model.NewCIStr($7),
|
|
SplitOpt: $8.(*ast.SplitOption),
|
|
}
|
|
}
|
|
|
|
SplitOption:
|
|
"BETWEEN" RowValue "AND" RowValue "REGIONS" Int64Num
|
|
{
|
|
$$ = &ast.SplitOption{
|
|
Lower: $2.([]ast.ExprNode),
|
|
Upper: $4.([]ast.ExprNode),
|
|
Num: $6.(int64),
|
|
}
|
|
}
|
|
| "BY" ValuesList
|
|
{
|
|
$$ = &ast.SplitOption{
|
|
ValueLists: $2.([][]ast.ExprNode),
|
|
}
|
|
}
|
|
|
|
SplitSyntaxOption:
|
|
/* empty */
|
|
{
|
|
$$ = &ast.SplitSyntaxOption{}
|
|
}
|
|
| "REGION" "FOR"
|
|
{
|
|
$$ = &ast.SplitSyntaxOption{
|
|
HasRegionFor: true,
|
|
}
|
|
}
|
|
| "PARTITION"
|
|
{
|
|
$$ = &ast.SplitSyntaxOption{
|
|
HasPartition: true,
|
|
}
|
|
}
|
|
| "REGION" "FOR" "PARTITION"
|
|
{
|
|
$$ = &ast.SplitSyntaxOption{
|
|
HasRegionFor: true,
|
|
HasPartition: true,
|
|
}
|
|
}
|
|
|
|
AnalyzeTableStmt:
|
|
"ANALYZE" "TABLE" TableNameList AllColumnsOrPredicateColumnsOpt AnalyzeOptionListOpt
|
|
{
|
|
$$ = &ast.AnalyzeTableStmt{TableNames: $3.([]*ast.TableName), ColumnChoice: $4.(model.ColumnChoice), AnalyzeOpts: $5.([]ast.AnalyzeOpt)}
|
|
}
|
|
| "ANALYZE" "TABLE" TableName "INDEX" IndexNameList AnalyzeOptionListOpt
|
|
{
|
|
$$ = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{$3.(*ast.TableName)}, IndexNames: $5.([]model.CIStr), IndexFlag: true, AnalyzeOpts: $6.([]ast.AnalyzeOpt)}
|
|
}
|
|
| "ANALYZE" "INCREMENTAL" "TABLE" TableName "INDEX" IndexNameList AnalyzeOptionListOpt
|
|
{
|
|
$$ = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{$4.(*ast.TableName)}, IndexNames: $6.([]model.CIStr), IndexFlag: true, Incremental: true, AnalyzeOpts: $7.([]ast.AnalyzeOpt)}
|
|
}
|
|
| "ANALYZE" "TABLE" TableName "PARTITION" PartitionNameList AllColumnsOrPredicateColumnsOpt AnalyzeOptionListOpt
|
|
{
|
|
$$ = &ast.AnalyzeTableStmt{TableNames: []*ast.TableName{$3.(*ast.TableName)}, PartitionNames: $5.([]model.CIStr), ColumnChoice: $6.(model.ColumnChoice), AnalyzeOpts: $7.([]ast.AnalyzeOpt)}
|
|
}
|
|
| "ANALYZE" "TABLE" TableName "PARTITION" PartitionNameList "INDEX" IndexNameList AnalyzeOptionListOpt
|
|
{
|
|
$$ = &ast.AnalyzeTableStmt{
|
|
TableNames: []*ast.TableName{$3.(*ast.TableName)},
|
|
PartitionNames: $5.([]model.CIStr),
|
|
IndexNames: $7.([]model.CIStr),
|
|
IndexFlag: true,
|
|
AnalyzeOpts: $8.([]ast.AnalyzeOpt),
|
|
}
|
|
}
|
|
| "ANALYZE" "INCREMENTAL" "TABLE" TableName "PARTITION" PartitionNameList "INDEX" IndexNameList AnalyzeOptionListOpt
|
|
{
|
|
$$ = &ast.AnalyzeTableStmt{
|
|
TableNames: []*ast.TableName{$4.(*ast.TableName)},
|
|
PartitionNames: $6.([]model.CIStr),
|
|
IndexNames: $8.([]model.CIStr),
|
|
IndexFlag: true,
|
|
Incremental: true,
|
|
AnalyzeOpts: $9.([]ast.AnalyzeOpt),
|
|
}
|
|
}
|
|
| "ANALYZE" "TABLE" TableName "UPDATE" "HISTOGRAM" "ON" IdentList AnalyzeOptionListOpt
|
|
{
|
|
$$ = &ast.AnalyzeTableStmt{
|
|
TableNames: []*ast.TableName{$3.(*ast.TableName)},
|
|
ColumnNames: $7.([]model.CIStr),
|
|
AnalyzeOpts: $8.([]ast.AnalyzeOpt),
|
|
HistogramOperation: ast.HistogramOperationUpdate,
|
|
}
|
|
}
|
|
| "ANALYZE" "TABLE" TableName "DROP" "HISTOGRAM" "ON" IdentList
|
|
{
|
|
$$ = &ast.AnalyzeTableStmt{
|
|
TableNames: []*ast.TableName{$3.(*ast.TableName)},
|
|
ColumnNames: $7.([]model.CIStr),
|
|
HistogramOperation: ast.HistogramOperationDrop,
|
|
}
|
|
}
|
|
| "ANALYZE" "TABLE" TableName "COLUMNS" IdentList AnalyzeOptionListOpt
|
|
{
|
|
$$ = &ast.AnalyzeTableStmt{
|
|
TableNames: []*ast.TableName{$3.(*ast.TableName)},
|
|
ColumnNames: $5.([]model.CIStr),
|
|
ColumnChoice: model.ColumnList,
|
|
AnalyzeOpts: $6.([]ast.AnalyzeOpt)}
|
|
}
|
|
| "ANALYZE" "TABLE" TableName "PARTITION" PartitionNameList "COLUMNS" IdentList AnalyzeOptionListOpt
|
|
{
|
|
$$ = &ast.AnalyzeTableStmt{
|
|
TableNames: []*ast.TableName{$3.(*ast.TableName)},
|
|
PartitionNames: $5.([]model.CIStr),
|
|
ColumnNames: $7.([]model.CIStr),
|
|
ColumnChoice: model.ColumnList,
|
|
AnalyzeOpts: $8.([]ast.AnalyzeOpt)}
|
|
}
|
|
|
|
AllColumnsOrPredicateColumnsOpt:
|
|
/* empty */
|
|
{
|
|
$$ = model.DefaultChoice
|
|
}
|
|
| "ALL" "COLUMNS"
|
|
{
|
|
$$ = model.AllColumns
|
|
}
|
|
| "PREDICATE" "COLUMNS"
|
|
{
|
|
$$ = model.PredicateColumns
|
|
}
|
|
|
|
AnalyzeOptionListOpt:
|
|
{
|
|
$$ = []ast.AnalyzeOpt{}
|
|
}
|
|
| "WITH" AnalyzeOptionList
|
|
{
|
|
$$ = $2.([]ast.AnalyzeOpt)
|
|
}
|
|
|
|
AnalyzeOptionList:
|
|
AnalyzeOption
|
|
{
|
|
$$ = []ast.AnalyzeOpt{$1.(ast.AnalyzeOpt)}
|
|
}
|
|
| AnalyzeOptionList ',' AnalyzeOption
|
|
{
|
|
$$ = append($1.([]ast.AnalyzeOpt), $3.(ast.AnalyzeOpt))
|
|
}
|
|
|
|
AnalyzeOption:
|
|
NUM "BUCKETS"
|
|
{
|
|
$$ = ast.AnalyzeOpt{Type: ast.AnalyzeOptNumBuckets, Value: ast.NewValueExpr($1, "", "")}
|
|
}
|
|
| NUM "TOPN"
|
|
{
|
|
$$ = ast.AnalyzeOpt{Type: ast.AnalyzeOptNumTopN, Value: ast.NewValueExpr($1, "", "")}
|
|
}
|
|
| NUM "CMSKETCH" "DEPTH"
|
|
{
|
|
$$ = ast.AnalyzeOpt{Type: ast.AnalyzeOptCMSketchDepth, Value: ast.NewValueExpr($1, "", "")}
|
|
}
|
|
| NUM "CMSKETCH" "WIDTH"
|
|
{
|
|
$$ = ast.AnalyzeOpt{Type: ast.AnalyzeOptCMSketchWidth, Value: ast.NewValueExpr($1, "", "")}
|
|
}
|
|
| NUM "SAMPLES"
|
|
{
|
|
$$ = ast.AnalyzeOpt{Type: ast.AnalyzeOptNumSamples, Value: ast.NewValueExpr($1, "", "")}
|
|
}
|
|
| NumLiteral "SAMPLERATE"
|
|
{
|
|
$$ = ast.AnalyzeOpt{Type: ast.AnalyzeOptSampleRate, Value: ast.NewValueExpr($1, "", "")}
|
|
}
|
|
|
|
/*******************************************************************************************/
|
|
Assignment:
|
|
ColumnName EqOrAssignmentEq ExprOrDefault
|
|
{
|
|
$$ = &ast.Assignment{Column: $1.(*ast.ColumnName), Expr: $3}
|
|
}
|
|
|
|
AssignmentList:
|
|
Assignment
|
|
{
|
|
$$ = []*ast.Assignment{$1.(*ast.Assignment)}
|
|
}
|
|
| AssignmentList ',' Assignment
|
|
{
|
|
$$ = append($1.([]*ast.Assignment), $3.(*ast.Assignment))
|
|
}
|
|
|
|
AssignmentListOpt:
|
|
/* EMPTY */
|
|
{
|
|
$$ = []*ast.Assignment{}
|
|
}
|
|
| AssignmentList
|
|
|
|
BeginTransactionStmt:
|
|
"BEGIN"
|
|
{
|
|
$$ = &ast.BeginStmt{}
|
|
}
|
|
| "BEGIN" "PESSIMISTIC"
|
|
{
|
|
$$ = &ast.BeginStmt{
|
|
Mode: ast.Pessimistic,
|
|
}
|
|
}
|
|
| "BEGIN" "OPTIMISTIC"
|
|
{
|
|
$$ = &ast.BeginStmt{
|
|
Mode: ast.Optimistic,
|
|
}
|
|
}
|
|
| "START" "TRANSACTION"
|
|
{
|
|
$$ = &ast.BeginStmt{}
|
|
}
|
|
| "START" "TRANSACTION" "READ" "WRITE"
|
|
{
|
|
$$ = &ast.BeginStmt{}
|
|
}
|
|
| "START" "TRANSACTION" "WITH" "CONSISTENT" "SNAPSHOT"
|
|
{
|
|
$$ = &ast.BeginStmt{}
|
|
}
|
|
| "START" "TRANSACTION" "WITH" "CAUSAL" "CONSISTENCY" "ONLY"
|
|
{
|
|
$$ = &ast.BeginStmt{
|
|
CausalConsistencyOnly: true,
|
|
}
|
|
}
|
|
| "START" "TRANSACTION" "READ" "ONLY"
|
|
{
|
|
$$ = &ast.BeginStmt{
|
|
ReadOnly: true,
|
|
}
|
|
}
|
|
| "START" "TRANSACTION" "READ" "ONLY" AsOfClause
|
|
{
|
|
$$ = &ast.BeginStmt{
|
|
ReadOnly: true,
|
|
AsOf: $5.(*ast.AsOfClause),
|
|
}
|
|
}
|
|
|
|
BinlogStmt:
|
|
"BINLOG" stringLit
|
|
{
|
|
$$ = &ast.BinlogStmt{Str: $2}
|
|
}
|
|
|
|
ColumnDefList:
|
|
ColumnDef
|
|
{
|
|
$$ = []*ast.ColumnDef{$1.(*ast.ColumnDef)}
|
|
}
|
|
| ColumnDefList ',' ColumnDef
|
|
{
|
|
$$ = append($1.([]*ast.ColumnDef), $3.(*ast.ColumnDef))
|
|
}
|
|
|
|
ColumnDef:
|
|
ColumnName Type ColumnOptionListOpt
|
|
{
|
|
colDef := &ast.ColumnDef{Name: $1.(*ast.ColumnName), Tp: $2.(*types.FieldType), Options: $3.([]*ast.ColumnOption)}
|
|
if err := colDef.Validate(); err != nil {
|
|
yylex.AppendError(err)
|
|
return 1
|
|
}
|
|
$$ = colDef
|
|
}
|
|
| ColumnName "SERIAL" ColumnOptionListOpt
|
|
{
|
|
// TODO: check flen 0
|
|
tp := types.NewFieldType(mysql.TypeLonglong)
|
|
options := []*ast.ColumnOption{{Tp: ast.ColumnOptionNotNull}, {Tp: ast.ColumnOptionAutoIncrement}, {Tp: ast.ColumnOptionUniqKey}}
|
|
options = append(options, $3.([]*ast.ColumnOption)...)
|
|
tp.AddFlag(mysql.UnsignedFlag)
|
|
colDef := &ast.ColumnDef{Name: $1.(*ast.ColumnName), Tp: tp, Options: options}
|
|
if err := colDef.Validate(); err != nil {
|
|
yylex.AppendError(err)
|
|
return 1
|
|
}
|
|
$$ = colDef
|
|
}
|
|
|
|
ColumnName:
|
|
Identifier
|
|
{
|
|
$$ = &ast.ColumnName{Name: model.NewCIStr($1)}
|
|
}
|
|
| Identifier '.' Identifier
|
|
{
|
|
$$ = &ast.ColumnName{Table: model.NewCIStr($1), Name: model.NewCIStr($3)}
|
|
}
|
|
| Identifier '.' Identifier '.' Identifier
|
|
{
|
|
$$ = &ast.ColumnName{Schema: model.NewCIStr($1), Table: model.NewCIStr($3), Name: model.NewCIStr($5)}
|
|
}
|
|
|
|
ColumnNameList:
|
|
ColumnName
|
|
{
|
|
$$ = []*ast.ColumnName{$1.(*ast.ColumnName)}
|
|
}
|
|
| ColumnNameList ',' ColumnName
|
|
{
|
|
$$ = append($1.([]*ast.ColumnName), $3.(*ast.ColumnName))
|
|
}
|
|
|
|
ColumnNameListOpt:
|
|
/* EMPTY */
|
|
{
|
|
$$ = []*ast.ColumnName{}
|
|
}
|
|
| ColumnNameList
|
|
|
|
IdentListWithParenOpt:
|
|
/* EMPTY */
|
|
{
|
|
$$ = []model.CIStr{}
|
|
}
|
|
| '(' IdentList ')'
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
IdentList:
|
|
Identifier
|
|
{
|
|
$$ = []model.CIStr{model.NewCIStr($1)}
|
|
}
|
|
| IdentList ',' Identifier
|
|
{
|
|
$$ = append($1.([]model.CIStr), model.NewCIStr($3))
|
|
}
|
|
|
|
ColumnNameOrUserVarListOpt:
|
|
/* EMPTY */
|
|
{
|
|
$$ = []*ast.ColumnNameOrUserVar{}
|
|
}
|
|
| ColumnNameOrUserVariableList
|
|
|
|
ColumnNameOrUserVariableList:
|
|
ColumnNameOrUserVariable
|
|
{
|
|
$$ = []*ast.ColumnNameOrUserVar{$1.(*ast.ColumnNameOrUserVar)}
|
|
}
|
|
| ColumnNameOrUserVariableList ',' ColumnNameOrUserVariable
|
|
{
|
|
$$ = append($1.([]*ast.ColumnNameOrUserVar), $3.(*ast.ColumnNameOrUserVar))
|
|
}
|
|
|
|
ColumnNameOrUserVariable:
|
|
ColumnName
|
|
{
|
|
$$ = &ast.ColumnNameOrUserVar{ColumnName: $1.(*ast.ColumnName)}
|
|
}
|
|
| UserVariable
|
|
{
|
|
$$ = &ast.ColumnNameOrUserVar{UserVar: $1.(*ast.VariableExpr)}
|
|
}
|
|
|
|
ColumnNameOrUserVarListOptWithBrackets:
|
|
/* EMPTY */
|
|
{
|
|
$$ = []*ast.ColumnNameOrUserVar{}
|
|
}
|
|
| '(' ColumnNameOrUserVarListOpt ')'
|
|
{
|
|
$$ = $2.([]*ast.ColumnNameOrUserVar)
|
|
}
|
|
|
|
CommitStmt:
|
|
"COMMIT"
|
|
{
|
|
$$ = &ast.CommitStmt{}
|
|
}
|
|
| "COMMIT" CompletionTypeWithinTransaction
|
|
{
|
|
$$ = &ast.CommitStmt{CompletionType: $2.(ast.CompletionType)}
|
|
}
|
|
|
|
PrimaryOpt:
|
|
{}
|
|
| "PRIMARY"
|
|
|
|
NotSym:
|
|
not
|
|
| not2
|
|
{
|
|
$$ = "NOT"
|
|
}
|
|
|
|
EnforcedOrNot:
|
|
"ENFORCED"
|
|
{
|
|
$$ = true
|
|
}
|
|
| NotSym "ENFORCED"
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
EnforcedOrNotOpt:
|
|
%prec lowerThanNot
|
|
{
|
|
$$ = true
|
|
}
|
|
| EnforcedOrNot
|
|
|
|
EnforcedOrNotOrNotNullOpt:
|
|
// This branch is needed to workaround the need of a lookahead of 2 for the grammar:
|
|
//
|
|
// { [NOT] NULL | CHECK(...) [NOT] ENFORCED } ...
|
|
NotSym "NULL"
|
|
{
|
|
$$ = 0
|
|
}
|
|
| EnforcedOrNotOpt
|
|
{
|
|
if $1.(bool) {
|
|
$$ = 1
|
|
} else {
|
|
$$ = 2
|
|
}
|
|
}
|
|
|
|
ColumnOption:
|
|
NotSym "NULL"
|
|
{
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionNotNull}
|
|
}
|
|
| "NULL"
|
|
{
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionNull}
|
|
}
|
|
| "AUTO_INCREMENT"
|
|
{
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionAutoIncrement}
|
|
}
|
|
| PrimaryOpt "KEY"
|
|
{
|
|
// KEY is normally a synonym for INDEX. The key attribute PRIMARY KEY
|
|
// can also be specified as just KEY when given in a column definition.
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/create-table.html
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionPrimaryKey}
|
|
}
|
|
| PrimaryOpt "KEY" WithClustered
|
|
{
|
|
// KEY is normally a synonym for INDEX. The key attribute PRIMARY KEY
|
|
// can also be specified as just KEY when given in a column definition.
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/create-table.html
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionPrimaryKey, PrimaryKeyTp: $3.(model.PrimaryKeyType)}
|
|
}
|
|
| "UNIQUE" %prec lowerThanKey
|
|
{
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionUniqKey}
|
|
}
|
|
| "UNIQUE" "KEY"
|
|
{
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionUniqKey}
|
|
}
|
|
| "DEFAULT" DefaultValueExpr
|
|
{
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionDefaultValue, Expr: $2}
|
|
}
|
|
| "SERIAL" "DEFAULT" "VALUE"
|
|
{
|
|
$$ = []*ast.ColumnOption{{Tp: ast.ColumnOptionNotNull}, {Tp: ast.ColumnOptionAutoIncrement}, {Tp: ast.ColumnOptionUniqKey}}
|
|
}
|
|
| "ON" "UPDATE" NowSymOptionFraction
|
|
{
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionOnUpdate, Expr: $3}
|
|
}
|
|
| "COMMENT" stringLit
|
|
{
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionComment, Expr: ast.NewValueExpr($2, "", "")}
|
|
}
|
|
| ConstraintKeywordOpt "CHECK" '(' Expression ')' EnforcedOrNotOrNotNullOpt
|
|
{
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/create-table.html
|
|
// The CHECK clause is parsed but ignored by all storage engines.
|
|
// See the branch named `EnforcedOrNotOrNotNullOpt`.
|
|
|
|
optionCheck := &ast.ColumnOption{
|
|
Tp: ast.ColumnOptionCheck,
|
|
Expr: $4,
|
|
Enforced: true,
|
|
}
|
|
// Keep the column type check constraint name.
|
|
if $1 != nil {
|
|
optionCheck.ConstraintName = $1.(string)
|
|
}
|
|
switch $6.(int) {
|
|
case 0:
|
|
$$ = []*ast.ColumnOption{optionCheck, {Tp: ast.ColumnOptionNotNull}}
|
|
case 1:
|
|
optionCheck.Enforced = true
|
|
$$ = optionCheck
|
|
case 2:
|
|
optionCheck.Enforced = false
|
|
$$ = optionCheck
|
|
default:
|
|
}
|
|
}
|
|
| GeneratedAlways "AS" '(' Expression ')' VirtualOrStored
|
|
{
|
|
startOffset := parser.startOffset(&yyS[yypt-2])
|
|
endOffset := parser.endOffset(&yyS[yypt-1])
|
|
expr := $4
|
|
expr.SetText(parser.lexer.client, parser.src[startOffset:endOffset])
|
|
|
|
$$ = &ast.ColumnOption{
|
|
Tp: ast.ColumnOptionGenerated,
|
|
Expr: expr,
|
|
Stored: $6.(bool),
|
|
}
|
|
}
|
|
| ReferDef
|
|
{
|
|
$$ = &ast.ColumnOption{
|
|
Tp: ast.ColumnOptionReference,
|
|
Refer: $1.(*ast.ReferenceDef),
|
|
}
|
|
}
|
|
| "COLLATE" CollationName
|
|
{
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionCollate, StrValue: $2}
|
|
}
|
|
| "COLUMN_FORMAT" ColumnFormat
|
|
{
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionColumnFormat, StrValue: $2}
|
|
}
|
|
| "STORAGE" StorageMedia
|
|
{
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionStorage, StrValue: $2}
|
|
yylex.AppendError(yylex.Errorf("The STORAGE clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "AUTO_RANDOM" AutoRandomOpt
|
|
{
|
|
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionAutoRandom, AutoRandOpt: $2.(ast.AutoRandomOption)}
|
|
}
|
|
|
|
AutoRandomOpt:
|
|
{
|
|
$$ = ast.AutoRandomOption{ShardBits: types.UnspecifiedLength, RangeBits: types.UnspecifiedLength}
|
|
}
|
|
| '(' LengthNum ')'
|
|
{
|
|
$$ = ast.AutoRandomOption{ShardBits: int($2.(uint64)), RangeBits: types.UnspecifiedLength}
|
|
}
|
|
| '(' LengthNum ',' LengthNum ')'
|
|
{
|
|
$$ = ast.AutoRandomOption{ShardBits: int($2.(uint64)), RangeBits: int($4.(uint64))}
|
|
}
|
|
|
|
StorageMedia:
|
|
"DEFAULT"
|
|
| "DISK"
|
|
| "MEMORY"
|
|
|
|
ColumnFormat:
|
|
"DEFAULT"
|
|
{
|
|
$$ = "DEFAULT"
|
|
}
|
|
| "FIXED"
|
|
{
|
|
$$ = "FIXED"
|
|
}
|
|
| "DYNAMIC"
|
|
{
|
|
$$ = "DYNAMIC"
|
|
}
|
|
|
|
GeneratedAlways:
|
|
|
|
| "GENERATED" "ALWAYS"
|
|
|
|
VirtualOrStored:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "VIRTUAL"
|
|
{
|
|
$$ = false
|
|
}
|
|
| "STORED"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
ColumnOptionList:
|
|
ColumnOption
|
|
{
|
|
if columnOption, ok := $1.(*ast.ColumnOption); ok {
|
|
$$ = []*ast.ColumnOption{columnOption}
|
|
} else {
|
|
$$ = $1
|
|
}
|
|
}
|
|
| ColumnOptionList ColumnOption
|
|
{
|
|
if columnOption, ok := $2.(*ast.ColumnOption); ok {
|
|
$$ = append($1.([]*ast.ColumnOption), columnOption)
|
|
} else {
|
|
$$ = append($1.([]*ast.ColumnOption), $2.([]*ast.ColumnOption)...)
|
|
}
|
|
}
|
|
|
|
ColumnOptionListOpt:
|
|
{
|
|
$$ = []*ast.ColumnOption{}
|
|
}
|
|
| ColumnOptionList
|
|
|
|
ConstraintElem:
|
|
"PRIMARY" "KEY" IndexNameAndTypeOpt '(' IndexPartSpecificationList ')' IndexOptionList
|
|
{
|
|
c := &ast.Constraint{
|
|
Tp: ast.ConstraintPrimaryKey,
|
|
Keys: $5.([]*ast.IndexPartSpecification),
|
|
Name: $3.([]interface{})[0].(*ast.NullString).String,
|
|
IsEmptyIndex: $3.([]interface{})[0].(*ast.NullString).Empty,
|
|
}
|
|
if $7 != nil {
|
|
c.Option = $7.(*ast.IndexOption)
|
|
}
|
|
if indexType := $3.([]interface{})[1]; indexType != nil {
|
|
if c.Option == nil {
|
|
c.Option = &ast.IndexOption{}
|
|
}
|
|
c.Option.Tp = indexType.(model.IndexType)
|
|
}
|
|
$$ = c
|
|
}
|
|
| "FULLTEXT" KeyOrIndexOpt IndexName '(' IndexPartSpecificationList ')' IndexOptionList
|
|
{
|
|
c := &ast.Constraint{
|
|
Tp: ast.ConstraintFulltext,
|
|
Keys: $5.([]*ast.IndexPartSpecification),
|
|
Name: $3.(*ast.NullString).String,
|
|
IsEmptyIndex: $3.(*ast.NullString).Empty,
|
|
}
|
|
if $7 != nil {
|
|
c.Option = $7.(*ast.IndexOption)
|
|
}
|
|
$$ = c
|
|
}
|
|
| KeyOrIndex IfNotExists IndexNameAndTypeOpt '(' IndexPartSpecificationList ')' IndexOptionList
|
|
{
|
|
c := &ast.Constraint{
|
|
IfNotExists: $2.(bool),
|
|
Tp: ast.ConstraintIndex,
|
|
Keys: $5.([]*ast.IndexPartSpecification),
|
|
Name: $3.([]interface{})[0].(*ast.NullString).String,
|
|
IsEmptyIndex: $3.([]interface{})[0].(*ast.NullString).Empty,
|
|
}
|
|
if $7 != nil {
|
|
c.Option = $7.(*ast.IndexOption)
|
|
}
|
|
if indexType := $3.([]interface{})[1]; indexType != nil {
|
|
if c.Option == nil {
|
|
c.Option = &ast.IndexOption{}
|
|
}
|
|
c.Option.Tp = indexType.(model.IndexType)
|
|
}
|
|
$$ = c
|
|
}
|
|
| "UNIQUE" KeyOrIndexOpt IndexNameAndTypeOpt '(' IndexPartSpecificationList ')' IndexOptionList
|
|
{
|
|
c := &ast.Constraint{
|
|
Tp: ast.ConstraintUniq,
|
|
Keys: $5.([]*ast.IndexPartSpecification),
|
|
Name: $3.([]interface{})[0].(*ast.NullString).String,
|
|
IsEmptyIndex: $3.([]interface{})[0].(*ast.NullString).Empty,
|
|
}
|
|
if $7 != nil {
|
|
c.Option = $7.(*ast.IndexOption)
|
|
}
|
|
|
|
if indexType := $3.([]interface{})[1]; indexType != nil {
|
|
if c.Option == nil {
|
|
c.Option = &ast.IndexOption{}
|
|
}
|
|
c.Option.Tp = indexType.(model.IndexType)
|
|
}
|
|
$$ = c
|
|
}
|
|
| "FOREIGN" "KEY" IfNotExists IndexName '(' IndexPartSpecificationList ')' ReferDef
|
|
{
|
|
$$ = &ast.Constraint{
|
|
IfNotExists: $3.(bool),
|
|
Tp: ast.ConstraintForeignKey,
|
|
Keys: $6.([]*ast.IndexPartSpecification),
|
|
Name: $4.(*ast.NullString).String,
|
|
Refer: $8.(*ast.ReferenceDef),
|
|
IsEmptyIndex: $4.(*ast.NullString).Empty,
|
|
}
|
|
}
|
|
| "CHECK" '(' Expression ')' EnforcedOrNotOpt
|
|
{
|
|
$$ = &ast.Constraint{
|
|
Tp: ast.ConstraintCheck,
|
|
Expr: $3.(ast.ExprNode),
|
|
Enforced: $5.(bool),
|
|
}
|
|
}
|
|
|
|
Match:
|
|
"MATCH" "FULL"
|
|
{
|
|
$$ = ast.MatchFull
|
|
}
|
|
| "MATCH" "PARTIAL"
|
|
{
|
|
$$ = ast.MatchPartial
|
|
}
|
|
| "MATCH" "SIMPLE"
|
|
{
|
|
$$ = ast.MatchSimple
|
|
}
|
|
|
|
MatchOpt:
|
|
{
|
|
$$ = ast.MatchNone
|
|
}
|
|
| Match
|
|
{
|
|
$$ = $1
|
|
yylex.AppendError(yylex.Errorf("The MATCH clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
|
|
ReferDef:
|
|
"REFERENCES" TableName IndexPartSpecificationListOpt MatchOpt OnDeleteUpdateOpt
|
|
{
|
|
onDeleteUpdate := $5.([2]interface{})
|
|
$$ = &ast.ReferenceDef{
|
|
Table: $2.(*ast.TableName),
|
|
IndexPartSpecifications: $3.([]*ast.IndexPartSpecification),
|
|
OnDelete: onDeleteUpdate[0].(*ast.OnDeleteOpt),
|
|
OnUpdate: onDeleteUpdate[1].(*ast.OnUpdateOpt),
|
|
Match: $4.(ast.MatchType),
|
|
}
|
|
}
|
|
|
|
OnDelete:
|
|
"ON" "DELETE" ReferOpt
|
|
{
|
|
$$ = &ast.OnDeleteOpt{ReferOpt: $3.(model.ReferOptionType)}
|
|
}
|
|
|
|
OnUpdate:
|
|
"ON" "UPDATE" ReferOpt
|
|
{
|
|
$$ = &ast.OnUpdateOpt{ReferOpt: $3.(model.ReferOptionType)}
|
|
}
|
|
|
|
OnDeleteUpdateOpt:
|
|
%prec lowerThanOn
|
|
{
|
|
$$ = [2]interface{}{&ast.OnDeleteOpt{}, &ast.OnUpdateOpt{}}
|
|
}
|
|
| OnDelete %prec lowerThanOn
|
|
{
|
|
$$ = [2]interface{}{$1, &ast.OnUpdateOpt{}}
|
|
}
|
|
| OnUpdate %prec lowerThanOn
|
|
{
|
|
$$ = [2]interface{}{&ast.OnDeleteOpt{}, $1}
|
|
}
|
|
| OnDelete OnUpdate
|
|
{
|
|
$$ = [2]interface{}{$1, $2}
|
|
}
|
|
| OnUpdate OnDelete
|
|
{
|
|
$$ = [2]interface{}{$2, $1}
|
|
}
|
|
|
|
ReferOpt:
|
|
"RESTRICT"
|
|
{
|
|
$$ = model.ReferOptionRestrict
|
|
}
|
|
| "CASCADE"
|
|
{
|
|
$$ = model.ReferOptionCascade
|
|
}
|
|
| "SET" "NULL"
|
|
{
|
|
$$ = model.ReferOptionSetNull
|
|
}
|
|
| "NO" "ACTION"
|
|
{
|
|
$$ = model.ReferOptionNoAction
|
|
}
|
|
| "SET" "DEFAULT"
|
|
{
|
|
$$ = model.ReferOptionSetDefault
|
|
yylex.AppendError(yylex.Errorf("The SET DEFAULT clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
|
|
/*
|
|
* The DEFAULT clause specifies a default value for a column.
|
|
* It can be a function or an expression. This means, for example,
|
|
* that you can set the default for a date column to be the value of
|
|
* a function such as NOW() or CURRENT_DATE. While in MySQL 8.0
|
|
* expression default values are required to be enclosed in parentheses,
|
|
* they are NOT required so in TiDB.
|
|
*
|
|
* See https://dev.mysql.com/doc/refman/8.0/en/create-table.html
|
|
* https://dev.mysql.com/doc/refman/8.0/en/data-type-defaults.html
|
|
*/
|
|
DefaultValueExpr:
|
|
NowSymOptionFractionParentheses
|
|
| SignedLiteral
|
|
| NextValueForSequence
|
|
| BuiltinFunction
|
|
|
|
BuiltinFunction:
|
|
'(' BuiltinFunction ')'
|
|
{
|
|
$$ = $2.(*ast.FuncCallExpr)
|
|
}
|
|
| identifier '(' ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
}
|
|
}
|
|
| identifier '(' ExpressionList ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: $3.([]ast.ExprNode),
|
|
}
|
|
}
|
|
|
|
NowSymOptionFractionParentheses:
|
|
'(' NowSymOptionFractionParentheses ')'
|
|
{
|
|
$$ = $2.(*ast.FuncCallExpr)
|
|
}
|
|
| NowSymOptionFraction
|
|
|
|
NowSymOptionFraction:
|
|
NowSym
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")}
|
|
}
|
|
| NowSymFunc '(' ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")}
|
|
}
|
|
| NowSymFunc '(' NUM ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr($3, parser.charset, parser.collation)}}
|
|
}
|
|
| CurdateSym '(' ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_DATE")}
|
|
}
|
|
| "CURRENT_DATE"
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_DATE")}
|
|
}
|
|
|
|
NextValueForSequence:
|
|
"NEXT" "VALUE" forKwd TableName
|
|
{
|
|
objNameExpr := &ast.TableNameExpr{
|
|
Name: $4.(*ast.TableName),
|
|
}
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr(ast.NextVal),
|
|
Args: []ast.ExprNode{objNameExpr},
|
|
}
|
|
}
|
|
| "NEXTVAL" '(' TableName ')'
|
|
{
|
|
objNameExpr := &ast.TableNameExpr{
|
|
Name: $3.(*ast.TableName),
|
|
}
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr(ast.NextVal),
|
|
Args: []ast.ExprNode{objNameExpr},
|
|
}
|
|
}
|
|
|
|
/*
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_localtime
|
|
* TODO: Process other three keywords
|
|
*/
|
|
NowSymFunc:
|
|
"CURRENT_TIMESTAMP"
|
|
| "LOCALTIME"
|
|
| "LOCALTIMESTAMP"
|
|
| builtinNow
|
|
|
|
NowSym:
|
|
"CURRENT_TIMESTAMP"
|
|
| "LOCALTIME"
|
|
| "LOCALTIMESTAMP"
|
|
|
|
CurdateSym:
|
|
builtinCurDate
|
|
| "CURRENT_DATE"
|
|
|
|
SignedLiteral:
|
|
Literal
|
|
{
|
|
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
|
|
}
|
|
| '+' NumLiteral
|
|
{
|
|
$$ = &ast.UnaryOperationExpr{Op: opcode.Plus, V: ast.NewValueExpr($2, parser.charset, parser.collation)}
|
|
}
|
|
| '-' NumLiteral
|
|
{
|
|
$$ = &ast.UnaryOperationExpr{Op: opcode.Minus, V: ast.NewValueExpr($2, parser.charset, parser.collation)}
|
|
}
|
|
|
|
NumLiteral:
|
|
intLit
|
|
| floatLit
|
|
| decLit
|
|
|
|
StatsType:
|
|
"CARDINALITY"
|
|
{
|
|
$$ = ast.StatsTypeCardinality
|
|
}
|
|
| "DEPENDENCY"
|
|
{
|
|
$$ = ast.StatsTypeDependency
|
|
}
|
|
| "CORRELATION"
|
|
{
|
|
$$ = ast.StatsTypeCorrelation
|
|
}
|
|
|
|
BindingStatusType:
|
|
"ENABLED"
|
|
{
|
|
$$ = ast.BindingStatusTypeEnabled
|
|
}
|
|
| "DISABLED"
|
|
{
|
|
$$ = ast.BindingStatusTypeDisabled
|
|
}
|
|
|
|
CreateStatisticsStmt:
|
|
"CREATE" "STATISTICS" IfNotExists Identifier '(' StatsType ')' "ON" TableName '(' ColumnNameList ')'
|
|
{
|
|
$$ = &ast.CreateStatisticsStmt{
|
|
IfNotExists: $3.(bool),
|
|
StatsName: $4,
|
|
StatsType: $6.(uint8),
|
|
Table: $9.(*ast.TableName),
|
|
Columns: $11.([]*ast.ColumnName),
|
|
}
|
|
}
|
|
|
|
DropStatisticsStmt:
|
|
"DROP" "STATISTICS" Identifier
|
|
{
|
|
$$ = &ast.DropStatisticsStmt{StatsName: $3}
|
|
}
|
|
|
|
/**************************************CreateIndexStmt***************************************
|
|
* See https://dev.mysql.com/doc/refman/8.0/en/create-index.html
|
|
*
|
|
* TYPE type_name is recognized as a synonym for USING type_name. However, USING is the preferred form.
|
|
*
|
|
* CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name
|
|
* [index_type]
|
|
* ON tbl_name (key_part,...)
|
|
* [index_option]
|
|
* [algorithm_option | lock_option] ...
|
|
*
|
|
* key_part: {col_name [(length)] | (expr)} [ASC | DESC]
|
|
*
|
|
* index_option:
|
|
* KEY_BLOCK_SIZE [=] value
|
|
* | index_type
|
|
* | WITH PARSER parser_name
|
|
* | COMMENT 'string'
|
|
* | {VISIBLE | INVISIBLE}
|
|
*
|
|
* index_type:
|
|
* USING {BTREE | HASH}
|
|
*
|
|
* algorithm_option:
|
|
* ALGORITHM [=] {DEFAULT | INPLACE | COPY}
|
|
*
|
|
* lock_option:
|
|
* LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}
|
|
*******************************************************************************************/
|
|
CreateIndexStmt:
|
|
"CREATE" IndexKeyTypeOpt "INDEX" IfNotExists Identifier IndexTypeOpt "ON" TableName '(' IndexPartSpecificationList ')' IndexOptionList IndexLockAndAlgorithmOpt
|
|
{
|
|
var indexOption *ast.IndexOption
|
|
if $12 != nil {
|
|
indexOption = $12.(*ast.IndexOption)
|
|
if indexOption.Tp == model.IndexTypeInvalid {
|
|
if $6 != nil {
|
|
indexOption.Tp = $6.(model.IndexType)
|
|
}
|
|
}
|
|
} else {
|
|
indexOption = &ast.IndexOption{}
|
|
if $6 != nil {
|
|
indexOption.Tp = $6.(model.IndexType)
|
|
}
|
|
}
|
|
var indexLockAndAlgorithm *ast.IndexLockAndAlgorithm
|
|
if $13 != nil {
|
|
indexLockAndAlgorithm = $13.(*ast.IndexLockAndAlgorithm)
|
|
if indexLockAndAlgorithm.LockTp == ast.LockTypeDefault && indexLockAndAlgorithm.AlgorithmTp == ast.AlgorithmTypeDefault {
|
|
indexLockAndAlgorithm = nil
|
|
}
|
|
}
|
|
$$ = &ast.CreateIndexStmt{
|
|
IfNotExists: $4.(bool),
|
|
IndexName: $5,
|
|
Table: $8.(*ast.TableName),
|
|
IndexPartSpecifications: $10.([]*ast.IndexPartSpecification),
|
|
IndexOption: indexOption,
|
|
KeyType: $2.(ast.IndexKeyType),
|
|
LockAlg: indexLockAndAlgorithm,
|
|
}
|
|
}
|
|
|
|
IndexPartSpecificationListOpt:
|
|
{
|
|
$$ = ([]*ast.IndexPartSpecification)(nil)
|
|
}
|
|
| '(' IndexPartSpecificationList ')'
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
IndexPartSpecificationList:
|
|
IndexPartSpecification
|
|
{
|
|
$$ = []*ast.IndexPartSpecification{$1.(*ast.IndexPartSpecification)}
|
|
}
|
|
| IndexPartSpecificationList ',' IndexPartSpecification
|
|
{
|
|
$$ = append($1.([]*ast.IndexPartSpecification), $3.(*ast.IndexPartSpecification))
|
|
}
|
|
|
|
IndexPartSpecification:
|
|
ColumnName OptFieldLen OptOrder
|
|
{
|
|
$$ = &ast.IndexPartSpecification{Column: $1.(*ast.ColumnName), Length: $2.(int), Desc: $3.(bool)}
|
|
}
|
|
| '(' Expression ')' OptOrder
|
|
{
|
|
$$ = &ast.IndexPartSpecification{Expr: $2, Desc: $4.(bool)}
|
|
}
|
|
|
|
IndexLockAndAlgorithmOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| LockClause
|
|
{
|
|
$$ = &ast.IndexLockAndAlgorithm{
|
|
LockTp: $1.(ast.LockType),
|
|
AlgorithmTp: ast.AlgorithmTypeDefault,
|
|
}
|
|
}
|
|
| AlgorithmClause
|
|
{
|
|
$$ = &ast.IndexLockAndAlgorithm{
|
|
LockTp: ast.LockTypeDefault,
|
|
AlgorithmTp: $1.(ast.AlgorithmType),
|
|
}
|
|
}
|
|
| LockClause AlgorithmClause
|
|
{
|
|
$$ = &ast.IndexLockAndAlgorithm{
|
|
LockTp: $1.(ast.LockType),
|
|
AlgorithmTp: $2.(ast.AlgorithmType),
|
|
}
|
|
}
|
|
| AlgorithmClause LockClause
|
|
{
|
|
$$ = &ast.IndexLockAndAlgorithm{
|
|
LockTp: $2.(ast.LockType),
|
|
AlgorithmTp: $1.(ast.AlgorithmType),
|
|
}
|
|
}
|
|
|
|
IndexKeyTypeOpt:
|
|
{
|
|
$$ = ast.IndexKeyTypeNone
|
|
}
|
|
| "UNIQUE"
|
|
{
|
|
$$ = ast.IndexKeyTypeUnique
|
|
}
|
|
| "SPATIAL"
|
|
{
|
|
$$ = ast.IndexKeyTypeSpatial
|
|
}
|
|
| "FULLTEXT"
|
|
{
|
|
$$ = ast.IndexKeyTypeFullText
|
|
}
|
|
|
|
/**************************************AlterDatabaseStmt***************************************
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/alter-database.html
|
|
* 'ALTER DATABASE ... UPGRADE DATA DIRECTORY NAME' is not supported yet.
|
|
*
|
|
* ALTER {DATABASE | SCHEMA} [db_name]
|
|
* alter_specification ...
|
|
*
|
|
* alter_specification:
|
|
* [DEFAULT] CHARACTER SET [=] charset_name
|
|
* | [DEFAULT] COLLATE [=] collation_name
|
|
* | [DEFAULT] ENCRYPTION [=] {'Y' | 'N'}
|
|
*******************************************************************************************/
|
|
AlterDatabaseStmt:
|
|
"ALTER" DatabaseSym DBName DatabaseOptionList
|
|
{
|
|
$$ = &ast.AlterDatabaseStmt{
|
|
Name: model.NewCIStr($3),
|
|
AlterDefaultDatabase: false,
|
|
Options: $4.([]*ast.DatabaseOption),
|
|
}
|
|
}
|
|
| "ALTER" DatabaseSym DatabaseOptionList
|
|
{
|
|
$$ = &ast.AlterDatabaseStmt{
|
|
Name: model.NewCIStr(""),
|
|
AlterDefaultDatabase: true,
|
|
Options: $3.([]*ast.DatabaseOption),
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Create Database Statement
|
|
* CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
|
|
* [create_specification] ...
|
|
*
|
|
* create_specification:
|
|
* [DEFAULT] CHARACTER SET [=] charset_name
|
|
* | [DEFAULT] COLLATE [=] collation_name
|
|
* | [DEFAULT] ENCRYPTION [=] {'Y' | 'N'}
|
|
*******************************************************************/
|
|
CreateDatabaseStmt:
|
|
"CREATE" DatabaseSym IfNotExists DBName DatabaseOptionListOpt
|
|
{
|
|
$$ = &ast.CreateDatabaseStmt{
|
|
IfNotExists: $3.(bool),
|
|
Name: model.NewCIStr($4),
|
|
Options: $5.([]*ast.DatabaseOption),
|
|
}
|
|
}
|
|
|
|
DBName:
|
|
Identifier
|
|
|
|
PolicyName:
|
|
Identifier
|
|
|
|
ResourceGroupName:
|
|
Identifier
|
|
| "DEFAULT"
|
|
|
|
DatabaseOption:
|
|
DefaultKwdOpt CharsetKw EqOpt CharsetName
|
|
{
|
|
$$ = &ast.DatabaseOption{Tp: ast.DatabaseOptionCharset, Value: $4}
|
|
}
|
|
| DefaultKwdOpt "COLLATE" EqOpt CollationName
|
|
{
|
|
$$ = &ast.DatabaseOption{Tp: ast.DatabaseOptionCollate, Value: $4}
|
|
}
|
|
| DefaultKwdOpt "ENCRYPTION" EqOpt EncryptionOpt
|
|
{
|
|
$$ = &ast.DatabaseOption{Tp: ast.DatabaseOptionEncryption, Value: $4}
|
|
}
|
|
| DefaultKwdOpt PlacementPolicyOption
|
|
{
|
|
placementOptions := $2.(*ast.PlacementOption)
|
|
$$ = &ast.DatabaseOption{
|
|
// offset trick, enums are identical but of different type
|
|
Tp: ast.DatabaseOptionType(placementOptions.Tp),
|
|
Value: placementOptions.StrValue,
|
|
UintValue: placementOptions.UintValue,
|
|
}
|
|
}
|
|
| PlacementPolicyOption
|
|
{
|
|
placementOptions := $1.(*ast.PlacementOption)
|
|
$$ = &ast.DatabaseOption{
|
|
// offset trick, enums are identical but of different type
|
|
Tp: ast.DatabaseOptionType(placementOptions.Tp),
|
|
Value: placementOptions.StrValue,
|
|
UintValue: placementOptions.UintValue,
|
|
}
|
|
}
|
|
| "SET" "TIFLASH" "REPLICA" LengthNum LocationLabelList
|
|
{
|
|
tiflashReplicaSpec := &ast.TiFlashReplicaSpec{
|
|
Count: $4.(uint64),
|
|
Labels: $5.([]string),
|
|
}
|
|
$$ = &ast.DatabaseOption{
|
|
Tp: ast.DatabaseSetTiFlashReplica,
|
|
TiFlashReplica: tiflashReplicaSpec,
|
|
}
|
|
}
|
|
|
|
DatabaseOptionListOpt:
|
|
{
|
|
$$ = []*ast.DatabaseOption{}
|
|
}
|
|
| DatabaseOptionList
|
|
|
|
DatabaseOptionList:
|
|
DatabaseOption
|
|
{
|
|
$$ = []*ast.DatabaseOption{$1.(*ast.DatabaseOption)}
|
|
}
|
|
| DatabaseOptionList DatabaseOption
|
|
{
|
|
$$ = append($1.([]*ast.DatabaseOption), $2.(*ast.DatabaseOption))
|
|
}
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Create Table Statement
|
|
*
|
|
* Example:
|
|
* CREATE TABLE Persons
|
|
* (
|
|
* P_Id int NOT NULL,
|
|
* LastName varchar(255) NOT NULL,
|
|
* FirstName varchar(255),
|
|
* Address varchar(255),
|
|
* City varchar(255),
|
|
* PRIMARY KEY (P_Id)
|
|
* )
|
|
*******************************************************************/
|
|
CreateTableStmt:
|
|
"CREATE" OptTemporary "TABLE" IfNotExists TableName TableElementListOpt CreateTableOptionListOpt PartitionOpt DuplicateOpt AsOpt CreateTableSelectOpt OnCommitOpt
|
|
{
|
|
stmt := $6.(*ast.CreateTableStmt)
|
|
stmt.Table = $5.(*ast.TableName)
|
|
stmt.IfNotExists = $4.(bool)
|
|
stmt.TemporaryKeyword = $2.(ast.TemporaryKeyword)
|
|
stmt.Options = $7.([]*ast.TableOption)
|
|
if $8 != nil {
|
|
stmt.Partition = $8.(*ast.PartitionOptions)
|
|
}
|
|
stmt.OnDuplicate = $9.(ast.OnDuplicateKeyHandlingType)
|
|
stmt.Select = $11.(*ast.CreateTableStmt).Select
|
|
if ($12 != nil && stmt.TemporaryKeyword != ast.TemporaryGlobal) || (stmt.TemporaryKeyword == ast.TemporaryGlobal && $12 == nil) {
|
|
yylex.AppendError(yylex.Errorf("GLOBAL TEMPORARY and ON COMMIT DELETE ROWS must appear together"))
|
|
} else {
|
|
if stmt.TemporaryKeyword == ast.TemporaryGlobal {
|
|
stmt.OnCommitDelete = $12.(bool)
|
|
}
|
|
}
|
|
$$ = stmt
|
|
}
|
|
| "CREATE" OptTemporary "TABLE" IfNotExists TableName LikeTableWithOrWithoutParen OnCommitOpt
|
|
{
|
|
tmp := &ast.CreateTableStmt{
|
|
Table: $5.(*ast.TableName),
|
|
ReferTable: $6.(*ast.TableName),
|
|
IfNotExists: $4.(bool),
|
|
TemporaryKeyword: $2.(ast.TemporaryKeyword),
|
|
}
|
|
if ($7 != nil && tmp.TemporaryKeyword != ast.TemporaryGlobal) || (tmp.TemporaryKeyword == ast.TemporaryGlobal && $7 == nil) {
|
|
yylex.AppendError(yylex.Errorf("GLOBAL TEMPORARY and ON COMMIT DELETE ROWS must appear together"))
|
|
} else {
|
|
if tmp.TemporaryKeyword == ast.TemporaryGlobal {
|
|
tmp.OnCommitDelete = $7.(bool)
|
|
}
|
|
}
|
|
$$ = tmp
|
|
}
|
|
|
|
OnCommitOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "ON" "COMMIT" "DELETE" "ROWS"
|
|
{
|
|
$$ = true
|
|
}
|
|
| "ON" "COMMIT" "PRESERVE" "ROWS"
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
DefaultKwdOpt:
|
|
%prec lowerThanCharsetKwd
|
|
{}
|
|
| "DEFAULT"
|
|
|
|
PartitionOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "PARTITION" "BY" PartitionMethod PartitionNumOpt SubPartitionOpt PartitionDefinitionListOpt
|
|
{
|
|
method := $3.(*ast.PartitionMethod)
|
|
method.Num = $4.(uint64)
|
|
sub, _ := $5.(*ast.PartitionMethod)
|
|
defs, _ := $6.([]*ast.PartitionDefinition)
|
|
opt := &ast.PartitionOptions{
|
|
PartitionMethod: *method,
|
|
Sub: sub,
|
|
Definitions: defs,
|
|
}
|
|
if err := opt.Validate(); err != nil {
|
|
yylex.AppendError(err)
|
|
return 1
|
|
}
|
|
$$ = opt
|
|
}
|
|
|
|
SubPartitionMethod:
|
|
LinearOpt "KEY" PartitionKeyAlgorithmOpt '(' ColumnNameListOpt ')'
|
|
{
|
|
keyAlgorithm, _ := $3.(*ast.PartitionKeyAlgorithm)
|
|
$$ = &ast.PartitionMethod{
|
|
Tp: model.PartitionTypeKey,
|
|
Linear: len($1) != 0,
|
|
ColumnNames: $5.([]*ast.ColumnName),
|
|
KeyAlgorithm: keyAlgorithm,
|
|
}
|
|
}
|
|
| LinearOpt "HASH" '(' BitExpr ')'
|
|
{
|
|
$$ = &ast.PartitionMethod{
|
|
Tp: model.PartitionTypeHash,
|
|
Linear: len($1) != 0,
|
|
Expr: $4.(ast.ExprNode),
|
|
}
|
|
}
|
|
|
|
PartitionKeyAlgorithmOpt:
|
|
/* empty */
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "ALGORITHM" eq NUM
|
|
{
|
|
tp := getUint64FromNUM($3)
|
|
if tp != 1 && tp != 2 {
|
|
yylex.AppendError(ErrSyntax)
|
|
return 1
|
|
}
|
|
$$ = &ast.PartitionKeyAlgorithm{
|
|
Type: tp,
|
|
}
|
|
}
|
|
|
|
PartitionMethod:
|
|
SubPartitionMethod
|
|
| "RANGE" '(' BitExpr ')' PartitionIntervalOpt
|
|
{
|
|
partitionInterval, _ := $5.(*ast.PartitionInterval)
|
|
$$ = &ast.PartitionMethod{
|
|
Tp: model.PartitionTypeRange,
|
|
Expr: $3.(ast.ExprNode),
|
|
Interval: partitionInterval,
|
|
}
|
|
}
|
|
| "RANGE" FieldsOrColumns '(' ColumnNameList ')' PartitionIntervalOpt
|
|
{
|
|
partitionInterval, _ := $6.(*ast.PartitionInterval)
|
|
$$ = &ast.PartitionMethod{
|
|
Tp: model.PartitionTypeRange,
|
|
ColumnNames: $4.([]*ast.ColumnName),
|
|
Interval: partitionInterval,
|
|
}
|
|
}
|
|
| "LIST" '(' BitExpr ')'
|
|
{
|
|
$$ = &ast.PartitionMethod{
|
|
Tp: model.PartitionTypeList,
|
|
Expr: $3.(ast.ExprNode),
|
|
}
|
|
}
|
|
| "LIST" FieldsOrColumns '(' ColumnNameList ')'
|
|
{
|
|
$$ = &ast.PartitionMethod{
|
|
Tp: model.PartitionTypeList,
|
|
ColumnNames: $4.([]*ast.ColumnName),
|
|
}
|
|
}
|
|
| "SYSTEM_TIME" "INTERVAL" Expression TimeUnit
|
|
{
|
|
$$ = &ast.PartitionMethod{
|
|
Tp: model.PartitionTypeSystemTime,
|
|
Expr: $3.(ast.ExprNode),
|
|
Unit: $4.(ast.TimeUnitType),
|
|
}
|
|
}
|
|
| "SYSTEM_TIME" "LIMIT" LengthNum
|
|
{
|
|
$$ = &ast.PartitionMethod{
|
|
Tp: model.PartitionTypeSystemTime,
|
|
Limit: $3.(uint64),
|
|
}
|
|
}
|
|
| "SYSTEM_TIME"
|
|
{
|
|
$$ = &ast.PartitionMethod{
|
|
Tp: model.PartitionTypeSystemTime,
|
|
}
|
|
}
|
|
|
|
PartitionIntervalOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "INTERVAL" '(' IntervalExpr ')' FirstAndLastPartOpt NullPartOpt MaxValPartOpt
|
|
{
|
|
partitionInterval := &ast.PartitionInterval{
|
|
IntervalExpr: $3.(ast.PartitionIntervalExpr),
|
|
FirstRangeEnd: $5.(ast.PartitionInterval).FirstRangeEnd,
|
|
LastRangeEnd: $5.(ast.PartitionInterval).LastRangeEnd,
|
|
NullPart: $6.(bool),
|
|
MaxValPart: $7.(bool),
|
|
}
|
|
startOffset := parser.yyVAL.offset
|
|
endOffset := parser.yylval.offset
|
|
partitionInterval.SetText(parser.lexer.client, parser.src[startOffset:endOffset])
|
|
// Needed for replacing syntactic sugar with generated partitioning definition string
|
|
partitionInterval.SetOriginTextPosition(startOffset)
|
|
$$ = partitionInterval
|
|
}
|
|
|
|
IntervalExpr:
|
|
BitExpr
|
|
{
|
|
$$ = ast.PartitionIntervalExpr{Expr: $1, TimeUnit: ast.TimeUnitInvalid}
|
|
}
|
|
| BitExpr TimeUnit
|
|
{
|
|
$$ = ast.PartitionIntervalExpr{Expr: $1, TimeUnit: $2.(ast.TimeUnitType)}
|
|
}
|
|
|
|
NullPartOpt:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "NULL" "PARTITION"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
MaxValPartOpt:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "MAXVALUE" "PARTITION"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
FirstAndLastPartOpt:
|
|
{
|
|
$$ = ast.PartitionInterval{} // First/LastRangeEnd defaults to nil
|
|
}
|
|
| "FIRST" "PARTITION" "LESS" "THAN" '(' BitExpr ')' "LAST" "PARTITION" "LESS" "THAN" '(' BitExpr ')'
|
|
{
|
|
first := $6.(ast.ExprNode)
|
|
last := $13.(ast.ExprNode)
|
|
$$ = ast.PartitionInterval{
|
|
FirstRangeEnd: &first,
|
|
LastRangeEnd: &last,
|
|
}
|
|
}
|
|
|
|
LinearOpt:
|
|
{
|
|
$$ = ""
|
|
}
|
|
| "LINEAR"
|
|
|
|
SubPartitionOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "SUBPARTITION" "BY" SubPartitionMethod SubPartitionNumOpt
|
|
{
|
|
method := $3.(*ast.PartitionMethod)
|
|
method.Num = $4.(uint64)
|
|
$$ = method
|
|
}
|
|
|
|
SubPartitionNumOpt:
|
|
{
|
|
$$ = uint64(0)
|
|
}
|
|
| "SUBPARTITIONS" LengthNum
|
|
{
|
|
res := $2.(uint64)
|
|
if res == 0 {
|
|
yylex.AppendError(ast.ErrNoParts.GenWithStackByArgs("subpartitions"))
|
|
return 1
|
|
}
|
|
$$ = res
|
|
}
|
|
|
|
PartitionNumOpt:
|
|
{
|
|
$$ = uint64(0)
|
|
}
|
|
| "PARTITIONS" LengthNum
|
|
{
|
|
res := $2.(uint64)
|
|
if res == 0 {
|
|
yylex.AppendError(ast.ErrNoParts.GenWithStackByArgs("partitions"))
|
|
return 1
|
|
}
|
|
$$ = res
|
|
}
|
|
|
|
PartitionDefinitionListOpt:
|
|
/* empty */ %prec lowerThanCreateTableSelect
|
|
{
|
|
$$ = nil
|
|
}
|
|
| '(' PartitionDefinitionList ')'
|
|
{
|
|
$$ = $2.([]*ast.PartitionDefinition)
|
|
}
|
|
|
|
PartitionDefinitionList:
|
|
PartitionDefinition
|
|
{
|
|
$$ = []*ast.PartitionDefinition{$1.(*ast.PartitionDefinition)}
|
|
}
|
|
| PartitionDefinitionList ',' PartitionDefinition
|
|
{
|
|
$$ = append($1.([]*ast.PartitionDefinition), $3.(*ast.PartitionDefinition))
|
|
}
|
|
|
|
PartitionDefinition:
|
|
"PARTITION" Identifier PartDefValuesOpt PartDefOptionList SubPartDefinitionListOpt
|
|
{
|
|
$$ = &ast.PartitionDefinition{
|
|
Name: model.NewCIStr($2),
|
|
Clause: $3.(ast.PartitionDefinitionClause),
|
|
Options: $4.([]*ast.TableOption),
|
|
Sub: $5.([]*ast.SubPartitionDefinition),
|
|
}
|
|
}
|
|
|
|
SubPartDefinitionListOpt:
|
|
/*empty*/
|
|
{
|
|
$$ = make([]*ast.SubPartitionDefinition, 0)
|
|
}
|
|
| '(' SubPartDefinitionList ')'
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
SubPartDefinitionList:
|
|
SubPartDefinition
|
|
{
|
|
$$ = []*ast.SubPartitionDefinition{$1.(*ast.SubPartitionDefinition)}
|
|
}
|
|
| SubPartDefinitionList ',' SubPartDefinition
|
|
{
|
|
list := $1.([]*ast.SubPartitionDefinition)
|
|
$$ = append(list, $3.(*ast.SubPartitionDefinition))
|
|
}
|
|
|
|
SubPartDefinition:
|
|
"SUBPARTITION" Identifier PartDefOptionList
|
|
{
|
|
$$ = &ast.SubPartitionDefinition{
|
|
Name: model.NewCIStr($2),
|
|
Options: $3.([]*ast.TableOption),
|
|
}
|
|
}
|
|
|
|
PartDefOptionList:
|
|
/*empty*/
|
|
{
|
|
$$ = make([]*ast.TableOption, 0)
|
|
}
|
|
| PartDefOptionList PartDefOption
|
|
{
|
|
list := $1.([]*ast.TableOption)
|
|
$$ = append(list, $2.(*ast.TableOption))
|
|
}
|
|
|
|
PartDefOption:
|
|
"COMMENT" EqOpt stringLit
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionComment, StrValue: $3}
|
|
}
|
|
| "ENGINE" EqOpt StringName
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionEngine, StrValue: $3}
|
|
}
|
|
| "STORAGE" "ENGINE" EqOpt StringName
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionEngine, StrValue: $4}
|
|
}
|
|
| "INSERT_METHOD" EqOpt StringName
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionInsertMethod, StrValue: $3}
|
|
}
|
|
| "DATA" "DIRECTORY" EqOpt stringLit
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionDataDirectory, StrValue: $4}
|
|
}
|
|
| "INDEX" "DIRECTORY" EqOpt stringLit
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionIndexDirectory, StrValue: $4}
|
|
}
|
|
| "MAX_ROWS" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionMaxRows, UintValue: $3.(uint64)}
|
|
}
|
|
| "MIN_ROWS" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionMinRows, UintValue: $3.(uint64)}
|
|
}
|
|
| "TABLESPACE" EqOpt Identifier
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionTablespace, StrValue: $3}
|
|
}
|
|
| "NODEGROUP" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionNodegroup, UintValue: $3.(uint64)}
|
|
}
|
|
| PlacementPolicyOption
|
|
{
|
|
placementOptions := $1.(*ast.PlacementOption)
|
|
$$ = &ast.TableOption{
|
|
// offset trick, enums are identical but of different type
|
|
Tp: ast.TableOptionType(placementOptions.Tp),
|
|
StrValue: placementOptions.StrValue,
|
|
UintValue: placementOptions.UintValue,
|
|
}
|
|
}
|
|
|
|
PartDefValuesOpt:
|
|
{
|
|
$$ = &ast.PartitionDefinitionClauseNone{}
|
|
}
|
|
| "VALUES" "LESS" "THAN" "MAXVALUE"
|
|
{
|
|
$$ = &ast.PartitionDefinitionClauseLessThan{
|
|
Exprs: []ast.ExprNode{&ast.MaxValueExpr{}},
|
|
}
|
|
}
|
|
| "VALUES" "LESS" "THAN" '(' MaxValueOrExpressionList ')'
|
|
{
|
|
$$ = &ast.PartitionDefinitionClauseLessThan{
|
|
Exprs: $5.([]ast.ExprNode),
|
|
}
|
|
}
|
|
| "DEFAULT"
|
|
{
|
|
$$ = &ast.PartitionDefinitionClauseIn{
|
|
Values: [][]ast.ExprNode{{&ast.DefaultExpr{}}},
|
|
}
|
|
}
|
|
| "VALUES" "IN" '(' DefaultOrExpressionList ')'
|
|
{
|
|
exprs := $4.([]ast.ExprNode)
|
|
values := make([][]ast.ExprNode, 0, len(exprs))
|
|
for _, expr := range exprs {
|
|
if row, ok := expr.(*ast.RowExpr); ok {
|
|
values = append(values, row.Values)
|
|
} else {
|
|
values = append(values, []ast.ExprNode{expr})
|
|
}
|
|
}
|
|
$$ = &ast.PartitionDefinitionClauseIn{Values: values}
|
|
}
|
|
| "HISTORY"
|
|
{
|
|
$$ = &ast.PartitionDefinitionClauseHistory{Current: false}
|
|
}
|
|
| "CURRENT"
|
|
{
|
|
$$ = &ast.PartitionDefinitionClauseHistory{Current: true}
|
|
}
|
|
|
|
DuplicateOpt:
|
|
{
|
|
$$ = ast.OnDuplicateKeyHandlingError
|
|
}
|
|
| "IGNORE"
|
|
{
|
|
$$ = ast.OnDuplicateKeyHandlingIgnore
|
|
}
|
|
| "REPLACE"
|
|
{
|
|
$$ = ast.OnDuplicateKeyHandlingReplace
|
|
}
|
|
|
|
AsOpt:
|
|
{}
|
|
| "AS"
|
|
{}
|
|
|
|
CreateTableSelectOpt:
|
|
/* empty */
|
|
{
|
|
$$ = &ast.CreateTableStmt{}
|
|
}
|
|
| SetOprStmt
|
|
{
|
|
$$ = &ast.CreateTableStmt{Select: $1.(ast.ResultSetNode)}
|
|
}
|
|
| SelectStmt
|
|
{
|
|
$$ = &ast.CreateTableStmt{Select: $1.(ast.ResultSetNode)}
|
|
}
|
|
| SelectStmtWithClause
|
|
{
|
|
$$ = &ast.CreateTableStmt{Select: $1.(ast.ResultSetNode)}
|
|
}
|
|
| SubSelect
|
|
{
|
|
var sel ast.ResultSetNode
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
case *ast.SetOprStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
}
|
|
$$ = &ast.CreateTableStmt{Select: sel}
|
|
}
|
|
|
|
CreateViewSelectOpt:
|
|
SetOprStmt
|
|
| SelectStmt
|
|
| SelectStmtWithClause
|
|
| SubSelect
|
|
{
|
|
var sel ast.StmtNode
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
case *ast.SetOprStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
}
|
|
$$ = sel
|
|
}
|
|
|
|
LikeTableWithOrWithoutParen:
|
|
"LIKE" TableName
|
|
{
|
|
$$ = $2
|
|
}
|
|
| '(' "LIKE" TableName ')'
|
|
{
|
|
$$ = $3
|
|
}
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Create View Statement
|
|
*
|
|
* Example:
|
|
* CREATE VIEW OR REPLACE ALGORITHM = MERGE DEFINER="root@localhost" SQL SECURITY = definer view_name (col1,col2)
|
|
* as select Col1,Col2 from table WITH LOCAL CHECK OPTION
|
|
*******************************************************************/
|
|
CreateViewStmt:
|
|
"CREATE" OrReplace ViewAlgorithm ViewDefiner ViewSQLSecurity "VIEW" ViewName ViewFieldList "AS" CreateViewSelectOpt ViewCheckOption
|
|
{
|
|
startOffset := parser.startOffset(&yyS[yypt-1])
|
|
selStmt := $10.(ast.StmtNode)
|
|
selStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:]))
|
|
x := &ast.CreateViewStmt{
|
|
OrReplace: $2.(bool),
|
|
ViewName: $7.(*ast.TableName),
|
|
Select: selStmt,
|
|
Algorithm: $3.(model.ViewAlgorithm),
|
|
Definer: $4.(*auth.UserIdentity),
|
|
Security: $5.(model.ViewSecurity),
|
|
}
|
|
if $8 != nil {
|
|
x.Cols = $8.([]model.CIStr)
|
|
}
|
|
if $11 != nil {
|
|
x.CheckOption = $11.(model.ViewCheckOption)
|
|
endOffset := parser.startOffset(&yyS[yypt])
|
|
selStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:endOffset]))
|
|
} else {
|
|
x.CheckOption = model.CheckOptionCascaded
|
|
}
|
|
$$ = x
|
|
}
|
|
|
|
OrReplace:
|
|
/* EMPTY */
|
|
{
|
|
$$ = false
|
|
}
|
|
| "OR" "REPLACE"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
ViewAlgorithm:
|
|
/* EMPTY */
|
|
{
|
|
$$ = model.AlgorithmUndefined
|
|
}
|
|
| "ALGORITHM" "=" "UNDEFINED"
|
|
{
|
|
$$ = model.AlgorithmUndefined
|
|
}
|
|
| "ALGORITHM" "=" "MERGE"
|
|
{
|
|
$$ = model.AlgorithmMerge
|
|
}
|
|
| "ALGORITHM" "=" "TEMPTABLE"
|
|
{
|
|
$$ = model.AlgorithmTemptable
|
|
}
|
|
|
|
ViewDefiner:
|
|
/* EMPTY */
|
|
{
|
|
$$ = &auth.UserIdentity{CurrentUser: true}
|
|
}
|
|
| "DEFINER" "=" Username
|
|
{
|
|
$$ = $3
|
|
}
|
|
|
|
ViewSQLSecurity:
|
|
/* EMPTY */
|
|
{
|
|
$$ = model.SecurityDefiner
|
|
}
|
|
| "SQL" "SECURITY" "DEFINER"
|
|
{
|
|
$$ = model.SecurityDefiner
|
|
}
|
|
| "SQL" "SECURITY" "INVOKER"
|
|
{
|
|
$$ = model.SecurityInvoker
|
|
}
|
|
|
|
ViewName:
|
|
TableName
|
|
|
|
ViewFieldList:
|
|
/* Empty */
|
|
{
|
|
$$ = nil
|
|
}
|
|
| '(' ColumnList ')'
|
|
{
|
|
$$ = $2.([]model.CIStr)
|
|
}
|
|
|
|
ColumnList:
|
|
Identifier
|
|
{
|
|
$$ = []model.CIStr{model.NewCIStr($1)}
|
|
}
|
|
| ColumnList ',' Identifier
|
|
{
|
|
$$ = append($1.([]model.CIStr), model.NewCIStr($3))
|
|
}
|
|
|
|
ViewCheckOption:
|
|
/* EMPTY */
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "WITH" "CASCADED" "CHECK" "OPTION"
|
|
{
|
|
$$ = model.CheckOptionCascaded
|
|
}
|
|
| "WITH" "LOCAL" "CHECK" "OPTION"
|
|
{
|
|
$$ = model.CheckOptionLocal
|
|
}
|
|
|
|
/******************************************************************
|
|
* Do statement
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/do.html
|
|
******************************************************************/
|
|
DoStmt:
|
|
"DO" ExpressionList
|
|
{
|
|
$$ = &ast.DoStmt{
|
|
Exprs: $2.([]ast.ExprNode),
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Delete Statement
|
|
*
|
|
*******************************************************************/
|
|
DeleteWithoutUsingStmt:
|
|
"DELETE" TableOptimizerHintsOpt PriorityOpt QuickOptional IgnoreOptional "FROM" TableName PartitionNameListOpt TableAsNameOpt IndexHintListOpt WhereClauseOptional OrderByOptional LimitClause
|
|
{
|
|
// Single Table
|
|
tn := $7.(*ast.TableName)
|
|
tn.IndexHints = $10.([]*ast.IndexHint)
|
|
tn.PartitionNames = $8.([]model.CIStr)
|
|
join := &ast.Join{Left: &ast.TableSource{Source: tn, AsName: $9.(model.CIStr)}, Right: nil}
|
|
x := &ast.DeleteStmt{
|
|
TableRefs: &ast.TableRefsClause{TableRefs: join},
|
|
Priority: $3.(mysql.PriorityEnum),
|
|
Quick: $4.(bool),
|
|
IgnoreErr: $5.(bool),
|
|
}
|
|
if $2 != nil {
|
|
x.TableHints = $2.([]*ast.TableOptimizerHint)
|
|
}
|
|
if $11 != nil {
|
|
x.Where = $11.(ast.ExprNode)
|
|
}
|
|
if $12 != nil {
|
|
x.Order = $12.(*ast.OrderByClause)
|
|
}
|
|
if $13 != nil {
|
|
x.Limit = $13.(*ast.Limit)
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
| "DELETE" TableOptimizerHintsOpt PriorityOpt QuickOptional IgnoreOptional TableAliasRefList "FROM" TableRefs WhereClauseOptional
|
|
{
|
|
// Multiple Table
|
|
x := &ast.DeleteStmt{
|
|
Priority: $3.(mysql.PriorityEnum),
|
|
Quick: $4.(bool),
|
|
IgnoreErr: $5.(bool),
|
|
IsMultiTable: true,
|
|
BeforeFrom: true,
|
|
Tables: &ast.DeleteTableList{Tables: $6.([]*ast.TableName)},
|
|
TableRefs: &ast.TableRefsClause{TableRefs: $8.(*ast.Join)},
|
|
}
|
|
if $2 != nil {
|
|
x.TableHints = $2.([]*ast.TableOptimizerHint)
|
|
}
|
|
if $9 != nil {
|
|
x.Where = $9.(ast.ExprNode)
|
|
}
|
|
$$ = x
|
|
}
|
|
|
|
DeleteWithUsingStmt:
|
|
"DELETE" TableOptimizerHintsOpt PriorityOpt QuickOptional IgnoreOptional "FROM" TableAliasRefList "USING" TableRefs WhereClauseOptional
|
|
{
|
|
// Multiple Table
|
|
x := &ast.DeleteStmt{
|
|
Priority: $3.(mysql.PriorityEnum),
|
|
Quick: $4.(bool),
|
|
IgnoreErr: $5.(bool),
|
|
IsMultiTable: true,
|
|
Tables: &ast.DeleteTableList{Tables: $7.([]*ast.TableName)},
|
|
TableRefs: &ast.TableRefsClause{TableRefs: $9.(*ast.Join)},
|
|
}
|
|
if $2 != nil {
|
|
x.TableHints = $2.([]*ast.TableOptimizerHint)
|
|
}
|
|
if $10 != nil {
|
|
x.Where = $10.(ast.ExprNode)
|
|
}
|
|
$$ = x
|
|
}
|
|
|
|
DeleteFromStmt:
|
|
DeleteWithoutUsingStmt
|
|
| DeleteWithUsingStmt
|
|
| WithClause DeleteWithoutUsingStmt
|
|
{
|
|
d := $2.(*ast.DeleteStmt)
|
|
d.With = $1.(*ast.WithClause)
|
|
$$ = d
|
|
}
|
|
| WithClause DeleteWithUsingStmt
|
|
{
|
|
d := $2.(*ast.DeleteStmt)
|
|
d.With = $1.(*ast.WithClause)
|
|
$$ = d
|
|
}
|
|
|
|
DatabaseSym:
|
|
"DATABASE"
|
|
|
|
DropDatabaseStmt:
|
|
"DROP" DatabaseSym IfExists DBName
|
|
{
|
|
$$ = &ast.DropDatabaseStmt{IfExists: $3.(bool), Name: model.NewCIStr($4)}
|
|
}
|
|
|
|
/******************************************************************
|
|
* Drop Index Statement
|
|
* See https://dev.mysql.com/doc/refman/8.0/en/drop-index.html
|
|
*
|
|
* DROP INDEX index_name ON tbl_name
|
|
* [algorithm_option | lock_option] ...
|
|
*
|
|
* algorithm_option:
|
|
* ALGORITHM [=] {DEFAULT|INPLACE|COPY}
|
|
*
|
|
* lock_option:
|
|
* LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}
|
|
******************************************************************/
|
|
DropIndexStmt:
|
|
"DROP" "INDEX" IfExists Identifier "ON" TableName IndexLockAndAlgorithmOpt
|
|
{
|
|
var indexLockAndAlgorithm *ast.IndexLockAndAlgorithm
|
|
if $7 != nil {
|
|
indexLockAndAlgorithm = $7.(*ast.IndexLockAndAlgorithm)
|
|
if indexLockAndAlgorithm.LockTp == ast.LockTypeDefault && indexLockAndAlgorithm.AlgorithmTp == ast.AlgorithmTypeDefault {
|
|
indexLockAndAlgorithm = nil
|
|
}
|
|
}
|
|
$$ = &ast.DropIndexStmt{IfExists: $3.(bool), IndexName: $4, Table: $6.(*ast.TableName), LockAlg: indexLockAndAlgorithm}
|
|
}
|
|
| "DROP" "HYPO" "INDEX" IfExists Identifier "ON" TableName
|
|
{
|
|
$$ = &ast.DropIndexStmt{IfExists: $4.(bool), IndexName: $5, Table: $7.(*ast.TableName), IsHypo: true}
|
|
}
|
|
|
|
DropTableStmt:
|
|
"DROP" OptTemporary TableOrTables IfExists TableNameList RestrictOrCascadeOpt
|
|
{
|
|
$$ = &ast.DropTableStmt{IfExists: $4.(bool), Tables: $5.([]*ast.TableName), IsView: false, TemporaryKeyword: $2.(ast.TemporaryKeyword)}
|
|
}
|
|
|
|
OptTemporary:
|
|
/* empty */
|
|
{
|
|
$$ = ast.TemporaryNone
|
|
}
|
|
| "TEMPORARY"
|
|
{
|
|
$$ = ast.TemporaryLocal
|
|
}
|
|
| "GLOBAL" "TEMPORARY"
|
|
{
|
|
$$ = ast.TemporaryGlobal
|
|
}
|
|
|
|
DropViewStmt:
|
|
"DROP" "VIEW" TableNameList RestrictOrCascadeOpt
|
|
{
|
|
$$ = &ast.DropTableStmt{Tables: $3.([]*ast.TableName), IsView: true}
|
|
}
|
|
| "DROP" "VIEW" "IF" "EXISTS" TableNameList RestrictOrCascadeOpt
|
|
{
|
|
$$ = &ast.DropTableStmt{IfExists: true, Tables: $5.([]*ast.TableName), IsView: true}
|
|
}
|
|
|
|
DropUserStmt:
|
|
"DROP" "USER" UsernameList
|
|
{
|
|
$$ = &ast.DropUserStmt{IsDropRole: false, IfExists: false, UserList: $3.([]*auth.UserIdentity)}
|
|
}
|
|
| "DROP" "USER" "IF" "EXISTS" UsernameList
|
|
{
|
|
$$ = &ast.DropUserStmt{IsDropRole: false, IfExists: true, UserList: $5.([]*auth.UserIdentity)}
|
|
}
|
|
|
|
DropRoleStmt:
|
|
"DROP" "ROLE" RolenameList
|
|
{
|
|
tmp := make([]*auth.UserIdentity, 0, 10)
|
|
roleList := $3.([]*auth.RoleIdentity)
|
|
for _, r := range roleList {
|
|
tmp = append(tmp, &auth.UserIdentity{Username: r.Username, Hostname: r.Hostname})
|
|
}
|
|
$$ = &ast.DropUserStmt{IsDropRole: true, IfExists: false, UserList: tmp}
|
|
}
|
|
| "DROP" "ROLE" "IF" "EXISTS" RolenameList
|
|
{
|
|
tmp := make([]*auth.UserIdentity, 0, 10)
|
|
roleList := $5.([]*auth.RoleIdentity)
|
|
for _, r := range roleList {
|
|
tmp = append(tmp, &auth.UserIdentity{Username: r.Username, Hostname: r.Hostname})
|
|
}
|
|
$$ = &ast.DropUserStmt{IsDropRole: true, IfExists: true, UserList: tmp}
|
|
}
|
|
|
|
DropStatsStmt:
|
|
"DROP" "STATS" TableNameList
|
|
{
|
|
$$ = &ast.DropStatsStmt{Tables: $3.([]*ast.TableName)}
|
|
}
|
|
| "DROP" "STATS" TableName "PARTITION" PartitionNameList
|
|
{
|
|
yylex.AppendError(ErrWarnDeprecatedSyntaxNoReplacement.FastGenByArgs("'DROP STATS ... PARTITION ...'",""))
|
|
parser.lastErrorAsWarn()
|
|
$$ = &ast.DropStatsStmt{
|
|
Tables: []*ast.TableName{$3.(*ast.TableName)},
|
|
PartitionNames: $5.([]model.CIStr),
|
|
}
|
|
}
|
|
| "DROP" "STATS" TableName "GLOBAL"
|
|
{
|
|
yylex.AppendError(ErrWarnDeprecatedSyntax.FastGenByArgs("DROP STATS ... GLOBAL", "DROP STATS ..."))
|
|
parser.lastErrorAsWarn()
|
|
$$ = &ast.DropStatsStmt{
|
|
Tables: []*ast.TableName{$3.(*ast.TableName)},
|
|
IsGlobalStats: true,
|
|
}
|
|
}
|
|
|
|
RestrictOrCascadeOpt:
|
|
{}
|
|
| "RESTRICT"
|
|
| "CASCADE"
|
|
|
|
TableOrTables:
|
|
"TABLE"
|
|
| "TABLES"
|
|
|
|
EqOpt:
|
|
{}
|
|
| eq
|
|
|
|
EmptyStmt:
|
|
/* EMPTY */
|
|
{
|
|
$$ = nil
|
|
}
|
|
|
|
TraceStmt:
|
|
"TRACE" TraceableStmt
|
|
{
|
|
$$ = &ast.TraceStmt{
|
|
Stmt: $2,
|
|
Format: "row",
|
|
TracePlan: false,
|
|
}
|
|
startOffset := parser.startOffset(&yyS[yypt])
|
|
$2.SetText(parser.lexer.client, string(parser.src[startOffset:]))
|
|
}
|
|
| "TRACE" "FORMAT" "=" stringLit TraceableStmt
|
|
{
|
|
$$ = &ast.TraceStmt{
|
|
Stmt: $5,
|
|
Format: $4,
|
|
TracePlan: false,
|
|
}
|
|
startOffset := parser.startOffset(&yyS[yypt])
|
|
$5.SetText(parser.lexer.client, string(parser.src[startOffset:]))
|
|
}
|
|
| "TRACE" "PLAN" TraceableStmt
|
|
{
|
|
$$ = &ast.TraceStmt{
|
|
Stmt: $3,
|
|
TracePlan: true,
|
|
}
|
|
startOffset := parser.startOffset(&yyS[yypt])
|
|
$3.SetText(parser.lexer.client, string(parser.src[startOffset:]))
|
|
}
|
|
| "TRACE" "PLAN" "TARGET" "=" stringLit TraceableStmt
|
|
{
|
|
$$ = &ast.TraceStmt{
|
|
Stmt: $6,
|
|
TracePlan: true,
|
|
TracePlanTarget: $5,
|
|
}
|
|
startOffset := parser.startOffset(&yyS[yypt])
|
|
$6.SetText(parser.lexer.client, string(parser.src[startOffset:]))
|
|
}
|
|
|
|
ExplainSym:
|
|
"EXPLAIN"
|
|
| "DESCRIBE"
|
|
| "DESC"
|
|
|
|
ExplainStmt:
|
|
ExplainSym TableName
|
|
{
|
|
$$ = &ast.ExplainStmt{
|
|
Stmt: &ast.ShowStmt{
|
|
Tp: ast.ShowColumns,
|
|
Table: $2.(*ast.TableName),
|
|
},
|
|
}
|
|
}
|
|
| ExplainSym TableName ColumnName
|
|
{
|
|
$$ = &ast.ExplainStmt{
|
|
Stmt: &ast.ShowStmt{
|
|
Tp: ast.ShowColumns,
|
|
Table: $2.(*ast.TableName),
|
|
Column: $3.(*ast.ColumnName),
|
|
},
|
|
}
|
|
}
|
|
| ExplainSym ExplainableStmt
|
|
{
|
|
$$ = &ast.ExplainStmt{
|
|
Stmt: $2,
|
|
Format: "row",
|
|
}
|
|
}
|
|
| ExplainSym "FOR" "CONNECTION" NUM
|
|
{
|
|
$$ = &ast.ExplainForStmt{
|
|
Format: "row",
|
|
ConnectionID: getUint64FromNUM($4),
|
|
}
|
|
}
|
|
| ExplainSym "FORMAT" "=" stringLit "FOR" "CONNECTION" NUM
|
|
{
|
|
$$ = &ast.ExplainForStmt{
|
|
Format: $4,
|
|
ConnectionID: getUint64FromNUM($7),
|
|
}
|
|
}
|
|
| ExplainSym "FORMAT" "=" stringLit ExplainableStmt
|
|
{
|
|
$$ = &ast.ExplainStmt{
|
|
Stmt: $5,
|
|
Format: $4,
|
|
}
|
|
}
|
|
| ExplainSym "FORMAT" "=" ExplainFormatType "FOR" "CONNECTION" NUM
|
|
{
|
|
$$ = &ast.ExplainForStmt{
|
|
Format: $4,
|
|
ConnectionID: getUint64FromNUM($7),
|
|
}
|
|
}
|
|
| ExplainSym "FORMAT" "=" ExplainFormatType ExplainableStmt
|
|
{
|
|
$$ = &ast.ExplainStmt{
|
|
Stmt: $5,
|
|
Format: $4,
|
|
}
|
|
}
|
|
| ExplainSym "ANALYZE" ExplainableStmt
|
|
{
|
|
$$ = &ast.ExplainStmt{
|
|
Stmt: $3,
|
|
Format: "row",
|
|
Analyze: true,
|
|
}
|
|
}
|
|
| ExplainSym "ANALYZE" "FORMAT" "=" ExplainFormatType ExplainableStmt
|
|
{
|
|
$$ = &ast.ExplainStmt{
|
|
Stmt: $6,
|
|
Format: $5,
|
|
Analyze: true,
|
|
}
|
|
}
|
|
| ExplainSym "ANALYZE" "FORMAT" "=" stringLit ExplainableStmt
|
|
{
|
|
$$ = &ast.ExplainStmt{
|
|
Stmt: $6,
|
|
Format: $5,
|
|
Analyze: true,
|
|
}
|
|
}
|
|
|
|
ExplainFormatType:
|
|
"TRADITIONAL"
|
|
| "JSON"
|
|
| "ROW"
|
|
| "DOT"
|
|
| "BRIEF"
|
|
| "VERBOSE"
|
|
| "TRUE_CARD_COST"
|
|
| "TIDB_JSON"
|
|
|
|
SavepointStmt:
|
|
"SAVEPOINT" Identifier
|
|
{
|
|
$$ = &ast.SavepointStmt{Name: $2}
|
|
}
|
|
|
|
ReleaseSavepointStmt:
|
|
"RELEASE" "SAVEPOINT" Identifier
|
|
{
|
|
$$ = &ast.ReleaseSavepointStmt{Name: $3}
|
|
}
|
|
|
|
/*******************************************************************
|
|
* Backup / restore / import statements
|
|
*
|
|
* BACKUP DATABASE [ * | db1, db2, db3 ] TO 'scheme://location' [ options... ]
|
|
* BACKUP TABLE [ db1.tbl1, db2.tbl2 ] TO 'scheme://location' [ options... ]
|
|
* RESTORE DATABASE [ * | db1, db2, db3 ] FROM 'scheme://location' [ options... ]
|
|
* RESTORE TABLE [ db1.tbl1, db2.tbl2 ] FROM 'scheme://location' [ options... ]
|
|
*/
|
|
BRIEStmt:
|
|
"BACKUP" BRIETables "TO" stringLit BRIEOptions
|
|
{
|
|
stmt := $2.(*ast.BRIEStmt)
|
|
stmt.Kind = ast.BRIEKindBackup
|
|
stmt.Storage = $4
|
|
stmt.Options = $5.([]*ast.BRIEOption)
|
|
$$ = stmt
|
|
}
|
|
| "BACKUP" "LOGS" "TO" stringLit BRIEOptions
|
|
{
|
|
stmt := &ast.BRIEStmt{}
|
|
stmt.Kind = ast.BRIEKindStreamStart
|
|
stmt.Storage = $4
|
|
stmt.Options = $5.([]*ast.BRIEOption)
|
|
$$ = stmt
|
|
}
|
|
| "STOP" "BACKUP" "LOGS"
|
|
{
|
|
stmt := &ast.BRIEStmt{}
|
|
stmt.Kind = ast.BRIEKindStreamStop
|
|
$$ = stmt
|
|
}
|
|
| "PAUSE" "BACKUP" "LOGS" BRIEOptions
|
|
{
|
|
stmt := &ast.BRIEStmt{}
|
|
stmt.Kind = ast.BRIEKindStreamPause
|
|
stmt.Options = $4.([]*ast.BRIEOption)
|
|
$$ = stmt
|
|
}
|
|
| "RESUME" "BACKUP" "LOGS"
|
|
{
|
|
stmt := &ast.BRIEStmt{}
|
|
stmt.Kind = ast.BRIEKindStreamResume
|
|
$$ = stmt
|
|
}
|
|
| "PURGE" "BACKUP" "LOGS" "FROM" stringLit BRIEOptions
|
|
{
|
|
stmt := &ast.BRIEStmt{}
|
|
stmt.Kind = ast.BRIEKindStreamPurge
|
|
stmt.Storage = $5
|
|
stmt.Options = $6.([]*ast.BRIEOption)
|
|
$$ = stmt
|
|
}
|
|
| "SHOW" "BACKUP" "LOGS" "STATUS"
|
|
{
|
|
stmt := &ast.BRIEStmt{}
|
|
stmt.Kind = ast.BRIEKindStreamStatus
|
|
$$ = stmt
|
|
}
|
|
| "SHOW" "BACKUP" "LOGS" "METADATA" "FROM" stringLit
|
|
{
|
|
stmt := &ast.BRIEStmt{}
|
|
stmt.Kind = ast.BRIEKindStreamMetaData
|
|
stmt.Storage = $6
|
|
$$ = stmt
|
|
}
|
|
| "SHOW" "BR" "JOB" Int64Num
|
|
{
|
|
stmt := &ast.BRIEStmt{}
|
|
stmt.Kind = ast.BRIEKindShowJob
|
|
stmt.JobID = $4.(int64)
|
|
$$ = stmt
|
|
}
|
|
| "SHOW" "BR" "JOB" "QUERY" Int64Num
|
|
{
|
|
stmt := &ast.BRIEStmt{}
|
|
stmt.Kind = ast.BRIEKindShowQuery
|
|
stmt.JobID = $5.(int64)
|
|
$$ = stmt
|
|
}
|
|
| "CANCEL" "BR" "JOB" Int64Num
|
|
{
|
|
stmt := &ast.BRIEStmt{}
|
|
stmt.Kind = ast.BRIEKindCancelJob
|
|
stmt.JobID = $4.(int64)
|
|
$$ = stmt
|
|
}
|
|
| "SHOW" "BACKUP" "METADATA" "FROM" stringLit
|
|
{
|
|
stmt := &ast.BRIEStmt{}
|
|
stmt.Kind = ast.BRIEKindShowBackupMeta
|
|
stmt.Storage = $5
|
|
$$ = stmt
|
|
}
|
|
| "RESTORE" BRIETables "FROM" stringLit BRIEOptions
|
|
{
|
|
stmt := $2.(*ast.BRIEStmt)
|
|
stmt.Kind = ast.BRIEKindRestore
|
|
stmt.Storage = $4
|
|
stmt.Options = $5.([]*ast.BRIEOption)
|
|
$$ = stmt
|
|
}
|
|
| "RESTORE" "POINT" "FROM" stringLit BRIEOptions
|
|
{
|
|
stmt := &ast.BRIEStmt{}
|
|
stmt.Kind = ast.BRIEKindRestorePIT
|
|
stmt.Storage = $4
|
|
stmt.Options = $5.([]*ast.BRIEOption)
|
|
$$ = stmt
|
|
}
|
|
|
|
BRIETables:
|
|
DatabaseSym '*'
|
|
{
|
|
$$ = &ast.BRIEStmt{}
|
|
}
|
|
| DatabaseSym DBNameList
|
|
{
|
|
$$ = &ast.BRIEStmt{Schemas: $2.([]string)}
|
|
}
|
|
| "TABLE" TableNameList
|
|
{
|
|
$$ = &ast.BRIEStmt{Tables: $2.([]*ast.TableName)}
|
|
}
|
|
|
|
DBNameList:
|
|
DBName
|
|
{
|
|
$$ = []string{$1}
|
|
}
|
|
| DBNameList ',' DBName
|
|
{
|
|
$$ = append($1.([]string), $3)
|
|
}
|
|
|
|
BRIEOptions:
|
|
%prec empty
|
|
{
|
|
$$ = []*ast.BRIEOption{}
|
|
}
|
|
| BRIEOptions BRIEOption
|
|
{
|
|
$$ = append($1.([]*ast.BRIEOption), $2.(*ast.BRIEOption))
|
|
}
|
|
|
|
BRIEIntegerOptionName:
|
|
"CONCURRENCY"
|
|
{
|
|
$$ = ast.BRIEOptionConcurrency
|
|
}
|
|
| "RESUME"
|
|
{
|
|
$$ = ast.BRIEOptionResume
|
|
}
|
|
|
|
BRIEBooleanOptionName:
|
|
"SEND_CREDENTIALS_TO_TIKV"
|
|
{
|
|
$$ = ast.BRIEOptionSendCreds
|
|
}
|
|
| "ONLINE"
|
|
{
|
|
$$ = ast.BRIEOptionOnline
|
|
}
|
|
| "CHECKPOINT"
|
|
{
|
|
$$ = ast.BRIEOptionCheckpoint
|
|
}
|
|
| "SKIP_SCHEMA_FILES"
|
|
{
|
|
$$ = ast.BRIEOptionSkipSchemaFiles
|
|
}
|
|
| "STRICT_FORMAT"
|
|
{
|
|
$$ = ast.BRIEOptionStrictFormat
|
|
}
|
|
| "CSV_NOT_NULL"
|
|
{
|
|
$$ = ast.BRIEOptionCSVNotNull
|
|
}
|
|
| "CSV_BACKSLASH_ESCAPE"
|
|
{
|
|
$$ = ast.BRIEOptionCSVBackslashEscape
|
|
}
|
|
| "CSV_TRIM_LAST_SEPARATORS"
|
|
{
|
|
$$ = ast.BRIEOptionCSVTrimLastSeparators
|
|
}
|
|
|
|
BRIEStringOptionName:
|
|
"TIKV_IMPORTER"
|
|
{
|
|
$$ = ast.BRIEOptionTiKVImporter
|
|
}
|
|
| "CSV_SEPARATOR"
|
|
{
|
|
$$ = ast.BRIEOptionCSVSeparator
|
|
}
|
|
| "CSV_DELIMITER"
|
|
{
|
|
$$ = ast.BRIEOptionCSVDelimiter
|
|
}
|
|
| "CSV_NULL"
|
|
{
|
|
$$ = ast.BRIEOptionCSVNull
|
|
}
|
|
|
|
BRIEKeywordOptionName:
|
|
"BACKEND"
|
|
{
|
|
$$ = ast.BRIEOptionBackend
|
|
}
|
|
| "ON_DUPLICATE"
|
|
{
|
|
$$ = ast.BRIEOptionOnDuplicate
|
|
}
|
|
| "ON" "DUPLICATE"
|
|
{
|
|
$$ = ast.BRIEOptionOnDuplicate
|
|
}
|
|
|
|
BRIEOption:
|
|
BRIEIntegerOptionName EqOpt LengthNum
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: $1.(ast.BRIEOptionType),
|
|
UintValue: $3.(uint64),
|
|
}
|
|
}
|
|
| BRIEBooleanOptionName EqOpt Boolean
|
|
{
|
|
value := uint64(0)
|
|
if $3.(bool) {
|
|
value = 1
|
|
}
|
|
$$ = &ast.BRIEOption{
|
|
Tp: $1.(ast.BRIEOptionType),
|
|
UintValue: value,
|
|
}
|
|
}
|
|
| BRIEStringOptionName EqOpt stringLit
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: $1.(ast.BRIEOptionType),
|
|
StrValue: $3,
|
|
}
|
|
}
|
|
| BRIEKeywordOptionName EqOpt StringNameOrBRIEOptionKeyword
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: $1.(ast.BRIEOptionType),
|
|
StrValue: strings.ToLower($3),
|
|
}
|
|
}
|
|
| "SNAPSHOT" EqOpt LengthNum TimestampUnit "AGO"
|
|
{
|
|
unit, err := $4.(ast.TimeUnitType).Duration()
|
|
if err != nil {
|
|
yylex.AppendError(err)
|
|
return 1
|
|
}
|
|
// TODO: check overflow?
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionBackupTimeAgo,
|
|
UintValue: $3.(uint64) * uint64(unit),
|
|
}
|
|
}
|
|
| "SNAPSHOT" EqOpt stringLit
|
|
// not including this into BRIEStringOptionName to avoid shift/reduce conflict
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionBackupTS,
|
|
StrValue: $3,
|
|
}
|
|
}
|
|
| "SNAPSHOT" EqOpt LengthNum
|
|
// not including this into BRIEIntegerOptionName to avoid shift/reduce conflict
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionBackupTSO,
|
|
UintValue: $3.(uint64),
|
|
}
|
|
}
|
|
| "LAST_BACKUP" EqOpt stringLit
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionLastBackupTS,
|
|
StrValue: $3,
|
|
}
|
|
}
|
|
| "LAST_BACKUP" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionLastBackupTSO,
|
|
UintValue: $3.(uint64),
|
|
}
|
|
}
|
|
| "RATE_LIMIT" EqOpt LengthNum "MB" '/' "SECOND"
|
|
{
|
|
// TODO: check overflow?
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionRateLimit,
|
|
UintValue: $3.(uint64) * 1048576,
|
|
}
|
|
}
|
|
| "CSV_HEADER" EqOpt FieldsOrColumns
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionCSVHeader,
|
|
UintValue: ast.BRIECSVHeaderIsColumns,
|
|
}
|
|
}
|
|
| "CSV_HEADER" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionCSVHeader,
|
|
UintValue: $3.(uint64),
|
|
}
|
|
}
|
|
| "CHECKSUM" EqOpt Boolean
|
|
{
|
|
value := uint64(0)
|
|
if $3.(bool) {
|
|
value = 1
|
|
}
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionChecksum,
|
|
UintValue: value,
|
|
}
|
|
}
|
|
| "CHECKSUM" EqOpt OptionLevel
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionChecksum,
|
|
UintValue: uint64($3.(ast.BRIEOptionLevel)),
|
|
}
|
|
}
|
|
| "ANALYZE" EqOpt Boolean
|
|
{
|
|
value := uint64(0)
|
|
if $3.(bool) {
|
|
value = 1
|
|
}
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionAnalyze,
|
|
UintValue: value,
|
|
}
|
|
}
|
|
| "ANALYZE" EqOpt OptionLevel
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionAnalyze,
|
|
UintValue: uint64($3.(ast.BRIEOptionLevel)),
|
|
}
|
|
}
|
|
| "FULL_BACKUP_STORAGE" EqOpt stringLit
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionFullBackupStorage,
|
|
StrValue: $3,
|
|
}
|
|
}
|
|
| "RESTORED_TS" EqOpt stringLit
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionRestoredTS,
|
|
StrValue: $3,
|
|
}
|
|
}
|
|
| "START_TS" EqOpt stringLit
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionStartTS,
|
|
StrValue: $3,
|
|
}
|
|
}
|
|
| "UNTIL_TS" EqOpt stringLit
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionUntilTS,
|
|
StrValue: $3,
|
|
}
|
|
}
|
|
| "GC_TTL" EqOpt stringLit
|
|
{
|
|
$$ = &ast.BRIEOption{
|
|
Tp: ast.BRIEOptionGCTTL,
|
|
StrValue: $3,
|
|
}
|
|
}
|
|
|
|
LengthNum:
|
|
NUM
|
|
{
|
|
$$ = getUint64FromNUM($1)
|
|
}
|
|
|
|
Int64Num:
|
|
NUM
|
|
{
|
|
v, rangeErrMsg := getInt64FromNUM($1)
|
|
if len(rangeErrMsg) != 0 {
|
|
yylex.AppendError(yylex.Errorf(rangeErrMsg))
|
|
return 1
|
|
}
|
|
$$ = v
|
|
}
|
|
|
|
NUM:
|
|
intLit
|
|
|
|
Boolean:
|
|
NUM
|
|
{
|
|
$$ = $1.(int64) != 0
|
|
}
|
|
| "FALSE"
|
|
{
|
|
$$ = false
|
|
}
|
|
| "TRUE"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
OptionLevel:
|
|
"OFF"
|
|
{
|
|
$$ = ast.BRIEOptionLevelOff
|
|
}
|
|
| "OPTIONAL"
|
|
{
|
|
$$ = ast.BRIEOptionLevelOptional
|
|
}
|
|
| "REQUIRED"
|
|
{
|
|
$$ = ast.BRIEOptionLevelRequired
|
|
}
|
|
|
|
PauseLoadDataStmt:
|
|
"PAUSE" "LOAD" "DATA" "JOB" Int64Num
|
|
{
|
|
$$ = &ast.LoadDataActionStmt{
|
|
Tp: ast.LoadDataPause,
|
|
JobID: $5.(int64),
|
|
}
|
|
}
|
|
|
|
ResumeLoadDataStmt:
|
|
"RESUME" "LOAD" "DATA" "JOB" Int64Num
|
|
{
|
|
$$ = &ast.LoadDataActionStmt{
|
|
Tp: ast.LoadDataResume,
|
|
JobID: $5.(int64),
|
|
}
|
|
}
|
|
|
|
CancelImportStmt:
|
|
"CANCEL" "IMPORT" "JOB" Int64Num
|
|
{
|
|
$$ = &ast.ImportIntoActionStmt{
|
|
Tp: ast.ImportIntoCancel,
|
|
JobID: $4.(int64),
|
|
}
|
|
}
|
|
|
|
DropLoadDataStmt:
|
|
"DROP" "LOAD" "DATA" "JOB" Int64Num
|
|
{
|
|
$$ = &ast.LoadDataActionStmt{
|
|
Tp: ast.LoadDataDrop,
|
|
JobID: $5.(int64),
|
|
}
|
|
}
|
|
|
|
Expression:
|
|
singleAtIdentifier assignmentEq Expression %prec assignmentEq
|
|
{
|
|
v := $1
|
|
v = strings.TrimPrefix(v, "@")
|
|
$$ = &ast.VariableExpr{
|
|
Name: v,
|
|
IsGlobal: false,
|
|
IsSystem: false,
|
|
Value: $3,
|
|
}
|
|
}
|
|
| Expression logOr Expression %prec pipes
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.LogicOr, L: $1, R: $3}
|
|
}
|
|
| Expression "XOR" Expression %prec xor
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.LogicXor, L: $1, R: $3}
|
|
}
|
|
| Expression logAnd Expression %prec andand
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.LogicAnd, L: $1, R: $3}
|
|
}
|
|
| "NOT" Expression %prec not
|
|
{
|
|
expr, ok := $2.(*ast.ExistsSubqueryExpr)
|
|
if ok {
|
|
expr.Not = !expr.Not
|
|
$$ = $2
|
|
} else {
|
|
$$ = &ast.UnaryOperationExpr{Op: opcode.Not, V: $2}
|
|
}
|
|
}
|
|
| "MATCH" '(' ColumnNameList ')' "AGAINST" '(' BitExpr FulltextSearchModifierOpt ')'
|
|
{
|
|
$$ = &ast.MatchAgainst{
|
|
ColumnNames: $3.([]*ast.ColumnName),
|
|
Against: $7,
|
|
Modifier: ast.FulltextSearchModifier($8.(int)),
|
|
}
|
|
}
|
|
| BoolPri IsOrNotOp trueKwd %prec is
|
|
{
|
|
$$ = &ast.IsTruthExpr{Expr: $1, Not: !$2.(bool), True: int64(1)}
|
|
}
|
|
| BoolPri IsOrNotOp falseKwd %prec is
|
|
{
|
|
$$ = &ast.IsTruthExpr{Expr: $1, Not: !$2.(bool), True: int64(0)}
|
|
}
|
|
| BoolPri IsOrNotOp "UNKNOWN" %prec is
|
|
{
|
|
/* https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_is */
|
|
$$ = &ast.IsNullExpr{Expr: $1, Not: !$2.(bool)}
|
|
}
|
|
| BoolPri
|
|
|
|
DefaultOrExpression:
|
|
"DEFAULT"
|
|
{
|
|
$$ = &ast.DefaultExpr{}
|
|
}
|
|
| BitExpr
|
|
|
|
MaxValueOrExpression:
|
|
"MAXVALUE"
|
|
{
|
|
$$ = &ast.MaxValueExpr{}
|
|
}
|
|
| BitExpr
|
|
|
|
FulltextSearchModifierOpt:
|
|
/* empty */
|
|
{
|
|
$$ = ast.FulltextSearchModifierNaturalLanguageMode
|
|
}
|
|
| "IN" "NATURAL" "LANGUAGE" "MODE"
|
|
{
|
|
$$ = ast.FulltextSearchModifierNaturalLanguageMode
|
|
}
|
|
| "IN" "NATURAL" "LANGUAGE" "MODE" "WITH" "QUERY" "EXPANSION"
|
|
{
|
|
$$ = ast.FulltextSearchModifierNaturalLanguageMode | ast.FulltextSearchModifierWithQueryExpansion
|
|
}
|
|
| "IN" "BOOLEAN" "MODE"
|
|
{
|
|
$$ = ast.FulltextSearchModifierBooleanMode
|
|
}
|
|
| "WITH" "QUERY" "EXPANSION"
|
|
{
|
|
$$ = ast.FulltextSearchModifierWithQueryExpansion
|
|
}
|
|
|
|
logOr:
|
|
pipesAsOr
|
|
| "OR"
|
|
|
|
logAnd:
|
|
"&&"
|
|
| "AND"
|
|
|
|
ExpressionList:
|
|
Expression
|
|
{
|
|
$$ = []ast.ExprNode{$1}
|
|
}
|
|
| ExpressionList ',' Expression
|
|
{
|
|
$$ = append($1.([]ast.ExprNode), $3)
|
|
}
|
|
|
|
MaxValueOrExpressionList:
|
|
MaxValueOrExpression
|
|
{
|
|
$$ = []ast.ExprNode{$1}
|
|
}
|
|
| MaxValueOrExpressionList ',' MaxValueOrExpression
|
|
{
|
|
$$ = append($1.([]ast.ExprNode), $3)
|
|
}
|
|
|
|
DefaultOrExpressionList:
|
|
DefaultOrExpression
|
|
{
|
|
$$ = []ast.ExprNode{$1}
|
|
}
|
|
| DefaultOrExpressionList ',' DefaultOrExpression
|
|
{
|
|
$$ = append($1.([]ast.ExprNode), $3)
|
|
}
|
|
|
|
ExpressionListOpt:
|
|
{
|
|
$$ = []ast.ExprNode{}
|
|
}
|
|
| ExpressionList
|
|
|
|
FuncDatetimePrecListOpt:
|
|
{
|
|
$$ = []ast.ExprNode{}
|
|
}
|
|
| FuncDatetimePrecList
|
|
|
|
FuncDatetimePrecList:
|
|
intLit
|
|
{
|
|
expr := ast.NewValueExpr($1, parser.charset, parser.collation)
|
|
$$ = []ast.ExprNode{expr}
|
|
}
|
|
|
|
BoolPri:
|
|
BoolPri IsOrNotOp "NULL" %prec is
|
|
{
|
|
$$ = &ast.IsNullExpr{Expr: $1, Not: !$2.(bool)}
|
|
}
|
|
| BoolPri CompareOp PredicateExpr %prec eq
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: $2.(opcode.Op), L: $1, R: $3}
|
|
}
|
|
| BoolPri CompareOp AnyOrAll SubSelect %prec eq
|
|
{
|
|
sq := $4.(*ast.SubqueryExpr)
|
|
sq.MultiRows = true
|
|
$$ = &ast.CompareSubqueryExpr{Op: $2.(opcode.Op), L: $1, R: sq, All: $3.(bool)}
|
|
}
|
|
| BoolPri CompareOp singleAtIdentifier assignmentEq PredicateExpr %prec assignmentEq
|
|
{
|
|
v := $3
|
|
v = strings.TrimPrefix(v, "@")
|
|
variable := &ast.VariableExpr{
|
|
Name: v,
|
|
IsGlobal: false,
|
|
IsSystem: false,
|
|
Value: $5,
|
|
}
|
|
$$ = &ast.BinaryOperationExpr{Op: $2.(opcode.Op), L: $1, R: variable}
|
|
}
|
|
| PredicateExpr
|
|
|
|
CompareOp:
|
|
">="
|
|
{
|
|
$$ = opcode.GE
|
|
}
|
|
| '>'
|
|
{
|
|
$$ = opcode.GT
|
|
}
|
|
| "<="
|
|
{
|
|
$$ = opcode.LE
|
|
}
|
|
| '<'
|
|
{
|
|
$$ = opcode.LT
|
|
}
|
|
| "!="
|
|
{
|
|
$$ = opcode.NE
|
|
}
|
|
| "<>"
|
|
{
|
|
$$ = opcode.NE
|
|
}
|
|
| "="
|
|
{
|
|
$$ = opcode.EQ
|
|
}
|
|
| "<=>"
|
|
{
|
|
$$ = opcode.NullEQ
|
|
}
|
|
|
|
BetweenOrNotOp:
|
|
"BETWEEN"
|
|
{
|
|
$$ = true
|
|
}
|
|
| NotSym "BETWEEN"
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
IsOrNotOp:
|
|
"IS"
|
|
{
|
|
$$ = true
|
|
}
|
|
| "IS" NotSym
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
InOrNotOp:
|
|
"IN"
|
|
{
|
|
$$ = true
|
|
}
|
|
| NotSym "IN"
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
LikeOrNotOp:
|
|
"LIKE"
|
|
{
|
|
$$ = true
|
|
}
|
|
| NotSym "LIKE"
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
IlikeOrNotOp:
|
|
"ILIKE"
|
|
{
|
|
$$ = true
|
|
}
|
|
| NotSym "ILIKE"
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
RegexpOrNotOp:
|
|
RegexpSym
|
|
{
|
|
$$ = true
|
|
}
|
|
| NotSym RegexpSym
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
AnyOrAll:
|
|
"ANY"
|
|
{
|
|
$$ = false
|
|
}
|
|
| "SOME"
|
|
{
|
|
$$ = false
|
|
}
|
|
| "ALL"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
PredicateExpr:
|
|
BitExpr InOrNotOp '(' ExpressionList ')'
|
|
{
|
|
$$ = &ast.PatternInExpr{Expr: $1, Not: !$2.(bool), List: $4.([]ast.ExprNode)}
|
|
}
|
|
| BitExpr InOrNotOp SubSelect
|
|
{
|
|
sq := $3.(*ast.SubqueryExpr)
|
|
sq.MultiRows = true
|
|
$$ = &ast.PatternInExpr{Expr: $1, Not: !$2.(bool), Sel: sq}
|
|
}
|
|
| BitExpr BetweenOrNotOp BitExpr "AND" PredicateExpr
|
|
{
|
|
$$ = &ast.BetweenExpr{
|
|
Expr: $1,
|
|
Left: $3,
|
|
Right: $5,
|
|
Not: !$2.(bool),
|
|
}
|
|
}
|
|
| BitExpr LikeOrNotOp SimpleExpr LikeOrIlikeEscapeOpt
|
|
{
|
|
escape := $4
|
|
if len(escape) > 1 {
|
|
yylex.AppendError(ErrWrongArguments.GenWithStackByArgs("ESCAPE"))
|
|
return 1
|
|
} else if len(escape) == 0 {
|
|
escape = "\\"
|
|
}
|
|
$$ = &ast.PatternLikeOrIlikeExpr{
|
|
Expr: $1,
|
|
Pattern: $3,
|
|
Not: !$2.(bool),
|
|
Escape: escape[0],
|
|
IsLike: true,
|
|
}
|
|
}
|
|
| BitExpr IlikeOrNotOp SimpleExpr LikeOrIlikeEscapeOpt
|
|
{
|
|
escape := $4
|
|
if len(escape) > 1 {
|
|
yylex.AppendError(ErrWrongArguments.GenWithStackByArgs("ESCAPE"))
|
|
return 1
|
|
} else if len(escape) == 0 {
|
|
escape = "\\"
|
|
}
|
|
$$ = &ast.PatternLikeOrIlikeExpr{
|
|
Expr: $1,
|
|
Pattern: $3,
|
|
Not: !$2.(bool),
|
|
Escape: escape[0],
|
|
IsLike: false,
|
|
}
|
|
}
|
|
| BitExpr RegexpOrNotOp SimpleExpr
|
|
{
|
|
$$ = &ast.PatternRegexpExpr{Expr: $1, Pattern: $3, Not: !$2.(bool)}
|
|
}
|
|
| BitExpr memberof '(' SimpleExpr ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONMemberOf), Args: []ast.ExprNode{$1, $4}}
|
|
}
|
|
| BitExpr
|
|
|
|
RegexpSym:
|
|
"REGEXP"
|
|
| "RLIKE"
|
|
|
|
LikeOrIlikeEscapeOpt:
|
|
%prec empty
|
|
{
|
|
$$ = "\\"
|
|
}
|
|
| "ESCAPE" stringLit
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
Field:
|
|
'*' %prec '*'
|
|
{
|
|
$$ = &ast.SelectField{WildCard: &ast.WildCardField{}}
|
|
}
|
|
| Identifier '.' '*' %prec '*'
|
|
{
|
|
wildCard := &ast.WildCardField{Table: model.NewCIStr($1)}
|
|
$$ = &ast.SelectField{WildCard: wildCard}
|
|
}
|
|
| Identifier '.' Identifier '.' '*' %prec '*'
|
|
{
|
|
wildCard := &ast.WildCardField{Schema: model.NewCIStr($1), Table: model.NewCIStr($3)}
|
|
$$ = &ast.SelectField{WildCard: wildCard}
|
|
}
|
|
| Expression FieldAsNameOpt
|
|
{
|
|
expr := $1
|
|
asName := $2
|
|
$$ = &ast.SelectField{Expr: expr, AsName: model.NewCIStr(asName)}
|
|
}
|
|
|
|
FieldAsNameOpt:
|
|
/* EMPTY */
|
|
{
|
|
$$ = ""
|
|
}
|
|
| FieldAsName
|
|
|
|
FieldAsName:
|
|
Identifier
|
|
| "AS" Identifier
|
|
{
|
|
$$ = $2
|
|
}
|
|
| stringLit
|
|
| "AS" stringLit
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
FieldList:
|
|
Field
|
|
{
|
|
field := $1.(*ast.SelectField)
|
|
field.Offset = parser.startOffset(&yyS[yypt])
|
|
if field.Expr != nil {
|
|
endOffset := parser.yylval.offset
|
|
field.SetText(parser.lexer.client, strings.TrimSpace(parser.src[field.Offset:endOffset]))
|
|
}
|
|
$$ = []*ast.SelectField{field}
|
|
}
|
|
| FieldList ',' Field
|
|
{
|
|
fl := $1.([]*ast.SelectField)
|
|
field := $3.(*ast.SelectField)
|
|
field.Offset = parser.startOffset(&yyS[yypt])
|
|
if field.Expr != nil {
|
|
endOffset := parser.yylval.offset
|
|
field.SetText(parser.lexer.client, strings.TrimSpace(parser.src[field.Offset:endOffset]))
|
|
}
|
|
$$ = append(fl, field)
|
|
}
|
|
|
|
WithRollupClause:
|
|
%prec lowerThanWith
|
|
{
|
|
$$ = false
|
|
}
|
|
| "WITH" "ROLLUP"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
GroupByClause:
|
|
"GROUP" "BY" ByList WithRollupClause
|
|
{
|
|
$$ = &ast.GroupByClause{Items: $3.([]*ast.ByItem), Rollup: $4.(bool)}
|
|
}
|
|
|
|
HavingClause:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "HAVING" Expression
|
|
{
|
|
$$ = &ast.HavingClause{Expr: $2}
|
|
}
|
|
|
|
AsOfClauseOpt:
|
|
%prec empty
|
|
{
|
|
$$ = nil
|
|
}
|
|
| AsOfClause
|
|
|
|
AsOfClause:
|
|
asof "TIMESTAMP" Expression
|
|
{
|
|
$$ = &ast.AsOfClause{
|
|
TsExpr: $3.(ast.ExprNode),
|
|
}
|
|
}
|
|
|
|
IfExists:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "IF" "EXISTS"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
IfNotExists:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "IF" NotSym "EXISTS"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
IgnoreOptional:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "IGNORE"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
IndexName:
|
|
{
|
|
$$ = &ast.NullString{
|
|
String: "",
|
|
Empty: false,
|
|
}
|
|
}
|
|
| Identifier
|
|
{
|
|
$$ = &ast.NullString{
|
|
String: $1,
|
|
Empty: len($1) == 0,
|
|
}
|
|
}
|
|
|
|
IndexOptionList:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| IndexOptionList IndexOption
|
|
{
|
|
// Merge the options
|
|
if $1 == nil {
|
|
$$ = $2
|
|
} else {
|
|
opt1 := $1.(*ast.IndexOption)
|
|
opt2 := $2.(*ast.IndexOption)
|
|
if len(opt2.Comment) > 0 {
|
|
opt1.Comment = opt2.Comment
|
|
} else if opt2.Tp != 0 {
|
|
opt1.Tp = opt2.Tp
|
|
} else if opt2.KeyBlockSize > 0 {
|
|
opt1.KeyBlockSize = opt2.KeyBlockSize
|
|
} else if len(opt2.ParserName.O) > 0 {
|
|
opt1.ParserName = opt2.ParserName
|
|
} else if opt2.Visibility != ast.IndexVisibilityDefault {
|
|
opt1.Visibility = opt2.Visibility
|
|
} else if opt2.PrimaryKeyTp != model.PrimaryKeyTypeDefault {
|
|
opt1.PrimaryKeyTp = opt2.PrimaryKeyTp
|
|
}
|
|
$$ = opt1
|
|
}
|
|
}
|
|
|
|
IndexOption:
|
|
"KEY_BLOCK_SIZE" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.IndexOption{
|
|
KeyBlockSize: $3.(uint64),
|
|
}
|
|
}
|
|
| IndexType
|
|
{
|
|
$$ = &ast.IndexOption{
|
|
Tp: $1.(model.IndexType),
|
|
}
|
|
}
|
|
| "WITH" "PARSER" Identifier
|
|
{
|
|
$$ = &ast.IndexOption{
|
|
ParserName: model.NewCIStr($3),
|
|
}
|
|
yylex.AppendError(yylex.Errorf("The WITH PARASER clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "COMMENT" stringLit
|
|
{
|
|
$$ = &ast.IndexOption{
|
|
Comment: $2,
|
|
}
|
|
}
|
|
| IndexInvisible
|
|
{
|
|
$$ = &ast.IndexOption{
|
|
Visibility: $1.(ast.IndexVisibility),
|
|
}
|
|
}
|
|
| WithClustered
|
|
{
|
|
$$ = &ast.IndexOption{
|
|
PrimaryKeyTp: $1.(model.PrimaryKeyType),
|
|
}
|
|
}
|
|
|
|
/*
|
|
See: https://github.com/mysql/mysql-server/blob/8.0/sql/sql_yacc.yy#L7179
|
|
|
|
The syntax for defining an index is:
|
|
|
|
... INDEX [index_name] [USING|TYPE] <index_type> ...
|
|
|
|
The problem is that whereas USING is a reserved word, TYPE is not. We can
|
|
still handle it if an index name is supplied, i.e.:
|
|
|
|
... INDEX type TYPE <index_type> ...
|
|
|
|
here the index's name is unmbiguously 'type', but for this:
|
|
|
|
... INDEX TYPE <index_type> ...
|
|
|
|
it's impossible to know what this actually mean - is 'type' the name or the
|
|
type? For this reason we accept the TYPE syntax only if a name is supplied.
|
|
*/
|
|
IndexNameAndTypeOpt:
|
|
IndexName
|
|
{
|
|
$$ = []interface{}{$1, nil}
|
|
}
|
|
| IndexName "USING" IndexTypeName
|
|
{
|
|
$$ = []interface{}{$1, $3}
|
|
}
|
|
| Identifier "TYPE" IndexTypeName
|
|
{
|
|
$$ = []interface{}{&ast.NullString{String: $1, Empty: len($1) == 0}, $3}
|
|
}
|
|
|
|
IndexTypeOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| IndexType
|
|
|
|
IndexType:
|
|
"USING" IndexTypeName
|
|
{
|
|
$$ = $2
|
|
}
|
|
| "TYPE" IndexTypeName
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
IndexTypeName:
|
|
"BTREE"
|
|
{
|
|
$$ = model.IndexTypeBtree
|
|
}
|
|
| "HASH"
|
|
{
|
|
$$ = model.IndexTypeHash
|
|
}
|
|
| "RTREE"
|
|
{
|
|
$$ = model.IndexTypeRtree
|
|
}
|
|
| "HYPO"
|
|
{
|
|
$$ = model.IndexTypeHypo
|
|
}
|
|
|
|
IndexInvisible:
|
|
"VISIBLE"
|
|
{
|
|
$$ = ast.IndexVisibilityVisible
|
|
}
|
|
| "INVISIBLE"
|
|
{
|
|
$$ = ast.IndexVisibilityInvisible
|
|
}
|
|
|
|
/**********************************Identifier********************************************/
|
|
Identifier:
|
|
identifier
|
|
| UnReservedKeyword
|
|
| NotKeywordToken
|
|
| TiDBKeyword
|
|
|
|
UnReservedKeyword:
|
|
"ACTION"
|
|
| "ADVISE"
|
|
| "ASCII"
|
|
| "ATTRIBUTE"
|
|
| "ATTRIBUTES"
|
|
| "BINDING_CACHE"
|
|
| "STATS_OPTIONS"
|
|
| "STATS_SAMPLE_RATE"
|
|
| "STATS_COL_CHOICE"
|
|
| "STATS_COL_LIST"
|
|
| "AUTO_ID_CACHE"
|
|
| "AUTO_INCREMENT"
|
|
| "AFTER"
|
|
| "ALWAYS"
|
|
| "AVG"
|
|
| "BEGIN"
|
|
| "BIT"
|
|
| "BOOL"
|
|
| "BOOLEAN"
|
|
| "BTREE"
|
|
| "BYTE"
|
|
| "CAPTURE"
|
|
| "CAUSAL"
|
|
| "CLEANUP"
|
|
| "CLOSE"
|
|
| "CHAIN"
|
|
| "CHARSET"
|
|
| "COLUMNS"
|
|
| "CONFIG"
|
|
| "SAN"
|
|
| "COMMIT"
|
|
| "COMPACT"
|
|
| "COMPRESSED"
|
|
| "CONSISTENCY"
|
|
| "CONSISTENT"
|
|
| "CURRENT"
|
|
| "DATA"
|
|
| "DATE" %prec lowerThanStringLitToken
|
|
| "DATETIME"
|
|
| "DAY"
|
|
| "DEALLOCATE"
|
|
| "DO"
|
|
| "DUPLICATE"
|
|
| "DYNAMIC"
|
|
| "ENCRYPTION"
|
|
| "END"
|
|
| "ENFORCED"
|
|
| "ENGINE"
|
|
| "ENGINES"
|
|
| "ENUM"
|
|
| "ERROR"
|
|
| "ERRORS"
|
|
| "ESCAPE"
|
|
| "EVOLVE"
|
|
| "EXECUTE"
|
|
| "EXTENDED"
|
|
| "FIELDS"
|
|
| "FILE"
|
|
| "FIRST"
|
|
| "FIXED"
|
|
| "FLUSH"
|
|
| "FOLLOWING"
|
|
| "FORMAT"
|
|
| "FULL"
|
|
| "GENERAL"
|
|
| "GLOBAL"
|
|
| "HASH"
|
|
| "HELP"
|
|
| "HOUR"
|
|
| "INSERT_METHOD"
|
|
| "LESS"
|
|
| "LOCAL"
|
|
| "LAST"
|
|
| "NAMES"
|
|
| "NVARCHAR"
|
|
| "OFFSET"
|
|
| "PACK_KEYS"
|
|
| "PARSER"
|
|
| "PASSWORD" %prec lowerThanEq
|
|
| "PREPARE"
|
|
| "PRE_SPLIT_REGIONS"
|
|
| "PROXY"
|
|
| "QUICK"
|
|
| "REBUILD"
|
|
| "REDUNDANT"
|
|
| "REORGANIZE"
|
|
| "RESOURCE"
|
|
| "RESTART"
|
|
| "ROLE"
|
|
| "ROLLBACK"
|
|
| "ROLLUP"
|
|
| "SESSION"
|
|
| "SIGNED"
|
|
| "SHARD_ROW_ID_BITS"
|
|
| "SHUTDOWN"
|
|
| "SNAPSHOT"
|
|
| "START"
|
|
| "STATUS"
|
|
| "OPEN"
|
|
| "POINT"
|
|
| "SUBPARTITIONS"
|
|
| "SUBPARTITION"
|
|
| "TABLES"
|
|
| "TABLESPACE"
|
|
| "TEXT"
|
|
| "THAN"
|
|
| "TIME" %prec lowerThanStringLitToken
|
|
| "TIMESTAMP" %prec lowerThanStringLitToken
|
|
| "TRACE"
|
|
| "TRANSACTION"
|
|
| "TRUNCATE"
|
|
| "UNBOUNDED"
|
|
| "UNKNOWN"
|
|
| "VALUE" %prec lowerThanValueKeyword
|
|
| "WARNINGS"
|
|
| "YEAR"
|
|
| "MODE"
|
|
| "WEEK"
|
|
| "WEIGHT_STRING"
|
|
| "ANY"
|
|
| "SOME"
|
|
| "USER"
|
|
| "IDENTIFIED"
|
|
| "COLLATION"
|
|
| "COMMENT"
|
|
| "AVG_ROW_LENGTH"
|
|
| "CONNECTION"
|
|
| "CHECKSUM"
|
|
| "COMPRESSION"
|
|
| "KEY_BLOCK_SIZE"
|
|
| "MASTER"
|
|
| "MAX_ROWS"
|
|
| "MIN_ROWS"
|
|
| "NATIONAL"
|
|
| "NCHAR"
|
|
| "ROW_FORMAT"
|
|
| "QUARTER"
|
|
| "GRANTS"
|
|
| "TRIGGERS"
|
|
| "DELAY_KEY_WRITE"
|
|
| "ISOLATION"
|
|
| "JSON"
|
|
| "REPEATABLE"
|
|
| "RESPECT"
|
|
| "COMMITTED"
|
|
| "UNCOMMITTED"
|
|
| "ONLY"
|
|
| "SERIAL"
|
|
| "SERIALIZABLE"
|
|
| "LEVEL"
|
|
| "VARIABLES"
|
|
| "SQL_CACHE"
|
|
| "INDEXES"
|
|
| "PROCESSLIST"
|
|
| "SQL_NO_CACHE"
|
|
| "DISABLE"
|
|
| "DISABLED"
|
|
| "ENABLE"
|
|
| "ENABLED"
|
|
| "REVERSE"
|
|
| "PRIVILEGES"
|
|
| "NO"
|
|
| "BINLOG"
|
|
| "FUNCTION"
|
|
| "VIEW"
|
|
| "BINDING"
|
|
| "BINDINGS"
|
|
| "MODIFY"
|
|
| "EVENTS"
|
|
| "PARTITIONS"
|
|
| "NONE"
|
|
| "NULLS"
|
|
| "SUPER"
|
|
| "EXCLUSIVE"
|
|
| "STATS_PERSISTENT"
|
|
| "STATS_AUTO_RECALC"
|
|
| "ROW_COUNT"
|
|
| "COALESCE"
|
|
| "MONTH"
|
|
| "PROCESS"
|
|
| "PROFILE"
|
|
| "PROFILES"
|
|
| "MICROSECOND"
|
|
| "MINUTE"
|
|
| "PLUGINS"
|
|
| "PRECEDING"
|
|
| "QUERY"
|
|
| "QUERIES"
|
|
| "SAVEPOINT"
|
|
| "SECOND"
|
|
| "SEPARATOR"
|
|
| "SHARE"
|
|
| "SHARED"
|
|
| "SLOW"
|
|
| "MAX_CONNECTIONS_PER_HOUR"
|
|
| "MAX_QUERIES_PER_HOUR"
|
|
| "MAX_UPDATES_PER_HOUR"
|
|
| "MAX_USER_CONNECTIONS"
|
|
| "REPLICATION"
|
|
| "CLIENT"
|
|
| "SLAVE"
|
|
| "RELOAD"
|
|
| "TEMPORARY"
|
|
| "ROUTINE"
|
|
| "EVENT"
|
|
| "ALGORITHM"
|
|
| "DEFINER"
|
|
| "INVOKER"
|
|
| "MERGE"
|
|
| "TEMPTABLE"
|
|
| "UNDEFINED"
|
|
| "SECURITY"
|
|
| "CASCADED"
|
|
| "RECOVER"
|
|
| "CIPHER"
|
|
| "SUBJECT"
|
|
| "ISSUER"
|
|
| "X509"
|
|
| "NEVER"
|
|
| "EXPIRE"
|
|
| "ACCOUNT"
|
|
| "INCREMENTAL"
|
|
| "CPU"
|
|
| "MEMBER"
|
|
| "MEMORY"
|
|
| "BLOCK"
|
|
| "IO"
|
|
| "CONTEXT"
|
|
| "SWITCHES"
|
|
| "PAGE"
|
|
| "FAULTS"
|
|
| "IPC"
|
|
| "SWAPS"
|
|
| "SOURCE"
|
|
| "TRADITIONAL"
|
|
| "SQL_BUFFER_RESULT"
|
|
| "DIRECTORY"
|
|
| "HISTOGRAM"
|
|
| "HISTORY"
|
|
| "LIST"
|
|
| "NODEGROUP"
|
|
| "SYSTEM_TIME"
|
|
| "PARTIAL"
|
|
| "SIMPLE"
|
|
| "REMOVE"
|
|
| "PARTITIONING"
|
|
| "STORAGE"
|
|
| "DISK"
|
|
| "STATS_SAMPLE_PAGES"
|
|
| "SECONDARY_ENGINE"
|
|
| "SECONDARY_LOAD"
|
|
| "SECONDARY_UNLOAD"
|
|
| "VALIDATION"
|
|
| "WITHOUT"
|
|
| "RTREE"
|
|
| "HYPO"
|
|
| "EXCHANGE"
|
|
| "COLUMN_FORMAT"
|
|
| "REPAIR"
|
|
| "IMPORT"
|
|
| "IMPORTS"
|
|
| "DISCARD"
|
|
| "TABLE_CHECKSUM"
|
|
| "UNICODE"
|
|
| "AUTO_RANDOM"
|
|
| "AUTO_RANDOM_BASE"
|
|
| "SQL_TSI_DAY"
|
|
| "SQL_TSI_HOUR"
|
|
| "SQL_TSI_MINUTE"
|
|
| "SQL_TSI_MONTH"
|
|
| "SQL_TSI_QUARTER"
|
|
| "SQL_TSI_SECOND"
|
|
| "LANGUAGE"
|
|
| "SQL_TSI_WEEK"
|
|
| "SQL_TSI_YEAR"
|
|
| "INVISIBLE"
|
|
| "VISIBLE"
|
|
| "TYPE"
|
|
| "NOWAIT"
|
|
| "INSTANCE"
|
|
| "REPLICA"
|
|
| "LOCATION"
|
|
| "LABELS"
|
|
| "LOGS"
|
|
| "HOSTS"
|
|
| "AGAINST"
|
|
| "EXPANSION"
|
|
| "INCREMENT"
|
|
| "MINVALUE"
|
|
| "NOMAXVALUE"
|
|
| "NOMINVALUE"
|
|
| "NOCACHE"
|
|
| "CACHE"
|
|
| "CYCLE"
|
|
| "NOCYCLE"
|
|
| "SEQUENCE"
|
|
| "MAX_MINUTES"
|
|
| "MAX_IDXNUM"
|
|
| "PER_TABLE"
|
|
| "PER_DB"
|
|
| "NEXT"
|
|
| "NEXTVAL"
|
|
| "LASTVAL"
|
|
| "SETVAL"
|
|
| "AGO"
|
|
| "BACKUP"
|
|
| "BACKUPS"
|
|
| "CONCURRENCY"
|
|
| "MB"
|
|
| "ONLINE"
|
|
| "RATE_LIMIT"
|
|
| "RESTORE"
|
|
| "RESTORES"
|
|
| "SEND_CREDENTIALS_TO_TIKV"
|
|
| "LAST_BACKUP"
|
|
| "CHECKPOINT"
|
|
| "SKIP_SCHEMA_FILES"
|
|
| "STRICT_FORMAT"
|
|
| "BACKEND"
|
|
| "CSV_BACKSLASH_ESCAPE"
|
|
| "CSV_NOT_NULL"
|
|
| "CSV_TRIM_LAST_SEPARATORS"
|
|
| "CSV_DELIMITER"
|
|
| "CSV_HEADER"
|
|
| "CSV_NULL"
|
|
| "CSV_SEPARATOR"
|
|
| "ON_DUPLICATE"
|
|
| "TIKV_IMPORTER"
|
|
| "REPLICAS"
|
|
| "POLICY"
|
|
| "WAIT"
|
|
| "CLIENT_ERRORS_SUMMARY"
|
|
| "BERNOULLI"
|
|
| "SYSTEM"
|
|
| "PERCENT"
|
|
| "PAUSE"
|
|
| "RESUME"
|
|
| "OFF"
|
|
| "OPTIONAL"
|
|
| "REQUIRED"
|
|
| "PURGE"
|
|
| "SKIP"
|
|
| "LOCKED"
|
|
| "CLUSTER"
|
|
| "CLUSTERED"
|
|
| "NONCLUSTERED"
|
|
| "PRESERVE"
|
|
| "TOKEN_ISSUER"
|
|
| "TTL"
|
|
| "TTL_ENABLE"
|
|
| "TTL_JOB_INTERVAL"
|
|
| "FAILED_LOGIN_ATTEMPTS"
|
|
| "PASSWORD_LOCK_TIME"
|
|
| "DIGEST"
|
|
| "REUSE" %prec lowerThanEq
|
|
| "DECLARE"
|
|
| "HANDLER"
|
|
| "FOUND"
|
|
| "CALIBRATE"
|
|
| "WORKLOAD"
|
|
| "TPCC"
|
|
| "OLTP_READ_WRITE"
|
|
| "OLTP_READ_ONLY"
|
|
| "OLTP_WRITE_ONLY"
|
|
|
|
TiDBKeyword:
|
|
"ADMIN"
|
|
| "BATCH"
|
|
| "BUCKETS"
|
|
| "BUILTINS"
|
|
| "CANCEL"
|
|
| "CARDINALITY"
|
|
| "CMSKETCH"
|
|
| "COLUMN_STATS_USAGE"
|
|
| "CORRELATION"
|
|
| "DDL"
|
|
| "DEPENDENCY"
|
|
| "DEPTH"
|
|
| "DRAINER"
|
|
| "JOBS"
|
|
| "JOB"
|
|
| "NODE_ID"
|
|
| "NODE_STATE"
|
|
| "PUMP"
|
|
| "SAMPLES"
|
|
| "SAMPLERATE"
|
|
| "SESSION_STATES"
|
|
| "STATISTICS"
|
|
| "STATS"
|
|
| "STATS_META"
|
|
| "STATS_HISTOGRAMS"
|
|
| "STATS_TOPN"
|
|
| "STATS_BUCKETS"
|
|
| "STATS_HEALTHY"
|
|
| "STATS_LOCKED"
|
|
| "HISTOGRAMS_IN_FLIGHT"
|
|
| "TELEMETRY"
|
|
| "TELEMETRY_ID"
|
|
| "TIDB"
|
|
| "TIFLASH"
|
|
| "TOPN"
|
|
| "SPLIT"
|
|
| "OPTIMISTIC"
|
|
| "PESSIMISTIC"
|
|
| "WIDTH"
|
|
| "REGIONS"
|
|
| "REGION"
|
|
| "RESET"
|
|
| "DRY"
|
|
| "RUN"
|
|
|
|
NotKeywordToken:
|
|
"ADDDATE"
|
|
| "APPROX_COUNT_DISTINCT"
|
|
| "APPROX_PERCENTILE"
|
|
| "BIT_AND"
|
|
| "BIT_OR"
|
|
| "BIT_XOR"
|
|
| "BRIEF"
|
|
| "CAST"
|
|
| "COPY"
|
|
| "CURTIME"
|
|
| "CURDATE"
|
|
| "DATE_ADD"
|
|
| "DATE_SUB"
|
|
| "DEFINED"
|
|
| "DOT"
|
|
| "DUMP"
|
|
| "DURATION"
|
|
| "EXTRACT"
|
|
| "END_TIME"
|
|
| "GET_FORMAT"
|
|
| "GROUP_CONCAT"
|
|
| "INPLACE"
|
|
| "INSTANT"
|
|
| "INTERNAL"
|
|
| "MIN"
|
|
| "MAX"
|
|
| "NOW"
|
|
| "RECENT"
|
|
| "REPLAYER"
|
|
| "RUNNING"
|
|
| "PLACEMENT"
|
|
| "PLAN"
|
|
| "PLAN_CACHE"
|
|
| "POSITION"
|
|
| "PREDICATE"
|
|
| "S3"
|
|
| "STRICT"
|
|
| "SUBDATE"
|
|
| "SUBSTRING"
|
|
| "SUM"
|
|
| "START_TIME"
|
|
| "STD"
|
|
| "STDDEV"
|
|
| "STDDEV_POP"
|
|
| "STDDEV_SAMP"
|
|
| "STOP"
|
|
| "VARIANCE"
|
|
| "VAR_POP"
|
|
| "VAR_SAMP"
|
|
| "TARGET"
|
|
| "TIMESTAMPADD"
|
|
| "TIMESTAMPDIFF"
|
|
| "TOKUDB_DEFAULT"
|
|
| "TOKUDB_FAST"
|
|
| "TOKUDB_LZMA"
|
|
| "TOKUDB_QUICKLZ"
|
|
| "TOKUDB_SNAPPY"
|
|
| "TOKUDB_SMALL"
|
|
| "TOKUDB_UNCOMPRESSED"
|
|
| "TOKUDB_ZLIB"
|
|
| "TOKUDB_ZSTD"
|
|
| "TOP"
|
|
| "TRIM"
|
|
| "NEXT_ROW_ID"
|
|
| "EXPR_PUSHDOWN_BLACKLIST"
|
|
| "OPT_RULE_BLACKLIST"
|
|
| "BOUND"
|
|
| "EXACT" %prec lowerThanStringLitToken
|
|
| "STALENESS"
|
|
| "STRONG"
|
|
| "FLASHBACK"
|
|
| "JSON_OBJECTAGG"
|
|
| "JSON_ARRAYAGG"
|
|
| "TLS"
|
|
| "FOLLOWER"
|
|
| "FOLLOWERS"
|
|
| "LEADER"
|
|
| "LEARNER"
|
|
| "LEARNERS"
|
|
| "VERBOSE"
|
|
| "TRUE_CARD_COST"
|
|
| "VOTER"
|
|
| "VOTERS"
|
|
| "CONSTRAINTS"
|
|
| "PRIMARY_REGION"
|
|
| "SCHEDULE"
|
|
| "SURVIVAL_PREFERENCES"
|
|
| "LEADER_CONSTRAINTS"
|
|
| "FOLLOWER_CONSTRAINTS"
|
|
| "LEARNER_CONSTRAINTS"
|
|
| "VOTER_CONSTRAINTS"
|
|
| "TIDB_JSON"
|
|
| "IO_READ_BANDWIDTH"
|
|
| "IO_WRITE_BANDWIDTH"
|
|
| "RU_PER_SEC"
|
|
| "PRIORITY"
|
|
| "HIGH"
|
|
| "MEDIUM"
|
|
| "LOW"
|
|
| "BURSTABLE"
|
|
| "BR"
|
|
| "GC_TTL"
|
|
| "METADATA"
|
|
| "START_TS"
|
|
| "UNTIL_TS"
|
|
| "RESTORED_TS"
|
|
| "FULL_BACKUP_STORAGE"
|
|
| "EXEC_ELAPSED"
|
|
| "DRYRUN"
|
|
| "COOLDOWN"
|
|
| "WATCH"
|
|
| "SIMILAR"
|
|
| "QUERY_LIMIT"
|
|
| "BACKGROUND"
|
|
| "TASK_TYPES"
|
|
| "UNLIMITED"
|
|
|
|
/************************************************************************************
|
|
*
|
|
* Call Statements
|
|
*
|
|
**********************************************************************************/
|
|
CallStmt:
|
|
"CALL" ProcedureCall
|
|
{
|
|
$$ = &ast.CallStmt{
|
|
Procedure: $2.(*ast.FuncCallExpr),
|
|
}
|
|
}
|
|
|
|
ProcedureCall:
|
|
identifier
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
Tp: ast.FuncCallExprTypeGeneric,
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{},
|
|
}
|
|
}
|
|
| Identifier '.' Identifier
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
Tp: ast.FuncCallExprTypeGeneric,
|
|
Schema: model.NewCIStr($1),
|
|
FnName: model.NewCIStr($3),
|
|
Args: []ast.ExprNode{},
|
|
}
|
|
}
|
|
| identifier '(' ExpressionListOpt ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
Tp: ast.FuncCallExprTypeGeneric,
|
|
FnName: model.NewCIStr($1),
|
|
Args: $3.([]ast.ExprNode),
|
|
}
|
|
}
|
|
| Identifier '.' Identifier '(' ExpressionListOpt ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
Tp: ast.FuncCallExprTypeGeneric,
|
|
Schema: model.NewCIStr($1),
|
|
FnName: model.NewCIStr($3),
|
|
Args: $5.([]ast.ExprNode),
|
|
}
|
|
}
|
|
|
|
/************************************************************************************
|
|
*
|
|
* Insert Statements
|
|
*
|
|
**********************************************************************************/
|
|
InsertIntoStmt:
|
|
"INSERT" TableOptimizerHintsOpt PriorityOpt IgnoreOptional IntoOpt TableName PartitionNameListOpt InsertValues OnDuplicateKeyUpdate
|
|
{
|
|
x := $8.(*ast.InsertStmt)
|
|
x.Priority = $3.(mysql.PriorityEnum)
|
|
x.IgnoreErr = $4.(bool)
|
|
// Wraps many layers here so that it can be processed the same way as select statement.
|
|
ts := &ast.TableSource{Source: $6.(*ast.TableName)}
|
|
x.Table = &ast.TableRefsClause{TableRefs: &ast.Join{Left: ts}}
|
|
if $9 != nil {
|
|
x.OnDuplicate = $9.([]*ast.Assignment)
|
|
}
|
|
if $2 != nil {
|
|
x.TableHints = $2.([]*ast.TableOptimizerHint)
|
|
}
|
|
x.PartitionNames = $7.([]model.CIStr)
|
|
$$ = x
|
|
}
|
|
|
|
IntoOpt:
|
|
{}
|
|
| "INTO"
|
|
|
|
InsertValues:
|
|
'(' ColumnNameListOpt ')' ValueSym ValuesList
|
|
{
|
|
$$ = &ast.InsertStmt{
|
|
Columns: $2.([]*ast.ColumnName),
|
|
Lists: $5.([][]ast.ExprNode),
|
|
}
|
|
}
|
|
| '(' ColumnNameListOpt ')' SetOprStmt
|
|
{
|
|
$$ = &ast.InsertStmt{Columns: $2.([]*ast.ColumnName), Select: $4.(ast.ResultSetNode)}
|
|
}
|
|
| '(' ColumnNameListOpt ')' SelectStmt
|
|
{
|
|
$$ = &ast.InsertStmt{Columns: $2.([]*ast.ColumnName), Select: $4.(ast.ResultSetNode)}
|
|
}
|
|
| '(' ColumnNameListOpt ')' SelectStmtWithClause
|
|
{
|
|
$$ = &ast.InsertStmt{Columns: $2.([]*ast.ColumnName), Select: $4.(ast.ResultSetNode)}
|
|
}
|
|
| '(' ColumnNameListOpt ')' SubSelect
|
|
{
|
|
var sel ast.ResultSetNode
|
|
switch x := $4.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
case *ast.SetOprStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
}
|
|
$$ = &ast.InsertStmt{Columns: $2.([]*ast.ColumnName), Select: sel}
|
|
}
|
|
| ValueSym ValuesList %prec insertValues
|
|
{
|
|
$$ = &ast.InsertStmt{Lists: $2.([][]ast.ExprNode)}
|
|
}
|
|
| SetOprStmt
|
|
{
|
|
$$ = &ast.InsertStmt{Select: $1.(ast.ResultSetNode)}
|
|
}
|
|
| SelectStmt
|
|
{
|
|
$$ = &ast.InsertStmt{Select: $1.(ast.ResultSetNode)}
|
|
}
|
|
| SelectStmtWithClause
|
|
{
|
|
$$ = &ast.InsertStmt{Select: $1.(ast.ResultSetNode)}
|
|
}
|
|
| SubSelect
|
|
{
|
|
var sel ast.ResultSetNode
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
case *ast.SetOprStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
}
|
|
$$ = &ast.InsertStmt{Select: sel}
|
|
}
|
|
| "SET" ColumnSetValueList
|
|
{
|
|
$$ = $2.(*ast.InsertStmt)
|
|
}
|
|
|
|
ValueSym:
|
|
"VALUE"
|
|
| "VALUES"
|
|
|
|
ValuesList:
|
|
RowValue
|
|
{
|
|
$$ = [][]ast.ExprNode{$1.([]ast.ExprNode)}
|
|
}
|
|
| ValuesList ',' RowValue
|
|
{
|
|
$$ = append($1.([][]ast.ExprNode), $3.([]ast.ExprNode))
|
|
}
|
|
|
|
RowValue:
|
|
'(' ValuesOpt ')'
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
ValuesOpt:
|
|
{
|
|
$$ = []ast.ExprNode{}
|
|
}
|
|
| Values
|
|
|
|
Values:
|
|
Values ',' ExprOrDefault
|
|
{
|
|
$$ = append($1.([]ast.ExprNode), $3)
|
|
}
|
|
| ExprOrDefault
|
|
{
|
|
$$ = []ast.ExprNode{$1}
|
|
}
|
|
|
|
ExprOrDefault:
|
|
Expression
|
|
| "DEFAULT"
|
|
{
|
|
$$ = &ast.DefaultExpr{}
|
|
}
|
|
|
|
ColumnSetValueList:
|
|
ColumnName EqOrAssignmentEq ExprOrDefault
|
|
{
|
|
$$ = &ast.InsertStmt{
|
|
Columns: []*ast.ColumnName{$1.(*ast.ColumnName)},
|
|
Lists: [][]ast.ExprNode{{$3.(ast.ExprNode)}},
|
|
Setlist: true,
|
|
}
|
|
}
|
|
| ColumnSetValueList ',' ColumnName EqOrAssignmentEq ExprOrDefault
|
|
{
|
|
ins := $1.(*ast.InsertStmt)
|
|
ins.Columns = append(ins.Columns, $3.(*ast.ColumnName))
|
|
ins.Lists[0] = append(ins.Lists[0], $5.(ast.ExprNode))
|
|
$$ = ins
|
|
}
|
|
|
|
/*
|
|
* ON DUPLICATE KEY UPDATE col_name=expr [, col_name=expr] ...
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
|
|
*/
|
|
OnDuplicateKeyUpdate:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "ON" "DUPLICATE" "KEY" "UPDATE" AssignmentList
|
|
{
|
|
$$ = $5
|
|
}
|
|
|
|
/************************************************************************************
|
|
* Replace Statements
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/replace.html
|
|
*
|
|
**********************************************************************************/
|
|
ReplaceIntoStmt:
|
|
"REPLACE" PriorityOpt IntoOpt TableName PartitionNameListOpt InsertValues
|
|
{
|
|
x := $6.(*ast.InsertStmt)
|
|
x.IsReplace = true
|
|
x.Priority = $2.(mysql.PriorityEnum)
|
|
ts := &ast.TableSource{Source: $4.(*ast.TableName)}
|
|
x.Table = &ast.TableRefsClause{TableRefs: &ast.Join{Left: ts}}
|
|
x.PartitionNames = $5.([]model.CIStr)
|
|
$$ = x
|
|
}
|
|
|
|
Literal:
|
|
"FALSE"
|
|
{
|
|
$$ = ast.NewValueExpr(false, parser.charset, parser.collation)
|
|
}
|
|
| "NULL"
|
|
{
|
|
$$ = ast.NewValueExpr(nil, parser.charset, parser.collation)
|
|
}
|
|
| "TRUE"
|
|
{
|
|
$$ = ast.NewValueExpr(true, parser.charset, parser.collation)
|
|
}
|
|
| floatLit
|
|
{
|
|
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
|
|
}
|
|
| decLit
|
|
{
|
|
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
|
|
}
|
|
| intLit
|
|
{
|
|
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
|
|
}
|
|
| StringLiteral %prec lowerThanStringLitToken
|
|
| "UNDERSCORE_CHARSET" stringLit
|
|
{
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/charset-literal.html
|
|
co, err := charset.GetDefaultCollationLegacy($1)
|
|
if err != nil {
|
|
yylex.AppendError(ast.ErrUnknownCharacterSet.GenWithStack("Unsupported character introducer: '%-.64s'", $1))
|
|
return 1
|
|
}
|
|
expr := ast.NewValueExpr($2, $1, co)
|
|
tp := expr.GetType()
|
|
tp.SetCharset($1)
|
|
tp.SetCollate(co)
|
|
tp.AddFlag(mysql.UnderScoreCharsetFlag)
|
|
if tp.GetCollate() == charset.CollationBin {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = expr
|
|
}
|
|
| hexLit
|
|
{
|
|
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
|
|
}
|
|
| bitLit
|
|
{
|
|
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
|
|
}
|
|
| "UNDERSCORE_CHARSET" hexLit
|
|
{
|
|
co, err := charset.GetDefaultCollationLegacy($1)
|
|
if err != nil {
|
|
yylex.AppendError(ast.ErrUnknownCharacterSet.GenWithStack("Unsupported character introducer: '%-.64s'", $1))
|
|
return 1
|
|
}
|
|
expr := ast.NewValueExpr($2, $1, co)
|
|
tp := expr.GetType()
|
|
tp.SetCharset($1)
|
|
tp.SetCollate(co)
|
|
tp.AddFlag(mysql.UnderScoreCharsetFlag)
|
|
if tp.GetCollate() == charset.CollationBin {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = expr
|
|
}
|
|
| "UNDERSCORE_CHARSET" bitLit
|
|
{
|
|
co, err := charset.GetDefaultCollationLegacy($1)
|
|
if err != nil {
|
|
yylex.AppendError(ast.ErrUnknownCharacterSet.GenWithStack("Unsupported character introducer: '%-.64s'", $1))
|
|
return 1
|
|
}
|
|
expr := ast.NewValueExpr($2, $1, co)
|
|
tp := expr.GetType()
|
|
tp.SetCharset($1)
|
|
tp.SetCollate(co)
|
|
tp.AddFlag(mysql.UnderScoreCharsetFlag)
|
|
if tp.GetCollate() == charset.CollationBin {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = expr
|
|
}
|
|
|
|
StringLiteral:
|
|
stringLit
|
|
{
|
|
expr := ast.NewValueExpr($1, parser.charset, parser.collation)
|
|
$$ = expr
|
|
}
|
|
| StringLiteral stringLit
|
|
{
|
|
valExpr := $1.(ast.ValueExpr)
|
|
strLit := valExpr.GetString()
|
|
expr := ast.NewValueExpr(strLit+$2, parser.charset, parser.collation)
|
|
// Fix #4239, use first string literal as projection name.
|
|
if valExpr.GetProjectionOffset() >= 0 {
|
|
expr.SetProjectionOffset(valExpr.GetProjectionOffset())
|
|
} else {
|
|
expr.SetProjectionOffset(len(strLit))
|
|
}
|
|
$$ = expr
|
|
}
|
|
|
|
AlterOrderList:
|
|
AlterOrderItem
|
|
{
|
|
$$ = []*ast.AlterOrderItem{$1.(*ast.AlterOrderItem)}
|
|
}
|
|
| AlterOrderList ',' AlterOrderItem
|
|
{
|
|
$$ = append($1.([]*ast.AlterOrderItem), $3.(*ast.AlterOrderItem))
|
|
}
|
|
|
|
AlterOrderItem:
|
|
ColumnName OptOrder
|
|
{
|
|
$$ = &ast.AlterOrderItem{Column: $1.(*ast.ColumnName), Desc: $2.(bool)}
|
|
}
|
|
|
|
OrderBy:
|
|
"ORDER" "BY" ByList
|
|
{
|
|
$$ = &ast.OrderByClause{Items: $3.([]*ast.ByItem)}
|
|
}
|
|
|
|
ByList:
|
|
ByItem
|
|
{
|
|
$$ = []*ast.ByItem{$1.(*ast.ByItem)}
|
|
}
|
|
| ByList ',' ByItem
|
|
{
|
|
$$ = append($1.([]*ast.ByItem), $3.(*ast.ByItem))
|
|
}
|
|
|
|
ByItem:
|
|
Expression
|
|
{
|
|
expr := $1
|
|
valueExpr, ok := expr.(ast.ValueExpr)
|
|
if ok {
|
|
position, isPosition := valueExpr.GetValue().(int64)
|
|
if isPosition {
|
|
expr = &ast.PositionExpr{N: int(position)}
|
|
}
|
|
}
|
|
$$ = &ast.ByItem{Expr: expr, NullOrder: true}
|
|
}
|
|
| Expression Order
|
|
{
|
|
expr := $1
|
|
valueExpr, ok := expr.(ast.ValueExpr)
|
|
if ok {
|
|
position, isPosition := valueExpr.GetValue().(int64)
|
|
if isPosition {
|
|
expr = &ast.PositionExpr{N: int(position)}
|
|
}
|
|
}
|
|
$$ = &ast.ByItem{Expr: expr, Desc: $2.(bool)}
|
|
}
|
|
|
|
Order:
|
|
"ASC"
|
|
{
|
|
$$ = false
|
|
}
|
|
| "DESC"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
OptOrder:
|
|
/* EMPTY */
|
|
{
|
|
$$ = false // ASC by default
|
|
}
|
|
| "ASC"
|
|
{
|
|
$$ = false
|
|
}
|
|
| "DESC"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
OrderByOptional:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| OrderBy
|
|
|
|
BitExpr:
|
|
BitExpr '|' BitExpr %prec '|'
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.Or, L: $1, R: $3}
|
|
}
|
|
| BitExpr '&' BitExpr %prec '&'
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.And, L: $1, R: $3}
|
|
}
|
|
| BitExpr "<<" BitExpr %prec lsh
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.LeftShift, L: $1, R: $3}
|
|
}
|
|
| BitExpr ">>" BitExpr %prec rsh
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.RightShift, L: $1, R: $3}
|
|
}
|
|
| BitExpr '+' BitExpr %prec '+'
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.Plus, L: $1, R: $3}
|
|
}
|
|
| BitExpr '-' BitExpr %prec '-'
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.Minus, L: $1, R: $3}
|
|
}
|
|
| BitExpr '+' "INTERVAL" Expression TimeUnit %prec '+'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr("DATE_ADD"),
|
|
Args: []ast.ExprNode{
|
|
$1,
|
|
$4,
|
|
&ast.TimeUnitExpr{Unit: $5.(ast.TimeUnitType)},
|
|
},
|
|
}
|
|
}
|
|
| BitExpr '-' "INTERVAL" Expression TimeUnit %prec '+'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr("DATE_SUB"),
|
|
Args: []ast.ExprNode{
|
|
$1,
|
|
$4,
|
|
&ast.TimeUnitExpr{Unit: $5.(ast.TimeUnitType)},
|
|
},
|
|
}
|
|
}
|
|
| "INTERVAL" Expression TimeUnit '+' BitExpr %prec '+'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr("DATE_ADD"),
|
|
Args: []ast.ExprNode{
|
|
$5,
|
|
$2,
|
|
&ast.TimeUnitExpr{Unit: $3.(ast.TimeUnitType)},
|
|
},
|
|
}
|
|
}
|
|
| BitExpr '*' BitExpr %prec '*'
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.Mul, L: $1, R: $3}
|
|
}
|
|
| BitExpr '/' BitExpr %prec '/'
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.Div, L: $1, R: $3}
|
|
}
|
|
| BitExpr '%' BitExpr %prec '%'
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.Mod, L: $1, R: $3}
|
|
}
|
|
| BitExpr "DIV" BitExpr %prec div
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.IntDiv, L: $1, R: $3}
|
|
}
|
|
| BitExpr "MOD" BitExpr %prec mod
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.Mod, L: $1, R: $3}
|
|
}
|
|
| BitExpr '^' BitExpr
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.Xor, L: $1, R: $3}
|
|
}
|
|
| SimpleExpr
|
|
|
|
SimpleIdent:
|
|
Identifier
|
|
{
|
|
$$ = &ast.ColumnNameExpr{Name: &ast.ColumnName{
|
|
Name: model.NewCIStr($1),
|
|
}}
|
|
}
|
|
| Identifier '.' Identifier
|
|
{
|
|
$$ = &ast.ColumnNameExpr{Name: &ast.ColumnName{
|
|
Table: model.NewCIStr($1),
|
|
Name: model.NewCIStr($3),
|
|
}}
|
|
}
|
|
| Identifier '.' Identifier '.' Identifier
|
|
{
|
|
$$ = &ast.ColumnNameExpr{Name: &ast.ColumnName{
|
|
Schema: model.NewCIStr($1),
|
|
Table: model.NewCIStr($3),
|
|
Name: model.NewCIStr($5),
|
|
}}
|
|
}
|
|
|
|
SimpleExpr:
|
|
SimpleIdent
|
|
| FunctionCallKeyword
|
|
| FunctionCallNonKeyword
|
|
| FunctionCallGeneric
|
|
| SimpleExpr "COLLATE" CollationName
|
|
{
|
|
$$ = &ast.SetCollationExpr{Expr: $1, Collate: $3}
|
|
}
|
|
| WindowFuncCall
|
|
| Literal
|
|
| paramMarker
|
|
{
|
|
$$ = ast.NewParamMarkerExpr(yyS[yypt].offset)
|
|
}
|
|
| Variable
|
|
| SumExpr
|
|
| '!' SimpleExpr %prec neg
|
|
{
|
|
$$ = &ast.UnaryOperationExpr{Op: opcode.Not2, V: $2}
|
|
}
|
|
| '~' SimpleExpr %prec neg
|
|
{
|
|
$$ = &ast.UnaryOperationExpr{Op: opcode.BitNeg, V: $2}
|
|
}
|
|
| '-' SimpleExpr %prec neg
|
|
{
|
|
$$ = &ast.UnaryOperationExpr{Op: opcode.Minus, V: $2}
|
|
}
|
|
| '+' SimpleExpr %prec neg
|
|
{
|
|
$$ = &ast.UnaryOperationExpr{Op: opcode.Plus, V: $2}
|
|
}
|
|
| SimpleExpr pipes SimpleExpr
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.Concat), Args: []ast.ExprNode{$1, $3}}
|
|
}
|
|
| not2 SimpleExpr %prec neg
|
|
{
|
|
$$ = &ast.UnaryOperationExpr{Op: opcode.Not2, V: $2}
|
|
}
|
|
| SubSelect %prec neg
|
|
| '(' Expression ')'
|
|
{
|
|
startOffset := parser.startOffset(&yyS[yypt-1])
|
|
endOffset := parser.endOffset(&yyS[yypt])
|
|
expr := $2
|
|
expr.SetText(parser.lexer.client, parser.src[startOffset:endOffset])
|
|
$$ = &ast.ParenthesesExpr{Expr: expr}
|
|
}
|
|
| '(' ExpressionList ',' Expression ')'
|
|
{
|
|
values := append($2.([]ast.ExprNode), $4)
|
|
$$ = &ast.RowExpr{Values: values}
|
|
}
|
|
| "ROW" '(' ExpressionList ',' Expression ')'
|
|
{
|
|
values := append($3.([]ast.ExprNode), $5)
|
|
$$ = &ast.RowExpr{Values: values}
|
|
}
|
|
| "EXISTS" SubSelect
|
|
{
|
|
sq := $2.(*ast.SubqueryExpr)
|
|
sq.Exists = true
|
|
$$ = &ast.ExistsSubqueryExpr{Sel: sq}
|
|
}
|
|
| '{' Identifier Expression '}'
|
|
{
|
|
/*
|
|
* ODBC escape syntax.
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/expressions.html
|
|
*/
|
|
tp := $3.GetType()
|
|
switch $2 {
|
|
case "d":
|
|
tp.SetCharset("")
|
|
tp.SetCollate("")
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.DateLiteral), Args: []ast.ExprNode{$3}}
|
|
case "t":
|
|
tp.SetCharset("")
|
|
tp.SetCollate("")
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimeLiteral), Args: []ast.ExprNode{$3}}
|
|
case "ts":
|
|
tp.SetCharset("")
|
|
tp.SetCollate("")
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimestampLiteral), Args: []ast.ExprNode{$3}}
|
|
default:
|
|
$$ = $3
|
|
}
|
|
}
|
|
| "BINARY" SimpleExpr %prec neg
|
|
{
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#operator_binary
|
|
tp := types.NewFieldType(mysql.TypeString)
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CharsetBin)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
$$ = &ast.FuncCastExpr{
|
|
Expr: $2,
|
|
Tp: tp,
|
|
FunctionType: ast.CastBinaryOperator,
|
|
}
|
|
}
|
|
| builtinCast '(' Expression "AS" CastType ArrayKwdOpt ')'
|
|
{
|
|
/* See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_cast */
|
|
tp := $5.(*types.FieldType)
|
|
defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimalForCast(tp.GetType())
|
|
if tp.GetFlen() == types.UnspecifiedLength {
|
|
tp.SetFlen(defaultFlen)
|
|
}
|
|
if tp.GetDecimal() == types.UnspecifiedLength {
|
|
tp.SetDecimal(defaultDecimal)
|
|
}
|
|
isArray := $6.(bool)
|
|
tp.SetArray(isArray)
|
|
explicitCharset := parser.explicitCharset
|
|
if isArray && !explicitCharset && tp.GetCharset() != charset.CharsetBin {
|
|
tp.SetCharset(charset.CharsetUTF8MB4)
|
|
tp.SetCollate(charset.CollationUTF8MB4)
|
|
}
|
|
parser.explicitCharset = false
|
|
$$ = &ast.FuncCastExpr{
|
|
Expr: $3,
|
|
Tp: tp,
|
|
FunctionType: ast.CastFunction,
|
|
ExplicitCharSet: explicitCharset,
|
|
}
|
|
}
|
|
| "CASE" ExpressionOpt WhenClauseList ElseOpt "END"
|
|
{
|
|
x := &ast.CaseExpr{WhenClauses: $3.([]*ast.WhenClause)}
|
|
if $2 != nil {
|
|
x.Value = $2
|
|
}
|
|
if $4 != nil {
|
|
x.ElseClause = $4.(ast.ExprNode)
|
|
}
|
|
$$ = x
|
|
}
|
|
| "CONVERT" '(' Expression ',' CastType ')'
|
|
{
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert
|
|
tp := $5.(*types.FieldType)
|
|
defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimalForCast(tp.GetType())
|
|
if tp.GetFlen() == types.UnspecifiedLength {
|
|
tp.SetFlen(defaultFlen)
|
|
}
|
|
if tp.GetDecimal() == types.UnspecifiedLength {
|
|
tp.SetDecimal(defaultDecimal)
|
|
}
|
|
explicitCharset := parser.explicitCharset
|
|
parser.explicitCharset = false
|
|
$$ = &ast.FuncCastExpr{
|
|
Expr: $3,
|
|
Tp: tp,
|
|
FunctionType: ast.CastConvertFunction,
|
|
ExplicitCharSet: explicitCharset,
|
|
}
|
|
}
|
|
| "CONVERT" '(' Expression "USING" CharsetName ')'
|
|
{
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert
|
|
charset1 := ast.NewValueExpr($5, "", "")
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$3, charset1},
|
|
}
|
|
}
|
|
| "DEFAULT" '(' SimpleIdent ')'
|
|
{
|
|
$$ = &ast.DefaultExpr{Name: $3.(*ast.ColumnNameExpr).Name}
|
|
}
|
|
| "VALUES" '(' SimpleIdent ')' %prec lowerThanInsertValues
|
|
{
|
|
$$ = &ast.ValuesExpr{Column: $3.(*ast.ColumnNameExpr)}
|
|
}
|
|
| SimpleIdent jss stringLit
|
|
{
|
|
expr := ast.NewValueExpr($3, parser.charset, parser.collation)
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONExtract), Args: []ast.ExprNode{$1, expr}}
|
|
}
|
|
| SimpleIdent juss stringLit
|
|
{
|
|
expr := ast.NewValueExpr($3, parser.charset, parser.collation)
|
|
extract := &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONExtract), Args: []ast.ExprNode{$1, expr}}
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONUnquote), Args: []ast.ExprNode{extract}}
|
|
}
|
|
|
|
ArrayKwdOpt:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "ARRAY"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
DistinctKwd:
|
|
"DISTINCT"
|
|
| "DISTINCTROW"
|
|
|
|
DistinctOpt:
|
|
"ALL"
|
|
{
|
|
$$ = false
|
|
}
|
|
| DistinctKwd
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
DefaultFalseDistinctOpt:
|
|
{
|
|
$$ = false
|
|
}
|
|
| DistinctOpt
|
|
|
|
DefaultTrueDistinctOpt:
|
|
{
|
|
$$ = true
|
|
}
|
|
| DistinctOpt
|
|
|
|
BuggyDefaultFalseDistinctOpt:
|
|
DefaultFalseDistinctOpt
|
|
| DistinctKwd "ALL"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
FunctionNameConflict:
|
|
"ASCII"
|
|
| "CHARSET"
|
|
| "COALESCE"
|
|
| "COLLATION"
|
|
| "DATE"
|
|
| "DATABASE"
|
|
| "DAY"
|
|
| "HOUR"
|
|
| "IF"
|
|
| "INTERVAL"
|
|
| "FORMAT"
|
|
| "LEFT"
|
|
| "MICROSECOND"
|
|
| "MINUTE"
|
|
| "MONTH"
|
|
| builtinNow
|
|
| "POINT"
|
|
| "QUARTER"
|
|
| "REPEAT"
|
|
| "REPLACE"
|
|
| "REVERSE"
|
|
| "RIGHT"
|
|
| "ROW_COUNT"
|
|
| "SECOND"
|
|
| "TIME"
|
|
| "TIMESTAMP"
|
|
| "TRUNCATE"
|
|
| "USER"
|
|
| "WEEK"
|
|
| "YEAR"
|
|
|
|
OptionalBraces:
|
|
{}
|
|
| '(' ')'
|
|
{}
|
|
|
|
FunctionNameOptionalBraces:
|
|
"CURRENT_USER"
|
|
| "CURRENT_DATE"
|
|
| "CURRENT_ROLE"
|
|
| "UTC_DATE"
|
|
| "TiDB_CURRENT_TSO"
|
|
|
|
FunctionNameDatetimePrecision:
|
|
"CURRENT_TIME"
|
|
| "CURRENT_TIMESTAMP"
|
|
| "LOCALTIME"
|
|
| "LOCALTIMESTAMP"
|
|
| "UTC_TIME"
|
|
| "UTC_TIMESTAMP"
|
|
|
|
FunctionCallKeyword:
|
|
FunctionNameConflict '(' ExpressionListOpt ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: $3.([]ast.ExprNode)}
|
|
}
|
|
| builtinUser '(' ExpressionListOpt ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: $3.([]ast.ExprNode)}
|
|
}
|
|
| FunctionNameOptionalBraces OptionalBraces
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1)}
|
|
}
|
|
| builtinCurDate '(' ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1)}
|
|
}
|
|
| FunctionNameDatetimePrecision FuncDatetimePrec
|
|
{
|
|
args := []ast.ExprNode{}
|
|
if $2 != nil {
|
|
args = append(args, $2.(ast.ExprNode))
|
|
}
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: args}
|
|
}
|
|
| "CHAR" '(' ExpressionList ')'
|
|
{
|
|
nilVal := ast.NewValueExpr(nil, parser.charset, parser.collation)
|
|
args := $3.([]ast.ExprNode)
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr(ast.CharFunc),
|
|
Args: append(args, nilVal),
|
|
}
|
|
}
|
|
| "CHAR" '(' ExpressionList "USING" CharsetName ')'
|
|
{
|
|
charset1 := ast.NewValueExpr($5, "", "")
|
|
args := $3.([]ast.ExprNode)
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr(ast.CharFunc),
|
|
Args: append(args, charset1),
|
|
}
|
|
}
|
|
| "DATE" stringLit
|
|
{
|
|
expr := ast.NewValueExpr($2, "", "")
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.DateLiteral), Args: []ast.ExprNode{expr}}
|
|
}
|
|
| "TIME" stringLit
|
|
{
|
|
expr := ast.NewValueExpr($2, "", "")
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimeLiteral), Args: []ast.ExprNode{expr}}
|
|
}
|
|
| "TIMESTAMP" stringLit
|
|
{
|
|
expr := ast.NewValueExpr($2, "", "")
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimestampLiteral), Args: []ast.ExprNode{expr}}
|
|
}
|
|
| "INSERT" '(' ExpressionListOpt ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.InsertFunc), Args: $3.([]ast.ExprNode)}
|
|
}
|
|
| "MOD" '(' BitExpr ',' BitExpr ')'
|
|
{
|
|
$$ = &ast.BinaryOperationExpr{Op: opcode.Mod, L: $3, R: $5}
|
|
}
|
|
| "PASSWORD" '(' ExpressionListOpt ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.PasswordFunc), Args: $3.([]ast.ExprNode)}
|
|
}
|
|
|
|
FunctionCallNonKeyword:
|
|
builtinCurTime '(' FuncDatetimePrecListOpt ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: $3.([]ast.ExprNode)}
|
|
}
|
|
| builtinSysDate '(' FuncDatetimePrecListOpt ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: $3.([]ast.ExprNode)}
|
|
}
|
|
| FunctionNameDateArithMultiForms '(' Expression ',' Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{
|
|
$3,
|
|
$5,
|
|
&ast.TimeUnitExpr{Unit: ast.TimeUnitDay},
|
|
},
|
|
}
|
|
}
|
|
| FunctionNameDateArithMultiForms '(' Expression ',' "INTERVAL" Expression TimeUnit ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{
|
|
$3,
|
|
$6,
|
|
&ast.TimeUnitExpr{Unit: $7.(ast.TimeUnitType)},
|
|
},
|
|
}
|
|
}
|
|
| FunctionNameDateArith '(' Expression ',' "INTERVAL" Expression TimeUnit ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{
|
|
$3,
|
|
$6,
|
|
&ast.TimeUnitExpr{Unit: $7.(ast.TimeUnitType)},
|
|
},
|
|
}
|
|
}
|
|
| builtinExtract '(' TimeUnit "FROM" Expression ')'
|
|
{
|
|
timeUnit := &ast.TimeUnitExpr{Unit: $3.(ast.TimeUnitType)}
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{timeUnit, $5},
|
|
}
|
|
}
|
|
| "GET_FORMAT" '(' GetFormatSelector ',' Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{
|
|
&ast.GetFormatSelectorExpr{Selector: $3.(ast.GetFormatSelectorType)},
|
|
$5,
|
|
},
|
|
}
|
|
}
|
|
| builtinPosition '(' BitExpr "IN" Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: []ast.ExprNode{$3, $5}}
|
|
}
|
|
| builtinSubstring '(' Expression ',' Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$3, $5},
|
|
}
|
|
}
|
|
| builtinSubstring '(' Expression "FROM" Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$3, $5},
|
|
}
|
|
}
|
|
| builtinSubstring '(' Expression ',' Expression ',' Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$3, $5, $7},
|
|
}
|
|
}
|
|
| builtinSubstring '(' Expression "FROM" Expression "FOR" Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$3, $5, $7},
|
|
}
|
|
}
|
|
| "TIMESTAMPADD" '(' TimestampUnit ',' Expression ',' Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{&ast.TimeUnitExpr{Unit: $3.(ast.TimeUnitType)}, $5, $7},
|
|
}
|
|
}
|
|
| "TIMESTAMPDIFF" '(' TimestampUnit ',' Expression ',' Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{&ast.TimeUnitExpr{Unit: $3.(ast.TimeUnitType)}, $5, $7},
|
|
}
|
|
}
|
|
| builtinTrim '(' Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$3},
|
|
}
|
|
}
|
|
| builtinTrim '(' Expression "FROM" Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$5, $3},
|
|
}
|
|
}
|
|
| builtinTrim '(' TrimDirection "FROM" Expression ')'
|
|
{
|
|
spaceVal := ast.NewValueExpr(" ", parser.charset, parser.collation)
|
|
direction := &ast.TrimDirectionExpr{Direction: $3.(ast.TrimDirectionType)}
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$5, spaceVal, direction},
|
|
}
|
|
}
|
|
| builtinTrim '(' TrimDirection Expression "FROM" Expression ')'
|
|
{
|
|
direction := &ast.TrimDirectionExpr{Direction: $3.(ast.TrimDirectionType)}
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$6, $4, direction},
|
|
}
|
|
}
|
|
| weightString '(' Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$3},
|
|
}
|
|
}
|
|
| weightString '(' Expression "AS" Char FieldLen ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$3, ast.NewValueExpr("CHAR", parser.charset, parser.collation), ast.NewValueExpr($6, parser.charset, parser.collation)},
|
|
}
|
|
}
|
|
| weightString '(' Expression "AS" "BINARY" FieldLen ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$3, ast.NewValueExpr("BINARY", parser.charset, parser.collation), ast.NewValueExpr($6, parser.charset, parser.collation)},
|
|
}
|
|
}
|
|
| FunctionNameSequence
|
|
| builtinTranslate '(' Expression ',' Expression ',' Expression ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: []ast.ExprNode{$3, $5, $7},
|
|
}
|
|
}
|
|
|
|
GetFormatSelector:
|
|
"DATE"
|
|
{
|
|
$$ = ast.GetFormatSelectorDate
|
|
}
|
|
| "DATETIME"
|
|
{
|
|
$$ = ast.GetFormatSelectorDatetime
|
|
}
|
|
| "TIME"
|
|
{
|
|
$$ = ast.GetFormatSelectorTime
|
|
}
|
|
| "TIMESTAMP"
|
|
{
|
|
$$ = ast.GetFormatSelectorDatetime
|
|
}
|
|
|
|
FunctionNameDateArith:
|
|
builtinDateAdd
|
|
| builtinDateSub
|
|
|
|
FunctionNameDateArithMultiForms:
|
|
addDate
|
|
| subDate
|
|
|
|
TrimDirection:
|
|
"BOTH"
|
|
{
|
|
$$ = ast.TrimBoth
|
|
}
|
|
| "LEADING"
|
|
{
|
|
$$ = ast.TrimLeading
|
|
}
|
|
| "TRAILING"
|
|
{
|
|
$$ = ast.TrimTrailing
|
|
}
|
|
|
|
FunctionNameSequence:
|
|
"LASTVAL" '(' TableName ')'
|
|
{
|
|
objNameExpr := &ast.TableNameExpr{
|
|
Name: $3.(*ast.TableName),
|
|
}
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr(ast.LastVal),
|
|
Args: []ast.ExprNode{objNameExpr},
|
|
}
|
|
}
|
|
| "SETVAL" '(' TableName ',' SignedNum ')'
|
|
{
|
|
objNameExpr := &ast.TableNameExpr{
|
|
Name: $3.(*ast.TableName),
|
|
}
|
|
valueExpr := ast.NewValueExpr($5, parser.charset, parser.collation)
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr(ast.SetVal),
|
|
Args: []ast.ExprNode{objNameExpr, valueExpr},
|
|
}
|
|
}
|
|
| NextValueForSequence
|
|
|
|
SumExpr:
|
|
"AVG" '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause
|
|
{
|
|
if $6 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)}
|
|
}
|
|
}
|
|
| builtinApproxCountDistinct '(' ExpressionList ')'
|
|
{
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: $3.([]ast.ExprNode), Distinct: false}
|
|
}
|
|
| builtinApproxPercentile '(' ExpressionList ')'
|
|
{
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: $3.([]ast.ExprNode)}
|
|
}
|
|
| builtinBitAnd '(' Expression ')' OptWindowingClause
|
|
{
|
|
if $5 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$3}, Spec: *($5.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$3}}
|
|
}
|
|
}
|
|
| builtinBitAnd '(' "ALL" Expression ')' OptWindowingClause
|
|
{
|
|
if $6 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$4}, Spec: *($6.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}}
|
|
}
|
|
}
|
|
| builtinBitOr '(' Expression ')' OptWindowingClause
|
|
{
|
|
if $5 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$3}, Spec: *($5.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$3}}
|
|
}
|
|
}
|
|
| builtinBitOr '(' "ALL" Expression ')' OptWindowingClause
|
|
{
|
|
if $6 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$4}, Spec: *($6.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}}
|
|
}
|
|
}
|
|
| builtinBitXor '(' Expression ')' OptWindowingClause
|
|
{
|
|
if $5 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$3}, Spec: *($5.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$3}}
|
|
}
|
|
}
|
|
| builtinBitXor '(' "ALL" Expression ')' OptWindowingClause
|
|
{
|
|
if $6 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$4}, Spec: *($6.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}}
|
|
}
|
|
}
|
|
| builtinCount '(' DistinctKwd ExpressionList ')'
|
|
{
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: $4.([]ast.ExprNode), Distinct: true}
|
|
}
|
|
| builtinCount '(' "ALL" Expression ')' OptWindowingClause
|
|
{
|
|
if $6 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$4}, Spec: *($6.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}}
|
|
}
|
|
}
|
|
| builtinCount '(' Expression ')' OptWindowingClause
|
|
{
|
|
if $5 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$3}, Spec: *($5.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$3}}
|
|
}
|
|
}
|
|
| builtinCount '(' '*' ')' OptWindowingClause
|
|
{
|
|
args := []ast.ExprNode{ast.NewValueExpr(1, parser.charset, parser.collation)}
|
|
if $5 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: args, Spec: *($5.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: args}
|
|
}
|
|
}
|
|
| builtinGroupConcat '(' BuggyDefaultFalseDistinctOpt ExpressionList OrderByOptional OptGConcatSeparator ')' OptWindowingClause
|
|
{
|
|
args := $4.([]ast.ExprNode)
|
|
args = append(args, $6.(ast.ExprNode))
|
|
if $8 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: args, Distinct: $3.(bool), Spec: *($8.(*ast.WindowSpec))}
|
|
} else {
|
|
agg := &ast.AggregateFuncExpr{F: $1, Args: args, Distinct: $3.(bool)}
|
|
if $5 != nil {
|
|
agg.Order = $5.(*ast.OrderByClause)
|
|
}
|
|
$$ = agg
|
|
}
|
|
}
|
|
| builtinMax '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause
|
|
{
|
|
if $6 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)}
|
|
}
|
|
}
|
|
| builtinMin '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause
|
|
{
|
|
if $6 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)}
|
|
}
|
|
}
|
|
| builtinSum '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause
|
|
{
|
|
if $6 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)}
|
|
}
|
|
}
|
|
| builtinStddevPop '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause
|
|
{
|
|
if $6 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: ast.AggFuncStddevPop, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: ast.AggFuncStddevPop, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)}
|
|
}
|
|
}
|
|
| builtinStddevSamp '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause
|
|
{
|
|
if $6 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)}
|
|
}
|
|
}
|
|
| builtinVarPop '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause
|
|
{
|
|
if $6 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: ast.AggFuncVarPop, Args: []ast.ExprNode{$4}, Distinct: $3.(bool), Spec: *($6.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: ast.AggFuncVarPop, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)}
|
|
}
|
|
}
|
|
| builtinVarSamp '(' BuggyDefaultFalseDistinctOpt Expression ')' OptWindowingClause
|
|
{
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}, Distinct: $3.(bool)}
|
|
}
|
|
| "JSON_ARRAYAGG" '(' Expression ')' OptWindowingClause
|
|
{
|
|
if $5 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$3}, Spec: *($5.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$3}}
|
|
}
|
|
}
|
|
| "JSON_ARRAYAGG" '(' "ALL" Expression ')' OptWindowingClause
|
|
{
|
|
if $6 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$4}, Spec: *($6.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4}}
|
|
}
|
|
}
|
|
| "JSON_OBJECTAGG" '(' Expression ',' Expression ')' OptWindowingClause
|
|
{
|
|
if $7 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$3, $5}, Spec: *($7.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$3, $5}}
|
|
}
|
|
}
|
|
| "JSON_OBJECTAGG" '(' "ALL" Expression ',' Expression ')' OptWindowingClause
|
|
{
|
|
if $8 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$4, $6}, Spec: *($8.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4, $6}}
|
|
}
|
|
}
|
|
| "JSON_OBJECTAGG" '(' Expression ',' "ALL" Expression ')' OptWindowingClause
|
|
{
|
|
if $8 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$3, $6}, Spec: *($8.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$3, $6}}
|
|
}
|
|
}
|
|
| "JSON_OBJECTAGG" '(' "ALL" Expression ',' "ALL" Expression ')' OptWindowingClause
|
|
{
|
|
if $9 != nil {
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$4, $7}, Spec: *($9.(*ast.WindowSpec))}
|
|
} else {
|
|
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4, $7}}
|
|
}
|
|
}
|
|
|
|
OptGConcatSeparator:
|
|
{
|
|
$$ = ast.NewValueExpr(",", "", "")
|
|
}
|
|
| "SEPARATOR" stringLit
|
|
{
|
|
$$ = ast.NewValueExpr($2, "", "")
|
|
}
|
|
|
|
FunctionCallGeneric:
|
|
identifier '(' ExpressionListOpt ')'
|
|
{
|
|
$$ = &ast.FuncCallExpr{
|
|
FnName: model.NewCIStr($1),
|
|
Args: $3.([]ast.ExprNode),
|
|
}
|
|
}
|
|
| Identifier '.' Identifier '(' ExpressionListOpt ')'
|
|
{
|
|
var tp ast.FuncCallExprType
|
|
if isInTokenMap($3) {
|
|
tp = ast.FuncCallExprTypeKeyword
|
|
} else {
|
|
tp = ast.FuncCallExprTypeGeneric
|
|
}
|
|
$$ = &ast.FuncCallExpr{
|
|
Tp: tp,
|
|
Schema: model.NewCIStr($1),
|
|
FnName: model.NewCIStr($3),
|
|
Args: $5.([]ast.ExprNode),
|
|
}
|
|
}
|
|
|
|
FuncDatetimePrec:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| '(' ')'
|
|
{
|
|
$$ = nil
|
|
}
|
|
| '(' intLit ')'
|
|
{
|
|
expr := ast.NewValueExpr($2, parser.charset, parser.collation)
|
|
$$ = expr
|
|
}
|
|
|
|
TimeUnit:
|
|
TimestampUnit
|
|
| "SECOND_MICROSECOND"
|
|
{
|
|
$$ = ast.TimeUnitSecondMicrosecond
|
|
}
|
|
| "MINUTE_MICROSECOND"
|
|
{
|
|
$$ = ast.TimeUnitMinuteMicrosecond
|
|
}
|
|
| "MINUTE_SECOND"
|
|
{
|
|
$$ = ast.TimeUnitMinuteSecond
|
|
}
|
|
| "HOUR_MICROSECOND"
|
|
{
|
|
$$ = ast.TimeUnitHourMicrosecond
|
|
}
|
|
| "HOUR_SECOND"
|
|
{
|
|
$$ = ast.TimeUnitHourSecond
|
|
}
|
|
| "HOUR_MINUTE"
|
|
{
|
|
$$ = ast.TimeUnitHourMinute
|
|
}
|
|
| "DAY_MICROSECOND"
|
|
{
|
|
$$ = ast.TimeUnitDayMicrosecond
|
|
}
|
|
| "DAY_SECOND"
|
|
{
|
|
$$ = ast.TimeUnitDaySecond
|
|
}
|
|
| "DAY_MINUTE"
|
|
{
|
|
$$ = ast.TimeUnitDayMinute
|
|
}
|
|
| "DAY_HOUR"
|
|
{
|
|
$$ = ast.TimeUnitDayHour
|
|
}
|
|
| "YEAR_MONTH"
|
|
{
|
|
$$ = ast.TimeUnitYearMonth
|
|
}
|
|
|
|
TimestampUnit:
|
|
"MICROSECOND"
|
|
{
|
|
$$ = ast.TimeUnitMicrosecond
|
|
}
|
|
| "SECOND"
|
|
{
|
|
$$ = ast.TimeUnitSecond
|
|
}
|
|
| "MINUTE"
|
|
{
|
|
$$ = ast.TimeUnitMinute
|
|
}
|
|
| "HOUR"
|
|
{
|
|
$$ = ast.TimeUnitHour
|
|
}
|
|
| "DAY"
|
|
{
|
|
$$ = ast.TimeUnitDay
|
|
}
|
|
| "WEEK"
|
|
{
|
|
$$ = ast.TimeUnitWeek
|
|
}
|
|
| "MONTH"
|
|
{
|
|
$$ = ast.TimeUnitMonth
|
|
}
|
|
| "QUARTER"
|
|
{
|
|
$$ = ast.TimeUnitQuarter
|
|
}
|
|
| "YEAR"
|
|
{
|
|
$$ = ast.TimeUnitYear
|
|
}
|
|
| "SQL_TSI_SECOND"
|
|
{
|
|
$$ = ast.TimeUnitSecond
|
|
}
|
|
| "SQL_TSI_MINUTE"
|
|
{
|
|
$$ = ast.TimeUnitMinute
|
|
}
|
|
| "SQL_TSI_HOUR"
|
|
{
|
|
$$ = ast.TimeUnitHour
|
|
}
|
|
| "SQL_TSI_DAY"
|
|
{
|
|
$$ = ast.TimeUnitDay
|
|
}
|
|
| "SQL_TSI_WEEK"
|
|
{
|
|
$$ = ast.TimeUnitWeek
|
|
}
|
|
| "SQL_TSI_MONTH"
|
|
{
|
|
$$ = ast.TimeUnitMonth
|
|
}
|
|
| "SQL_TSI_QUARTER"
|
|
{
|
|
$$ = ast.TimeUnitQuarter
|
|
}
|
|
| "SQL_TSI_YEAR"
|
|
{
|
|
$$ = ast.TimeUnitYear
|
|
}
|
|
|
|
ExpressionOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| Expression
|
|
|
|
WhenClauseList:
|
|
WhenClause
|
|
{
|
|
$$ = []*ast.WhenClause{$1.(*ast.WhenClause)}
|
|
}
|
|
| WhenClauseList WhenClause
|
|
{
|
|
$$ = append($1.([]*ast.WhenClause), $2.(*ast.WhenClause))
|
|
}
|
|
|
|
WhenClause:
|
|
"WHEN" Expression "THEN" Expression
|
|
{
|
|
$$ = &ast.WhenClause{
|
|
Expr: $2,
|
|
Result: $4,
|
|
}
|
|
}
|
|
|
|
ElseOpt:
|
|
/* empty */
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "ELSE" Expression
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
CastType:
|
|
"BINARY" OptFieldLen
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeVarString)
|
|
tp.SetFlen($2.(int)) // TODO: Flen should be the flen of expression
|
|
if tp.GetFlen() != types.UnspecifiedLength {
|
|
tp.SetType(mysql.TypeString)
|
|
}
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
$$ = tp
|
|
}
|
|
| Char OptFieldLen OptBinary
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeVarString)
|
|
tp.SetFlen($2.(int)) // TODO: Flen should be the flen of expression
|
|
tp.SetCharset($3.(*ast.OptBinary).Charset)
|
|
if $3.(*ast.OptBinary).IsBinary {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
} else if tp.GetCharset() != "" {
|
|
co, err := charset.GetDefaultCollation(tp.GetCharset())
|
|
if err != nil {
|
|
yylex.AppendError(yylex.Errorf("Get collation error for charset: %s", tp.GetCharset()))
|
|
return 1
|
|
}
|
|
tp.SetCollate(co)
|
|
parser.explicitCharset = true
|
|
} else {
|
|
tp.SetCharset(parser.charset)
|
|
tp.SetCollate(parser.collation)
|
|
}
|
|
$$ = tp
|
|
}
|
|
| "DATE"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeDate)
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
$$ = tp
|
|
}
|
|
| "YEAR"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeYear)
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
$$ = tp
|
|
}
|
|
| "DATETIME" OptFieldLen
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeDatetime)
|
|
flen, _ := mysql.GetDefaultFieldLengthAndDecimalForCast(mysql.TypeDatetime)
|
|
tp.SetFlen(flen)
|
|
tp.SetDecimal($2.(int))
|
|
if tp.GetDecimal() > 0 {
|
|
tp.SetFlen(tp.GetFlen() + 1 + tp.GetDecimal())
|
|
}
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
$$ = tp
|
|
}
|
|
| "DECIMAL" FloatOpt
|
|
{
|
|
fopt := $2.(*ast.FloatOpt)
|
|
tp := types.NewFieldType(mysql.TypeNewDecimal)
|
|
tp.SetFlen(fopt.Flen)
|
|
tp.SetDecimal(fopt.Decimal)
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
$$ = tp
|
|
}
|
|
| "TIME" OptFieldLen
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeDuration)
|
|
flen, _ := mysql.GetDefaultFieldLengthAndDecimalForCast(mysql.TypeDuration)
|
|
tp.SetFlen(flen)
|
|
tp.SetDecimal($2.(int))
|
|
if tp.GetDecimal() > 0 {
|
|
tp.SetFlen(tp.GetFlen() + 1 + tp.GetDecimal())
|
|
}
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
$$ = tp
|
|
}
|
|
| "SIGNED" OptInteger
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeLonglong)
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
$$ = tp
|
|
}
|
|
| "UNSIGNED" OptInteger
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeLonglong)
|
|
tp.AddFlag(mysql.UnsignedFlag | mysql.BinaryFlag)
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
$$ = tp
|
|
}
|
|
| "JSON"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeJSON)
|
|
tp.AddFlag(mysql.BinaryFlag | mysql.ParseToJSONFlag)
|
|
tp.SetCharset(mysql.DefaultCharset)
|
|
tp.SetCollate(mysql.DefaultCollationName)
|
|
$$ = tp
|
|
}
|
|
| "DOUBLE"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeDouble)
|
|
flen, decimal := mysql.GetDefaultFieldLengthAndDecimalForCast(mysql.TypeDouble)
|
|
tp.SetFlen(flen)
|
|
tp.SetDecimal(decimal)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
$$ = tp
|
|
}
|
|
| "FLOAT" FloatOpt
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeFloat)
|
|
fopt := $2.(*ast.FloatOpt)
|
|
if fopt.Flen >= 54 {
|
|
yylex.AppendError(ErrTooBigPrecision.GenWithStackByArgs(fopt.Flen, "CAST", 53))
|
|
} else if fopt.Flen >= 25 {
|
|
tp = types.NewFieldType(mysql.TypeDouble)
|
|
}
|
|
flen, decimal := mysql.GetDefaultFieldLengthAndDecimalForCast(tp.GetType())
|
|
tp.SetFlen(flen)
|
|
tp.SetDecimal(decimal)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
$$ = tp
|
|
}
|
|
| "REAL"
|
|
{
|
|
var tp *types.FieldType
|
|
if parser.lexer.GetSQLMode().HasRealAsFloatMode() {
|
|
tp = types.NewFieldType(mysql.TypeFloat)
|
|
} else {
|
|
tp = types.NewFieldType(mysql.TypeDouble)
|
|
}
|
|
flen, decimal := mysql.GetDefaultFieldLengthAndDecimalForCast(tp.GetType())
|
|
tp.SetFlen(flen)
|
|
tp.SetDecimal(decimal)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
$$ = tp
|
|
}
|
|
|
|
Priority:
|
|
"LOW_PRIORITY"
|
|
{
|
|
$$ = mysql.LowPriority
|
|
}
|
|
| "HIGH_PRIORITY"
|
|
{
|
|
$$ = mysql.HighPriority
|
|
}
|
|
| "DELAYED"
|
|
{
|
|
$$ = mysql.DelayedPriority
|
|
}
|
|
|
|
PriorityOpt:
|
|
{
|
|
$$ = mysql.NoPriority
|
|
}
|
|
| Priority
|
|
|
|
TableName:
|
|
Identifier
|
|
{
|
|
$$ = &ast.TableName{Name: model.NewCIStr($1)}
|
|
}
|
|
| Identifier '.' Identifier
|
|
{
|
|
$$ = &ast.TableName{Schema: model.NewCIStr($1), Name: model.NewCIStr($3)}
|
|
}
|
|
|
|
TableNameList:
|
|
TableName
|
|
{
|
|
tbl := []*ast.TableName{$1.(*ast.TableName)}
|
|
$$ = tbl
|
|
}
|
|
| TableNameList ',' TableName
|
|
{
|
|
$$ = append($1.([]*ast.TableName), $3.(*ast.TableName))
|
|
}
|
|
|
|
TableNameOptWild:
|
|
Identifier OptWild
|
|
{
|
|
$$ = &ast.TableName{Name: model.NewCIStr($1)}
|
|
}
|
|
| Identifier '.' Identifier OptWild
|
|
{
|
|
$$ = &ast.TableName{Schema: model.NewCIStr($1), Name: model.NewCIStr($3)}
|
|
}
|
|
|
|
TableAliasRefList:
|
|
TableNameOptWild
|
|
{
|
|
tbl := []*ast.TableName{$1.(*ast.TableName)}
|
|
$$ = tbl
|
|
}
|
|
| TableAliasRefList ',' TableNameOptWild
|
|
{
|
|
$$ = append($1.([]*ast.TableName), $3.(*ast.TableName))
|
|
}
|
|
|
|
OptWild:
|
|
%prec empty
|
|
{}
|
|
| '.' '*'
|
|
{}
|
|
|
|
QuickOptional:
|
|
%prec empty
|
|
{
|
|
$$ = false
|
|
}
|
|
| "QUICK"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
/***************************Prepared Statement Start******************************
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/prepare.html
|
|
* Example:
|
|
* PREPARE stmt_name FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
|
|
* OR
|
|
* SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
|
|
* PREPARE stmt_name FROM @s;
|
|
*/
|
|
PreparedStmt:
|
|
"PREPARE" Identifier "FROM" PrepareSQL
|
|
{
|
|
var sqlText string
|
|
var sqlVar *ast.VariableExpr
|
|
switch x := $4.(type) {
|
|
case string:
|
|
sqlText = x
|
|
case *ast.VariableExpr:
|
|
sqlVar = x
|
|
}
|
|
$$ = &ast.PrepareStmt{
|
|
Name: $2,
|
|
SQLText: sqlText,
|
|
SQLVar: sqlVar,
|
|
}
|
|
}
|
|
|
|
PrepareSQL:
|
|
stringLit
|
|
{
|
|
$$ = $1
|
|
}
|
|
| UserVariable
|
|
{
|
|
$$ = $1
|
|
}
|
|
|
|
/*
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/execute.html
|
|
* Example:
|
|
* EXECUTE stmt1 USING @a, @b;
|
|
* OR
|
|
* EXECUTE stmt1;
|
|
*/
|
|
ExecuteStmt:
|
|
"EXECUTE" Identifier
|
|
{
|
|
$$ = &ast.ExecuteStmt{Name: $2}
|
|
}
|
|
| "EXECUTE" Identifier "USING" UserVariableList
|
|
{
|
|
$$ = &ast.ExecuteStmt{
|
|
Name: $2,
|
|
UsingVars: $4.([]ast.ExprNode),
|
|
}
|
|
}
|
|
|
|
UserVariableList:
|
|
UserVariable
|
|
{
|
|
$$ = []ast.ExprNode{$1}
|
|
}
|
|
| UserVariableList ',' UserVariable
|
|
{
|
|
$$ = append($1.([]ast.ExprNode), $3)
|
|
}
|
|
|
|
DeallocateStmt:
|
|
DeallocateSym "PREPARE" Identifier
|
|
{
|
|
$$ = &ast.DeallocateStmt{Name: $3}
|
|
}
|
|
|
|
DeallocateSym:
|
|
"DEALLOCATE"
|
|
| "DROP"
|
|
|
|
RollbackStmt:
|
|
"ROLLBACK"
|
|
{
|
|
$$ = &ast.RollbackStmt{}
|
|
}
|
|
| "ROLLBACK" CompletionTypeWithinTransaction
|
|
{
|
|
$$ = &ast.RollbackStmt{CompletionType: $2.(ast.CompletionType)}
|
|
}
|
|
| "ROLLBACK" "TO" Identifier
|
|
{
|
|
$$ = &ast.RollbackStmt{SavepointName: $3}
|
|
}
|
|
| "ROLLBACK" "TO" "SAVEPOINT" Identifier
|
|
{
|
|
$$ = &ast.RollbackStmt{SavepointName: $4}
|
|
}
|
|
|
|
CompletionTypeWithinTransaction:
|
|
"AND" "CHAIN" "NO" "RELEASE"
|
|
{
|
|
$$ = ast.CompletionTypeChain
|
|
}
|
|
| "AND" "NO" "CHAIN" "RELEASE"
|
|
{
|
|
$$ = ast.CompletionTypeRelease
|
|
}
|
|
| "AND" "NO" "CHAIN" "NO" "RELEASE"
|
|
{
|
|
$$ = ast.CompletionTypeDefault
|
|
}
|
|
| "AND" "CHAIN"
|
|
{
|
|
$$ = ast.CompletionTypeChain
|
|
}
|
|
| "AND" "NO" "CHAIN"
|
|
{
|
|
$$ = ast.CompletionTypeDefault
|
|
}
|
|
| "RELEASE"
|
|
{
|
|
$$ = ast.CompletionTypeRelease
|
|
}
|
|
| "NO" "RELEASE"
|
|
{
|
|
$$ = ast.CompletionTypeDefault
|
|
}
|
|
|
|
ShutdownStmt:
|
|
"SHUTDOWN"
|
|
{
|
|
$$ = &ast.ShutdownStmt{}
|
|
}
|
|
|
|
RestartStmt:
|
|
"RESTART"
|
|
{
|
|
$$ = &ast.RestartStmt{}
|
|
}
|
|
|
|
HelpStmt:
|
|
"HELP" stringLit
|
|
{
|
|
$$ = &ast.HelpStmt{Topic: $2}
|
|
}
|
|
|
|
SelectStmtBasic:
|
|
"SELECT" SelectStmtOpts SelectStmtFieldList HavingClause
|
|
{
|
|
st := &ast.SelectStmt{
|
|
SelectStmtOpts: $2.(*ast.SelectStmtOpts),
|
|
Distinct: $2.(*ast.SelectStmtOpts).Distinct,
|
|
Fields: $3.(*ast.FieldList),
|
|
Kind: ast.SelectStmtKindSelect,
|
|
}
|
|
if st.SelectStmtOpts.TableHints != nil {
|
|
st.TableHints = st.SelectStmtOpts.TableHints
|
|
}
|
|
if $4 != nil {
|
|
st.Having = $4.(*ast.HavingClause)
|
|
}
|
|
$$ = st
|
|
}
|
|
|
|
SelectStmtFromDualTable:
|
|
SelectStmtBasic FromDual WhereClauseOptional
|
|
{
|
|
st := $1.(*ast.SelectStmt)
|
|
lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
|
|
if lastField.Expr != nil && lastField.AsName.O == "" {
|
|
lastEnd := yyS[yypt-1].offset - 1
|
|
lastField.SetText(parser.lexer.client, parser.src[lastField.Offset:lastEnd])
|
|
}
|
|
if $3 != nil {
|
|
st.Where = $3.(ast.ExprNode)
|
|
}
|
|
}
|
|
|
|
SelectStmtFromTable:
|
|
SelectStmtBasic "FROM" TableRefsClause WhereClauseOptional SelectStmtGroup HavingClause WindowClauseOptional
|
|
{
|
|
st := $1.(*ast.SelectStmt)
|
|
st.From = $3.(*ast.TableRefsClause)
|
|
lastField := st.Fields.Fields[len(st.Fields.Fields)-1]
|
|
if lastField.Expr != nil && lastField.AsName.O == "" {
|
|
lastEnd := parser.endOffset(&yyS[yypt-5])
|
|
lastField.SetText(parser.lexer.client, parser.src[lastField.Offset:lastEnd])
|
|
}
|
|
if $4 != nil {
|
|
st.Where = $4.(ast.ExprNode)
|
|
}
|
|
if $5 != nil {
|
|
st.GroupBy = $5.(*ast.GroupByClause)
|
|
}
|
|
if $6 != nil {
|
|
st.Having = $6.(*ast.HavingClause)
|
|
}
|
|
if $7 != nil {
|
|
st.WindowSpecs = ($7.([]ast.WindowSpec))
|
|
}
|
|
$$ = st
|
|
}
|
|
|
|
TableSampleOpt:
|
|
%prec empty
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "TABLESAMPLE" TableSampleMethodOpt '(' Expression TableSampleUnitOpt ')' RepeatableOpt
|
|
{
|
|
var repSeed ast.ExprNode
|
|
if $7 != nil {
|
|
repSeed = ast.NewValueExpr($7, parser.charset, parser.collation)
|
|
}
|
|
$$ = &ast.TableSample{
|
|
SampleMethod: $2.(ast.SampleMethodType),
|
|
Expr: ast.NewValueExpr($4, parser.charset, parser.collation),
|
|
SampleClauseUnit: $5.(ast.SampleClauseUnitType),
|
|
RepeatableSeed: repSeed,
|
|
}
|
|
}
|
|
| "TABLESAMPLE" TableSampleMethodOpt '(' ')' RepeatableOpt
|
|
{
|
|
var repSeed ast.ExprNode
|
|
if $5 != nil {
|
|
repSeed = ast.NewValueExpr($5, parser.charset, parser.collation)
|
|
}
|
|
$$ = &ast.TableSample{
|
|
SampleMethod: $2.(ast.SampleMethodType),
|
|
RepeatableSeed: repSeed,
|
|
}
|
|
}
|
|
|
|
TableSampleMethodOpt:
|
|
%prec empty
|
|
{
|
|
$$ = ast.SampleMethodTypeNone
|
|
}
|
|
| "SYSTEM"
|
|
{
|
|
$$ = ast.SampleMethodTypeSystem
|
|
}
|
|
| "BERNOULLI"
|
|
{
|
|
$$ = ast.SampleMethodTypeBernoulli
|
|
}
|
|
| "REGIONS"
|
|
{
|
|
$$ = ast.SampleMethodTypeTiDBRegion
|
|
}
|
|
|
|
TableSampleUnitOpt:
|
|
%prec empty
|
|
{
|
|
$$ = ast.SampleClauseUnitTypeDefault
|
|
}
|
|
| "ROWS"
|
|
{
|
|
$$ = ast.SampleClauseUnitTypeRow
|
|
}
|
|
| "PERCENT"
|
|
{
|
|
$$ = ast.SampleClauseUnitTypePercent
|
|
}
|
|
|
|
RepeatableOpt:
|
|
%prec empty
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "REPEATABLE" '(' Expression ')'
|
|
{
|
|
$$ = $3
|
|
}
|
|
|
|
SelectStmt:
|
|
SelectStmtBasic WhereClauseOptional SelectStmtGroup OrderByOptional SelectStmtLimitOpt SelectLockOpt SelectStmtIntoOption
|
|
{
|
|
st := $1.(*ast.SelectStmt)
|
|
if $6 != nil {
|
|
st.LockInfo = $6.(*ast.SelectLockInfo)
|
|
}
|
|
if $2 != nil {
|
|
st.Where = $2.(ast.ExprNode)
|
|
}
|
|
if $3 != nil {
|
|
st.GroupBy = $3.(*ast.GroupByClause)
|
|
}
|
|
if $4 != nil {
|
|
st.OrderBy = $4.(*ast.OrderByClause)
|
|
}
|
|
if $5 != nil {
|
|
st.Limit = $5.(*ast.Limit)
|
|
}
|
|
if $7 != nil {
|
|
st.SelectIntoOpt = $7.(*ast.SelectIntoOption)
|
|
}
|
|
$$ = st
|
|
}
|
|
| SelectStmtFromDualTable SelectStmtGroup OrderByOptional SelectStmtLimitOpt SelectLockOpt SelectStmtIntoOption
|
|
{
|
|
st := $1.(*ast.SelectStmt)
|
|
if $2 != nil {
|
|
st.GroupBy = $2.(*ast.GroupByClause)
|
|
}
|
|
if $3 != nil {
|
|
st.OrderBy = $3.(*ast.OrderByClause)
|
|
}
|
|
if $4 != nil {
|
|
st.Limit = $4.(*ast.Limit)
|
|
}
|
|
if $5 != nil {
|
|
st.LockInfo = $5.(*ast.SelectLockInfo)
|
|
}
|
|
if $6 != nil {
|
|
st.SelectIntoOpt = $6.(*ast.SelectIntoOption)
|
|
}
|
|
$$ = st
|
|
}
|
|
| SelectStmtFromTable OrderByOptional SelectStmtLimitOpt SelectLockOpt SelectStmtIntoOption
|
|
{
|
|
st := $1.(*ast.SelectStmt)
|
|
if $4 != nil {
|
|
st.LockInfo = $4.(*ast.SelectLockInfo)
|
|
}
|
|
if $2 != nil {
|
|
st.OrderBy = $2.(*ast.OrderByClause)
|
|
}
|
|
if $3 != nil {
|
|
st.Limit = $3.(*ast.Limit)
|
|
}
|
|
if $5 != nil {
|
|
st.SelectIntoOpt = $5.(*ast.SelectIntoOption)
|
|
}
|
|
$$ = st
|
|
}
|
|
| "TABLE" TableName OrderByOptional SelectStmtLimitOpt SelectLockOpt SelectStmtIntoOption
|
|
{
|
|
st := &ast.SelectStmt{
|
|
Kind: ast.SelectStmtKindTable,
|
|
Fields: &ast.FieldList{Fields: []*ast.SelectField{{WildCard: &ast.WildCardField{}}}},
|
|
}
|
|
ts := &ast.TableSource{Source: $2.(*ast.TableName)}
|
|
st.From = &ast.TableRefsClause{TableRefs: &ast.Join{Left: ts}}
|
|
if $3 != nil {
|
|
st.OrderBy = $3.(*ast.OrderByClause)
|
|
}
|
|
if $4 != nil {
|
|
st.Limit = $4.(*ast.Limit)
|
|
}
|
|
if $5 != nil {
|
|
st.LockInfo = $5.(*ast.SelectLockInfo)
|
|
}
|
|
if $6 != nil {
|
|
st.SelectIntoOpt = $6.(*ast.SelectIntoOption)
|
|
}
|
|
$$ = st
|
|
}
|
|
| "VALUES" ValuesStmtList OrderByOptional SelectStmtLimitOpt SelectLockOpt SelectStmtIntoOption
|
|
{
|
|
st := &ast.SelectStmt{
|
|
Kind: ast.SelectStmtKindValues,
|
|
Fields: &ast.FieldList{Fields: []*ast.SelectField{{WildCard: &ast.WildCardField{}}}},
|
|
Lists: $2.([]*ast.RowExpr),
|
|
}
|
|
if $3 != nil {
|
|
st.OrderBy = $3.(*ast.OrderByClause)
|
|
}
|
|
if $4 != nil {
|
|
st.Limit = $4.(*ast.Limit)
|
|
}
|
|
if $5 != nil {
|
|
st.LockInfo = $5.(*ast.SelectLockInfo)
|
|
}
|
|
if $6 != nil {
|
|
st.SelectIntoOpt = $6.(*ast.SelectIntoOption)
|
|
}
|
|
$$ = st
|
|
}
|
|
|
|
SelectStmtWithClause:
|
|
WithClause SelectStmt
|
|
{
|
|
sel := $2.(*ast.SelectStmt)
|
|
sel.With = $1.(*ast.WithClause)
|
|
$$ = sel
|
|
}
|
|
| WithClause SubSelect
|
|
{
|
|
var sel ast.StmtNode
|
|
switch x := $2.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
x.IsInBraces = true
|
|
x.WithBeforeBraces = true
|
|
x.With = $1.(*ast.WithClause)
|
|
sel = x
|
|
case *ast.SetOprStmt:
|
|
x.IsInBraces = true
|
|
x.With = $1.(*ast.WithClause)
|
|
sel = x
|
|
}
|
|
$$ = sel
|
|
}
|
|
|
|
WithClause:
|
|
"WITH" WithList
|
|
{
|
|
$$ = $2
|
|
}
|
|
| "WITH" recursive WithList
|
|
{
|
|
ws := $3.(*ast.WithClause)
|
|
ws.IsRecursive = true
|
|
for _, cte := range ws.CTEs {
|
|
cte.IsRecursive = true
|
|
}
|
|
$$ = ws
|
|
}
|
|
|
|
WithList:
|
|
WithList ',' CommonTableExpr
|
|
{
|
|
ws := $1.(*ast.WithClause)
|
|
ws.CTEs = append(ws.CTEs, $3.(*ast.CommonTableExpression))
|
|
$$ = ws
|
|
}
|
|
| CommonTableExpr
|
|
{
|
|
ws := &ast.WithClause{}
|
|
ws.CTEs = make([]*ast.CommonTableExpression, 0, 4)
|
|
ws.CTEs = append(ws.CTEs, $1.(*ast.CommonTableExpression))
|
|
$$ = ws
|
|
}
|
|
|
|
CommonTableExpr:
|
|
Identifier IdentListWithParenOpt "AS" SubSelect
|
|
{
|
|
cte := &ast.CommonTableExpression{}
|
|
cte.Name = model.NewCIStr($1)
|
|
cte.ColNameList = $2.([]model.CIStr)
|
|
cte.Query = $4.(*ast.SubqueryExpr)
|
|
$$ = cte
|
|
}
|
|
|
|
FromDual:
|
|
"FROM" "DUAL"
|
|
|
|
WindowClauseOptional:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "WINDOW" WindowDefinitionList
|
|
{
|
|
$$ = $2.([]ast.WindowSpec)
|
|
}
|
|
|
|
WindowDefinitionList:
|
|
WindowDefinition
|
|
{
|
|
$$ = []ast.WindowSpec{$1.(ast.WindowSpec)}
|
|
}
|
|
| WindowDefinitionList ',' WindowDefinition
|
|
{
|
|
$$ = append($1.([]ast.WindowSpec), $3.(ast.WindowSpec))
|
|
}
|
|
|
|
WindowDefinition:
|
|
WindowName "AS" WindowSpec
|
|
{
|
|
var spec = $3.(ast.WindowSpec)
|
|
spec.Name = $1.(model.CIStr)
|
|
$$ = spec
|
|
}
|
|
|
|
WindowName:
|
|
Identifier
|
|
{
|
|
$$ = model.NewCIStr($1)
|
|
}
|
|
|
|
WindowSpec:
|
|
'(' WindowSpecDetails ')'
|
|
{
|
|
$$ = $2.(ast.WindowSpec)
|
|
}
|
|
|
|
WindowSpecDetails:
|
|
OptExistingWindowName OptPartitionClause OptWindowOrderByClause OptWindowFrameClause
|
|
{
|
|
spec := ast.WindowSpec{Ref: $1.(model.CIStr)}
|
|
if $2 != nil {
|
|
spec.PartitionBy = $2.(*ast.PartitionByClause)
|
|
}
|
|
if $3 != nil {
|
|
spec.OrderBy = $3.(*ast.OrderByClause)
|
|
}
|
|
if $4 != nil {
|
|
spec.Frame = $4.(*ast.FrameClause)
|
|
}
|
|
$$ = spec
|
|
}
|
|
|
|
OptExistingWindowName:
|
|
{
|
|
$$ = model.CIStr{}
|
|
}
|
|
| WindowName
|
|
|
|
OptPartitionClause:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "PARTITION" "BY" ByList
|
|
{
|
|
$$ = &ast.PartitionByClause{Items: $3.([]*ast.ByItem)}
|
|
}
|
|
|
|
OptWindowOrderByClause:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "ORDER" "BY" ByList
|
|
{
|
|
$$ = &ast.OrderByClause{Items: $3.([]*ast.ByItem)}
|
|
}
|
|
|
|
OptWindowFrameClause:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| WindowFrameUnits WindowFrameExtent
|
|
{
|
|
$$ = &ast.FrameClause{
|
|
Type: $1.(ast.FrameType),
|
|
Extent: $2.(ast.FrameExtent),
|
|
}
|
|
}
|
|
|
|
WindowFrameUnits:
|
|
"ROWS"
|
|
{
|
|
$$ = ast.FrameType(ast.Rows)
|
|
}
|
|
| "RANGE"
|
|
{
|
|
$$ = ast.FrameType(ast.Ranges)
|
|
}
|
|
| "GROUPS"
|
|
{
|
|
$$ = ast.FrameType(ast.Groups)
|
|
}
|
|
|
|
WindowFrameExtent:
|
|
WindowFrameStart
|
|
{
|
|
$$ = ast.FrameExtent{
|
|
Start: $1.(ast.FrameBound),
|
|
End: ast.FrameBound{Type: ast.CurrentRow},
|
|
}
|
|
}
|
|
| WindowFrameBetween
|
|
|
|
WindowFrameStart:
|
|
"UNBOUNDED" "PRECEDING"
|
|
{
|
|
$$ = ast.FrameBound{Type: ast.Preceding, UnBounded: true}
|
|
}
|
|
| NumLiteral "PRECEDING"
|
|
{
|
|
$$ = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr($1, parser.charset, parser.collation)}
|
|
}
|
|
| paramMarker "PRECEDING"
|
|
{
|
|
$$ = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewParamMarkerExpr(yyS[yypt].offset)}
|
|
}
|
|
| "INTERVAL" Expression TimeUnit "PRECEDING"
|
|
{
|
|
$$ = ast.FrameBound{Type: ast.Preceding, Expr: $2, Unit: $3.(ast.TimeUnitType)}
|
|
}
|
|
| "CURRENT" "ROW"
|
|
{
|
|
$$ = ast.FrameBound{Type: ast.CurrentRow}
|
|
}
|
|
|
|
WindowFrameBetween:
|
|
"BETWEEN" WindowFrameBound "AND" WindowFrameBound
|
|
{
|
|
$$ = ast.FrameExtent{Start: $2.(ast.FrameBound), End: $4.(ast.FrameBound)}
|
|
}
|
|
|
|
WindowFrameBound:
|
|
WindowFrameStart
|
|
| "UNBOUNDED" "FOLLOWING"
|
|
{
|
|
$$ = ast.FrameBound{Type: ast.Following, UnBounded: true}
|
|
}
|
|
| NumLiteral "FOLLOWING"
|
|
{
|
|
$$ = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr($1, parser.charset, parser.collation)}
|
|
}
|
|
| paramMarker "FOLLOWING"
|
|
{
|
|
$$ = ast.FrameBound{Type: ast.Following, Expr: ast.NewParamMarkerExpr(yyS[yypt].offset)}
|
|
}
|
|
| "INTERVAL" Expression TimeUnit "FOLLOWING"
|
|
{
|
|
$$ = ast.FrameBound{Type: ast.Following, Expr: $2, Unit: $3.(ast.TimeUnitType)}
|
|
}
|
|
|
|
OptWindowingClause:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| WindowingClause
|
|
{
|
|
spec := $1.(ast.WindowSpec)
|
|
$$ = &spec
|
|
}
|
|
|
|
WindowingClause:
|
|
"OVER" WindowNameOrSpec
|
|
{
|
|
$$ = $2.(ast.WindowSpec)
|
|
}
|
|
|
|
WindowNameOrSpec:
|
|
WindowName
|
|
{
|
|
$$ = ast.WindowSpec{Name: $1.(model.CIStr), OnlyAlias: true}
|
|
}
|
|
| WindowSpec
|
|
|
|
WindowFuncCall:
|
|
"ROW_NUMBER" '(' ')' WindowingClause
|
|
{
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Spec: $4.(ast.WindowSpec)}
|
|
}
|
|
| "RANK" '(' ')' WindowingClause
|
|
{
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Spec: $4.(ast.WindowSpec)}
|
|
}
|
|
| "DENSE_RANK" '(' ')' WindowingClause
|
|
{
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Spec: $4.(ast.WindowSpec)}
|
|
}
|
|
| "CUME_DIST" '(' ')' WindowingClause
|
|
{
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Spec: $4.(ast.WindowSpec)}
|
|
}
|
|
| "PERCENT_RANK" '(' ')' WindowingClause
|
|
{
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Spec: $4.(ast.WindowSpec)}
|
|
}
|
|
| "NTILE" '(' SimpleExpr ')' WindowingClause
|
|
{
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$3}, Spec: $5.(ast.WindowSpec)}
|
|
}
|
|
| "LEAD" '(' Expression OptLeadLagInfo ')' OptNullTreatment WindowingClause
|
|
{
|
|
args := []ast.ExprNode{$3}
|
|
if $4 != nil {
|
|
args = append(args, $4.([]ast.ExprNode)...)
|
|
}
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: args, IgnoreNull: $6.(bool), Spec: $7.(ast.WindowSpec)}
|
|
}
|
|
| "LAG" '(' Expression OptLeadLagInfo ')' OptNullTreatment WindowingClause
|
|
{
|
|
args := []ast.ExprNode{$3}
|
|
if $4 != nil {
|
|
args = append(args, $4.([]ast.ExprNode)...)
|
|
}
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: args, IgnoreNull: $6.(bool), Spec: $7.(ast.WindowSpec)}
|
|
}
|
|
| "FIRST_VALUE" '(' Expression ')' OptNullTreatment WindowingClause
|
|
{
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$3}, IgnoreNull: $5.(bool), Spec: $6.(ast.WindowSpec)}
|
|
}
|
|
| "LAST_VALUE" '(' Expression ')' OptNullTreatment WindowingClause
|
|
{
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$3}, IgnoreNull: $5.(bool), Spec: $6.(ast.WindowSpec)}
|
|
}
|
|
| "NTH_VALUE" '(' Expression ',' SimpleExpr ')' OptFromFirstLast OptNullTreatment WindowingClause
|
|
{
|
|
$$ = &ast.WindowFuncExpr{Name: $1, Args: []ast.ExprNode{$3, $5}, FromLast: $7.(bool), IgnoreNull: $8.(bool), Spec: $9.(ast.WindowSpec)}
|
|
}
|
|
|
|
OptLeadLagInfo:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| ',' NumLiteral OptLLDefault
|
|
{
|
|
args := []ast.ExprNode{ast.NewValueExpr($2, parser.charset, parser.collation)}
|
|
if $3 != nil {
|
|
args = append(args, $3.(ast.ExprNode))
|
|
}
|
|
$$ = args
|
|
}
|
|
| ',' paramMarker OptLLDefault
|
|
{
|
|
args := []ast.ExprNode{ast.NewParamMarkerExpr(yyS[yypt-1].offset)}
|
|
if $3 != nil {
|
|
args = append(args, $3.(ast.ExprNode))
|
|
}
|
|
$$ = args
|
|
}
|
|
|
|
OptLLDefault:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| ',' Expression
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
OptNullTreatment:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "RESPECT" "NULLS"
|
|
{
|
|
$$ = false
|
|
}
|
|
| "IGNORE" "NULLS"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
OptFromFirstLast:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "FROM" "FIRST"
|
|
{
|
|
$$ = false
|
|
}
|
|
| "FROM" "LAST"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
TableRefsClause:
|
|
TableRefs
|
|
{
|
|
$$ = &ast.TableRefsClause{TableRefs: $1.(*ast.Join)}
|
|
}
|
|
|
|
TableRefs:
|
|
EscapedTableRef
|
|
{
|
|
if j, ok := $1.(*ast.Join); ok {
|
|
// if $1 is Join, use it directly
|
|
$$ = j
|
|
} else {
|
|
$$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: nil}
|
|
}
|
|
}
|
|
| TableRefs ',' EscapedTableRef
|
|
{
|
|
/* from a, b is default cross join */
|
|
$$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $3.(ast.ResultSetNode), Tp: ast.CrossJoin}
|
|
}
|
|
|
|
EscapedTableRef:
|
|
TableRef %prec lowerThanSetKeyword
|
|
| '{' Identifier TableRef '}'
|
|
{
|
|
/*
|
|
* ODBC escape syntax for outer join is { OJ join_table }
|
|
* Use an Identifier for OJ
|
|
*/
|
|
$$ = $3
|
|
}
|
|
|
|
TableRef:
|
|
TableFactor
|
|
| JoinTable
|
|
|
|
TableFactor:
|
|
TableName PartitionNameListOpt TableAsNameOpt AsOfClauseOpt IndexHintListOpt TableSampleOpt
|
|
{
|
|
tn := $1.(*ast.TableName)
|
|
tn.PartitionNames = $2.([]model.CIStr)
|
|
tn.IndexHints = $5.([]*ast.IndexHint)
|
|
if $6 != nil {
|
|
tn.TableSample = $6.(*ast.TableSample)
|
|
}
|
|
if $4 != nil {
|
|
tn.AsOf = $4.(*ast.AsOfClause)
|
|
}
|
|
$$ = &ast.TableSource{Source: tn, AsName: $3.(model.CIStr)}
|
|
}
|
|
| SubSelect TableAsNameOpt
|
|
{
|
|
resultNode := $1.(*ast.SubqueryExpr).Query
|
|
$$ = &ast.TableSource{Source: resultNode, AsName: $2.(model.CIStr)}
|
|
}
|
|
| '(' TableRefs ')'
|
|
{
|
|
j := $2.(*ast.Join)
|
|
j.ExplicitParens = true
|
|
$$ = $2
|
|
}
|
|
|
|
PartitionNameListOpt:
|
|
/* empty */
|
|
{
|
|
$$ = []model.CIStr{}
|
|
}
|
|
| "PARTITION" '(' PartitionNameList ')'
|
|
{
|
|
$$ = $3
|
|
}
|
|
|
|
TableAsNameOpt:
|
|
%prec empty
|
|
{
|
|
$$ = model.CIStr{}
|
|
}
|
|
| TableAsName
|
|
|
|
TableAsName:
|
|
Identifier
|
|
{
|
|
$$ = model.NewCIStr($1)
|
|
}
|
|
| "AS" Identifier
|
|
{
|
|
$$ = model.NewCIStr($2)
|
|
}
|
|
|
|
IndexHintType:
|
|
"USE" KeyOrIndex
|
|
{
|
|
$$ = ast.HintUse
|
|
}
|
|
| "IGNORE" KeyOrIndex
|
|
{
|
|
$$ = ast.HintIgnore
|
|
}
|
|
| "FORCE" KeyOrIndex
|
|
{
|
|
$$ = ast.HintForce
|
|
}
|
|
|
|
IndexHintScope:
|
|
{
|
|
$$ = ast.HintForScan
|
|
}
|
|
| "FOR" "JOIN"
|
|
{
|
|
$$ = ast.HintForJoin
|
|
}
|
|
| "FOR" "ORDER" "BY"
|
|
{
|
|
$$ = ast.HintForOrderBy
|
|
}
|
|
| "FOR" "GROUP" "BY"
|
|
{
|
|
$$ = ast.HintForGroupBy
|
|
}
|
|
|
|
IndexHint:
|
|
IndexHintType IndexHintScope '(' IndexNameList ')'
|
|
{
|
|
$$ = &ast.IndexHint{
|
|
IndexNames: $4.([]model.CIStr),
|
|
HintType: $1.(ast.IndexHintType),
|
|
HintScope: $2.(ast.IndexHintScope),
|
|
}
|
|
}
|
|
|
|
IndexNameList:
|
|
{
|
|
var nameList []model.CIStr
|
|
$$ = nameList
|
|
}
|
|
| Identifier
|
|
{
|
|
$$ = []model.CIStr{model.NewCIStr($1)}
|
|
}
|
|
| IndexNameList ',' Identifier
|
|
{
|
|
$$ = append($1.([]model.CIStr), model.NewCIStr($3))
|
|
}
|
|
| "PRIMARY"
|
|
{
|
|
$$ = []model.CIStr{model.NewCIStr($1)}
|
|
}
|
|
| IndexNameList ',' "PRIMARY"
|
|
{
|
|
$$ = append($1.([]model.CIStr), model.NewCIStr($3))
|
|
}
|
|
|
|
IndexHintList:
|
|
IndexHint
|
|
{
|
|
$$ = []*ast.IndexHint{$1.(*ast.IndexHint)}
|
|
}
|
|
| IndexHintList IndexHint
|
|
{
|
|
$$ = append($1.([]*ast.IndexHint), $2.(*ast.IndexHint))
|
|
}
|
|
|
|
IndexHintListOpt:
|
|
{
|
|
$$ = []*ast.IndexHint{}
|
|
}
|
|
| IndexHintList
|
|
|
|
JoinTable:
|
|
/* Use %prec to evaluate production TableRef before cross join */
|
|
TableRef CrossOpt TableRef %prec tableRefPriority
|
|
{
|
|
$$ = ast.NewCrossJoin($1.(ast.ResultSetNode), $3.(ast.ResultSetNode))
|
|
}
|
|
| TableRef CrossOpt TableRef "ON" Expression
|
|
{
|
|
on := &ast.OnCondition{Expr: $5}
|
|
$$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $3.(ast.ResultSetNode), Tp: ast.CrossJoin, On: on}
|
|
}
|
|
| TableRef CrossOpt TableRef "USING" '(' ColumnNameList ')'
|
|
{
|
|
$$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $3.(ast.ResultSetNode), Tp: ast.CrossJoin, Using: $6.([]*ast.ColumnName)}
|
|
}
|
|
| TableRef JoinType OuterOpt "JOIN" TableRef "ON" Expression
|
|
{
|
|
on := &ast.OnCondition{Expr: $7}
|
|
$$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $5.(ast.ResultSetNode), Tp: $2.(ast.JoinType), On: on}
|
|
}
|
|
| TableRef JoinType OuterOpt "JOIN" TableRef "USING" '(' ColumnNameList ')'
|
|
{
|
|
$$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $5.(ast.ResultSetNode), Tp: $2.(ast.JoinType), Using: $8.([]*ast.ColumnName)}
|
|
}
|
|
| TableRef "NATURAL" "JOIN" TableRef
|
|
{
|
|
$$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $4.(ast.ResultSetNode), NaturalJoin: true}
|
|
}
|
|
| TableRef "NATURAL" JoinType OuterOpt "JOIN" TableRef
|
|
{
|
|
$$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $6.(ast.ResultSetNode), Tp: $3.(ast.JoinType), NaturalJoin: true}
|
|
}
|
|
| TableRef "STRAIGHT_JOIN" TableRef
|
|
{
|
|
$$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $3.(ast.ResultSetNode), StraightJoin: true}
|
|
}
|
|
| TableRef "STRAIGHT_JOIN" TableRef "ON" Expression
|
|
{
|
|
on := &ast.OnCondition{Expr: $5}
|
|
$$ = &ast.Join{Left: $1.(ast.ResultSetNode), Right: $3.(ast.ResultSetNode), StraightJoin: true, On: on}
|
|
}
|
|
|
|
JoinType:
|
|
"LEFT"
|
|
{
|
|
$$ = ast.LeftJoin
|
|
}
|
|
| "RIGHT"
|
|
{
|
|
$$ = ast.RightJoin
|
|
}
|
|
|
|
OuterOpt:
|
|
{}
|
|
| "OUTER"
|
|
|
|
CrossOpt:
|
|
"JOIN"
|
|
| "CROSS" "JOIN"
|
|
| "INNER" "JOIN"
|
|
|
|
LimitClause:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "LIMIT" LimitOption
|
|
{
|
|
$$ = &ast.Limit{Count: $2.(ast.ValueExpr)}
|
|
}
|
|
|
|
LimitOption:
|
|
LengthNum
|
|
{
|
|
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
|
|
}
|
|
| paramMarker
|
|
{
|
|
$$ = ast.NewParamMarkerExpr(yyS[yypt].offset)
|
|
}
|
|
|
|
RowOrRows:
|
|
"ROW"
|
|
| "ROWS"
|
|
|
|
FirstOrNext:
|
|
"FIRST"
|
|
| "NEXT"
|
|
|
|
FetchFirstOpt:
|
|
{
|
|
$$ = ast.NewValueExpr(uint64(1), parser.charset, parser.collation)
|
|
}
|
|
| LimitOption
|
|
|
|
SelectStmtLimit:
|
|
"LIMIT" LimitOption
|
|
{
|
|
$$ = &ast.Limit{Count: $2.(ast.ExprNode)}
|
|
}
|
|
| "LIMIT" LimitOption ',' LimitOption
|
|
{
|
|
$$ = &ast.Limit{Offset: $2.(ast.ExprNode), Count: $4.(ast.ExprNode)}
|
|
}
|
|
| "LIMIT" LimitOption "OFFSET" LimitOption
|
|
{
|
|
$$ = &ast.Limit{Offset: $4.(ast.ExprNode), Count: $2.(ast.ExprNode)}
|
|
}
|
|
| "FETCH" FirstOrNext FetchFirstOpt RowOrRows "ONLY"
|
|
{
|
|
$$ = &ast.Limit{Count: $3.(ast.ExprNode)}
|
|
}
|
|
|
|
SelectStmtLimitOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| SelectStmtLimit
|
|
|
|
SelectStmtOpt:
|
|
TableOptimizerHints
|
|
{
|
|
opt := &ast.SelectStmtOpts{}
|
|
opt.SQLCache = true
|
|
opt.TableHints = $1.([]*ast.TableOptimizerHint)
|
|
$$ = opt
|
|
}
|
|
| DistinctOpt
|
|
{
|
|
opt := &ast.SelectStmtOpts{}
|
|
opt.SQLCache = true
|
|
if $1.(bool) {
|
|
opt.Distinct = true
|
|
} else {
|
|
opt.Distinct = false
|
|
opt.ExplicitAll = true
|
|
}
|
|
$$ = opt
|
|
}
|
|
| Priority
|
|
{
|
|
opt := &ast.SelectStmtOpts{}
|
|
opt.SQLCache = true
|
|
opt.Priority = $1.(mysql.PriorityEnum)
|
|
$$ = opt
|
|
}
|
|
| "SQL_SMALL_RESULT"
|
|
{
|
|
opt := &ast.SelectStmtOpts{}
|
|
opt.SQLCache = true
|
|
opt.SQLSmallResult = true
|
|
$$ = opt
|
|
}
|
|
| "SQL_BIG_RESULT"
|
|
{
|
|
opt := &ast.SelectStmtOpts{}
|
|
opt.SQLCache = true
|
|
opt.SQLBigResult = true
|
|
$$ = opt
|
|
}
|
|
| "SQL_BUFFER_RESULT"
|
|
{
|
|
opt := &ast.SelectStmtOpts{}
|
|
opt.SQLCache = true
|
|
opt.SQLBufferResult = true
|
|
$$ = opt
|
|
}
|
|
| SelectStmtSQLCache
|
|
{
|
|
opt := &ast.SelectStmtOpts{}
|
|
opt.SQLCache = $1.(bool)
|
|
$$ = opt
|
|
}
|
|
| "SQL_CALC_FOUND_ROWS"
|
|
{
|
|
opt := &ast.SelectStmtOpts{}
|
|
opt.SQLCache = true
|
|
opt.CalcFoundRows = true
|
|
$$ = opt
|
|
}
|
|
| "STRAIGHT_JOIN"
|
|
{
|
|
opt := &ast.SelectStmtOpts{}
|
|
opt.SQLCache = true
|
|
opt.StraightJoin = true
|
|
$$ = opt
|
|
}
|
|
|
|
SelectStmtOpts:
|
|
%prec empty
|
|
{
|
|
opt := &ast.SelectStmtOpts{}
|
|
opt.SQLCache = true
|
|
$$ = opt
|
|
}
|
|
| SelectStmtOptsList %prec lowerThanSelectOpt
|
|
|
|
SelectStmtOptsList:
|
|
SelectStmtOptsList SelectStmtOpt
|
|
{
|
|
opts := $1.(*ast.SelectStmtOpts)
|
|
opt := $2.(*ast.SelectStmtOpts)
|
|
|
|
// Merge options.
|
|
// Always use the first hint.
|
|
if opt.TableHints != nil && opts.TableHints == nil {
|
|
opts.TableHints = opt.TableHints
|
|
}
|
|
if opt.Distinct {
|
|
opts.Distinct = true
|
|
}
|
|
if opt.Priority != mysql.NoPriority {
|
|
opts.Priority = opt.Priority
|
|
}
|
|
if opt.SQLSmallResult {
|
|
opts.SQLSmallResult = true
|
|
}
|
|
if opt.SQLBigResult {
|
|
opts.SQLBigResult = true
|
|
}
|
|
if opt.SQLBufferResult {
|
|
opts.SQLBufferResult = true
|
|
}
|
|
if !opt.SQLCache {
|
|
opts.SQLCache = false
|
|
}
|
|
if opt.CalcFoundRows {
|
|
opts.CalcFoundRows = true
|
|
}
|
|
if opt.StraightJoin {
|
|
opts.StraightJoin = true
|
|
}
|
|
if opt.ExplicitAll {
|
|
opts.ExplicitAll = true
|
|
}
|
|
|
|
if opts.Distinct && opts.ExplicitAll {
|
|
yylex.AppendError(ErrWrongUsage.GenWithStackByArgs("ALL", "DISTINCT"))
|
|
return 1
|
|
}
|
|
|
|
$$ = opts
|
|
}
|
|
| SelectStmtOpt
|
|
|
|
TableOptimizerHints:
|
|
hintComment
|
|
{
|
|
hints, warns := parser.parseHint($1)
|
|
for _, w := range warns {
|
|
yylex.AppendError(w)
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
$$ = hints
|
|
}
|
|
|
|
TableOptimizerHintsOpt:
|
|
/* empty */
|
|
{
|
|
$$ = nil
|
|
}
|
|
| TableOptimizerHints
|
|
|
|
SelectStmtSQLCache:
|
|
"SQL_CACHE"
|
|
{
|
|
$$ = true
|
|
}
|
|
| "SQL_NO_CACHE"
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
SelectStmtFieldList:
|
|
FieldList
|
|
{
|
|
$$ = &ast.FieldList{Fields: $1.([]*ast.SelectField)}
|
|
}
|
|
|
|
SelectStmtGroup:
|
|
/* EMPTY */
|
|
{
|
|
$$ = nil
|
|
}
|
|
| GroupByClause
|
|
|
|
SelectStmtIntoOption:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "INTO" "OUTFILE" stringLit Fields Lines
|
|
{
|
|
x := &ast.SelectIntoOption{
|
|
Tp: ast.SelectIntoOutfile,
|
|
FileName: $3,
|
|
}
|
|
if $4 != nil {
|
|
x.FieldsInfo = $4.(*ast.FieldsClause)
|
|
}
|
|
if $5 != nil {
|
|
x.LinesInfo = $5.(*ast.LinesClause)
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/subqueries.html
|
|
SubSelect:
|
|
'(' SelectStmt ')'
|
|
{
|
|
rs := $2.(*ast.SelectStmt)
|
|
endOffset := parser.endOffset(&yyS[yypt])
|
|
parser.setLastSelectFieldText(rs, endOffset)
|
|
src := parser.src
|
|
// See the implementation of yyParse function
|
|
rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset])
|
|
$$ = &ast.SubqueryExpr{Query: rs}
|
|
}
|
|
| '(' SetOprStmt ')'
|
|
{
|
|
rs := $2.(*ast.SetOprStmt)
|
|
src := parser.src
|
|
rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset])
|
|
$$ = &ast.SubqueryExpr{Query: rs}
|
|
}
|
|
| '(' SelectStmtWithClause ')'
|
|
{
|
|
switch rs := $2.(type) {
|
|
case *ast.SelectStmt:
|
|
endOffset := parser.endOffset(&yyS[yypt])
|
|
parser.setLastSelectFieldText(rs, endOffset)
|
|
src := parser.src
|
|
// See the implementation of yyParse function
|
|
rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset])
|
|
$$ = &ast.SubqueryExpr{Query: rs}
|
|
case *ast.SetOprStmt:
|
|
src := parser.src
|
|
rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset])
|
|
$$ = &ast.SubqueryExpr{Query: rs}
|
|
}
|
|
}
|
|
| '(' SubSelect ')'
|
|
{
|
|
subQuery := $2.(*ast.SubqueryExpr).Query
|
|
isRecursive := true
|
|
// remove redundant brackets like '((select 1))'
|
|
for isRecursive {
|
|
if _, isRecursive = subQuery.(*ast.SubqueryExpr); isRecursive {
|
|
subQuery = subQuery.(*ast.SubqueryExpr).Query
|
|
}
|
|
}
|
|
switch rs := subQuery.(type) {
|
|
case *ast.SelectStmt:
|
|
endOffset := parser.endOffset(&yyS[yypt])
|
|
parser.setLastSelectFieldText(rs, endOffset)
|
|
src := parser.src
|
|
rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset])
|
|
$$ = &ast.SubqueryExpr{Query: rs}
|
|
case *ast.SetOprStmt:
|
|
src := parser.src
|
|
rs.SetText(parser.lexer.client, src[yyS[yypt-1].offset:yyS[yypt].offset])
|
|
$$ = &ast.SubqueryExpr{Query: rs}
|
|
}
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html
|
|
SelectLockOpt:
|
|
/* empty */
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "FOR" "UPDATE" OfTablesOpt
|
|
{
|
|
$$ = &ast.SelectLockInfo{
|
|
LockType: ast.SelectLockForUpdate,
|
|
Tables: $3.([]*ast.TableName),
|
|
}
|
|
}
|
|
| "FOR" "SHARE" OfTablesOpt
|
|
{
|
|
$$ = &ast.SelectLockInfo{
|
|
LockType: ast.SelectLockForShare,
|
|
Tables: $3.([]*ast.TableName),
|
|
}
|
|
}
|
|
| "FOR" "UPDATE" OfTablesOpt "NOWAIT"
|
|
{
|
|
$$ = &ast.SelectLockInfo{
|
|
LockType: ast.SelectLockForUpdateNoWait,
|
|
Tables: $3.([]*ast.TableName),
|
|
}
|
|
}
|
|
| "FOR" "UPDATE" OfTablesOpt "WAIT" NUM
|
|
{
|
|
$$ = &ast.SelectLockInfo{
|
|
LockType: ast.SelectLockForUpdateWaitN,
|
|
WaitSec: getUint64FromNUM($5),
|
|
Tables: $3.([]*ast.TableName),
|
|
}
|
|
}
|
|
| "FOR" "SHARE" OfTablesOpt "NOWAIT"
|
|
{
|
|
$$ = &ast.SelectLockInfo{
|
|
LockType: ast.SelectLockForShareNoWait,
|
|
Tables: $3.([]*ast.TableName),
|
|
}
|
|
}
|
|
| "FOR" "UPDATE" OfTablesOpt "SKIP" "LOCKED"
|
|
{
|
|
$$ = &ast.SelectLockInfo{
|
|
LockType: ast.SelectLockForUpdateSkipLocked,
|
|
Tables: $3.([]*ast.TableName),
|
|
}
|
|
}
|
|
| "FOR" "SHARE" OfTablesOpt "SKIP" "LOCKED"
|
|
{
|
|
$$ = &ast.SelectLockInfo{
|
|
LockType: ast.SelectLockForShareSkipLocked,
|
|
Tables: $3.([]*ast.TableName),
|
|
}
|
|
}
|
|
| "LOCK" "IN" "SHARE" "MODE"
|
|
{
|
|
$$ = &ast.SelectLockInfo{
|
|
LockType: ast.SelectLockForShare,
|
|
Tables: []*ast.TableName{},
|
|
}
|
|
}
|
|
|
|
OfTablesOpt:
|
|
/* empty */
|
|
{
|
|
$$ = []*ast.TableName{}
|
|
}
|
|
| "OF" TableNameList
|
|
{
|
|
$$ = $2.([]*ast.TableName)
|
|
}
|
|
|
|
SetOprStmt:
|
|
SetOprStmtWoutLimitOrderBy
|
|
| SetOprStmtWithLimitOrderBy
|
|
| WithClause SetOprStmtWithLimitOrderBy
|
|
{
|
|
setOpr := $2.(*ast.SetOprStmt)
|
|
setOpr.With = $1.(*ast.WithClause)
|
|
$$ = setOpr
|
|
}
|
|
| WithClause SetOprStmtWoutLimitOrderBy
|
|
{
|
|
setOpr := $2.(*ast.SetOprStmt)
|
|
setOpr.With = $1.(*ast.WithClause)
|
|
$$ = setOpr
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/union.html
|
|
// See https://mariadb.com/kb/en/intersect/
|
|
// See https://mariadb.com/kb/en/except/
|
|
SetOprStmtWoutLimitOrderBy:
|
|
SetOprClauseList SetOpr SelectStmt
|
|
{
|
|
setOprList1 := $1.([]ast.Node)
|
|
if sel, isSelect := setOprList1[len(setOprList1)-1].(*ast.SelectStmt); isSelect && !sel.IsInBraces {
|
|
endOffset := parser.endOffset(&yyS[yypt-1])
|
|
parser.setLastSelectFieldText(sel, endOffset)
|
|
}
|
|
setOpr := &ast.SetOprStmt{SelectList: &ast.SetOprSelectList{Selects: $1.([]ast.Node)}}
|
|
st := $3.(*ast.SelectStmt)
|
|
setOpr.Limit = st.Limit
|
|
setOpr.OrderBy = st.OrderBy
|
|
st.Limit = nil
|
|
st.OrderBy = nil
|
|
st.AfterSetOperator = $2.(*ast.SetOprType)
|
|
setOpr.SelectList.Selects = append(setOpr.SelectList.Selects, st)
|
|
$$ = setOpr
|
|
}
|
|
| SetOprClauseList SetOpr SubSelect
|
|
{
|
|
setOprList1 := $1.([]ast.Node)
|
|
if sel, isSelect := setOprList1[len(setOprList1)-1].(*ast.SelectStmt); isSelect && !sel.IsInBraces {
|
|
endOffset := parser.endOffset(&yyS[yypt-1])
|
|
parser.setLastSelectFieldText(sel, endOffset)
|
|
}
|
|
var setOprList2 []ast.Node
|
|
var with2 *ast.WithClause
|
|
switch x := $3.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
setOprList2 = []ast.Node{x}
|
|
with2 = x.With
|
|
case *ast.SetOprStmt:
|
|
setOprList2 = x.SelectList.Selects
|
|
with2 = x.With
|
|
}
|
|
nextSetOprList := &ast.SetOprSelectList{Selects: setOprList2, With: with2}
|
|
nextSetOprList.AfterSetOperator = $2.(*ast.SetOprType)
|
|
setOprList := append(setOprList1, nextSetOprList)
|
|
setOpr := &ast.SetOprStmt{SelectList: &ast.SetOprSelectList{Selects: setOprList}}
|
|
$$ = setOpr
|
|
}
|
|
|
|
SetOprStmtWithLimitOrderBy:
|
|
SetOprClauseList SetOpr SubSelect OrderBy
|
|
{
|
|
setOprList1 := $1.([]ast.Node)
|
|
if sel, isSelect := setOprList1[len(setOprList1)-1].(*ast.SelectStmt); isSelect && !sel.IsInBraces {
|
|
endOffset := parser.endOffset(&yyS[yypt-2])
|
|
parser.setLastSelectFieldText(sel, endOffset)
|
|
}
|
|
var setOprList2 []ast.Node
|
|
var with2 *ast.WithClause
|
|
switch x := $3.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
setOprList2 = []ast.Node{x}
|
|
with2 = x.With
|
|
case *ast.SetOprStmt:
|
|
setOprList2 = x.SelectList.Selects
|
|
with2 = x.With
|
|
}
|
|
nextSetOprList := &ast.SetOprSelectList{Selects: setOprList2, With: with2}
|
|
nextSetOprList.AfterSetOperator = $2.(*ast.SetOprType)
|
|
setOprList := append(setOprList1, nextSetOprList)
|
|
setOpr := &ast.SetOprStmt{SelectList: &ast.SetOprSelectList{Selects: setOprList}}
|
|
setOpr.OrderBy = $4.(*ast.OrderByClause)
|
|
$$ = setOpr
|
|
}
|
|
| SetOprClauseList SetOpr SubSelect SelectStmtLimit
|
|
{
|
|
setOprList1 := $1.([]ast.Node)
|
|
if sel, isSelect := setOprList1[len(setOprList1)-1].(*ast.SelectStmt); isSelect && !sel.IsInBraces {
|
|
endOffset := parser.endOffset(&yyS[yypt-2])
|
|
parser.setLastSelectFieldText(sel, endOffset)
|
|
}
|
|
var setOprList2 []ast.Node
|
|
var with2 *ast.WithClause
|
|
switch x := $3.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
setOprList2 = []ast.Node{x}
|
|
with2 = x.With
|
|
case *ast.SetOprStmt:
|
|
setOprList2 = x.SelectList.Selects
|
|
with2 = x.With
|
|
}
|
|
nextSetOprList := &ast.SetOprSelectList{Selects: setOprList2, With: with2}
|
|
nextSetOprList.AfterSetOperator = $2.(*ast.SetOprType)
|
|
setOprList := append(setOprList1, nextSetOprList)
|
|
setOpr := &ast.SetOprStmt{SelectList: &ast.SetOprSelectList{Selects: setOprList}}
|
|
setOpr.Limit = $4.(*ast.Limit)
|
|
$$ = setOpr
|
|
}
|
|
| SetOprClauseList SetOpr SubSelect OrderBy SelectStmtLimit
|
|
{
|
|
setOprList1 := $1.([]ast.Node)
|
|
if sel, isSelect := setOprList1[len(setOprList1)-1].(*ast.SelectStmt); isSelect && !sel.IsInBraces {
|
|
endOffset := parser.endOffset(&yyS[yypt-3])
|
|
parser.setLastSelectFieldText(sel, endOffset)
|
|
}
|
|
var setOprList2 []ast.Node
|
|
var with2 *ast.WithClause
|
|
switch x := $3.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
setOprList2 = []ast.Node{x}
|
|
with2 = x.With
|
|
case *ast.SetOprStmt:
|
|
setOprList2 = x.SelectList.Selects
|
|
with2 = x.With
|
|
}
|
|
nextSetOprList := &ast.SetOprSelectList{Selects: setOprList2, With: with2}
|
|
nextSetOprList.AfterSetOperator = $2.(*ast.SetOprType)
|
|
setOprList := append(setOprList1, nextSetOprList)
|
|
setOpr := &ast.SetOprStmt{SelectList: &ast.SetOprSelectList{Selects: setOprList}}
|
|
setOpr.OrderBy = $4.(*ast.OrderByClause)
|
|
setOpr.Limit = $5.(*ast.Limit)
|
|
$$ = setOpr
|
|
}
|
|
| SubSelect OrderBy
|
|
{
|
|
var setOprList []ast.Node
|
|
var with *ast.WithClause
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
setOprList = []ast.Node{x}
|
|
with = x.With
|
|
case *ast.SetOprStmt:
|
|
setOprList = x.SelectList.Selects
|
|
with = x.With
|
|
}
|
|
setOpr := &ast.SetOprStmt{SelectList: &ast.SetOprSelectList{Selects: setOprList}, With: with}
|
|
setOpr.OrderBy = $2.(*ast.OrderByClause)
|
|
$$ = setOpr
|
|
}
|
|
| SubSelect SelectStmtLimit
|
|
{
|
|
var setOprList []ast.Node
|
|
var with *ast.WithClause
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
setOprList = []ast.Node{x}
|
|
with = x.With
|
|
case *ast.SetOprStmt:
|
|
setOprList = x.SelectList.Selects
|
|
with = x.With
|
|
}
|
|
setOpr := &ast.SetOprStmt{SelectList: &ast.SetOprSelectList{Selects: setOprList}, With: with}
|
|
setOpr.Limit = $2.(*ast.Limit)
|
|
$$ = setOpr
|
|
}
|
|
| SubSelect OrderBy SelectStmtLimit
|
|
{
|
|
var setOprList []ast.Node
|
|
var with *ast.WithClause
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
setOprList = []ast.Node{x}
|
|
with = x.With
|
|
case *ast.SetOprStmt:
|
|
setOprList = x.SelectList.Selects
|
|
with = x.With
|
|
}
|
|
setOpr := &ast.SetOprStmt{SelectList: &ast.SetOprSelectList{Selects: setOprList}, With: with}
|
|
setOpr.OrderBy = $2.(*ast.OrderByClause)
|
|
setOpr.Limit = $3.(*ast.Limit)
|
|
$$ = setOpr
|
|
}
|
|
|
|
SetOprClauseList:
|
|
SetOprClause
|
|
| SetOprClauseList SetOpr SetOprClause
|
|
{
|
|
setOprList1 := $1.([]ast.Node)
|
|
setOprList2 := $3.([]ast.Node)
|
|
if sel, isSelect := setOprList1[len(setOprList1)-1].(*ast.SelectStmt); isSelect && !sel.IsInBraces {
|
|
endOffset := parser.endOffset(&yyS[yypt-1])
|
|
parser.setLastSelectFieldText(sel, endOffset)
|
|
}
|
|
switch x := setOprList2[0].(type) {
|
|
case *ast.SelectStmt:
|
|
x.AfterSetOperator = $2.(*ast.SetOprType)
|
|
case *ast.SetOprSelectList:
|
|
x.AfterSetOperator = $2.(*ast.SetOprType)
|
|
}
|
|
$$ = append(setOprList1, setOprList2...)
|
|
}
|
|
|
|
SetOprClause:
|
|
SelectStmt
|
|
{
|
|
$$ = []ast.Node{$1.(*ast.SelectStmt)}
|
|
}
|
|
| SubSelect
|
|
{
|
|
var setOprList []ast.Node
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
setOprList = []ast.Node{&ast.SetOprSelectList{Selects: []ast.Node{x}}}
|
|
case *ast.SetOprStmt:
|
|
setOprList = []ast.Node{&ast.SetOprSelectList{Selects: x.SelectList.Selects, With: x.With}}
|
|
}
|
|
$$ = setOprList
|
|
}
|
|
|
|
SetOpr:
|
|
"UNION" SetOprOpt
|
|
{
|
|
var tp ast.SetOprType
|
|
tp = ast.Union
|
|
if $2 == false {
|
|
tp = ast.UnionAll
|
|
}
|
|
$$ = &tp
|
|
}
|
|
| "EXCEPT" SetOprOpt
|
|
{
|
|
var tp ast.SetOprType
|
|
tp = ast.Except
|
|
if $2 == false {
|
|
tp = ast.ExceptAll
|
|
}
|
|
$$ = &tp
|
|
}
|
|
| "INTERSECT" SetOprOpt
|
|
{
|
|
var tp ast.SetOprType
|
|
tp = ast.Intersect
|
|
if $2 == false {
|
|
tp = ast.IntersectAll
|
|
}
|
|
$$ = &tp
|
|
}
|
|
|
|
SetOprOpt:
|
|
DefaultTrueDistinctOpt
|
|
|
|
/********************Change Statement*******************************/
|
|
ChangeStmt:
|
|
"CHANGE" "PUMP" "TO" "NODE_STATE" eq stringLit forKwd "NODE_ID" stringLit
|
|
{
|
|
$$ = &ast.ChangeStmt{
|
|
NodeType: ast.PumpType,
|
|
State: $6,
|
|
NodeID: $9,
|
|
}
|
|
}
|
|
| "CHANGE" "DRAINER" "TO" "NODE_STATE" eq stringLit forKwd "NODE_ID" stringLit
|
|
{
|
|
$$ = &ast.ChangeStmt{
|
|
NodeType: ast.DrainerType,
|
|
State: $6,
|
|
NodeID: $9,
|
|
}
|
|
}
|
|
|
|
/********************Set Statement*******************************/
|
|
SetStmt:
|
|
"SET" VariableAssignmentList
|
|
{
|
|
$$ = &ast.SetStmt{Variables: $2.([]*ast.VariableAssignment)}
|
|
}
|
|
| "SET" "PASSWORD" EqOrAssignmentEq PasswordOpt
|
|
{
|
|
$$ = &ast.SetPwdStmt{Password: $4}
|
|
}
|
|
| "SET" "PASSWORD" "FOR" Username EqOrAssignmentEq PasswordOpt
|
|
{
|
|
$$ = &ast.SetPwdStmt{User: $4.(*auth.UserIdentity), Password: $6}
|
|
}
|
|
| "SET" "GLOBAL" "TRANSACTION" TransactionChars
|
|
{
|
|
vars := $4.([]*ast.VariableAssignment)
|
|
for _, v := range vars {
|
|
v.IsGlobal = true
|
|
}
|
|
$$ = &ast.SetStmt{Variables: vars}
|
|
}
|
|
| "SET" "SESSION" "TRANSACTION" TransactionChars
|
|
{
|
|
$$ = &ast.SetStmt{Variables: $4.([]*ast.VariableAssignment)}
|
|
}
|
|
| "SET" "TRANSACTION" TransactionChars
|
|
{
|
|
assigns := $3.([]*ast.VariableAssignment)
|
|
for i := 0; i < len(assigns); i++ {
|
|
if assigns[i].Name == "tx_isolation" {
|
|
// A special session variable that make setting tx_isolation take effect one time.
|
|
assigns[i].Name = "tx_isolation_one_shot"
|
|
}
|
|
}
|
|
$$ = &ast.SetStmt{Variables: assigns}
|
|
}
|
|
| "SET" "CONFIG" Identifier ConfigItemName EqOrAssignmentEq SetExpr
|
|
{
|
|
$$ = &ast.SetConfigStmt{Type: strings.ToLower($3), Name: $4, Value: $6}
|
|
}
|
|
| "SET" "CONFIG" stringLit ConfigItemName EqOrAssignmentEq SetExpr
|
|
{
|
|
$$ = &ast.SetConfigStmt{Instance: $3, Name: $4, Value: $6}
|
|
}
|
|
| "SET" "SESSION_STATES" stringLit
|
|
{
|
|
$$ = &ast.SetSessionStatesStmt{SessionStates: $3}
|
|
}
|
|
| "SET" "RESOURCE" "GROUP" ResourceGroupName
|
|
{
|
|
$$ = &ast.SetResourceGroupStmt{Name: model.NewCIStr($4)}
|
|
}
|
|
|
|
SetRoleStmt:
|
|
"SET" "ROLE" SetRoleOpt
|
|
{
|
|
$$ = $3.(*ast.SetRoleStmt)
|
|
}
|
|
|
|
SetDefaultRoleStmt:
|
|
"SET" "DEFAULT" "ROLE" SetDefaultRoleOpt "TO" UsernameList
|
|
{
|
|
tmp := $4.(*ast.SetRoleStmt)
|
|
$$ = &ast.SetDefaultRoleStmt{
|
|
SetRoleOpt: tmp.SetRoleOpt,
|
|
RoleList: tmp.RoleList,
|
|
UserList: $6.([]*auth.UserIdentity),
|
|
}
|
|
}
|
|
|
|
SetDefaultRoleOpt:
|
|
"NONE"
|
|
{
|
|
$$ = &ast.SetRoleStmt{SetRoleOpt: ast.SetRoleNone, RoleList: nil}
|
|
}
|
|
| "ALL"
|
|
{
|
|
$$ = &ast.SetRoleStmt{SetRoleOpt: ast.SetRoleAll, RoleList: nil}
|
|
}
|
|
| RolenameList
|
|
{
|
|
$$ = &ast.SetRoleStmt{SetRoleOpt: ast.SetRoleRegular, RoleList: $1.([]*auth.RoleIdentity)}
|
|
}
|
|
|
|
SetRoleOpt:
|
|
"ALL" "EXCEPT" RolenameList
|
|
{
|
|
$$ = &ast.SetRoleStmt{SetRoleOpt: ast.SetRoleAllExcept, RoleList: $3.([]*auth.RoleIdentity)}
|
|
}
|
|
| SetDefaultRoleOpt
|
|
| "DEFAULT"
|
|
{
|
|
$$ = &ast.SetRoleStmt{SetRoleOpt: ast.SetRoleDefault, RoleList: nil}
|
|
}
|
|
|
|
TransactionChars:
|
|
TransactionChar
|
|
{
|
|
if $1 != nil {
|
|
$$ = $1
|
|
} else {
|
|
$$ = []*ast.VariableAssignment{}
|
|
}
|
|
}
|
|
| TransactionChars ',' TransactionChar
|
|
{
|
|
if $3 != nil {
|
|
varAssigns := $3.([]*ast.VariableAssignment)
|
|
$$ = append($1.([]*ast.VariableAssignment), varAssigns...)
|
|
} else {
|
|
$$ = $1
|
|
}
|
|
}
|
|
|
|
TransactionChar:
|
|
"ISOLATION" "LEVEL" IsolationLevel
|
|
{
|
|
varAssigns := []*ast.VariableAssignment{}
|
|
expr := ast.NewValueExpr($3, parser.charset, parser.collation)
|
|
varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_isolation", Value: expr, IsSystem: true})
|
|
$$ = varAssigns
|
|
}
|
|
| "READ" "WRITE"
|
|
{
|
|
varAssigns := []*ast.VariableAssignment{}
|
|
expr := ast.NewValueExpr("0", parser.charset, parser.collation)
|
|
varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_read_only", Value: expr, IsSystem: true})
|
|
$$ = varAssigns
|
|
}
|
|
| "READ" "ONLY"
|
|
{
|
|
varAssigns := []*ast.VariableAssignment{}
|
|
expr := ast.NewValueExpr("1", parser.charset, parser.collation)
|
|
varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_read_only", Value: expr, IsSystem: true})
|
|
$$ = varAssigns
|
|
}
|
|
| "READ" "ONLY" AsOfClause
|
|
{
|
|
varAssigns := []*ast.VariableAssignment{}
|
|
asof := $3.(*ast.AsOfClause)
|
|
if asof != nil {
|
|
varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_read_ts", Value: asof.TsExpr, IsSystem: true})
|
|
}
|
|
$$ = varAssigns
|
|
}
|
|
|
|
IsolationLevel:
|
|
"REPEATABLE" "READ"
|
|
{
|
|
$$ = ast.RepeatableRead
|
|
}
|
|
| "READ" "COMMITTED"
|
|
{
|
|
$$ = ast.ReadCommitted
|
|
}
|
|
| "READ" "UNCOMMITTED"
|
|
{
|
|
$$ = ast.ReadUncommitted
|
|
}
|
|
| "SERIALIZABLE"
|
|
{
|
|
$$ = ast.Serializable
|
|
}
|
|
|
|
SetExpr:
|
|
"ON"
|
|
{
|
|
$$ = ast.NewValueExpr("ON", parser.charset, parser.collation)
|
|
}
|
|
| "BINARY"
|
|
{
|
|
$$ = ast.NewValueExpr("BINARY", parser.charset, parser.collation)
|
|
}
|
|
| ExprOrDefault
|
|
|
|
EqOrAssignmentEq:
|
|
eq
|
|
| assignmentEq
|
|
|
|
VariableName:
|
|
Identifier
|
|
| Identifier '.' Identifier
|
|
{
|
|
$$ = $1 + "." + $3
|
|
}
|
|
|
|
ConfigItemName:
|
|
Identifier
|
|
| Identifier '.' ConfigItemName
|
|
{
|
|
$$ = $1 + "." + $3
|
|
}
|
|
| Identifier '-' ConfigItemName
|
|
{
|
|
$$ = $1 + "-" + $3
|
|
}
|
|
|
|
VariableAssignment:
|
|
VariableName EqOrAssignmentEq SetExpr
|
|
{
|
|
$$ = &ast.VariableAssignment{Name: $1, Value: $3, IsSystem: true}
|
|
}
|
|
| "GLOBAL" VariableName EqOrAssignmentEq SetExpr
|
|
{
|
|
$$ = &ast.VariableAssignment{Name: $2, Value: $4, IsGlobal: true, IsSystem: true}
|
|
}
|
|
| "SESSION" VariableName EqOrAssignmentEq SetExpr
|
|
{
|
|
$$ = &ast.VariableAssignment{Name: $2, Value: $4, IsSystem: true}
|
|
}
|
|
| "LOCAL" VariableName EqOrAssignmentEq SetExpr
|
|
{
|
|
$$ = &ast.VariableAssignment{Name: $2, Value: $4, IsSystem: true}
|
|
}
|
|
| doubleAtIdentifier EqOrAssignmentEq SetExpr
|
|
{
|
|
v := strings.ToLower($1)
|
|
var isGlobal bool
|
|
if strings.HasPrefix(v, "@@global.") {
|
|
isGlobal = true
|
|
v = strings.TrimPrefix(v, "@@global.")
|
|
} else if strings.HasPrefix(v, "@@session.") {
|
|
v = strings.TrimPrefix(v, "@@session.")
|
|
} else if strings.HasPrefix(v, "@@local.") {
|
|
v = strings.TrimPrefix(v, "@@local.")
|
|
} else if strings.HasPrefix(v, "@@") {
|
|
v = strings.TrimPrefix(v, "@@")
|
|
}
|
|
$$ = &ast.VariableAssignment{Name: v, Value: $3, IsGlobal: isGlobal, IsSystem: true}
|
|
}
|
|
| singleAtIdentifier EqOrAssignmentEq Expression
|
|
{
|
|
v := $1
|
|
v = strings.TrimPrefix(v, "@")
|
|
$$ = &ast.VariableAssignment{Name: v, Value: $3}
|
|
}
|
|
| "NAMES" CharsetName
|
|
{
|
|
$$ = &ast.VariableAssignment{
|
|
Name: ast.SetNames,
|
|
Value: ast.NewValueExpr($2, "", ""),
|
|
}
|
|
}
|
|
| "NAMES" CharsetName "COLLATE" "DEFAULT"
|
|
{
|
|
$$ = &ast.VariableAssignment{
|
|
Name: ast.SetNames,
|
|
Value: ast.NewValueExpr($2, "", ""),
|
|
}
|
|
}
|
|
| "NAMES" CharsetName "COLLATE" StringName
|
|
{
|
|
$$ = &ast.VariableAssignment{
|
|
Name: ast.SetNames,
|
|
Value: ast.NewValueExpr($2, "", ""),
|
|
ExtendValue: ast.NewValueExpr($4, "", ""),
|
|
}
|
|
}
|
|
| "NAMES" "DEFAULT"
|
|
{
|
|
v := &ast.DefaultExpr{}
|
|
$$ = &ast.VariableAssignment{Name: ast.SetNames, Value: v}
|
|
}
|
|
| CharsetKw CharsetNameOrDefault
|
|
{
|
|
$$ = &ast.VariableAssignment{Name: ast.SetCharset, Value: $2}
|
|
}
|
|
|
|
CharsetNameOrDefault:
|
|
CharsetName
|
|
{
|
|
$$ = ast.NewValueExpr($1, "", "")
|
|
}
|
|
| "DEFAULT"
|
|
{
|
|
$$ = &ast.DefaultExpr{}
|
|
}
|
|
|
|
CharsetName:
|
|
StringName
|
|
{
|
|
// Validate input charset name to keep the same behavior as parser of MySQL.
|
|
cs, err := charset.GetCharsetInfo($1)
|
|
if err != nil {
|
|
yylex.AppendError(ErrUnknownCharacterSet.GenWithStackByArgs($1))
|
|
return 1
|
|
}
|
|
// Use charset name returned from charset.GetCharsetInfo(),
|
|
// to keep lower case of input for generated column restore.
|
|
$$ = cs.Name
|
|
}
|
|
| binaryType
|
|
{
|
|
$$ = charset.CharsetBin
|
|
}
|
|
|
|
CollationName:
|
|
StringName
|
|
{
|
|
info, err := charset.GetCollationByName($1)
|
|
if err != nil {
|
|
yylex.AppendError(err)
|
|
return 1
|
|
}
|
|
$$ = info.Name
|
|
}
|
|
| binaryType
|
|
{
|
|
$$ = charset.CollationBin
|
|
}
|
|
|
|
VariableAssignmentList:
|
|
VariableAssignment
|
|
{
|
|
$$ = []*ast.VariableAssignment{$1.(*ast.VariableAssignment)}
|
|
}
|
|
| VariableAssignmentList ',' VariableAssignment
|
|
{
|
|
$$ = append($1.([]*ast.VariableAssignment), $3.(*ast.VariableAssignment))
|
|
}
|
|
|
|
Variable:
|
|
SystemVariable
|
|
| UserVariable
|
|
|
|
SystemVariable:
|
|
doubleAtIdentifier
|
|
{
|
|
v := strings.ToLower($1)
|
|
var isGlobal bool
|
|
explicitScope := true
|
|
if strings.HasPrefix(v, "@@global.") {
|
|
isGlobal = true
|
|
v = strings.TrimPrefix(v, "@@global.")
|
|
} else if strings.HasPrefix(v, "@@session.") {
|
|
v = strings.TrimPrefix(v, "@@session.")
|
|
} else if strings.HasPrefix(v, "@@local.") {
|
|
v = strings.TrimPrefix(v, "@@local.")
|
|
} else if strings.HasPrefix(v, "@@") {
|
|
v, explicitScope = strings.TrimPrefix(v, "@@"), false
|
|
}
|
|
$$ = &ast.VariableExpr{Name: v, IsGlobal: isGlobal, IsSystem: true, ExplicitScope: explicitScope}
|
|
}
|
|
|
|
UserVariable:
|
|
singleAtIdentifier
|
|
{
|
|
v := $1
|
|
v = strings.TrimPrefix(v, "@")
|
|
$$ = &ast.VariableExpr{Name: v, IsGlobal: false, IsSystem: false}
|
|
}
|
|
|
|
Username:
|
|
StringName
|
|
{
|
|
$$ = &auth.UserIdentity{Username: $1, Hostname: "%"}
|
|
}
|
|
| StringName '@' StringName
|
|
{
|
|
$$ = &auth.UserIdentity{Username: $1, Hostname: strings.ToLower($3)}
|
|
}
|
|
| StringName singleAtIdentifier
|
|
{
|
|
$$ = &auth.UserIdentity{Username: $1, Hostname: strings.ToLower(strings.TrimPrefix($2, "@"))}
|
|
}
|
|
| "CURRENT_USER" OptionalBraces
|
|
{
|
|
$$ = &auth.UserIdentity{CurrentUser: true}
|
|
}
|
|
|
|
UsernameList:
|
|
Username
|
|
{
|
|
$$ = []*auth.UserIdentity{$1.(*auth.UserIdentity)}
|
|
}
|
|
| UsernameList ',' Username
|
|
{
|
|
$$ = append($1.([]*auth.UserIdentity), $3.(*auth.UserIdentity))
|
|
}
|
|
|
|
PasswordOpt:
|
|
stringLit
|
|
| "PASSWORD" '(' AuthString ')'
|
|
{
|
|
$$ = $3
|
|
}
|
|
|
|
AuthString:
|
|
stringLit
|
|
|
|
RoleNameString:
|
|
stringLit
|
|
| identifier
|
|
|
|
RolenameComposed:
|
|
StringName '@' StringName
|
|
{
|
|
$$ = &auth.RoleIdentity{Username: $1, Hostname: strings.ToLower($3)}
|
|
}
|
|
| StringName singleAtIdentifier
|
|
{
|
|
$$ = &auth.RoleIdentity{Username: $1, Hostname: strings.ToLower(strings.TrimPrefix($2, "@"))}
|
|
}
|
|
|
|
RolenameWithoutIdent:
|
|
stringLit
|
|
{
|
|
$$ = &auth.RoleIdentity{Username: $1, Hostname: "%"}
|
|
}
|
|
| RolenameComposed
|
|
{
|
|
$$ = $1
|
|
}
|
|
|
|
Rolename:
|
|
RoleNameString
|
|
{
|
|
$$ = &auth.RoleIdentity{Username: $1, Hostname: "%"}
|
|
}
|
|
| RolenameComposed
|
|
{
|
|
$$ = $1
|
|
}
|
|
|
|
RolenameList:
|
|
Rolename
|
|
{
|
|
$$ = []*auth.RoleIdentity{$1.(*auth.RoleIdentity)}
|
|
}
|
|
| RolenameList ',' Rolename
|
|
{
|
|
$$ = append($1.([]*auth.RoleIdentity), $3.(*auth.RoleIdentity))
|
|
}
|
|
|
|
/****************************Admin Statement*******************************/
|
|
AdminStmtLimitOpt:
|
|
"LIMIT" LengthNum
|
|
{
|
|
$$ = &ast.LimitSimple{Offset: 0, Count: $2.(uint64)}
|
|
}
|
|
| "LIMIT" LengthNum ',' LengthNum
|
|
{
|
|
$$ = &ast.LimitSimple{Offset: $2.(uint64), Count: $4.(uint64)}
|
|
}
|
|
| "LIMIT" LengthNum "OFFSET" LengthNum
|
|
{
|
|
$$ = &ast.LimitSimple{Offset: $4.(uint64), Count: $2.(uint64)}
|
|
}
|
|
|
|
AdminStmt:
|
|
"ADMIN" "SHOW" "DDL"
|
|
{
|
|
$$ = &ast.AdminStmt{Tp: ast.AdminShowDDL}
|
|
}
|
|
| "ADMIN" "SHOW" "DDL" "JOBS" WhereClauseOptional
|
|
{
|
|
stmt := &ast.AdminStmt{Tp: ast.AdminShowDDLJobs}
|
|
if $5 != nil {
|
|
stmt.Where = $5.(ast.ExprNode)
|
|
}
|
|
$$ = stmt
|
|
}
|
|
| "ADMIN" "SHOW" "DDL" "JOBS" Int64Num WhereClauseOptional
|
|
{
|
|
stmt := &ast.AdminStmt{
|
|
Tp: ast.AdminShowDDLJobs,
|
|
JobNumber: $5.(int64),
|
|
}
|
|
if $6 != nil {
|
|
stmt.Where = $6.(ast.ExprNode)
|
|
}
|
|
$$ = stmt
|
|
}
|
|
| "ADMIN" "SHOW" TableName "NEXT_ROW_ID"
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminShowNextRowID,
|
|
Tables: []*ast.TableName{$3.(*ast.TableName)},
|
|
}
|
|
}
|
|
| "ADMIN" "CHECK" "TABLE" TableNameList
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminCheckTable,
|
|
Tables: $4.([]*ast.TableName),
|
|
}
|
|
}
|
|
| "ADMIN" "CHECK" "INDEX" TableName Identifier
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminCheckIndex,
|
|
Tables: []*ast.TableName{$4.(*ast.TableName)},
|
|
Index: string($5),
|
|
}
|
|
}
|
|
| "ADMIN" "RECOVER" "INDEX" TableName Identifier
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminRecoverIndex,
|
|
Tables: []*ast.TableName{$4.(*ast.TableName)},
|
|
Index: string($5),
|
|
}
|
|
}
|
|
| "ADMIN" "CLEANUP" "INDEX" TableName Identifier
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminCleanupIndex,
|
|
Tables: []*ast.TableName{$4.(*ast.TableName)},
|
|
Index: string($5),
|
|
}
|
|
}
|
|
| "ADMIN" "CHECK" "INDEX" TableName Identifier HandleRangeList
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminCheckIndexRange,
|
|
Tables: []*ast.TableName{$4.(*ast.TableName)},
|
|
Index: string($5),
|
|
HandleRanges: $6.([]ast.HandleRange),
|
|
}
|
|
}
|
|
| "ADMIN" "CHECKSUM" "TABLE" TableNameList
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminChecksumTable,
|
|
Tables: $4.([]*ast.TableName),
|
|
}
|
|
}
|
|
| "ADMIN" "CANCEL" "DDL" "JOBS" NumList
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminCancelDDLJobs,
|
|
JobIDs: $5.([]int64),
|
|
}
|
|
}
|
|
| "ADMIN" "PAUSE" "DDL" "JOBS" NumList
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminPauseDDLJobs,
|
|
JobIDs: $5.([]int64),
|
|
}
|
|
}
|
|
| "ADMIN" "RESUME" "DDL" "JOBS" NumList
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminResumeDDLJobs,
|
|
JobIDs: $5.([]int64),
|
|
}
|
|
}
|
|
| "ADMIN" "SHOW" "DDL" "JOB" "QUERIES" NumList
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminShowDDLJobQueries,
|
|
JobIDs: $6.([]int64),
|
|
}
|
|
}
|
|
| "ADMIN" "SHOW" "DDL" "JOB" "QUERIES" AdminStmtLimitOpt
|
|
{
|
|
ret := &ast.AdminStmt{
|
|
Tp: ast.AdminShowDDLJobQueriesWithRange,
|
|
}
|
|
ret.LimitSimple.Count = $6.(*ast.LimitSimple).Count
|
|
ret.LimitSimple.Offset = $6.(*ast.LimitSimple).Offset
|
|
$$ = ret
|
|
}
|
|
| "ADMIN" "SHOW" "SLOW" AdminShowSlow
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminShowSlow,
|
|
ShowSlow: $4.(*ast.ShowSlow),
|
|
}
|
|
}
|
|
| "ADMIN" "RELOAD" "EXPR_PUSHDOWN_BLACKLIST"
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminReloadExprPushdownBlacklist,
|
|
}
|
|
}
|
|
| "ADMIN" "RELOAD" "OPT_RULE_BLACKLIST"
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminReloadOptRuleBlacklist,
|
|
}
|
|
}
|
|
| "ADMIN" "PLUGINS" "ENABLE" PluginNameList
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminPluginEnable,
|
|
Plugins: $4.([]string),
|
|
}
|
|
}
|
|
| "ADMIN" "PLUGINS" "DISABLE" PluginNameList
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminPluginDisable,
|
|
Plugins: $4.([]string),
|
|
}
|
|
}
|
|
| "ADMIN" "CLEANUP" "TABLE" "LOCK" TableNameList
|
|
{
|
|
$$ = &ast.CleanupTableLockStmt{
|
|
Tables: $5.([]*ast.TableName),
|
|
}
|
|
}
|
|
| "ADMIN" "REPAIR" "TABLE" TableName CreateTableStmt
|
|
{
|
|
$$ = &ast.RepairTableStmt{
|
|
Table: $4.(*ast.TableName),
|
|
CreateStmt: $5.(*ast.CreateTableStmt),
|
|
}
|
|
}
|
|
| "ADMIN" "FLUSH" "BINDINGS"
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminFlushBindings,
|
|
}
|
|
}
|
|
| "ADMIN" "CAPTURE" "BINDINGS"
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminCaptureBindings,
|
|
}
|
|
}
|
|
| "ADMIN" "EVOLVE" "BINDINGS"
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminEvolveBindings,
|
|
}
|
|
}
|
|
| "ADMIN" "RELOAD" "BINDINGS"
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminReloadBindings,
|
|
}
|
|
}
|
|
| "ADMIN" "RELOAD" "STATS_EXTENDED"
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminReloadStatistics,
|
|
}
|
|
}
|
|
| "ADMIN" "RELOAD" "STATISTICS"
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminReloadStatistics,
|
|
}
|
|
}
|
|
| "ADMIN" "SHOW" "TELEMETRY"
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminShowTelemetry,
|
|
}
|
|
}
|
|
| "ADMIN" "RESET" "TELEMETRY_ID"
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminResetTelemetryID,
|
|
}
|
|
}
|
|
| "ADMIN" "FLUSH" StatementScope "PLAN_CACHE"
|
|
{
|
|
$$ = &ast.AdminStmt{
|
|
Tp: ast.AdminFlushPlanCache,
|
|
StatementScope: $3.(ast.StatementScope),
|
|
}
|
|
}
|
|
|
|
AdminShowSlow:
|
|
"RECENT" NUM
|
|
{
|
|
$$ = &ast.ShowSlow{
|
|
Tp: ast.ShowSlowRecent,
|
|
Count: getUint64FromNUM($2),
|
|
}
|
|
}
|
|
| "TOP" NUM
|
|
{
|
|
$$ = &ast.ShowSlow{
|
|
Tp: ast.ShowSlowTop,
|
|
Kind: ast.ShowSlowKindDefault,
|
|
Count: getUint64FromNUM($2),
|
|
}
|
|
}
|
|
| "TOP" "INTERNAL" NUM
|
|
{
|
|
$$ = &ast.ShowSlow{
|
|
Tp: ast.ShowSlowTop,
|
|
Kind: ast.ShowSlowKindInternal,
|
|
Count: getUint64FromNUM($3),
|
|
}
|
|
}
|
|
| "TOP" "ALL" NUM
|
|
{
|
|
$$ = &ast.ShowSlow{
|
|
Tp: ast.ShowSlowTop,
|
|
Kind: ast.ShowSlowKindAll,
|
|
Count: getUint64FromNUM($3),
|
|
}
|
|
}
|
|
|
|
HandleRangeList:
|
|
HandleRange
|
|
{
|
|
$$ = []ast.HandleRange{$1.(ast.HandleRange)}
|
|
}
|
|
| HandleRangeList ',' HandleRange
|
|
{
|
|
$$ = append($1.([]ast.HandleRange), $3.(ast.HandleRange))
|
|
}
|
|
|
|
HandleRange:
|
|
'(' Int64Num ',' Int64Num ')'
|
|
{
|
|
$$ = ast.HandleRange{Begin: $2.(int64), End: $4.(int64)}
|
|
}
|
|
|
|
NumList:
|
|
Int64Num
|
|
{
|
|
$$ = []int64{$1.(int64)}
|
|
}
|
|
| NumList ',' Int64Num
|
|
{
|
|
$$ = append($1.([]int64), $3.(int64))
|
|
}
|
|
|
|
/****************************Show Statement*******************************/
|
|
ShowStmt:
|
|
"SHOW" ShowTargetFilterable ShowLikeOrWhereOpt
|
|
{
|
|
stmt := $2.(*ast.ShowStmt)
|
|
if $3 != nil {
|
|
if x, ok := $3.(*ast.PatternLikeOrIlikeExpr); ok && x.Expr == nil {
|
|
stmt.Pattern = x
|
|
} else {
|
|
stmt.Where = $3.(ast.ExprNode)
|
|
}
|
|
}
|
|
$$ = stmt
|
|
}
|
|
| "SHOW" "CREATE" "TABLE" TableName
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowCreateTable,
|
|
Table: $4.(*ast.TableName),
|
|
}
|
|
}
|
|
| "SHOW" "CREATE" "VIEW" TableName
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowCreateView,
|
|
Table: $4.(*ast.TableName),
|
|
}
|
|
}
|
|
| "SHOW" "CREATE" "DATABASE" IfNotExists DBName
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowCreateDatabase,
|
|
IfNotExists: $4.(bool),
|
|
DBName: $5,
|
|
}
|
|
}
|
|
| "SHOW" "CREATE" "SEQUENCE" TableName
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowCreateSequence,
|
|
Table: $4.(*ast.TableName),
|
|
}
|
|
}
|
|
| "SHOW" "CREATE" "PLACEMENT" "POLICY" PolicyName
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowCreatePlacementPolicy,
|
|
DBName: $5,
|
|
}
|
|
}
|
|
| "SHOW" "CREATE" "RESOURCE" "GROUP" ResourceGroupName
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowCreateResourceGroup,
|
|
ResourceGroupName: $5,
|
|
}
|
|
}
|
|
| "SHOW" "CREATE" "USER" Username
|
|
{
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/show-create-user.html
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowCreateUser,
|
|
User: $4.(*auth.UserIdentity),
|
|
}
|
|
}
|
|
| "SHOW" "TABLE" TableName PartitionNameListOpt "REGIONS" WhereClauseOptional
|
|
{
|
|
stmt := &ast.ShowStmt{
|
|
Tp: ast.ShowRegions,
|
|
Table: $3.(*ast.TableName),
|
|
}
|
|
stmt.Table.PartitionNames = $4.([]model.CIStr)
|
|
if $6 != nil {
|
|
stmt.Where = $6.(ast.ExprNode)
|
|
}
|
|
$$ = stmt
|
|
}
|
|
| "SHOW" "TABLE" TableName "NEXT_ROW_ID"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowTableNextRowId,
|
|
Table: $3.(*ast.TableName),
|
|
}
|
|
}
|
|
| "SHOW" "TABLE" TableName PartitionNameListOpt "INDEX" Identifier "REGIONS" WhereClauseOptional
|
|
{
|
|
stmt := &ast.ShowStmt{
|
|
Tp: ast.ShowRegions,
|
|
Table: $3.(*ast.TableName),
|
|
IndexName: model.NewCIStr($6),
|
|
}
|
|
stmt.Table.PartitionNames = $4.([]model.CIStr)
|
|
if $8 != nil {
|
|
stmt.Where = $8.(ast.ExprNode)
|
|
}
|
|
$$ = stmt
|
|
}
|
|
| "SHOW" "GRANTS"
|
|
{
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/show-grants.html
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowGrants}
|
|
}
|
|
| "SHOW" "GRANTS" "FOR" Username UsingRoles
|
|
{
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/show-grants.html
|
|
if $5 != nil {
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowGrants,
|
|
User: $4.(*auth.UserIdentity),
|
|
Roles: $5.([]*auth.RoleIdentity),
|
|
}
|
|
} else {
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowGrants,
|
|
User: $4.(*auth.UserIdentity),
|
|
Roles: nil,
|
|
}
|
|
}
|
|
}
|
|
| "SHOW" "MASTER" "STATUS"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowMasterStatus,
|
|
}
|
|
}
|
|
| "SHOW" OptFull "PROCESSLIST"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowProcessList,
|
|
Full: $2.(bool),
|
|
}
|
|
}
|
|
| "SHOW" "PROFILES"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowProfiles,
|
|
}
|
|
}
|
|
| "SHOW" "PROFILE" ShowProfileTypesOpt ShowProfileArgsOpt SelectStmtLimitOpt
|
|
{
|
|
v := &ast.ShowStmt{
|
|
Tp: ast.ShowProfile,
|
|
}
|
|
if $3 != nil {
|
|
v.ShowProfileTypes = $3.([]int)
|
|
}
|
|
if $4 != nil {
|
|
v.ShowProfileArgs = $4.(*int64)
|
|
}
|
|
if $5 != nil {
|
|
v.ShowProfileLimit = $5.(*ast.Limit)
|
|
}
|
|
$$ = v
|
|
}
|
|
| "SHOW" "PRIVILEGES"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowPrivileges,
|
|
}
|
|
}
|
|
| "SHOW" "BUILTINS"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowBuiltins,
|
|
}
|
|
}
|
|
| "SHOW" "PLACEMENT" "FOR" ShowPlacementTarget
|
|
{
|
|
$$ = $4.(*ast.ShowStmt)
|
|
}
|
|
| "SHOW" "IMPORT" "JOB" Int64Num
|
|
{
|
|
v := $4.(int64)
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowImportJobs,
|
|
ImportJobID: &v,
|
|
}
|
|
}
|
|
| "SHOW" "CREATE" "PROCEDURE" TableName
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowCreateProcedure,
|
|
Procedure: $4.(*ast.TableName),
|
|
}
|
|
}
|
|
|
|
ShowPlacementTarget:
|
|
DatabaseSym DBName
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowPlacementForDatabase,
|
|
DBName: $2,
|
|
}
|
|
}
|
|
| "TABLE" TableName
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowPlacementForTable,
|
|
Table: $2.(*ast.TableName),
|
|
}
|
|
}
|
|
| "TABLE" TableName "PARTITION" Identifier
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowPlacementForPartition,
|
|
Table: $2.(*ast.TableName),
|
|
Partition: model.NewCIStr($4),
|
|
}
|
|
}
|
|
|
|
ShowProfileTypesOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| ShowProfileTypes
|
|
|
|
ShowProfileTypes:
|
|
ShowProfileType
|
|
{
|
|
$$ = []int{$1.(int)}
|
|
}
|
|
| ShowProfileTypes ',' ShowProfileType
|
|
{
|
|
l := $1.([]int)
|
|
l = append(l, $3.(int))
|
|
$$ = l
|
|
}
|
|
|
|
ShowProfileType:
|
|
"CPU"
|
|
{
|
|
$$ = ast.ProfileTypeCPU
|
|
}
|
|
| "MEMORY"
|
|
{
|
|
$$ = ast.ProfileTypeMemory
|
|
}
|
|
| "BLOCK" "IO"
|
|
{
|
|
$$ = ast.ProfileTypeBlockIo
|
|
}
|
|
| "CONTEXT" "SWITCHES"
|
|
{
|
|
$$ = ast.ProfileTypeContextSwitch
|
|
}
|
|
| "PAGE" "FAULTS"
|
|
{
|
|
$$ = ast.ProfileTypePageFaults
|
|
}
|
|
| "IPC"
|
|
{
|
|
$$ = ast.ProfileTypeIpc
|
|
}
|
|
| "SWAPS"
|
|
{
|
|
$$ = ast.ProfileTypeSwaps
|
|
}
|
|
| "SOURCE"
|
|
{
|
|
$$ = ast.ProfileTypeSource
|
|
}
|
|
| "ALL"
|
|
{
|
|
$$ = ast.ProfileTypeAll
|
|
}
|
|
|
|
ShowProfileArgsOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "FOR" "QUERY" Int64Num
|
|
{
|
|
v := $3.(int64)
|
|
$$ = &v
|
|
}
|
|
|
|
UsingRoles:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "USING" RolenameList
|
|
{
|
|
$$ = $2.([]*auth.RoleIdentity)
|
|
}
|
|
|
|
ShowIndexKwd:
|
|
"INDEX"
|
|
| "INDEXES"
|
|
| "KEYS"
|
|
|
|
FromOrIn:
|
|
"FROM"
|
|
| "IN"
|
|
|
|
ShowTargetFilterable:
|
|
"ENGINES"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowEngines}
|
|
}
|
|
| "DATABASES"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowDatabases}
|
|
}
|
|
| "CONFIG"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowConfig}
|
|
}
|
|
| CharsetKw
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowCharset}
|
|
}
|
|
| OptFull "TABLES" ShowDatabaseNameOpt
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowTables,
|
|
DBName: $3,
|
|
Full: $1.(bool),
|
|
}
|
|
}
|
|
| "OPEN" "TABLES" ShowDatabaseNameOpt
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowOpenTables,
|
|
DBName: $3,
|
|
}
|
|
}
|
|
| "TABLE" "STATUS" ShowDatabaseNameOpt
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowTableStatus,
|
|
DBName: $3,
|
|
}
|
|
}
|
|
| ShowIndexKwd FromOrIn TableName
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowIndex,
|
|
Table: $3.(*ast.TableName),
|
|
}
|
|
}
|
|
| ShowIndexKwd FromOrIn Identifier FromOrIn Identifier
|
|
{
|
|
show := &ast.ShowStmt{
|
|
Tp: ast.ShowIndex,
|
|
Table: &ast.TableName{Name: model.NewCIStr($3), Schema: model.NewCIStr($5)},
|
|
}
|
|
$$ = show
|
|
}
|
|
| OptFull FieldsOrColumns ShowTableAliasOpt ShowDatabaseNameOpt
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowColumns,
|
|
Table: $3.(*ast.TableName),
|
|
DBName: $4,
|
|
Full: $1.(bool),
|
|
}
|
|
}
|
|
| "EXTENDED" OptFull FieldsOrColumns ShowTableAliasOpt ShowDatabaseNameOpt
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowColumns,
|
|
Table: $4.(*ast.TableName),
|
|
DBName: $5,
|
|
Full: $2.(bool),
|
|
Extended: true,
|
|
}
|
|
}
|
|
| builtinCount '(' '*' ')' "WARNINGS"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowWarnings, CountWarningsOrErrors: true}
|
|
}
|
|
| "WARNINGS"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowWarnings}
|
|
}
|
|
| builtinCount '(' '*' ')' "ERRORS"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowErrors, CountWarningsOrErrors: true}
|
|
}
|
|
| "ERRORS"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowErrors}
|
|
}
|
|
| GlobalScope "VARIABLES"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowVariables,
|
|
GlobalScope: $1.(bool),
|
|
}
|
|
}
|
|
| GlobalScope "STATUS"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowStatus,
|
|
GlobalScope: $1.(bool),
|
|
}
|
|
}
|
|
| GlobalScope "BINDINGS"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowBindings,
|
|
GlobalScope: $1.(bool),
|
|
}
|
|
}
|
|
| "COLLATION"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowCollation,
|
|
}
|
|
}
|
|
| "TRIGGERS" ShowDatabaseNameOpt
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowTriggers,
|
|
DBName: $2,
|
|
}
|
|
}
|
|
| "BINDING_CACHE" "STATUS"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowBindingCacheStatus,
|
|
}
|
|
}
|
|
| "PROCEDURE" "STATUS"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowProcedureStatus,
|
|
}
|
|
}
|
|
| "PUMP" "STATUS"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowPumpStatus,
|
|
}
|
|
}
|
|
| "DRAINER" "STATUS"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowDrainerStatus,
|
|
}
|
|
}
|
|
| "FUNCTION" "STATUS"
|
|
{
|
|
// This statement is similar to SHOW PROCEDURE STATUS but for stored functions.
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/show-function-status.html
|
|
// We do not support neither stored functions nor stored procedures.
|
|
// So we reuse show procedure status process logic.
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowFunctionStatus,
|
|
}
|
|
}
|
|
| "EVENTS" ShowDatabaseNameOpt
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowEvents,
|
|
DBName: $2,
|
|
}
|
|
}
|
|
| "PLUGINS"
|
|
{
|
|
$$ = &ast.ShowStmt{
|
|
Tp: ast.ShowPlugins,
|
|
}
|
|
}
|
|
| "SESSION_STATES"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowSessionStates}
|
|
}
|
|
| "STATS_EXTENDED"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowStatsExtended}
|
|
}
|
|
| "STATS_META"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowStatsMeta, Table: &ast.TableName{Name: model.NewCIStr("STATS_META"), Schema: model.NewCIStr(mysql.SystemDB)}}
|
|
}
|
|
| "STATS_HISTOGRAMS"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowStatsHistograms, Table: &ast.TableName{Name: model.NewCIStr("STATS_HISTOGRAMS"), Schema: model.NewCIStr(mysql.SystemDB)}}
|
|
}
|
|
| "STATS_TOPN"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowStatsTopN}
|
|
}
|
|
| "STATS_BUCKETS"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowStatsBuckets, Table: &ast.TableName{Name: model.NewCIStr("STATS_BUCKETS"), Schema: model.NewCIStr(mysql.SystemDB)}}
|
|
}
|
|
| "STATS_HEALTHY"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowStatsHealthy}
|
|
}
|
|
| "STATS_LOCKED"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowStatsLocked, Table: &ast.TableName{Name: model.NewCIStr("STATS_TABLE_LOCKED"), Schema: model.NewCIStr(mysql.SystemDB)}}
|
|
}
|
|
| "HISTOGRAMS_IN_FLIGHT"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowHistogramsInFlight}
|
|
}
|
|
| "COLUMN_STATS_USAGE"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowColumnStatsUsage}
|
|
}
|
|
| "ANALYZE" "STATUS"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowAnalyzeStatus}
|
|
}
|
|
| "BACKUPS"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowBackups}
|
|
}
|
|
| "RESTORES"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowRestores}
|
|
}
|
|
| "PLACEMENT"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowPlacement}
|
|
}
|
|
| "PLACEMENT" "LABELS"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowPlacementLabels}
|
|
}
|
|
| "IMPORT" "JOBS"
|
|
{
|
|
$$ = &ast.ShowStmt{Tp: ast.ShowImportJobs}
|
|
}
|
|
|
|
ShowLikeOrWhereOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "LIKE" SimpleExpr
|
|
{
|
|
$$ = &ast.PatternLikeOrIlikeExpr{
|
|
Pattern: $2,
|
|
Escape: '\\',
|
|
IsLike: true,
|
|
}
|
|
}
|
|
| "WHERE" Expression
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
GlobalScope:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "GLOBAL"
|
|
{
|
|
$$ = true
|
|
}
|
|
| "SESSION"
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
StatementScope:
|
|
{
|
|
$$ = ast.StatementScopeSession
|
|
}
|
|
| "GLOBAL"
|
|
{
|
|
$$ = ast.StatementScopeGlobal
|
|
}
|
|
| "INSTANCE"
|
|
{
|
|
$$ = ast.StatementScopeInstance
|
|
}
|
|
| "SESSION"
|
|
{
|
|
$$ = ast.StatementScopeSession
|
|
}
|
|
|
|
OptFull:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "FULL"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
ShowDatabaseNameOpt:
|
|
{
|
|
$$ = ""
|
|
}
|
|
| FromOrIn DBName
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
ShowTableAliasOpt:
|
|
FromOrIn TableName
|
|
{
|
|
$$ = $2.(*ast.TableName)
|
|
}
|
|
|
|
FlushStmt:
|
|
"FLUSH" NoWriteToBinLogAliasOpt FlushOption
|
|
{
|
|
tmp := $3.(*ast.FlushStmt)
|
|
tmp.NoWriteToBinLog = $2.(bool)
|
|
$$ = tmp
|
|
}
|
|
|
|
PluginNameList:
|
|
Identifier
|
|
{
|
|
$$ = []string{$1}
|
|
}
|
|
| PluginNameList ',' Identifier
|
|
{
|
|
$$ = append($1.([]string), $3)
|
|
}
|
|
|
|
FlushOption:
|
|
"PRIVILEGES"
|
|
{
|
|
$$ = &ast.FlushStmt{
|
|
Tp: ast.FlushPrivileges,
|
|
}
|
|
}
|
|
| "STATUS"
|
|
{
|
|
$$ = &ast.FlushStmt{
|
|
Tp: ast.FlushStatus,
|
|
}
|
|
}
|
|
| "TIDB" "PLUGINS" PluginNameList
|
|
{
|
|
$$ = &ast.FlushStmt{
|
|
Tp: ast.FlushTiDBPlugin,
|
|
Plugins: $3.([]string),
|
|
}
|
|
}
|
|
| "HOSTS"
|
|
{
|
|
$$ = &ast.FlushStmt{
|
|
Tp: ast.FlushHosts,
|
|
}
|
|
}
|
|
| LogTypeOpt "LOGS"
|
|
{
|
|
$$ = &ast.FlushStmt{
|
|
Tp: ast.FlushLogs,
|
|
LogType: $1.(ast.LogType),
|
|
}
|
|
}
|
|
| TableOrTables TableNameListOpt WithReadLockOpt
|
|
{
|
|
$$ = &ast.FlushStmt{
|
|
Tp: ast.FlushTables,
|
|
Tables: $2.([]*ast.TableName),
|
|
ReadLock: $3.(bool),
|
|
}
|
|
}
|
|
| "CLIENT_ERRORS_SUMMARY"
|
|
{
|
|
$$ = &ast.FlushStmt{
|
|
Tp: ast.FlushClientErrorsSummary,
|
|
}
|
|
}
|
|
|
|
LogTypeOpt:
|
|
/* empty */
|
|
{
|
|
$$ = ast.LogTypeDefault
|
|
}
|
|
| "BINARY"
|
|
{
|
|
$$ = ast.LogTypeBinary
|
|
}
|
|
| "ENGINE"
|
|
{
|
|
$$ = ast.LogTypeEngine
|
|
}
|
|
| "ERROR"
|
|
{
|
|
$$ = ast.LogTypeError
|
|
}
|
|
| "GENERAL"
|
|
{
|
|
$$ = ast.LogTypeGeneral
|
|
}
|
|
| "SLOW"
|
|
{
|
|
$$ = ast.LogTypeSlow
|
|
}
|
|
|
|
NoWriteToBinLogAliasOpt:
|
|
%prec lowerThanLocal
|
|
{
|
|
$$ = false
|
|
}
|
|
| "NO_WRITE_TO_BINLOG"
|
|
{
|
|
$$ = true
|
|
}
|
|
| "LOCAL"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
TableNameListOpt:
|
|
%prec empty
|
|
{
|
|
$$ = []*ast.TableName{}
|
|
}
|
|
| TableNameList
|
|
|
|
TableNameListOpt2:
|
|
%prec empty
|
|
{
|
|
$$ = []*ast.TableName{}
|
|
}
|
|
| "TABLE" TableNameList
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
WithReadLockOpt:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "WITH" "READ" "LOCK"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
Statement:
|
|
EmptyStmt
|
|
| AdminStmt
|
|
| AlterDatabaseStmt
|
|
| AlterTableStmt
|
|
| AlterUserStmt
|
|
| AlterInstanceStmt
|
|
| AlterSequenceStmt
|
|
| AlterPolicyStmt
|
|
| AlterResourceGroupStmt
|
|
| AnalyzeTableStmt
|
|
| BeginTransactionStmt
|
|
| BinlogStmt
|
|
| BRIEStmt
|
|
| CommitStmt
|
|
| DeallocateStmt
|
|
| DeleteFromStmt
|
|
| ExecuteStmt
|
|
| ExplainStmt
|
|
| CalibrateResourceStmt
|
|
| ChangeStmt
|
|
| CreateDatabaseStmt
|
|
| CreateIndexStmt
|
|
| CreateTableStmt
|
|
| CreateViewStmt
|
|
| CreateUserStmt
|
|
| CreateRoleStmt
|
|
| CreateBindingStmt
|
|
| CreatePolicyStmt
|
|
| CreateProcedureStmt
|
|
| CreateResourceGroupStmt
|
|
| AddQueryWatchStmt
|
|
| CreateSequenceStmt
|
|
| CreateStatisticsStmt
|
|
| DoStmt
|
|
| DropDatabaseStmt
|
|
| DropIndexStmt
|
|
| DropTableStmt
|
|
| DropProcedureStmt
|
|
| DropPolicyStmt
|
|
| DropSequenceStmt
|
|
| DropViewStmt
|
|
| DropUserStmt
|
|
| DropResourceGroupStmt
|
|
| DropQueryWatchStmt
|
|
| DropRoleStmt
|
|
| DropStatisticsStmt
|
|
| DropStatsStmt
|
|
| DropBindingStmt
|
|
| FlushStmt
|
|
| FlashbackTableStmt
|
|
| FlashbackToTimestampStmt
|
|
| FlashbackDatabaseStmt
|
|
| GrantStmt
|
|
| GrantProxyStmt
|
|
| GrantRoleStmt
|
|
| CallStmt
|
|
| ImportIntoStmt
|
|
| InsertIntoStmt
|
|
| IndexAdviseStmt
|
|
| KillStmt
|
|
| LoadDataStmt
|
|
| LoadStatsStmt
|
|
| LockStatsStmt
|
|
| UnlockStatsStmt
|
|
| PlanReplayerStmt
|
|
| PreparedStmt
|
|
| RollbackStmt
|
|
| RenameTableStmt
|
|
| RenameUserStmt
|
|
| ReplaceIntoStmt
|
|
| RecoverTableStmt
|
|
| ReleaseSavepointStmt
|
|
| RevokeStmt
|
|
| RevokeRoleStmt
|
|
| SavepointStmt
|
|
| SetOprStmt
|
|
| SelectStmt
|
|
| SelectStmtWithClause
|
|
| SubSelect
|
|
{
|
|
var sel ast.StmtNode
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
case *ast.SetOprStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
}
|
|
$$ = sel
|
|
}
|
|
| SetStmt
|
|
| SetBindingStmt
|
|
| SetRoleStmt
|
|
| SetDefaultRoleStmt
|
|
| SplitRegionStmt
|
|
| ShowStmt
|
|
| TraceStmt
|
|
| TruncateTableStmt
|
|
| UpdateStmt
|
|
| UseStmt
|
|
| UnlockTablesStmt
|
|
| LockTablesStmt
|
|
| ShutdownStmt
|
|
| RestartStmt
|
|
| HelpStmt
|
|
| NonTransactionalDMLStmt
|
|
| PauseLoadDataStmt
|
|
| ResumeLoadDataStmt
|
|
| CancelImportStmt
|
|
| DropLoadDataStmt
|
|
|
|
TraceableStmt:
|
|
DeleteFromStmt
|
|
| UpdateStmt
|
|
| InsertIntoStmt
|
|
| ReplaceIntoStmt
|
|
| SetOprStmt
|
|
| SelectStmt
|
|
| SelectStmtWithClause
|
|
| SubSelect
|
|
{
|
|
var sel ast.StmtNode
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
case *ast.SetOprStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
}
|
|
$$ = sel
|
|
}
|
|
| LoadDataStmt
|
|
| BeginTransactionStmt
|
|
| CommitStmt
|
|
| SavepointStmt
|
|
| ReleaseSavepointStmt
|
|
| RollbackStmt
|
|
| SetStmt
|
|
| AnalyzeTableStmt
|
|
|
|
ExplainableStmt:
|
|
DeleteFromStmt
|
|
| UpdateStmt
|
|
| InsertIntoStmt
|
|
| ReplaceIntoStmt
|
|
| SetOprStmt
|
|
| SelectStmt
|
|
| SelectStmtWithClause
|
|
| SubSelect
|
|
{
|
|
var sel ast.StmtNode
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
case *ast.SetOprStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
}
|
|
$$ = sel
|
|
}
|
|
| AlterTableStmt
|
|
|
|
StatementList:
|
|
Statement
|
|
{
|
|
if $1 != nil {
|
|
s := $1
|
|
if lexer, ok := yylex.(stmtTexter); ok {
|
|
s.SetText(parser.lexer.client, lexer.stmtText())
|
|
}
|
|
parser.result = append(parser.result, s)
|
|
}
|
|
}
|
|
| StatementList ';' Statement
|
|
{
|
|
if $3 != nil {
|
|
s := $3
|
|
if lexer, ok := yylex.(stmtTexter); ok {
|
|
s.SetText(parser.lexer.client, lexer.stmtText())
|
|
}
|
|
parser.result = append(parser.result, s)
|
|
}
|
|
}
|
|
|
|
Constraint:
|
|
ConstraintKeywordOpt ConstraintElem
|
|
{
|
|
cst := $2.(*ast.Constraint)
|
|
if $1 != nil {
|
|
cst.Name = $1.(string)
|
|
cst.IsEmptyIndex = len(cst.Name) == 0
|
|
}
|
|
$$ = cst
|
|
}
|
|
|
|
CheckConstraintKeyword:
|
|
"CHECK"
|
|
| "CONSTRAINT"
|
|
|
|
TableElement:
|
|
ColumnDef
|
|
| Constraint
|
|
|
|
TableElementList:
|
|
TableElement
|
|
{
|
|
if $1 != nil {
|
|
$$ = []interface{}{$1.(interface{})}
|
|
} else {
|
|
$$ = []interface{}{}
|
|
}
|
|
}
|
|
| TableElementList ',' TableElement
|
|
{
|
|
if $3 != nil {
|
|
$$ = append($1.([]interface{}), $3)
|
|
} else {
|
|
$$ = $1
|
|
}
|
|
}
|
|
|
|
TableElementListOpt:
|
|
/* empty */ %prec lowerThanCreateTableSelect
|
|
{
|
|
var columnDefs []*ast.ColumnDef
|
|
var constraints []*ast.Constraint
|
|
$$ = &ast.CreateTableStmt{
|
|
Cols: columnDefs,
|
|
Constraints: constraints,
|
|
}
|
|
}
|
|
| '(' TableElementList ')'
|
|
{
|
|
tes := $2.([]interface{})
|
|
var columnDefs []*ast.ColumnDef
|
|
var constraints []*ast.Constraint
|
|
for _, te := range tes {
|
|
switch te := te.(type) {
|
|
case *ast.ColumnDef:
|
|
columnDefs = append(columnDefs, te)
|
|
case *ast.Constraint:
|
|
constraints = append(constraints, te)
|
|
}
|
|
}
|
|
$$ = &ast.CreateTableStmt{
|
|
Cols: columnDefs,
|
|
Constraints: constraints,
|
|
}
|
|
}
|
|
|
|
TableOption:
|
|
PartDefOption
|
|
| DefaultKwdOpt CharsetKw EqOpt CharsetName
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionCharset, StrValue: $4,
|
|
UintValue: ast.TableOptionCharsetWithoutConvertTo}
|
|
}
|
|
| DefaultKwdOpt "COLLATE" EqOpt CollationName
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionCollate, StrValue: $4,
|
|
UintValue: ast.TableOptionCharsetWithoutConvertTo}
|
|
}
|
|
| ForceOpt "AUTO_INCREMENT" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionAutoIncrement, UintValue: $4.(uint64), BoolValue: $1.(bool)}
|
|
}
|
|
| "AUTO_ID_CACHE" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionAutoIdCache, UintValue: $3.(uint64)}
|
|
}
|
|
| ForceOpt "AUTO_RANDOM_BASE" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionAutoRandomBase, UintValue: $4.(uint64), BoolValue: $1.(bool)}
|
|
}
|
|
| "AVG_ROW_LENGTH" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionAvgRowLength, UintValue: $3.(uint64)}
|
|
}
|
|
| "CONNECTION" EqOpt stringLit
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionConnection, StrValue: $3}
|
|
}
|
|
| "CHECKSUM" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionCheckSum, UintValue: $3.(uint64)}
|
|
}
|
|
| "TABLE_CHECKSUM" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionTableCheckSum, UintValue: $3.(uint64)}
|
|
}
|
|
| "PASSWORD" EqOpt stringLit
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionPassword, StrValue: $3}
|
|
}
|
|
| "COMPRESSION" EqOpt stringLit
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionCompression, StrValue: $3}
|
|
}
|
|
| "KEY_BLOCK_SIZE" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionKeyBlockSize, UintValue: $3.(uint64)}
|
|
}
|
|
| "DELAY_KEY_WRITE" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionDelayKeyWrite, UintValue: $3.(uint64)}
|
|
}
|
|
| RowFormat
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionRowFormat, UintValue: $1.(uint64)}
|
|
}
|
|
| "STATS_PERSISTENT" EqOpt StatsPersistentVal
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionStatsPersistent}
|
|
}
|
|
| "STATS_AUTO_RECALC" EqOpt LengthNum
|
|
{
|
|
n := $3.(uint64)
|
|
if n != 0 && n != 1 {
|
|
yylex.AppendError(yylex.Errorf("The value of STATS_AUTO_RECALC must be one of [0|1|DEFAULT]."))
|
|
return 1
|
|
}
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionStatsAutoRecalc, UintValue: n}
|
|
yylex.AppendError(yylex.Errorf("The STATS_AUTO_RECALC is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "STATS_AUTO_RECALC" EqOpt "DEFAULT"
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionStatsAutoRecalc, Default: true}
|
|
yylex.AppendError(yylex.Errorf("The STATS_AUTO_RECALC is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "STATS_SAMPLE_PAGES" EqOpt LengthNum
|
|
{
|
|
// Parse it but will ignore it.
|
|
// In MySQL, STATS_SAMPLE_PAGES=N(Where 0<N<=65535) or STAS_SAMPLE_PAGES=DEFAULT.
|
|
// Cause we don't support it, so we don't check range of the value.
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionStatsSamplePages, UintValue: $3.(uint64)}
|
|
yylex.AppendError(yylex.Errorf("The STATS_SAMPLE_PAGES is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "STATS_SAMPLE_PAGES" EqOpt "DEFAULT"
|
|
{
|
|
// Parse it but will ignore it.
|
|
// In MySQL, default value of STATS_SAMPLE_PAGES is 0.
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionStatsSamplePages, Default: true}
|
|
yylex.AppendError(yylex.Errorf("The STATS_SAMPLE_PAGES is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "STATS_BUCKETS" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionStatsBuckets, UintValue: $3.(uint64)}
|
|
}
|
|
| "STATS_TOPN" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionStatsTopN, UintValue: $3.(uint64)}
|
|
}
|
|
| "STATS_SAMPLE_RATE" EqOpt NumLiteral
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionStatsSampleRate, Value: ast.NewValueExpr($3, "", "")}
|
|
}
|
|
| "STATS_COL_CHOICE" EqOpt stringLit
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionStatsColsChoice, StrValue: $3}
|
|
}
|
|
| "STATS_COL_LIST" EqOpt stringLit
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionStatsColList, StrValue: $3}
|
|
}
|
|
| "SHARD_ROW_ID_BITS" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionShardRowID, UintValue: $3.(uint64)}
|
|
}
|
|
| "PRE_SPLIT_REGIONS" EqOpt LengthNum
|
|
{
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionPreSplitRegion, UintValue: $3.(uint64)}
|
|
}
|
|
| "PACK_KEYS" EqOpt StatsPersistentVal
|
|
{
|
|
// Parse it but will ignore it.
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionPackKeys}
|
|
}
|
|
| "STORAGE" "MEMORY"
|
|
{
|
|
// Parse it but will ignore it.
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionStorageMedia, StrValue: "MEMORY"}
|
|
yylex.AppendError(yylex.Errorf("The STORAGE clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "STORAGE" "DISK"
|
|
{
|
|
// Parse it but will ignore it.
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionStorageMedia, StrValue: "DISK"}
|
|
yylex.AppendError(yylex.Errorf("The STORAGE clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "SECONDARY_ENGINE" EqOpt "NULL"
|
|
{
|
|
// Parse it but will ignore it
|
|
// See https://github.com/mysql/mysql-server/blob/8.0/sql/sql_yacc.yy#L5977-L5984
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionSecondaryEngineNull}
|
|
yylex.AppendError(yylex.Errorf("The SECONDARY_ENGINE clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "SECONDARY_ENGINE" EqOpt StringName
|
|
{
|
|
// Parse it but will ignore it
|
|
// See https://github.com/mysql/mysql-server/blob/8.0/sql/sql_yacc.yy#L5977-L5984
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionSecondaryEngine, StrValue: $3}
|
|
yylex.AppendError(yylex.Errorf("The SECONDARY_ENGINE clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "UNION" EqOpt '(' TableNameListOpt ')'
|
|
{
|
|
// Parse it but will ignore it
|
|
$$ = &ast.TableOption{
|
|
Tp: ast.TableOptionUnion,
|
|
TableNames: $4.([]*ast.TableName),
|
|
}
|
|
yylex.AppendError(yylex.Errorf("The UNION option is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
| "ENCRYPTION" EqOpt EncryptionOpt
|
|
{
|
|
// Parse it but will ignore it
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionEncryption, StrValue: $3}
|
|
}
|
|
| "TTL" EqOpt Identifier '+' "INTERVAL" Literal TimeUnit
|
|
{
|
|
$$ = &ast.TableOption{
|
|
Tp: ast.TableOptionTTL,
|
|
ColumnName: &ast.ColumnName{Name: model.NewCIStr($3)},
|
|
Value: ast.NewValueExpr($6, parser.charset, parser.collation),
|
|
TimeUnitValue: &ast.TimeUnitExpr{Unit: $7.(ast.TimeUnitType)},
|
|
}
|
|
}
|
|
| "TTL_ENABLE" EqOpt stringLit
|
|
{
|
|
onOrOff := strings.ToLower($3)
|
|
if onOrOff == "on" {
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionTTLEnable, BoolValue: true}
|
|
} else if onOrOff == "off" {
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionTTLEnable, BoolValue: false}
|
|
} else {
|
|
yylex.AppendError(yylex.Errorf("The TTL_ENABLE option has to be set 'ON' or 'OFF'"))
|
|
return 1
|
|
}
|
|
}
|
|
| "TTL_JOB_INTERVAL" EqOpt stringLit
|
|
{
|
|
_, err := duration.ParseDuration($3)
|
|
if err != nil {
|
|
yylex.AppendError(yylex.Errorf("The TTL_JOB_INTERVAL option is not a valid duration: %s", err.Error()))
|
|
return 1
|
|
}
|
|
$$ = &ast.TableOption{Tp: ast.TableOptionTTLJobInterval, StrValue: $3}
|
|
}
|
|
|
|
ForceOpt:
|
|
/* empty */
|
|
{
|
|
$$ = false
|
|
}
|
|
| "FORCE"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
StatsPersistentVal:
|
|
"DEFAULT"
|
|
{}
|
|
| LengthNum
|
|
{}
|
|
|
|
CreateTableOptionListOpt:
|
|
/* empty */ %prec lowerThanCreateTableSelect
|
|
{
|
|
$$ = []*ast.TableOption{}
|
|
}
|
|
| TableOptionList %prec lowerThanComma
|
|
|
|
TableOptionList:
|
|
TableOption
|
|
{
|
|
$$ = []*ast.TableOption{$1.(*ast.TableOption)}
|
|
}
|
|
| TableOptionList TableOption
|
|
{
|
|
$$ = append($1.([]*ast.TableOption), $2.(*ast.TableOption))
|
|
}
|
|
| TableOptionList ',' TableOption
|
|
{
|
|
$$ = append($1.([]*ast.TableOption), $3.(*ast.TableOption))
|
|
}
|
|
|
|
OptTable:
|
|
{}
|
|
| "TABLE"
|
|
|
|
TruncateTableStmt:
|
|
"TRUNCATE" OptTable TableName
|
|
{
|
|
$$ = &ast.TruncateTableStmt{Table: $3.(*ast.TableName)}
|
|
}
|
|
|
|
RowFormat:
|
|
"ROW_FORMAT" EqOpt "DEFAULT"
|
|
{
|
|
$$ = ast.RowFormatDefault
|
|
}
|
|
| "ROW_FORMAT" EqOpt "DYNAMIC"
|
|
{
|
|
$$ = ast.RowFormatDynamic
|
|
}
|
|
| "ROW_FORMAT" EqOpt "FIXED"
|
|
{
|
|
$$ = ast.RowFormatFixed
|
|
}
|
|
| "ROW_FORMAT" EqOpt "COMPRESSED"
|
|
{
|
|
$$ = ast.RowFormatCompressed
|
|
}
|
|
| "ROW_FORMAT" EqOpt "REDUNDANT"
|
|
{
|
|
$$ = ast.RowFormatRedundant
|
|
}
|
|
| "ROW_FORMAT" EqOpt "COMPACT"
|
|
{
|
|
$$ = ast.RowFormatCompact
|
|
}
|
|
| "ROW_FORMAT" EqOpt "TOKUDB_DEFAULT"
|
|
{
|
|
$$ = ast.TokuDBRowFormatDefault
|
|
}
|
|
| "ROW_FORMAT" EqOpt "TOKUDB_FAST"
|
|
{
|
|
$$ = ast.TokuDBRowFormatFast
|
|
}
|
|
| "ROW_FORMAT" EqOpt "TOKUDB_SMALL"
|
|
{
|
|
$$ = ast.TokuDBRowFormatSmall
|
|
}
|
|
| "ROW_FORMAT" EqOpt "TOKUDB_ZLIB"
|
|
{
|
|
$$ = ast.TokuDBRowFormatZlib
|
|
}
|
|
| "ROW_FORMAT" EqOpt "TOKUDB_ZSTD"
|
|
{
|
|
$$ = ast.TokuDBRowFormatZstd
|
|
}
|
|
| "ROW_FORMAT" EqOpt "TOKUDB_QUICKLZ"
|
|
{
|
|
$$ = ast.TokuDBRowFormatQuickLZ
|
|
}
|
|
| "ROW_FORMAT" EqOpt "TOKUDB_LZMA"
|
|
{
|
|
$$ = ast.TokuDBRowFormatLzma
|
|
}
|
|
| "ROW_FORMAT" EqOpt "TOKUDB_SNAPPY"
|
|
{
|
|
$$ = ast.TokuDBRowFormatSnappy
|
|
}
|
|
| "ROW_FORMAT" EqOpt "TOKUDB_UNCOMPRESSED"
|
|
{
|
|
$$ = ast.TokuDBRowFormatUncompressed
|
|
}
|
|
|
|
/*************************************Type Begin***************************************/
|
|
Type:
|
|
NumericType
|
|
| StringType
|
|
| DateAndTimeType
|
|
|
|
NumericType:
|
|
IntegerType OptFieldLen FieldOpts
|
|
{
|
|
// TODO: check flen 0
|
|
tp := types.NewFieldType($1.(byte))
|
|
tp.SetFlen($2.(int))
|
|
for _, o := range $3.([]*ast.TypeOpt) {
|
|
if o.IsUnsigned {
|
|
tp.AddFlag(mysql.UnsignedFlag)
|
|
}
|
|
if o.IsZerofill {
|
|
tp.AddFlag(mysql.ZerofillFlag)
|
|
}
|
|
}
|
|
$$ = tp
|
|
}
|
|
| BooleanType FieldOpts
|
|
{
|
|
// TODO: check flen 0
|
|
tp := types.NewFieldType($1.(byte))
|
|
tp.SetFlen(1)
|
|
for _, o := range $2.([]*ast.TypeOpt) {
|
|
if o.IsUnsigned {
|
|
tp.AddFlag(mysql.UnsignedFlag)
|
|
}
|
|
if o.IsZerofill {
|
|
tp.AddFlag(mysql.ZerofillFlag)
|
|
}
|
|
}
|
|
$$ = tp
|
|
}
|
|
| FixedPointType FloatOpt FieldOpts
|
|
{
|
|
fopt := $2.(*ast.FloatOpt)
|
|
tp := types.NewFieldType($1.(byte))
|
|
tp.SetFlen(fopt.Flen)
|
|
tp.SetDecimal(fopt.Decimal)
|
|
for _, o := range $3.([]*ast.TypeOpt) {
|
|
if o.IsUnsigned {
|
|
tp.AddFlag(mysql.UnsignedFlag)
|
|
}
|
|
if o.IsZerofill {
|
|
tp.AddFlag(mysql.ZerofillFlag)
|
|
}
|
|
}
|
|
$$ = tp
|
|
}
|
|
| FloatingPointType FloatOpt FieldOpts
|
|
{
|
|
fopt := $2.(*ast.FloatOpt)
|
|
tp := types.NewFieldType($1.(byte))
|
|
// check for a double(10) for syntax error
|
|
if tp.GetType() == mysql.TypeDouble && parser.strictDoubleFieldType {
|
|
if fopt.Flen != types.UnspecifiedLength && fopt.Decimal == types.UnspecifiedLength {
|
|
yylex.AppendError(ErrSyntax)
|
|
return 1
|
|
}
|
|
}
|
|
tp.SetFlen(fopt.Flen)
|
|
if tp.GetType() == mysql.TypeFloat && fopt.Decimal == types.UnspecifiedLength && tp.GetFlen() <= mysql.MaxDoublePrecisionLength {
|
|
if tp.GetFlen() > mysql.MaxFloatPrecisionLength {
|
|
tp.SetType(mysql.TypeDouble)
|
|
}
|
|
tp.SetFlen(types.UnspecifiedLength)
|
|
}
|
|
tp.SetDecimal(fopt.Decimal)
|
|
for _, o := range $3.([]*ast.TypeOpt) {
|
|
if o.IsUnsigned {
|
|
tp.AddFlag(mysql.UnsignedFlag)
|
|
}
|
|
if o.IsZerofill {
|
|
tp.AddFlag(mysql.ZerofillFlag)
|
|
}
|
|
}
|
|
$$ = tp
|
|
}
|
|
| BitValueType OptFieldLen
|
|
{
|
|
tp := types.NewFieldType($1.(byte))
|
|
tp.SetFlen($2.(int))
|
|
if tp.GetFlen() == types.UnspecifiedLength {
|
|
tp.SetFlen(1)
|
|
}
|
|
$$ = tp
|
|
}
|
|
|
|
IntegerType:
|
|
"TINYINT"
|
|
{
|
|
$$ = mysql.TypeTiny
|
|
}
|
|
| "SMALLINT"
|
|
{
|
|
$$ = mysql.TypeShort
|
|
}
|
|
| "MEDIUMINT"
|
|
{
|
|
$$ = mysql.TypeInt24
|
|
}
|
|
| "MIDDLEINT"
|
|
{
|
|
$$ = mysql.TypeInt24
|
|
}
|
|
| "INT"
|
|
{
|
|
$$ = mysql.TypeLong
|
|
}
|
|
| "INT1"
|
|
{
|
|
$$ = mysql.TypeTiny
|
|
}
|
|
| "INT2"
|
|
{
|
|
$$ = mysql.TypeShort
|
|
}
|
|
| "INT3"
|
|
{
|
|
$$ = mysql.TypeInt24
|
|
}
|
|
| "INT4"
|
|
{
|
|
$$ = mysql.TypeLong
|
|
}
|
|
| "INT8"
|
|
{
|
|
$$ = mysql.TypeLonglong
|
|
}
|
|
| "INTEGER"
|
|
{
|
|
$$ = mysql.TypeLong
|
|
}
|
|
| "BIGINT"
|
|
{
|
|
$$ = mysql.TypeLonglong
|
|
}
|
|
|
|
BooleanType:
|
|
"BOOL"
|
|
{
|
|
$$ = mysql.TypeTiny
|
|
}
|
|
| "BOOLEAN"
|
|
{
|
|
$$ = mysql.TypeTiny
|
|
}
|
|
|
|
OptInteger:
|
|
{}
|
|
| "INTEGER"
|
|
| "INT"
|
|
|
|
FixedPointType:
|
|
"DECIMAL"
|
|
{
|
|
$$ = mysql.TypeNewDecimal
|
|
}
|
|
| "NUMERIC"
|
|
{
|
|
$$ = mysql.TypeNewDecimal
|
|
}
|
|
| "FIXED"
|
|
{
|
|
$$ = mysql.TypeNewDecimal
|
|
}
|
|
|
|
FloatingPointType:
|
|
"FLOAT"
|
|
{
|
|
$$ = mysql.TypeFloat
|
|
}
|
|
| "REAL"
|
|
{
|
|
if parser.lexer.GetSQLMode().HasRealAsFloatMode() {
|
|
$$ = mysql.TypeFloat
|
|
} else {
|
|
$$ = mysql.TypeDouble
|
|
}
|
|
}
|
|
| "DOUBLE"
|
|
{
|
|
$$ = mysql.TypeDouble
|
|
}
|
|
| "DOUBLE" "PRECISION"
|
|
{
|
|
$$ = mysql.TypeDouble
|
|
}
|
|
| "FLOAT4"
|
|
{
|
|
$$ = mysql.TypeFloat
|
|
}
|
|
| "FLOAT8"
|
|
{
|
|
$$ = mysql.TypeDouble
|
|
}
|
|
|
|
BitValueType:
|
|
"BIT"
|
|
{
|
|
$$ = mysql.TypeBit
|
|
}
|
|
|
|
StringType:
|
|
Char FieldLen OptBinary
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeString)
|
|
tp.SetFlen($2.(int))
|
|
tp.SetCharset($3.(*ast.OptBinary).Charset)
|
|
if $3.(*ast.OptBinary).IsBinary {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = tp
|
|
}
|
|
| Char OptBinary
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeString)
|
|
tp.SetCharset($2.(*ast.OptBinary).Charset)
|
|
if $2.(*ast.OptBinary).IsBinary {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = tp
|
|
}
|
|
| NChar FieldLen OptBinary
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeString)
|
|
tp.SetFlen($2.(int))
|
|
tp.SetCharset($3.(*ast.OptBinary).Charset)
|
|
if $3.(*ast.OptBinary).IsBinary {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = tp
|
|
}
|
|
| NChar OptBinary
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeString)
|
|
tp.SetCharset($2.(*ast.OptBinary).Charset)
|
|
if $2.(*ast.OptBinary).IsBinary {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = tp
|
|
}
|
|
| Varchar FieldLen OptBinary
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeVarchar)
|
|
tp.SetFlen($2.(int))
|
|
tp.SetCharset($3.(*ast.OptBinary).Charset)
|
|
if $3.(*ast.OptBinary).IsBinary {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = tp
|
|
}
|
|
| NVarchar FieldLen OptBinary
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeVarchar)
|
|
tp.SetFlen($2.(int))
|
|
tp.SetCharset($3.(*ast.OptBinary).Charset)
|
|
if $3.(*ast.OptBinary).IsBinary {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = tp
|
|
}
|
|
| "BINARY" OptFieldLen
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeString)
|
|
tp.SetFlen($2.(int))
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CharsetBin)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
$$ = tp
|
|
}
|
|
| "VARBINARY" FieldLen
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeVarchar)
|
|
tp.SetFlen($2.(int))
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CharsetBin)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
$$ = tp
|
|
}
|
|
| BlobType
|
|
{
|
|
tp := $1.(*types.FieldType)
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CharsetBin)
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
$$ = tp
|
|
}
|
|
| TextType OptCharsetWithOptBinary
|
|
{
|
|
tp := $1.(*types.FieldType)
|
|
tp.SetCharset($2.(*ast.OptBinary).Charset)
|
|
if $2.(*ast.OptBinary).Charset == charset.CharsetBin {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
tp.SetCollate(charset.CollationBin)
|
|
}
|
|
if $2.(*ast.OptBinary).IsBinary {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = tp
|
|
}
|
|
| "ENUM" '(' TextStringList ')' OptCharsetWithOptBinary
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeEnum)
|
|
elems := $3.([]*ast.TextString)
|
|
opt := $5.(*ast.OptBinary)
|
|
tp.SetElems(make([]string, len(elems)))
|
|
fieldLen := -1 // enum_flen = max(ele_flen)
|
|
for i, e := range elems {
|
|
trimmed := strings.TrimRight(e.Value, " ")
|
|
tp.SetElemWithIsBinaryLit(i, trimmed, e.IsBinaryLiteral)
|
|
if len(trimmed) > fieldLen {
|
|
fieldLen = len(trimmed)
|
|
}
|
|
}
|
|
tp.SetFlen(fieldLen)
|
|
tp.SetCharset(opt.Charset)
|
|
if opt.IsBinary {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = tp
|
|
}
|
|
| "SET" '(' TextStringList ')' OptCharsetWithOptBinary
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeSet)
|
|
elems := $3.([]*ast.TextString)
|
|
opt := $5.(*ast.OptBinary)
|
|
tp.SetElems(make([]string, len(elems)))
|
|
fieldLen := len(elems) - 1 // set_flen = sum(ele_flen) + number_of_ele - 1
|
|
for i, e := range elems {
|
|
trimmed := strings.TrimRight(e.Value, " ")
|
|
tp.SetElemWithIsBinaryLit(i, trimmed, e.IsBinaryLiteral)
|
|
fieldLen += len(trimmed)
|
|
}
|
|
tp.SetFlen(fieldLen)
|
|
tp.SetCharset(opt.Charset)
|
|
if opt.IsBinary {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = tp
|
|
}
|
|
| "JSON"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeJSON)
|
|
tp.SetDecimal(0)
|
|
tp.SetCharset(charset.CharsetBin)
|
|
tp.SetCollate(charset.CollationBin)
|
|
$$ = tp
|
|
}
|
|
| "LONG" Varchar OptCharsetWithOptBinary
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeMediumBlob)
|
|
tp.SetCharset($3.(*ast.OptBinary).Charset)
|
|
if $3.(*ast.OptBinary).Charset == charset.CharsetBin {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
tp.SetCollate(charset.CollationBin)
|
|
}
|
|
if $3.(*ast.OptBinary).IsBinary {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = tp
|
|
}
|
|
| "LONG" OptCharsetWithOptBinary
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeMediumBlob)
|
|
tp.SetCharset($2.(*ast.OptBinary).Charset)
|
|
if $2.(*ast.OptBinary).Charset == charset.CharsetBin {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
tp.SetCollate(charset.CollationBin)
|
|
}
|
|
if $2.(*ast.OptBinary).IsBinary {
|
|
tp.AddFlag(mysql.BinaryFlag)
|
|
}
|
|
$$ = tp
|
|
}
|
|
|
|
Char:
|
|
"CHARACTER"
|
|
| "CHAR"
|
|
|
|
NChar:
|
|
"NCHAR"
|
|
| "NATIONAL" "CHARACTER"
|
|
| "NATIONAL" "CHAR"
|
|
|
|
Varchar:
|
|
"CHARACTER" "VARYING"
|
|
| "CHAR" "VARYING"
|
|
| "VARCHAR"
|
|
| "VARCHARACTER"
|
|
|
|
NVarchar:
|
|
"NATIONAL" "VARCHAR"
|
|
| "NATIONAL" "VARCHARACTER"
|
|
| "NVARCHAR"
|
|
| "NCHAR" "VARCHAR"
|
|
| "NCHAR" "VARCHARACTER"
|
|
| "NATIONAL" "CHARACTER" "VARYING"
|
|
| "NATIONAL" "CHAR" "VARYING"
|
|
| "NCHAR" "VARYING"
|
|
|
|
Year:
|
|
"YEAR"
|
|
| "SQL_TSI_YEAR"
|
|
|
|
BlobType:
|
|
"TINYBLOB"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeTinyBlob)
|
|
$$ = tp
|
|
}
|
|
| "BLOB" OptFieldLen
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeBlob)
|
|
tp.SetFlen($2.(int))
|
|
$$ = tp
|
|
}
|
|
| "MEDIUMBLOB"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeMediumBlob)
|
|
$$ = tp
|
|
}
|
|
| "LONGBLOB"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeLongBlob)
|
|
$$ = tp
|
|
}
|
|
| "LONG" "VARBINARY"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeMediumBlob)
|
|
$$ = tp
|
|
}
|
|
|
|
TextType:
|
|
"TINYTEXT"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeTinyBlob)
|
|
$$ = tp
|
|
}
|
|
| "TEXT" OptFieldLen
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeBlob)
|
|
tp.SetFlen($2.(int))
|
|
$$ = tp
|
|
}
|
|
| "MEDIUMTEXT"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeMediumBlob)
|
|
$$ = tp
|
|
}
|
|
| "LONGTEXT"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeLongBlob)
|
|
$$ = tp
|
|
}
|
|
|
|
OptCharsetWithOptBinary:
|
|
OptBinary
|
|
| "ASCII"
|
|
{
|
|
$$ = &ast.OptBinary{
|
|
IsBinary: false,
|
|
Charset: charset.CharsetLatin1,
|
|
}
|
|
}
|
|
| "UNICODE"
|
|
{
|
|
cs, err := charset.GetCharsetInfo("ucs2")
|
|
if err != nil {
|
|
yylex.AppendError(ErrUnknownCharacterSet.GenWithStackByArgs("ucs2"))
|
|
return 1
|
|
}
|
|
$$ = &ast.OptBinary{
|
|
IsBinary: false,
|
|
Charset: cs.Name,
|
|
}
|
|
}
|
|
| "BYTE"
|
|
{
|
|
$$ = &ast.OptBinary{
|
|
IsBinary: false,
|
|
Charset: charset.CharsetBin,
|
|
}
|
|
}
|
|
|
|
DateAndTimeType:
|
|
"DATE"
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeDate)
|
|
$$ = tp
|
|
}
|
|
| "DATETIME" OptFieldLen
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeDatetime)
|
|
tp.SetFlen(mysql.MaxDatetimeWidthNoFsp)
|
|
tp.SetDecimal($2.(int))
|
|
if tp.GetDecimal() > 0 {
|
|
tp.SetFlen(tp.GetFlen() + 1 + tp.GetDecimal())
|
|
}
|
|
$$ = tp
|
|
}
|
|
| "TIMESTAMP" OptFieldLen
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeTimestamp)
|
|
tp.SetFlen(mysql.MaxDatetimeWidthNoFsp)
|
|
tp.SetDecimal($2.(int))
|
|
if tp.GetDecimal() > 0 {
|
|
tp.SetFlen(tp.GetFlen() + 1 + tp.GetDecimal())
|
|
}
|
|
$$ = tp
|
|
}
|
|
| "TIME" OptFieldLen
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeDuration)
|
|
tp.SetFlen(mysql.MaxDurationWidthNoFsp)
|
|
tp.SetDecimal($2.(int))
|
|
if tp.GetDecimal() > 0 {
|
|
tp.SetFlen(tp.GetFlen() + 1 + tp.GetDecimal())
|
|
}
|
|
$$ = tp
|
|
}
|
|
| Year OptFieldLen FieldOpts
|
|
{
|
|
tp := types.NewFieldType(mysql.TypeYear)
|
|
tp.SetFlen($2.(int))
|
|
if tp.GetFlen() != types.UnspecifiedLength && tp.GetFlen() != 4 {
|
|
yylex.AppendError(ErrInvalidYearColumnLength.GenWithStackByArgs())
|
|
return -1
|
|
}
|
|
$$ = tp
|
|
}
|
|
|
|
FieldLen:
|
|
'(' LengthNum ')'
|
|
{
|
|
$$ = int($2.(uint64))
|
|
}
|
|
|
|
OptFieldLen:
|
|
{
|
|
$$ = types.UnspecifiedLength
|
|
}
|
|
| FieldLen
|
|
|
|
FieldOpt:
|
|
"UNSIGNED"
|
|
{
|
|
$$ = &ast.TypeOpt{IsUnsigned: true}
|
|
}
|
|
| "SIGNED"
|
|
{
|
|
$$ = &ast.TypeOpt{IsUnsigned: false}
|
|
}
|
|
| "ZEROFILL"
|
|
{
|
|
$$ = &ast.TypeOpt{IsZerofill: true, IsUnsigned: true}
|
|
}
|
|
|
|
FieldOpts:
|
|
{
|
|
$$ = []*ast.TypeOpt{}
|
|
}
|
|
| FieldOpts FieldOpt
|
|
{
|
|
$$ = append($1.([]*ast.TypeOpt), $2.(*ast.TypeOpt))
|
|
}
|
|
|
|
FloatOpt:
|
|
{
|
|
$$ = &ast.FloatOpt{Flen: types.UnspecifiedLength, Decimal: types.UnspecifiedLength}
|
|
}
|
|
| FieldLen
|
|
{
|
|
$$ = &ast.FloatOpt{Flen: $1.(int), Decimal: types.UnspecifiedLength}
|
|
}
|
|
| Precision
|
|
|
|
Precision:
|
|
'(' LengthNum ',' LengthNum ')'
|
|
{
|
|
$$ = &ast.FloatOpt{Flen: int($2.(uint64)), Decimal: int($4.(uint64))}
|
|
}
|
|
|
|
OptBinMod:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "BINARY"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
OptBinary:
|
|
{
|
|
$$ = &ast.OptBinary{
|
|
IsBinary: false,
|
|
Charset: "",
|
|
}
|
|
}
|
|
| "BINARY" OptCharset
|
|
{
|
|
$$ = &ast.OptBinary{
|
|
IsBinary: true,
|
|
Charset: $2,
|
|
}
|
|
}
|
|
| CharsetKw CharsetName OptBinMod
|
|
{
|
|
$$ = &ast.OptBinary{
|
|
IsBinary: $3.(bool),
|
|
Charset: $2,
|
|
}
|
|
}
|
|
|
|
OptCharset:
|
|
{
|
|
$$ = ""
|
|
}
|
|
| CharsetKw CharsetName
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
CharsetKw:
|
|
"CHARACTER" "SET"
|
|
| "CHARSET"
|
|
| "CHAR" "SET"
|
|
|
|
OptCollate:
|
|
{
|
|
$$ = ""
|
|
}
|
|
| "COLLATE" CollationName
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
StringList:
|
|
stringLit
|
|
{
|
|
$$ = []string{$1}
|
|
}
|
|
| StringList ',' stringLit
|
|
{
|
|
$$ = append($1.([]string), $3)
|
|
}
|
|
|
|
TextString:
|
|
stringLit
|
|
{
|
|
$$ = &ast.TextString{Value: $1}
|
|
}
|
|
| hexLit
|
|
{
|
|
$$ = &ast.TextString{Value: $1.(ast.BinaryLiteral).ToString(), IsBinaryLiteral: true}
|
|
}
|
|
| bitLit
|
|
{
|
|
$$ = &ast.TextString{Value: $1.(ast.BinaryLiteral).ToString(), IsBinaryLiteral: true}
|
|
}
|
|
|
|
TextStringList:
|
|
TextString
|
|
{
|
|
$$ = []*ast.TextString{$1.(*ast.TextString)}
|
|
}
|
|
| TextStringList ',' TextString
|
|
{
|
|
$$ = append($1.([]*ast.TextString), $3.(*ast.TextString))
|
|
}
|
|
|
|
StringName:
|
|
stringLit
|
|
| Identifier
|
|
|
|
StringNameOrBRIEOptionKeyword:
|
|
StringName
|
|
| "IGNORE"
|
|
| "REPLACE"
|
|
|
|
/***********************************************************************************
|
|
* Update Statement
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/update.html
|
|
***********************************************************************************/
|
|
UpdateStmt:
|
|
UpdateStmtNoWith
|
|
| WithClause UpdateStmtNoWith
|
|
{
|
|
u := $2.(*ast.UpdateStmt)
|
|
u.With = $1.(*ast.WithClause)
|
|
$$ = u
|
|
}
|
|
|
|
UpdateStmtNoWith:
|
|
"UPDATE" TableOptimizerHintsOpt PriorityOpt IgnoreOptional TableRef "SET" AssignmentList WhereClauseOptional OrderByOptional LimitClause
|
|
{
|
|
var refs *ast.Join
|
|
if x, ok := $5.(*ast.Join); ok {
|
|
refs = x
|
|
} else {
|
|
refs = &ast.Join{Left: $5.(ast.ResultSetNode)}
|
|
}
|
|
st := &ast.UpdateStmt{
|
|
Priority: $3.(mysql.PriorityEnum),
|
|
TableRefs: &ast.TableRefsClause{TableRefs: refs},
|
|
List: $7.([]*ast.Assignment),
|
|
IgnoreErr: $4.(bool),
|
|
}
|
|
if $2 != nil {
|
|
st.TableHints = $2.([]*ast.TableOptimizerHint)
|
|
}
|
|
if $8 != nil {
|
|
st.Where = $8.(ast.ExprNode)
|
|
}
|
|
if $9 != nil {
|
|
st.Order = $9.(*ast.OrderByClause)
|
|
}
|
|
if $10 != nil {
|
|
st.Limit = $10.(*ast.Limit)
|
|
}
|
|
$$ = st
|
|
}
|
|
| "UPDATE" TableOptimizerHintsOpt PriorityOpt IgnoreOptional TableRefs "SET" AssignmentList WhereClauseOptional
|
|
{
|
|
st := &ast.UpdateStmt{
|
|
Priority: $3.(mysql.PriorityEnum),
|
|
TableRefs: &ast.TableRefsClause{TableRefs: $5.(*ast.Join)},
|
|
List: $7.([]*ast.Assignment),
|
|
IgnoreErr: $4.(bool),
|
|
}
|
|
if $2 != nil {
|
|
st.TableHints = $2.([]*ast.TableOptimizerHint)
|
|
}
|
|
if $8 != nil {
|
|
st.Where = $8.(ast.ExprNode)
|
|
}
|
|
$$ = st
|
|
}
|
|
|
|
UseStmt:
|
|
"USE" DBName
|
|
{
|
|
$$ = &ast.UseStmt{DBName: $2}
|
|
}
|
|
|
|
WhereClause:
|
|
"WHERE" Expression
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
WhereClauseOptional:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| WhereClause
|
|
|
|
CommaOpt:
|
|
{}
|
|
| ','
|
|
{}
|
|
|
|
/************************************************************************************
|
|
* Account Management Statements
|
|
* https://dev.mysql.com/doc/refman/5.7/en/account-management-sql.html
|
|
************************************************************************************/
|
|
CreateUserStmt:
|
|
"CREATE" "USER" IfNotExists UserSpecList RequireClauseOpt ConnectionOptions PasswordOrLockOptions CommentOrAttributeOption ResourceGroupNameOption
|
|
{
|
|
// See https://dev.mysql.com/doc/refman/8.0/en/create-user.html
|
|
ret := &ast.CreateUserStmt{
|
|
IsCreateRole: false,
|
|
IfNotExists: $3.(bool),
|
|
Specs: $4.([]*ast.UserSpec),
|
|
AuthTokenOrTLSOptions: $5.([]*ast.AuthTokenOrTLSOption),
|
|
ResourceOptions: $6.([]*ast.ResourceOption),
|
|
PasswordOrLockOptions: $7.([]*ast.PasswordOrLockOption),
|
|
}
|
|
if $8 != nil {
|
|
ret.CommentOrAttributeOption = $8.(*ast.CommentOrAttributeOption)
|
|
}
|
|
if $9 != nil {
|
|
ret.ResourceGroupNameOption = $9.(*ast.ResourceGroupNameOption)
|
|
}
|
|
$$ = ret
|
|
}
|
|
|
|
CreateRoleStmt:
|
|
"CREATE" "ROLE" IfNotExists RoleSpecList
|
|
{
|
|
// See https://dev.mysql.com/doc/refman/8.0/en/create-role.html
|
|
$$ = &ast.CreateUserStmt{
|
|
IsCreateRole: true,
|
|
IfNotExists: $3.(bool),
|
|
Specs: $4.([]*ast.UserSpec),
|
|
}
|
|
}
|
|
|
|
/* See http://dev.mysql.com/doc/refman/8.0/en/alter-user.html */
|
|
AlterUserStmt:
|
|
"ALTER" "USER" IfExists UserSpecList RequireClauseOpt ConnectionOptions PasswordOrLockOptions CommentOrAttributeOption ResourceGroupNameOption
|
|
{
|
|
ret := &ast.AlterUserStmt{
|
|
IfExists: $3.(bool),
|
|
Specs: $4.([]*ast.UserSpec),
|
|
AuthTokenOrTLSOptions: $5.([]*ast.AuthTokenOrTLSOption),
|
|
ResourceOptions: $6.([]*ast.ResourceOption),
|
|
PasswordOrLockOptions: $7.([]*ast.PasswordOrLockOption),
|
|
}
|
|
if $8 != nil {
|
|
ret.CommentOrAttributeOption = $8.(*ast.CommentOrAttributeOption)
|
|
}
|
|
if $9 != nil {
|
|
ret.ResourceGroupNameOption = $9.(*ast.ResourceGroupNameOption)
|
|
}
|
|
$$ = ret
|
|
}
|
|
| "ALTER" "USER" IfExists "USER" '(' ')' "IDENTIFIED" "BY" AuthString
|
|
{
|
|
auth := &ast.AuthOption{
|
|
AuthString: $9,
|
|
ByAuthString: true,
|
|
}
|
|
$$ = &ast.AlterUserStmt{
|
|
IfExists: $3.(bool),
|
|
CurrentAuth: auth,
|
|
}
|
|
}
|
|
|
|
/* See https://dev.mysql.com/doc/refman/8.0/en/alter-instance.html */
|
|
AlterInstanceStmt:
|
|
"ALTER" "INSTANCE" InstanceOption
|
|
{
|
|
$$ = $3.(*ast.AlterInstanceStmt)
|
|
}
|
|
|
|
InstanceOption:
|
|
"RELOAD" "TLS"
|
|
{
|
|
$$ = &ast.AlterInstanceStmt{
|
|
ReloadTLS: true,
|
|
}
|
|
}
|
|
| "RELOAD" "TLS" "NO" "ROLLBACK" "ON" "ERROR"
|
|
{
|
|
$$ = &ast.AlterInstanceStmt{
|
|
ReloadTLS: true,
|
|
NoRollbackOnError: true,
|
|
}
|
|
}
|
|
|
|
UserSpec:
|
|
Username AuthOption
|
|
{
|
|
userSpec := &ast.UserSpec{
|
|
User: $1.(*auth.UserIdentity),
|
|
}
|
|
if $2 != nil {
|
|
userSpec.AuthOpt = $2.(*ast.AuthOption)
|
|
}
|
|
$$ = userSpec
|
|
}
|
|
|
|
UserSpecList:
|
|
UserSpec
|
|
{
|
|
$$ = []*ast.UserSpec{$1.(*ast.UserSpec)}
|
|
}
|
|
| UserSpecList ',' UserSpec
|
|
{
|
|
$$ = append($1.([]*ast.UserSpec), $3.(*ast.UserSpec))
|
|
}
|
|
|
|
ConnectionOptions:
|
|
{
|
|
l := []*ast.ResourceOption{}
|
|
$$ = l
|
|
}
|
|
| "WITH" ConnectionOptionList
|
|
{
|
|
$$ = $2
|
|
yylex.AppendError(yylex.Errorf("TiDB does not support WITH ConnectionOptions now, they would be parsed but ignored."))
|
|
parser.lastErrorAsWarn()
|
|
}
|
|
|
|
ConnectionOptionList:
|
|
ConnectionOption
|
|
{
|
|
$$ = []*ast.ResourceOption{$1.(*ast.ResourceOption)}
|
|
}
|
|
| ConnectionOptionList ConnectionOption
|
|
{
|
|
l := $1.([]*ast.ResourceOption)
|
|
l = append(l, $2.(*ast.ResourceOption))
|
|
$$ = l
|
|
}
|
|
|
|
ConnectionOption:
|
|
"MAX_QUERIES_PER_HOUR" Int64Num
|
|
{
|
|
$$ = &ast.ResourceOption{
|
|
Type: ast.MaxQueriesPerHour,
|
|
Count: $2.(int64),
|
|
}
|
|
}
|
|
| "MAX_UPDATES_PER_HOUR" Int64Num
|
|
{
|
|
$$ = &ast.ResourceOption{
|
|
Type: ast.MaxUpdatesPerHour,
|
|
Count: $2.(int64),
|
|
}
|
|
}
|
|
| "MAX_CONNECTIONS_PER_HOUR" Int64Num
|
|
{
|
|
$$ = &ast.ResourceOption{
|
|
Type: ast.MaxConnectionsPerHour,
|
|
Count: $2.(int64),
|
|
}
|
|
}
|
|
| "MAX_USER_CONNECTIONS" Int64Num
|
|
{
|
|
$$ = &ast.ResourceOption{
|
|
Type: ast.MaxUserConnections,
|
|
Count: $2.(int64),
|
|
}
|
|
}
|
|
|
|
RequireClauseOpt:
|
|
{
|
|
$$ = []*ast.AuthTokenOrTLSOption{}
|
|
}
|
|
| RequireClause
|
|
|
|
RequireClause:
|
|
"REQUIRE" "NONE"
|
|
{
|
|
t := &ast.AuthTokenOrTLSOption{
|
|
Type: ast.TlsNone,
|
|
}
|
|
$$ = []*ast.AuthTokenOrTLSOption{t}
|
|
}
|
|
| "REQUIRE" "SSL"
|
|
{
|
|
t := &ast.AuthTokenOrTLSOption{
|
|
Type: ast.Ssl,
|
|
}
|
|
$$ = []*ast.AuthTokenOrTLSOption{t}
|
|
}
|
|
| "REQUIRE" "X509"
|
|
{
|
|
t := &ast.AuthTokenOrTLSOption{
|
|
Type: ast.X509,
|
|
}
|
|
$$ = []*ast.AuthTokenOrTLSOption{t}
|
|
}
|
|
| "REQUIRE" RequireList
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
RequireList:
|
|
RequireListElement
|
|
{
|
|
$$ = []*ast.AuthTokenOrTLSOption{$1.(*ast.AuthTokenOrTLSOption)}
|
|
}
|
|
| RequireList "AND" RequireListElement
|
|
{
|
|
l := $1.([]*ast.AuthTokenOrTLSOption)
|
|
l = append(l, $3.(*ast.AuthTokenOrTLSOption))
|
|
$$ = l
|
|
}
|
|
| RequireList RequireListElement
|
|
{
|
|
l := $1.([]*ast.AuthTokenOrTLSOption)
|
|
l = append(l, $2.(*ast.AuthTokenOrTLSOption))
|
|
$$ = l
|
|
}
|
|
|
|
RequireListElement:
|
|
"ISSUER" stringLit
|
|
{
|
|
$$ = &ast.AuthTokenOrTLSOption{
|
|
Type: ast.Issuer,
|
|
Value: $2,
|
|
}
|
|
}
|
|
| "SUBJECT" stringLit
|
|
{
|
|
$$ = &ast.AuthTokenOrTLSOption{
|
|
Type: ast.Subject,
|
|
Value: $2,
|
|
}
|
|
}
|
|
| "CIPHER" stringLit
|
|
{
|
|
$$ = &ast.AuthTokenOrTLSOption{
|
|
Type: ast.Cipher,
|
|
Value: $2,
|
|
}
|
|
}
|
|
| "SAN" stringLit
|
|
{
|
|
$$ = &ast.AuthTokenOrTLSOption{
|
|
Type: ast.SAN,
|
|
Value: $2,
|
|
}
|
|
}
|
|
| "TOKEN_ISSUER" stringLit
|
|
{
|
|
$$ = &ast.AuthTokenOrTLSOption{
|
|
Type: ast.TokenIssuer,
|
|
Value: $2,
|
|
}
|
|
}
|
|
|
|
CommentOrAttributeOption:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "COMMENT" stringLit
|
|
{
|
|
$$ = &ast.CommentOrAttributeOption{Type: ast.UserCommentType, Value: $2}
|
|
}
|
|
| "ATTRIBUTE" stringLit
|
|
{
|
|
$$ = &ast.CommentOrAttributeOption{Type: ast.UserAttributeType, Value: $2}
|
|
}
|
|
|
|
ResourceGroupNameOption:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "RESOURCE" "GROUP" ResourceGroupName
|
|
{
|
|
$$ = &ast.ResourceGroupNameOption{Value: $3}
|
|
}
|
|
|
|
PasswordOrLockOptions:
|
|
{
|
|
$$ = []*ast.PasswordOrLockOption{}
|
|
}
|
|
| PasswordOrLockOptionList
|
|
{
|
|
$$ = $1
|
|
}
|
|
|
|
PasswordOrLockOptionList:
|
|
PasswordOrLockOption
|
|
{
|
|
$$ = []*ast.PasswordOrLockOption{$1.(*ast.PasswordOrLockOption)}
|
|
}
|
|
| PasswordOrLockOptionList PasswordOrLockOption
|
|
{
|
|
l := $1.([]*ast.PasswordOrLockOption)
|
|
l = append(l, $2.(*ast.PasswordOrLockOption))
|
|
$$ = l
|
|
}
|
|
|
|
PasswordOrLockOption:
|
|
"ACCOUNT" "UNLOCK"
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.Unlock,
|
|
}
|
|
}
|
|
| "ACCOUNT" "LOCK"
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.Lock,
|
|
}
|
|
}
|
|
| "PASSWORD" "HISTORY" "DEFAULT"
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.PasswordHistoryDefault,
|
|
}
|
|
}
|
|
| "PASSWORD" "HISTORY" NUM
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.PasswordHistory,
|
|
Count: $3.(int64),
|
|
}
|
|
}
|
|
| "PASSWORD" "REUSE" "INTERVAL" "DEFAULT"
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.PasswordReuseDefault,
|
|
}
|
|
}
|
|
| "PASSWORD" "REUSE" "INTERVAL" NUM "DAY"
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.PasswordReuseInterval,
|
|
Count: $4.(int64),
|
|
}
|
|
}
|
|
| "PASSWORD" "EXPIRE"
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.PasswordExpire,
|
|
}
|
|
}
|
|
| "PASSWORD" "EXPIRE" "INTERVAL" Int64Num "DAY"
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.PasswordExpireInterval,
|
|
Count: $4.(int64),
|
|
}
|
|
}
|
|
| "PASSWORD" "EXPIRE" "NEVER"
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.PasswordExpireNever,
|
|
}
|
|
}
|
|
| "PASSWORD" "EXPIRE" "DEFAULT"
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.PasswordExpireDefault,
|
|
}
|
|
}
|
|
| "FAILED_LOGIN_ATTEMPTS" Int64Num
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.FailedLoginAttempts,
|
|
Count: $2.(int64),
|
|
}
|
|
}
|
|
| "PASSWORD_LOCK_TIME" Int64Num
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.PasswordLockTime,
|
|
Count: $2.(int64),
|
|
}
|
|
}
|
|
| "PASSWORD_LOCK_TIME" "UNBOUNDED"
|
|
{
|
|
$$ = &ast.PasswordOrLockOption{
|
|
Type: ast.PasswordLockTimeUnbounded,
|
|
}
|
|
}
|
|
|
|
AuthOption:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "IDENTIFIED" "BY" AuthString
|
|
{
|
|
$$ = &ast.AuthOption{
|
|
AuthString: $3,
|
|
ByAuthString: true,
|
|
}
|
|
}
|
|
| "IDENTIFIED" "WITH" AuthPlugin
|
|
{
|
|
$$ = &ast.AuthOption{
|
|
AuthPlugin: $3,
|
|
}
|
|
}
|
|
| "IDENTIFIED" "WITH" AuthPlugin "BY" AuthString
|
|
{
|
|
$$ = &ast.AuthOption{
|
|
AuthPlugin: $3,
|
|
AuthString: $5,
|
|
ByAuthString: true,
|
|
}
|
|
}
|
|
| "IDENTIFIED" "WITH" AuthPlugin "AS" HashString
|
|
{
|
|
$$ = &ast.AuthOption{
|
|
AuthPlugin: $3,
|
|
HashString: $5,
|
|
ByHashString: true,
|
|
}
|
|
}
|
|
| "IDENTIFIED" "BY" "PASSWORD" HashString
|
|
{
|
|
$$ = &ast.AuthOption{
|
|
AuthPlugin: mysql.AuthNativePassword,
|
|
HashString: $4,
|
|
ByHashString: true,
|
|
}
|
|
}
|
|
|
|
AuthPlugin:
|
|
StringName
|
|
|
|
HashString:
|
|
stringLit
|
|
| hexLit
|
|
{
|
|
$$ = $1.(ast.BinaryLiteral).ToString()
|
|
}
|
|
|
|
RoleSpec:
|
|
Rolename
|
|
{
|
|
role := $1.(*auth.RoleIdentity)
|
|
roleSpec := &ast.UserSpec{
|
|
User: &auth.UserIdentity{
|
|
Username: role.Username,
|
|
Hostname: role.Hostname,
|
|
},
|
|
IsRole: true,
|
|
}
|
|
$$ = roleSpec
|
|
}
|
|
|
|
RoleSpecList:
|
|
RoleSpec
|
|
{
|
|
$$ = []*ast.UserSpec{$1.(*ast.UserSpec)}
|
|
}
|
|
| RoleSpecList ',' RoleSpec
|
|
{
|
|
$$ = append($1.([]*ast.UserSpec), $3.(*ast.UserSpec))
|
|
}
|
|
|
|
BindableStmt:
|
|
SetOprStmt
|
|
| SelectStmt
|
|
| SelectStmtWithClause
|
|
| SubSelect
|
|
{
|
|
var sel ast.StmtNode
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
case *ast.SetOprStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
}
|
|
$$ = sel
|
|
}
|
|
| UpdateStmt
|
|
| DeleteWithoutUsingStmt
|
|
| InsertIntoStmt
|
|
| ReplaceIntoStmt
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Create Binding Statement
|
|
*
|
|
* Example:
|
|
* CREATE GLOBAL BINDING FOR select Col1,Col2 from table USING select Col1,Col2 from table use index(Col1)
|
|
*******************************************************************/
|
|
CreateBindingStmt:
|
|
"CREATE" GlobalScope "BINDING" "FOR" BindableStmt "USING" BindableStmt
|
|
{
|
|
startOffset := parser.startOffset(&yyS[yypt-2])
|
|
endOffset := parser.startOffset(&yyS[yypt-1])
|
|
originStmt := $5
|
|
originStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:endOffset]))
|
|
|
|
startOffset = parser.startOffset(&yyS[yypt])
|
|
hintedStmt := $7
|
|
hintedStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:]))
|
|
|
|
x := &ast.CreateBindingStmt{
|
|
OriginNode: originStmt,
|
|
HintedNode: hintedStmt,
|
|
GlobalScope: $2.(bool),
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
| "CREATE" GlobalScope "BINDING" "FROM" "HISTORY" "USING" "PLAN" "DIGEST" stringLit
|
|
{
|
|
x := &ast.CreateBindingStmt{
|
|
GlobalScope: $2.(bool),
|
|
PlanDigest: $9,
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Drop Binding Statement
|
|
*
|
|
* Example:
|
|
* DROP GLOBAL BINDING FOR select Col1,Col2 from table
|
|
*******************************************************************/
|
|
DropBindingStmt:
|
|
"DROP" GlobalScope "BINDING" "FOR" BindableStmt
|
|
{
|
|
startOffset := parser.startOffset(&yyS[yypt])
|
|
originStmt := $5
|
|
originStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:]))
|
|
|
|
x := &ast.DropBindingStmt{
|
|
OriginNode: originStmt,
|
|
GlobalScope: $2.(bool),
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
| "DROP" GlobalScope "BINDING" "FOR" BindableStmt "USING" BindableStmt
|
|
{
|
|
startOffset := parser.startOffset(&yyS[yypt-2])
|
|
endOffset := parser.startOffset(&yyS[yypt-1])
|
|
originStmt := $5
|
|
originStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:endOffset]))
|
|
|
|
startOffset = parser.startOffset(&yyS[yypt])
|
|
hintedStmt := $7
|
|
hintedStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:]))
|
|
|
|
x := &ast.DropBindingStmt{
|
|
OriginNode: originStmt,
|
|
HintedNode: hintedStmt,
|
|
GlobalScope: $2.(bool),
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
| "DROP" GlobalScope "BINDING" "FOR" "SQL" "DIGEST" stringLit
|
|
{
|
|
x := &ast.DropBindingStmt{
|
|
GlobalScope: $2.(bool),
|
|
SQLDigest: $7,
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
|
|
SetBindingStmt:
|
|
"SET" "BINDING" BindingStatusType "FOR" BindableStmt
|
|
{
|
|
startOffset := parser.startOffset(&yyS[yypt])
|
|
originStmt := $5
|
|
originStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:]))
|
|
|
|
x := &ast.SetBindingStmt{
|
|
BindingStatusType: $3.(ast.BindingStatusType),
|
|
OriginNode: originStmt,
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
| "SET" "BINDING" BindingStatusType "FOR" BindableStmt "USING" BindableStmt
|
|
{
|
|
startOffset := parser.startOffset(&yyS[yypt-2])
|
|
endOffset := parser.startOffset(&yyS[yypt-1])
|
|
originStmt := $5
|
|
originStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:endOffset]))
|
|
|
|
startOffset = parser.startOffset(&yyS[yypt])
|
|
hintedStmt := $7
|
|
hintedStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:]))
|
|
|
|
x := &ast.SetBindingStmt{
|
|
BindingStatusType: $3.(ast.BindingStatusType),
|
|
OriginNode: originStmt,
|
|
HintedNode: hintedStmt,
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
| "SET" "BINDING" BindingStatusType "FOR" "SQL" "DIGEST" stringLit
|
|
{
|
|
x := &ast.SetBindingStmt{
|
|
BindingStatusType: $3.(ast.BindingStatusType),
|
|
SQLDigest: $7,
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
|
|
/*************************************************************************************
|
|
* Grant statement
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/grant.html
|
|
*************************************************************************************/
|
|
GrantStmt:
|
|
"GRANT" RoleOrPrivElemList "ON" ObjectType PrivLevel "TO" UserSpecList RequireClauseOpt WithGrantOptionOpt
|
|
{
|
|
p, err := convertToPriv($2.([]*ast.RoleOrPriv))
|
|
if err != nil {
|
|
yylex.AppendError(err)
|
|
return 1
|
|
}
|
|
$$ = &ast.GrantStmt{
|
|
Privs: p,
|
|
ObjectType: $4.(ast.ObjectTypeType),
|
|
Level: $5.(*ast.GrantLevel),
|
|
Users: $7.([]*ast.UserSpec),
|
|
AuthTokenOrTLSOptions: $8.([]*ast.AuthTokenOrTLSOption),
|
|
WithGrant: $9.(bool),
|
|
}
|
|
}
|
|
|
|
GrantProxyStmt:
|
|
"GRANT" "PROXY" "ON" Username "TO" UsernameList WithGrantOptionOpt
|
|
{
|
|
$$ = &ast.GrantProxyStmt{
|
|
LocalUser: $4.(*auth.UserIdentity),
|
|
ExternalUsers: $6.([]*auth.UserIdentity),
|
|
WithGrant: $7.(bool),
|
|
}
|
|
}
|
|
|
|
GrantRoleStmt:
|
|
"GRANT" RoleOrPrivElemList "TO" UsernameList
|
|
{
|
|
r, err := convertToRole($2.([]*ast.RoleOrPriv))
|
|
if err != nil {
|
|
yylex.AppendError(err)
|
|
return 1
|
|
}
|
|
$$ = &ast.GrantRoleStmt{
|
|
Roles: r,
|
|
Users: $4.([]*auth.UserIdentity),
|
|
}
|
|
}
|
|
|
|
WithGrantOptionOpt:
|
|
{
|
|
$$ = false
|
|
}
|
|
| "WITH" "GRANT" "OPTION"
|
|
{
|
|
$$ = true
|
|
}
|
|
| "WITH" "MAX_QUERIES_PER_HOUR" NUM
|
|
{
|
|
$$ = false
|
|
}
|
|
| "WITH" "MAX_UPDATES_PER_HOUR" NUM
|
|
{
|
|
$$ = false
|
|
}
|
|
| "WITH" "MAX_CONNECTIONS_PER_HOUR" NUM
|
|
{
|
|
$$ = false
|
|
}
|
|
| "WITH" "MAX_USER_CONNECTIONS" NUM
|
|
{
|
|
$$ = false
|
|
}
|
|
|
|
ExtendedPriv:
|
|
identifier
|
|
{
|
|
$$ = []string{$1}
|
|
}
|
|
| ExtendedPriv identifier
|
|
{
|
|
$$ = append($1.([]string), $2)
|
|
}
|
|
|
|
RoleOrPrivElem:
|
|
PrivElem
|
|
{
|
|
$$ = &ast.RoleOrPriv{
|
|
Node: $1,
|
|
}
|
|
}
|
|
| RolenameWithoutIdent
|
|
{
|
|
$$ = &ast.RoleOrPriv{
|
|
Node: $1,
|
|
}
|
|
}
|
|
| ExtendedPriv
|
|
{
|
|
$$ = &ast.RoleOrPriv{
|
|
Symbols: strings.Join($1.([]string), " "),
|
|
}
|
|
}
|
|
| "LOAD" "FROM" "S3"
|
|
{
|
|
$$ = &ast.RoleOrPriv{
|
|
Symbols: "LOAD FROM S3",
|
|
}
|
|
}
|
|
| "SELECT" "INTO" "S3"
|
|
{
|
|
$$ = &ast.RoleOrPriv{
|
|
Symbols: "SELECT INTO S3",
|
|
}
|
|
}
|
|
|
|
RoleOrPrivElemList:
|
|
RoleOrPrivElem
|
|
{
|
|
$$ = []*ast.RoleOrPriv{$1.(*ast.RoleOrPriv)}
|
|
}
|
|
| RoleOrPrivElemList ',' RoleOrPrivElem
|
|
{
|
|
$$ = append($1.([]*ast.RoleOrPriv), $3.(*ast.RoleOrPriv))
|
|
}
|
|
|
|
PrivElem:
|
|
PrivType
|
|
{
|
|
$$ = &ast.PrivElem{
|
|
Priv: $1.(mysql.PrivilegeType),
|
|
}
|
|
}
|
|
| PrivType '(' ColumnNameList ')'
|
|
{
|
|
$$ = &ast.PrivElem{
|
|
Priv: $1.(mysql.PrivilegeType),
|
|
Cols: $3.([]*ast.ColumnName),
|
|
}
|
|
}
|
|
|
|
PrivType:
|
|
"ALL"
|
|
{
|
|
$$ = mysql.AllPriv
|
|
}
|
|
| "ALL" "PRIVILEGES"
|
|
{
|
|
$$ = mysql.AllPriv
|
|
}
|
|
| "ALTER"
|
|
{
|
|
$$ = mysql.AlterPriv
|
|
}
|
|
| "CREATE"
|
|
{
|
|
$$ = mysql.CreatePriv
|
|
}
|
|
| "CREATE" "USER"
|
|
{
|
|
$$ = mysql.CreateUserPriv
|
|
}
|
|
| "CREATE" "TABLESPACE"
|
|
{
|
|
$$ = mysql.CreateTablespacePriv
|
|
}
|
|
| "TRIGGER"
|
|
{
|
|
$$ = mysql.TriggerPriv
|
|
}
|
|
| "DELETE"
|
|
{
|
|
$$ = mysql.DeletePriv
|
|
}
|
|
| "DROP"
|
|
{
|
|
$$ = mysql.DropPriv
|
|
}
|
|
| "PROCESS"
|
|
{
|
|
$$ = mysql.ProcessPriv
|
|
}
|
|
| "EXECUTE"
|
|
{
|
|
$$ = mysql.ExecutePriv
|
|
}
|
|
| "INDEX"
|
|
{
|
|
$$ = mysql.IndexPriv
|
|
}
|
|
| "INSERT"
|
|
{
|
|
$$ = mysql.InsertPriv
|
|
}
|
|
| "SELECT"
|
|
{
|
|
$$ = mysql.SelectPriv
|
|
}
|
|
| "SUPER"
|
|
{
|
|
$$ = mysql.SuperPriv
|
|
}
|
|
| "SHOW" "DATABASES"
|
|
{
|
|
$$ = mysql.ShowDBPriv
|
|
}
|
|
| "UPDATE"
|
|
{
|
|
$$ = mysql.UpdatePriv
|
|
}
|
|
| "GRANT" "OPTION"
|
|
{
|
|
$$ = mysql.GrantPriv
|
|
}
|
|
| "REFERENCES"
|
|
{
|
|
$$ = mysql.ReferencesPriv
|
|
}
|
|
| "REPLICATION" "SLAVE"
|
|
{
|
|
$$ = mysql.ReplicationSlavePriv
|
|
}
|
|
| "REPLICATION" "CLIENT"
|
|
{
|
|
$$ = mysql.ReplicationClientPriv
|
|
}
|
|
| "USAGE"
|
|
{
|
|
$$ = mysql.UsagePriv
|
|
}
|
|
| "RELOAD"
|
|
{
|
|
$$ = mysql.ReloadPriv
|
|
}
|
|
| "FILE"
|
|
{
|
|
$$ = mysql.FilePriv
|
|
}
|
|
| "CONFIG"
|
|
{
|
|
$$ = mysql.ConfigPriv
|
|
}
|
|
| "CREATE" "TEMPORARY" "TABLES"
|
|
{
|
|
$$ = mysql.CreateTMPTablePriv
|
|
}
|
|
| "LOCK" "TABLES"
|
|
{
|
|
$$ = mysql.LockTablesPriv
|
|
}
|
|
| "CREATE" "VIEW"
|
|
{
|
|
$$ = mysql.CreateViewPriv
|
|
}
|
|
| "SHOW" "VIEW"
|
|
{
|
|
$$ = mysql.ShowViewPriv
|
|
}
|
|
| "CREATE" "ROLE"
|
|
{
|
|
$$ = mysql.CreateRolePriv
|
|
}
|
|
| "DROP" "ROLE"
|
|
{
|
|
$$ = mysql.DropRolePriv
|
|
}
|
|
| "CREATE" "ROUTINE"
|
|
{
|
|
$$ = mysql.CreateRoutinePriv
|
|
}
|
|
| "ALTER" "ROUTINE"
|
|
{
|
|
$$ = mysql.AlterRoutinePriv
|
|
}
|
|
| "EVENT"
|
|
{
|
|
$$ = mysql.EventPriv
|
|
}
|
|
| "SHUTDOWN"
|
|
{
|
|
$$ = mysql.ShutdownPriv
|
|
}
|
|
|
|
ObjectType:
|
|
%prec lowerThanFunction
|
|
{
|
|
$$ = ast.ObjectTypeNone
|
|
}
|
|
| "TABLE"
|
|
{
|
|
$$ = ast.ObjectTypeTable
|
|
}
|
|
| "FUNCTION"
|
|
{
|
|
$$ = ast.ObjectTypeFunction
|
|
}
|
|
| "PROCEDURE"
|
|
{
|
|
$$ = ast.ObjectTypeProcedure
|
|
}
|
|
|
|
PrivLevel:
|
|
'*'
|
|
{
|
|
$$ = &ast.GrantLevel{
|
|
Level: ast.GrantLevelDB,
|
|
}
|
|
}
|
|
| '*' '.' '*'
|
|
{
|
|
$$ = &ast.GrantLevel{
|
|
Level: ast.GrantLevelGlobal,
|
|
}
|
|
}
|
|
| Identifier '.' '*'
|
|
{
|
|
$$ = &ast.GrantLevel{
|
|
Level: ast.GrantLevelDB,
|
|
DBName: $1,
|
|
}
|
|
}
|
|
| Identifier '.' Identifier
|
|
{
|
|
$$ = &ast.GrantLevel{
|
|
Level: ast.GrantLevelTable,
|
|
DBName: $1,
|
|
TableName: $3,
|
|
}
|
|
}
|
|
| Identifier
|
|
{
|
|
$$ = &ast.GrantLevel{
|
|
Level: ast.GrantLevelTable,
|
|
TableName: $1,
|
|
}
|
|
}
|
|
|
|
/**************************************RevokeStmt*******************************************
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/revoke.html
|
|
*******************************************************************************************/
|
|
RevokeStmt:
|
|
"REVOKE" RoleOrPrivElemList "ON" ObjectType PrivLevel "FROM" UserSpecList
|
|
{
|
|
p, err := convertToPriv($2.([]*ast.RoleOrPriv))
|
|
if err != nil {
|
|
yylex.AppendError(err)
|
|
return 1
|
|
}
|
|
$$ = &ast.RevokeStmt{
|
|
Privs: p,
|
|
ObjectType: $4.(ast.ObjectTypeType),
|
|
Level: $5.(*ast.GrantLevel),
|
|
Users: $7.([]*ast.UserSpec),
|
|
}
|
|
}
|
|
|
|
RevokeRoleStmt:
|
|
"REVOKE" RoleOrPrivElemList "FROM" UsernameList
|
|
{
|
|
// MySQL has special syntax for REVOKE ALL [PRIVILEGES], GRANT OPTION
|
|
// which uses the RevokeRoleStmt syntax but is of type RevokeStmt.
|
|
// It is documented at https://dev.mysql.com/doc/refman/5.7/en/revoke.html
|
|
// as the "second syntax" for REVOKE. It is only valid if *both*
|
|
// ALL PRIVILEGES + GRANT OPTION are specified in that order.
|
|
if isRevokeAllGrant($2.([]*ast.RoleOrPriv)) {
|
|
var users []*ast.UserSpec
|
|
for _, u := range $4.([]*auth.UserIdentity) {
|
|
users = append(users, &ast.UserSpec{
|
|
User: u,
|
|
})
|
|
}
|
|
$$ = &ast.RevokeStmt{
|
|
Privs: []*ast.PrivElem{{Priv: mysql.AllPriv}, {Priv: mysql.GrantPriv}},
|
|
ObjectType: ast.ObjectTypeNone,
|
|
Level: &ast.GrantLevel{Level: ast.GrantLevelGlobal},
|
|
Users: users,
|
|
}
|
|
} else {
|
|
r, err := convertToRole($2.([]*ast.RoleOrPriv))
|
|
if err != nil {
|
|
yylex.AppendError(err)
|
|
return 1
|
|
}
|
|
$$ = &ast.RevokeRoleStmt{
|
|
Roles: r,
|
|
Users: $4.([]*auth.UserIdentity),
|
|
}
|
|
}
|
|
}
|
|
|
|
/**************************************LoadDataStmt*****************************************
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/load-data.html
|
|
* for load stmt with format see https://github.com/pingcap/tidb/issues/40499
|
|
*******************************************************************************************/
|
|
LoadDataStmt:
|
|
"LOAD" "DATA" LocalOpt "INFILE" stringLit FormatOpt DuplicateOpt "INTO" "TABLE" TableName CharsetOpt Fields Lines IgnoreLines ColumnNameOrUserVarListOptWithBrackets LoadDataSetSpecOpt LoadDataOptionListOpt
|
|
{
|
|
x := &ast.LoadDataStmt{
|
|
FileLocRef: ast.FileLocServerOrRemote,
|
|
Path: $5,
|
|
Format: $6.(*string),
|
|
OnDuplicate: $7.(ast.OnDuplicateKeyHandlingType),
|
|
Table: $10.(*ast.TableName),
|
|
Charset: $11.(*string),
|
|
FieldsInfo: $12.(*ast.FieldsClause),
|
|
LinesInfo: $13.(*ast.LinesClause),
|
|
IgnoreLines: $14.(*uint64),
|
|
ColumnsAndUserVars: $15.([]*ast.ColumnNameOrUserVar),
|
|
ColumnAssignments: $16.([]*ast.Assignment),
|
|
Options: $17.([]*ast.LoadDataOpt),
|
|
}
|
|
if $3 != nil {
|
|
x.FileLocRef = ast.FileLocClient
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/load-data.html#load-data-duplicate-key-handling
|
|
// If you do not specify IGNORE or REPLACE modifier , then we set default behavior to IGNORE when LOCAL modifier is specified
|
|
if x.OnDuplicate == ast.OnDuplicateKeyHandlingError {
|
|
x.OnDuplicate = ast.OnDuplicateKeyHandlingIgnore
|
|
}
|
|
}
|
|
columns := []*ast.ColumnName{}
|
|
for _, v := range x.ColumnsAndUserVars {
|
|
if v.ColumnName != nil {
|
|
columns = append(columns, v.ColumnName)
|
|
}
|
|
}
|
|
x.Columns = columns
|
|
|
|
$$ = x
|
|
}
|
|
|
|
FormatOpt:
|
|
{
|
|
$$ = (*string)(nil)
|
|
}
|
|
| "FORMAT" stringLit
|
|
{
|
|
str := $2
|
|
$$ = &str
|
|
}
|
|
|
|
IgnoreLines:
|
|
{
|
|
$$ = (*uint64)(nil)
|
|
}
|
|
| "IGNORE" NUM "LINES"
|
|
{
|
|
v := getUint64FromNUM($2)
|
|
$$ = &v
|
|
}
|
|
|
|
CharsetOpt:
|
|
{
|
|
$$ = (*string)(nil)
|
|
}
|
|
| "CHARACTER" "SET" CharsetName
|
|
{
|
|
v := $3
|
|
$$ = &v
|
|
}
|
|
|
|
LocalOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "LOCAL"
|
|
{
|
|
$$ = $1
|
|
}
|
|
|
|
Fields:
|
|
{
|
|
$$ = (*ast.FieldsClause)(nil)
|
|
}
|
|
| FieldsOrColumns FieldItemList
|
|
{
|
|
fieldsClause := &ast.FieldsClause{}
|
|
fieldItems := $2.([]*ast.FieldItem)
|
|
for _, item := range fieldItems {
|
|
switch item.Type {
|
|
case ast.Terminated:
|
|
fieldsClause.Terminated = &item.Value
|
|
case ast.Enclosed:
|
|
fieldsClause.Enclosed = &item.Value
|
|
fieldsClause.OptEnclosed = item.OptEnclosed
|
|
case ast.Escaped:
|
|
fieldsClause.Escaped = &item.Value
|
|
case ast.DefinedNullBy:
|
|
fieldsClause.DefinedNullBy = &item.Value
|
|
fieldsClause.NullValueOptEnclosed = item.OptEnclosed
|
|
}
|
|
}
|
|
$$ = fieldsClause
|
|
}
|
|
|
|
FieldsOrColumns:
|
|
"FIELDS"
|
|
| "COLUMNS"
|
|
|
|
FieldItemList:
|
|
FieldItemList FieldItem
|
|
{
|
|
fieldItems := $1.([]*ast.FieldItem)
|
|
$$ = append(fieldItems, $2.(*ast.FieldItem))
|
|
}
|
|
| FieldItem
|
|
{
|
|
fieldItems := make([]*ast.FieldItem, 1, 1)
|
|
fieldItems[0] = $1.(*ast.FieldItem)
|
|
$$ = fieldItems
|
|
}
|
|
|
|
FieldItem:
|
|
"TERMINATED" "BY" FieldTerminator
|
|
{
|
|
$$ = &ast.FieldItem{
|
|
Type: ast.Terminated,
|
|
Value: $3,
|
|
}
|
|
}
|
|
| optionallyEnclosedBy FieldTerminator
|
|
{
|
|
str := $2
|
|
if str != "\\" && len(str) > 1 {
|
|
yylex.AppendError(ErrWrongFieldTerminators.GenWithStackByArgs())
|
|
return 1
|
|
}
|
|
$$ = &ast.FieldItem{
|
|
Type: ast.Enclosed,
|
|
Value: str,
|
|
OptEnclosed: true,
|
|
}
|
|
}
|
|
| "ENCLOSED" "BY" FieldTerminator
|
|
{
|
|
str := $3
|
|
if str != "\\" && len(str) > 1 {
|
|
yylex.AppendError(ErrWrongFieldTerminators.GenWithStackByArgs())
|
|
return 1
|
|
}
|
|
$$ = &ast.FieldItem{
|
|
Type: ast.Enclosed,
|
|
Value: str,
|
|
}
|
|
}
|
|
| "ESCAPED" "BY" FieldTerminator
|
|
{
|
|
str := $3
|
|
if str != "\\" && len(str) > 1 {
|
|
yylex.AppendError(ErrWrongFieldTerminators.GenWithStackByArgs())
|
|
return 1
|
|
}
|
|
$$ = &ast.FieldItem{
|
|
Type: ast.Escaped,
|
|
Value: str,
|
|
}
|
|
}
|
|
| "DEFINED" "NULL" "BY" TextString
|
|
{
|
|
$$ = &ast.FieldItem{
|
|
Type: ast.DefinedNullBy,
|
|
Value: $4.(*ast.TextString).Value,
|
|
}
|
|
}
|
|
| "DEFINED" "NULL" "BY" TextString "OPTIONALLY" "ENCLOSED"
|
|
{
|
|
$$ = &ast.FieldItem{
|
|
Type: ast.DefinedNullBy,
|
|
Value: $4.(*ast.TextString).Value,
|
|
OptEnclosed: true,
|
|
}
|
|
}
|
|
|
|
FieldTerminator:
|
|
stringLit
|
|
| hexLit
|
|
{
|
|
$$ = $1.(ast.BinaryLiteral).ToString()
|
|
}
|
|
| bitLit
|
|
{
|
|
$$ = $1.(ast.BinaryLiteral).ToString()
|
|
}
|
|
|
|
Lines:
|
|
{
|
|
$$ = (*ast.LinesClause)(nil)
|
|
}
|
|
| "LINES" Starting LinesTerminated
|
|
{
|
|
$$ = &ast.LinesClause{Starting: $2.(*string), Terminated: $3.(*string)}
|
|
}
|
|
|
|
Starting:
|
|
{
|
|
$$ = (*string)(nil)
|
|
}
|
|
| "STARTING" "BY" FieldTerminator
|
|
{
|
|
s := $3
|
|
$$ = &s
|
|
}
|
|
|
|
LinesTerminated:
|
|
{
|
|
$$ = (*string)(nil)
|
|
}
|
|
| "TERMINATED" "BY" FieldTerminator
|
|
{
|
|
s := $3
|
|
$$ = &s
|
|
}
|
|
|
|
LoadDataSetSpecOpt:
|
|
{
|
|
$$ = ([]*ast.Assignment)(nil)
|
|
}
|
|
| "SET" LoadDataSetList
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
LoadDataSetList:
|
|
LoadDataSetList ',' LoadDataSetItem
|
|
{
|
|
l := $1.([]*ast.Assignment)
|
|
$$ = append(l, $3.(*ast.Assignment))
|
|
}
|
|
| LoadDataSetItem
|
|
{
|
|
$$ = []*ast.Assignment{$1.(*ast.Assignment)}
|
|
}
|
|
|
|
LoadDataSetItem:
|
|
SimpleIdent "=" ExprOrDefault
|
|
{
|
|
$$ = &ast.Assignment{
|
|
Column: $1.(*ast.ColumnNameExpr).Name,
|
|
Expr: $3,
|
|
}
|
|
}
|
|
|
|
LoadDataOptionListOpt:
|
|
{
|
|
$$ = []*ast.LoadDataOpt{}
|
|
}
|
|
| "WITH" LoadDataOptionList
|
|
{
|
|
$$ = $2.([]*ast.LoadDataOpt)
|
|
}
|
|
|
|
LoadDataOptionList:
|
|
LoadDataOption
|
|
{
|
|
$$ = []*ast.LoadDataOpt{$1.(*ast.LoadDataOpt)}
|
|
}
|
|
| LoadDataOptionList ',' LoadDataOption
|
|
{
|
|
$$ = append($1.([]*ast.LoadDataOpt), $3.(*ast.LoadDataOpt))
|
|
}
|
|
|
|
LoadDataOption:
|
|
identifier
|
|
{
|
|
$$ = &ast.LoadDataOpt{Name: strings.ToLower($1)}
|
|
}
|
|
| identifier "=" SignedLiteral
|
|
{
|
|
$$ = &ast.LoadDataOpt{Name: strings.ToLower($1), Value: $3.(ast.ExprNode)}
|
|
}
|
|
|
|
ImportIntoStmt:
|
|
"IMPORT" "INTO" TableName ColumnNameOrUserVarListOptWithBrackets LoadDataSetSpecOpt "FROM" stringLit FormatOpt LoadDataOptionListOpt
|
|
{
|
|
$$ = &ast.ImportIntoStmt{
|
|
Table: $3.(*ast.TableName),
|
|
ColumnsAndUserVars: $4.([]*ast.ColumnNameOrUserVar),
|
|
ColumnAssignments: $5.([]*ast.Assignment),
|
|
Path: $7,
|
|
Format: $8.(*string),
|
|
Options: $9.([]*ast.LoadDataOpt),
|
|
}
|
|
}
|
|
|
|
/*********************************************************************
|
|
* Lock/Unlock Tables
|
|
* See http://dev.mysql.com/doc/refman/5.7/en/lock-tables.html
|
|
* All the statement leaves empty. This is used to prevent mysqldump error.
|
|
*********************************************************************/
|
|
UnlockTablesStmt:
|
|
"UNLOCK" TablesTerminalSym
|
|
{
|
|
$$ = &ast.UnlockTablesStmt{}
|
|
}
|
|
|
|
LockTablesStmt:
|
|
"LOCK" TablesTerminalSym TableLockList
|
|
{
|
|
$$ = &ast.LockTablesStmt{
|
|
TableLocks: $3.([]ast.TableLock),
|
|
}
|
|
}
|
|
|
|
TablesTerminalSym:
|
|
"TABLES"
|
|
| "TABLE"
|
|
|
|
TableLock:
|
|
TableName LockType
|
|
{
|
|
$$ = ast.TableLock{
|
|
Table: $1.(*ast.TableName),
|
|
Type: $2.(model.TableLockType),
|
|
}
|
|
}
|
|
|
|
LockType:
|
|
"READ"
|
|
{
|
|
$$ = model.TableLockRead
|
|
}
|
|
| "READ" "LOCAL"
|
|
{
|
|
$$ = model.TableLockReadLocal
|
|
}
|
|
| "WRITE"
|
|
{
|
|
$$ = model.TableLockWrite
|
|
}
|
|
| "WRITE" "LOCAL"
|
|
{
|
|
$$ = model.TableLockWriteLocal
|
|
}
|
|
|
|
TableLockList:
|
|
TableLock
|
|
{
|
|
$$ = []ast.TableLock{$1.(ast.TableLock)}
|
|
}
|
|
| TableLockList ',' TableLock
|
|
{
|
|
$$ = append($1.([]ast.TableLock), $3.(ast.TableLock))
|
|
}
|
|
|
|
/********************************************************************
|
|
* Non-transactional Delete Statement
|
|
* Split a SQL on a column. Used for bulk delete that doesn't need ACID.
|
|
*******************************************************************/
|
|
NonTransactionalDMLStmt:
|
|
"BATCH" OptionalShardColumn "LIMIT" NUM DryRunOptions ShardableStmt
|
|
{
|
|
$$ = &ast.NonTransactionalDMLStmt{
|
|
DryRun: $5.(int),
|
|
ShardColumn: $2.(*ast.ColumnName),
|
|
Limit: getUint64FromNUM($4),
|
|
DMLStmt: $6.(ast.ShardableDMLStmt),
|
|
}
|
|
}
|
|
|
|
ShardableStmt:
|
|
DeleteFromStmt
|
|
| UpdateStmt
|
|
| InsertIntoStmt
|
|
| ReplaceIntoStmt
|
|
|
|
DryRunOptions:
|
|
{
|
|
$$ = ast.NoDryRun
|
|
}
|
|
| "DRY" "RUN"
|
|
{
|
|
$$ = ast.DryRunSplitDml
|
|
}
|
|
| "DRY" "RUN" "QUERY"
|
|
{
|
|
$$ = ast.DryRunQuery
|
|
}
|
|
|
|
OptionalShardColumn:
|
|
{
|
|
$$ = (*ast.ColumnName)(nil)
|
|
}
|
|
| "ON" ColumnName
|
|
{
|
|
$$ = $2.(*ast.ColumnName)
|
|
}
|
|
|
|
/********************************************************************
|
|
* Kill Statement
|
|
* See https://dev.mysql.com/doc/refman/5.7/en/kill.html
|
|
*******************************************************************/
|
|
KillStmt:
|
|
KillOrKillTiDB NUM
|
|
{
|
|
$$ = &ast.KillStmt{
|
|
ConnectionID: getUint64FromNUM($2),
|
|
TiDBExtension: $1.(bool),
|
|
}
|
|
}
|
|
| KillOrKillTiDB "CONNECTION" NUM
|
|
{
|
|
$$ = &ast.KillStmt{
|
|
ConnectionID: getUint64FromNUM($3),
|
|
TiDBExtension: $1.(bool),
|
|
}
|
|
}
|
|
| KillOrKillTiDB "QUERY" NUM
|
|
{
|
|
$$ = &ast.KillStmt{
|
|
ConnectionID: getUint64FromNUM($3),
|
|
Query: true,
|
|
TiDBExtension: $1.(bool),
|
|
}
|
|
}
|
|
| KillOrKillTiDB BuiltinFunction
|
|
{
|
|
$$ = &ast.KillStmt{
|
|
TiDBExtension: $1.(bool),
|
|
Expr: $2,
|
|
}
|
|
}
|
|
|
|
KillOrKillTiDB:
|
|
"KILL"
|
|
{
|
|
$$ = false
|
|
}
|
|
/* KILL TIDB is a special grammar extension in TiDB, it can be used only when
|
|
the client connect to TiDB directly, not proxied under LVS. */
|
|
| "KILL" "TIDB"
|
|
{
|
|
$$ = true
|
|
}
|
|
|
|
LoadStatsStmt:
|
|
"LOAD" "STATS" stringLit
|
|
{
|
|
$$ = &ast.LoadStatsStmt{
|
|
Path: $3,
|
|
}
|
|
}
|
|
|
|
LockStatsStmt:
|
|
"LOCK" "STATS" TableNameList
|
|
{
|
|
$$ = &ast.LockStatsStmt{
|
|
Tables: $3.([]*ast.TableName),
|
|
}
|
|
}
|
|
|
|
UnlockStatsStmt:
|
|
"UNLOCK" "STATS" TableNameList
|
|
{
|
|
$$ = &ast.UnlockStatsStmt{
|
|
Tables: $3.([]*ast.TableName),
|
|
}
|
|
}
|
|
|
|
DropPolicyStmt:
|
|
"DROP" "PLACEMENT" "POLICY" IfExists PolicyName
|
|
{
|
|
$$ = &ast.DropPlacementPolicyStmt{
|
|
IfExists: $4.(bool),
|
|
PolicyName: model.NewCIStr($5),
|
|
}
|
|
}
|
|
|
|
CreateResourceGroupStmt:
|
|
"CREATE" "RESOURCE" "GROUP" IfNotExists ResourceGroupName ResourceGroupOptionList
|
|
{
|
|
$$ = &ast.CreateResourceGroupStmt{
|
|
IfNotExists: $4.(bool),
|
|
ResourceGroupName: model.NewCIStr($5),
|
|
ResourceGroupOptionList: $6.([]*ast.ResourceGroupOption),
|
|
}
|
|
}
|
|
|
|
AlterResourceGroupStmt:
|
|
"ALTER" "RESOURCE" "GROUP" IfExists ResourceGroupName ResourceGroupOptionList
|
|
{
|
|
$$ = &ast.AlterResourceGroupStmt{
|
|
IfExists: $4.(bool),
|
|
ResourceGroupName: model.NewCIStr($5),
|
|
ResourceGroupOptionList: $6.([]*ast.ResourceGroupOption),
|
|
}
|
|
}
|
|
|
|
DropResourceGroupStmt:
|
|
"DROP" "RESOURCE" "GROUP" IfExists ResourceGroupName
|
|
{
|
|
$$ = &ast.DropResourceGroupStmt{
|
|
IfExists: $4.(bool),
|
|
ResourceGroupName: model.NewCIStr($5),
|
|
}
|
|
}
|
|
|
|
CreatePolicyStmt:
|
|
"CREATE" OrReplace "PLACEMENT" "POLICY" IfNotExists PolicyName PlacementOptionList
|
|
{
|
|
$$ = &ast.CreatePlacementPolicyStmt{
|
|
OrReplace: $2.(bool),
|
|
IfNotExists: $5.(bool),
|
|
PolicyName: model.NewCIStr($6),
|
|
PlacementOptions: $7.([]*ast.PlacementOption),
|
|
}
|
|
}
|
|
|
|
AlterPolicyStmt:
|
|
"ALTER" "PLACEMENT" "POLICY" IfExists PolicyName PlacementOptionList
|
|
{
|
|
$$ = &ast.AlterPlacementPolicyStmt{
|
|
IfExists: $4.(bool),
|
|
PolicyName: model.NewCIStr($5),
|
|
PlacementOptions: $6.([]*ast.PlacementOption),
|
|
}
|
|
}
|
|
|
|
/********************************************************************************************
|
|
*
|
|
* Create Sequence Statement
|
|
*
|
|
* Example:
|
|
* CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name
|
|
* [ INCREMENT [ BY | = ] increment ]
|
|
* [ MINVALUE [=] minvalue | NO MINVALUE | NOMINVALUE ]
|
|
* [ MAXVALUE [=] maxvalue | NO MAXVALUE | NOMAXVALUE ]
|
|
* [ START [ WITH | = ] start ]
|
|
* [ CACHE [=] cache | NOCACHE | NO CACHE]
|
|
* [ CYCLE | NOCYCLE | NO CYCLE]
|
|
* [table_options]
|
|
********************************************************************************************/
|
|
CreateSequenceStmt:
|
|
"CREATE" "SEQUENCE" IfNotExists TableName CreateSequenceOptionListOpt CreateTableOptionListOpt
|
|
{
|
|
$$ = &ast.CreateSequenceStmt{
|
|
IfNotExists: $3.(bool),
|
|
Name: $4.(*ast.TableName),
|
|
SeqOptions: $5.([]*ast.SequenceOption),
|
|
TblOptions: $6.([]*ast.TableOption),
|
|
}
|
|
}
|
|
|
|
CreateSequenceOptionListOpt:
|
|
{
|
|
$$ = []*ast.SequenceOption{}
|
|
}
|
|
| SequenceOptionList
|
|
|
|
SequenceOptionList:
|
|
SequenceOption
|
|
{
|
|
$$ = []*ast.SequenceOption{$1.(*ast.SequenceOption)}
|
|
}
|
|
| SequenceOptionList SequenceOption
|
|
{
|
|
$$ = append($1.([]*ast.SequenceOption), $2.(*ast.SequenceOption))
|
|
}
|
|
|
|
SequenceOption:
|
|
"INCREMENT" EqOpt SignedNum
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceOptionIncrementBy, IntValue: $3.(int64)}
|
|
}
|
|
| "INCREMENT" "BY" SignedNum
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceOptionIncrementBy, IntValue: $3.(int64)}
|
|
}
|
|
| "START" EqOpt SignedNum
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceStartWith, IntValue: $3.(int64)}
|
|
}
|
|
| "START" "WITH" SignedNum
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceStartWith, IntValue: $3.(int64)}
|
|
}
|
|
| "MINVALUE" EqOpt SignedNum
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceMinValue, IntValue: $3.(int64)}
|
|
}
|
|
| "NOMINVALUE"
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceNoMinValue}
|
|
}
|
|
| "NO" "MINVALUE"
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceNoMinValue}
|
|
}
|
|
| "MAXVALUE" EqOpt SignedNum
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceMaxValue, IntValue: $3.(int64)}
|
|
}
|
|
| "NOMAXVALUE"
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceNoMaxValue}
|
|
}
|
|
| "NO" "MAXVALUE"
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceNoMaxValue}
|
|
}
|
|
| "CACHE" EqOpt SignedNum
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceCache, IntValue: $3.(int64)}
|
|
}
|
|
| "NOCACHE"
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceNoCache}
|
|
}
|
|
| "NO" "CACHE"
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceNoCache}
|
|
}
|
|
| "CYCLE"
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceCycle}
|
|
}
|
|
| "NOCYCLE"
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceNoCycle}
|
|
}
|
|
| "NO" "CYCLE"
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceNoCycle}
|
|
}
|
|
|
|
SignedNum:
|
|
Int64Num
|
|
| '+' Int64Num
|
|
{
|
|
$$ = $2
|
|
}
|
|
| '-' NUM
|
|
{
|
|
unsigned_num := getUint64FromNUM($2)
|
|
if unsigned_num > 9223372036854775808 {
|
|
yylex.AppendError(yylex.Errorf("the Signed Value should be at the range of [-9223372036854775808, 9223372036854775807]."))
|
|
return 1
|
|
} else if unsigned_num == 9223372036854775808 {
|
|
signed_one := int64(1)
|
|
$$ = signed_one << 63
|
|
} else {
|
|
$$ = -int64(unsigned_num)
|
|
}
|
|
}
|
|
|
|
DropSequenceStmt:
|
|
"DROP" "SEQUENCE" IfExists TableNameList
|
|
{
|
|
$$ = &ast.DropSequenceStmt{
|
|
IfExists: $3.(bool),
|
|
Sequences: $4.([]*ast.TableName),
|
|
}
|
|
}
|
|
|
|
/********************************************************************************************
|
|
*
|
|
* Alter Sequence Statement
|
|
*
|
|
* Example:
|
|
* ALTER SEQUENCE [IF EXISTS] sequence_name
|
|
* [ INCREMENT [ BY | = ] increment ]
|
|
* [ MINVALUE [=] minvalue | NO MINVALUE | NOMINVALUE ]
|
|
* [ MAXVALUE [=] maxvalue | NO MAXVALUE | NOMAXVALUE ]
|
|
* [ START [ WITH | = ] start ]
|
|
* [ CACHE [=] cache | NOCACHE | NO CACHE]
|
|
* [ CYCLE | NOCYCLE | NO CYCLE]
|
|
* [ RESTART [WITH | = ] restart ]
|
|
********************************************************************************************/
|
|
AlterSequenceStmt:
|
|
"ALTER" "SEQUENCE" IfExists TableName AlterSequenceOptionList
|
|
{
|
|
$$ = &ast.AlterSequenceStmt{
|
|
IfExists: $3.(bool),
|
|
Name: $4.(*ast.TableName),
|
|
SeqOptions: $5.([]*ast.SequenceOption),
|
|
}
|
|
}
|
|
|
|
AlterSequenceOptionList:
|
|
AlterSequenceOption
|
|
{
|
|
$$ = []*ast.SequenceOption{$1.(*ast.SequenceOption)}
|
|
}
|
|
| AlterSequenceOptionList AlterSequenceOption
|
|
{
|
|
$$ = append($1.([]*ast.SequenceOption), $2.(*ast.SequenceOption))
|
|
}
|
|
|
|
AlterSequenceOption:
|
|
SequenceOption
|
|
| "RESTART"
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceRestart}
|
|
}
|
|
| "RESTART" EqOpt SignedNum
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceRestartWith, IntValue: $3.(int64)}
|
|
}
|
|
| "RESTART" "WITH" SignedNum
|
|
{
|
|
$$ = &ast.SequenceOption{Tp: ast.SequenceRestartWith, IntValue: $3.(int64)}
|
|
}
|
|
|
|
/********************************************************************
|
|
* Index Advisor Statement
|
|
*
|
|
* INDEX ADVISE
|
|
* [LOCAL]
|
|
* INFILE 'file_name'
|
|
* [MAX_MINUTES number]
|
|
* [MAX_IDXNUM
|
|
* [PER_TABLE number]
|
|
* [PER_DB number]
|
|
* ]
|
|
* [LINES
|
|
* [STARTING BY 'string']
|
|
* [TERMINATED BY 'string']
|
|
* ]
|
|
*******************************************************************/
|
|
IndexAdviseStmt:
|
|
"INDEX" "ADVISE" LocalOpt "INFILE" stringLit MaxMinutesOpt MaxIndexNumOpt Lines
|
|
{
|
|
x := &ast.IndexAdviseStmt{
|
|
Path: $5,
|
|
MaxMinutes: $6.(uint64),
|
|
}
|
|
if $3 != nil {
|
|
x.IsLocal = true
|
|
}
|
|
if $7 != nil {
|
|
x.MaxIndexNum = $7.(*ast.MaxIndexNumClause)
|
|
}
|
|
if $8 != nil {
|
|
x.LinesInfo = $8.(*ast.LinesClause)
|
|
}
|
|
$$ = x
|
|
}
|
|
|
|
MaxMinutesOpt:
|
|
{
|
|
$$ = uint64(ast.UnspecifiedSize)
|
|
}
|
|
| "MAX_MINUTES" NUM
|
|
{
|
|
$$ = getUint64FromNUM($2)
|
|
}
|
|
|
|
MaxIndexNumOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "MAX_IDXNUM" PerTable PerDB
|
|
{
|
|
$$ = &ast.MaxIndexNumClause{
|
|
PerTable: $2.(uint64),
|
|
PerDB: $3.(uint64),
|
|
}
|
|
}
|
|
|
|
PerTable:
|
|
{
|
|
$$ = uint64(ast.UnspecifiedSize)
|
|
}
|
|
| "PER_TABLE" NUM
|
|
{
|
|
$$ = getUint64FromNUM($2)
|
|
}
|
|
|
|
PerDB:
|
|
{
|
|
$$ = uint64(ast.UnspecifiedSize)
|
|
}
|
|
| "PER_DB" NUM
|
|
{
|
|
$$ = getUint64FromNUM($2)
|
|
}
|
|
|
|
EncryptionOpt:
|
|
stringLit
|
|
{
|
|
// Parse it but will ignore it
|
|
switch $1 {
|
|
case "Y", "y":
|
|
yylex.AppendError(yylex.Errorf("The ENCRYPTION clause is parsed but ignored by all storage engines."))
|
|
parser.lastErrorAsWarn()
|
|
case "N", "n":
|
|
break
|
|
default:
|
|
yylex.AppendError(ErrWrongValue.GenWithStackByArgs("argument (should be Y or N)", $1))
|
|
return 1
|
|
}
|
|
$$ = $1
|
|
}
|
|
|
|
ValuesStmtList:
|
|
RowStmt
|
|
{
|
|
$$ = append([]*ast.RowExpr{}, $1.(*ast.RowExpr))
|
|
}
|
|
| ValuesStmtList ',' RowStmt
|
|
{
|
|
$$ = append($1.([]*ast.RowExpr), $3.(*ast.RowExpr))
|
|
}
|
|
|
|
RowStmt:
|
|
"ROW" RowValue
|
|
{
|
|
$$ = &ast.RowExpr{Values: $2.([]ast.ExprNode)}
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* Plan Replayer Statement
|
|
*
|
|
* PLAN REPLAYER
|
|
* [DUMP EXPLAIN
|
|
* [ANALYZE]
|
|
* {ExplainableStmt
|
|
* | [WHERE where_condition]
|
|
* [ORDER BY {col_name | expr | position}
|
|
* [ASC | DESC], ... [WITH ROLLUP]]
|
|
* [LIMIT {[offset,] row_count | row_count OFFSET offset}]}
|
|
* | 'file_name'
|
|
* | LOAD 'file_name'
|
|
* | CAPTURE `sql_digest` `plan_digest`]
|
|
*******************************************************************/
|
|
PlanReplayerStmt:
|
|
"PLAN" "REPLAYER" "DUMP" PlanReplayerDumpOpt "EXPLAIN" ExplainableStmt
|
|
{
|
|
x := &ast.PlanReplayerStmt{
|
|
Stmt: $6,
|
|
Analyze: false,
|
|
Load: false,
|
|
File: "",
|
|
Where: nil,
|
|
OrderBy: nil,
|
|
Limit: nil,
|
|
}
|
|
if $4 != nil {
|
|
x.HistoricalStatsInfo = $4.(*ast.AsOfClause)
|
|
}
|
|
startOffset := parser.startOffset(&yyS[yypt])
|
|
x.Stmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:]))
|
|
|
|
$$ = x
|
|
}
|
|
| "PLAN" "REPLAYER" "DUMP" PlanReplayerDumpOpt "EXPLAIN" "ANALYZE" ExplainableStmt
|
|
{
|
|
x := &ast.PlanReplayerStmt{
|
|
Stmt: $7,
|
|
Analyze: true,
|
|
Load: false,
|
|
File: "",
|
|
Where: nil,
|
|
OrderBy: nil,
|
|
Limit: nil,
|
|
}
|
|
if $4 != nil {
|
|
x.HistoricalStatsInfo = $4.(*ast.AsOfClause)
|
|
}
|
|
startOffset := parser.startOffset(&yyS[yypt])
|
|
x.Stmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:]))
|
|
|
|
$$ = x
|
|
}
|
|
| "PLAN" "REPLAYER" "DUMP" PlanReplayerDumpOpt "EXPLAIN" "SLOW" "QUERY" WhereClauseOptional OrderByOptional SelectStmtLimitOpt
|
|
{
|
|
x := &ast.PlanReplayerStmt{
|
|
Stmt: nil,
|
|
Analyze: false,
|
|
Load: false,
|
|
File: "",
|
|
}
|
|
if $4 != nil {
|
|
x.HistoricalStatsInfo = $4.(*ast.AsOfClause)
|
|
}
|
|
if $8 != nil {
|
|
x.Where = $8.(ast.ExprNode)
|
|
}
|
|
if $9 != nil {
|
|
x.OrderBy = $9.(*ast.OrderByClause)
|
|
}
|
|
if $10 != nil {
|
|
x.Limit = $10.(*ast.Limit)
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
| "PLAN" "REPLAYER" "DUMP" PlanReplayerDumpOpt "EXPLAIN" "ANALYZE" "SLOW" "QUERY" WhereClauseOptional OrderByOptional SelectStmtLimitOpt
|
|
{
|
|
x := &ast.PlanReplayerStmt{
|
|
Stmt: nil,
|
|
Analyze: true,
|
|
Load: false,
|
|
File: "",
|
|
}
|
|
if $4 != nil {
|
|
x.HistoricalStatsInfo = $4.(*ast.AsOfClause)
|
|
}
|
|
if $9 != nil {
|
|
x.Where = $9.(ast.ExprNode)
|
|
}
|
|
if $10 != nil {
|
|
x.OrderBy = $10.(*ast.OrderByClause)
|
|
}
|
|
if $11 != nil {
|
|
x.Limit = $11.(*ast.Limit)
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
| "PLAN" "REPLAYER" "DUMP" PlanReplayerDumpOpt "EXPLAIN" stringLit
|
|
{
|
|
x := &ast.PlanReplayerStmt{
|
|
Stmt: nil,
|
|
Analyze: false,
|
|
Load: false,
|
|
File: $6,
|
|
}
|
|
if $4 != nil {
|
|
x.HistoricalStatsInfo = $4.(*ast.AsOfClause)
|
|
}
|
|
$$ = x
|
|
}
|
|
| "PLAN" "REPLAYER" "DUMP" PlanReplayerDumpOpt "EXPLAIN" "ANALYZE" stringLit
|
|
{
|
|
x := &ast.PlanReplayerStmt{
|
|
Stmt: nil,
|
|
Analyze: true,
|
|
Load: false,
|
|
File: $7,
|
|
}
|
|
if $4 != nil {
|
|
x.HistoricalStatsInfo = $4.(*ast.AsOfClause)
|
|
}
|
|
$$ = x
|
|
}
|
|
| "PLAN" "REPLAYER" "LOAD" stringLit
|
|
{
|
|
x := &ast.PlanReplayerStmt{
|
|
Stmt: nil,
|
|
Analyze: false,
|
|
Load: true,
|
|
File: $4,
|
|
Where: nil,
|
|
OrderBy: nil,
|
|
Limit: nil,
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
| "PLAN" "REPLAYER" "CAPTURE" stringLit stringLit
|
|
{
|
|
x := &ast.PlanReplayerStmt{
|
|
Stmt: nil,
|
|
Analyze: false,
|
|
Capture: true,
|
|
SQLDigest: $4,
|
|
PlanDigest: $5,
|
|
Where: nil,
|
|
OrderBy: nil,
|
|
Limit: nil,
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
| "PLAN" "REPLAYER" "CAPTURE" "REMOVE" stringLit stringLit
|
|
{
|
|
x := &ast.PlanReplayerStmt{
|
|
Stmt: nil,
|
|
Analyze: false,
|
|
Remove: true,
|
|
SQLDigest: $5,
|
|
PlanDigest: $6,
|
|
Where: nil,
|
|
OrderBy: nil,
|
|
Limit: nil,
|
|
}
|
|
|
|
$$ = x
|
|
}
|
|
|
|
PlanReplayerDumpOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "WITH" "STATS" AsOfClause
|
|
{
|
|
$$ = $3.(*ast.AsOfClause)
|
|
}
|
|
|
|
/* Stored PROCEDURE parameter declaration list */
|
|
OptSpPdparams:
|
|
/* Empty */
|
|
{
|
|
$$ = []*ast.StoreParameter{}
|
|
}
|
|
| SpPdparams
|
|
{
|
|
$$ = $1
|
|
}
|
|
|
|
SpPdparams:
|
|
SpPdparams ',' SpPdparam
|
|
{
|
|
l := $1.([]*ast.StoreParameter)
|
|
l = append(l, $3.(*ast.StoreParameter))
|
|
$$ = l
|
|
}
|
|
| SpPdparam
|
|
{
|
|
$$ = []*ast.StoreParameter{$1.(*ast.StoreParameter)}
|
|
}
|
|
|
|
SpPdparam:
|
|
SpOptInout Identifier Type
|
|
{
|
|
x := &ast.StoreParameter{
|
|
Paramstatus: $1.(int),
|
|
ParamType: $3.(*types.FieldType),
|
|
ParamName: $2,
|
|
}
|
|
$$ = x
|
|
}
|
|
|
|
SpOptInout:
|
|
/* Empty */
|
|
{
|
|
$$ = ast.MODE_IN
|
|
}
|
|
| "IN"
|
|
{
|
|
$$ = ast.MODE_IN
|
|
}
|
|
| "OUT"
|
|
{
|
|
$$ = ast.MODE_OUT
|
|
}
|
|
| "INOUT"
|
|
{
|
|
$$ = ast.MODE_INOUT
|
|
}
|
|
|
|
ProcedureStatementStmt:
|
|
SelectStmt
|
|
| SelectStmtWithClause
|
|
| SubSelect
|
|
{
|
|
var sel ast.StmtNode
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
case *ast.SetOprStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
}
|
|
$$ = sel
|
|
}
|
|
| SetStmt
|
|
| UpdateStmt
|
|
| UseStmt
|
|
| InsertIntoStmt
|
|
| ReplaceIntoStmt
|
|
| CommitStmt
|
|
| RollbackStmt
|
|
| ExplainStmt
|
|
| SetOprStmt
|
|
| DeleteFromStmt
|
|
| AnalyzeTableStmt
|
|
| TruncateTableStmt
|
|
|
|
ProcedureCursorSelectStmt:
|
|
SelectStmt
|
|
| SelectStmtWithClause
|
|
| SubSelect
|
|
{
|
|
var sel ast.StmtNode
|
|
switch x := $1.(*ast.SubqueryExpr).Query.(type) {
|
|
case *ast.SelectStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
case *ast.SetOprStmt:
|
|
x.IsInBraces = true
|
|
sel = x
|
|
}
|
|
$$ = sel
|
|
}
|
|
| SetOprStmt
|
|
|
|
ProcedureUnlabeledBlock:
|
|
ProcedureBlockContent
|
|
{
|
|
$$ = $1
|
|
}
|
|
|
|
ProcedureDeclIdents:
|
|
Identifier
|
|
{
|
|
$$ = []string{strings.ToLower($1)}
|
|
}
|
|
| ProcedureDeclIdents ',' Identifier
|
|
{
|
|
l := $1.([]string)
|
|
l = append(l, strings.ToLower($3))
|
|
$$ = l
|
|
}
|
|
|
|
ProcedureOptDefault:
|
|
/* Empty */
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "DEFAULT" Expression
|
|
{
|
|
$$ = $2
|
|
}
|
|
|
|
ProcedureDecl:
|
|
"DECLARE" ProcedureDeclIdents Type ProcedureOptDefault
|
|
{
|
|
x := &ast.ProcedureDecl{
|
|
DeclNames: $2.([]string),
|
|
DeclType: $3.(*types.FieldType),
|
|
}
|
|
if $4 != nil {
|
|
x.DeclDefault = $4.(ast.ExprNode)
|
|
}
|
|
$$ = x
|
|
}
|
|
| "DECLARE" identifier "CURSOR" "FOR" ProcedureCursorSelectStmt
|
|
{
|
|
name := strings.ToLower($2)
|
|
$$ = &ast.ProcedureCursor{
|
|
CurName: name,
|
|
Selectstring: $5.(ast.StmtNode),
|
|
}
|
|
}
|
|
| "DECLARE" ProcedureHandlerType "HANDLER" "FOR" ProcedureHcondList ProcedureProcStmt
|
|
{
|
|
$$ = &ast.ProcedureErrorControl{
|
|
ControlHandle: $2.(int),
|
|
ErrorCon: $5.([]ast.ErrNode),
|
|
Operate: $6.(ast.StmtNode),
|
|
}
|
|
}
|
|
|
|
ProcedureHandlerType:
|
|
"CONTINUE"
|
|
{
|
|
$$ = ast.PROCEDUR_CONTINUE
|
|
}
|
|
| "EXIT"
|
|
{
|
|
$$ = ast.PROCEDUR_EXIT
|
|
}
|
|
|
|
ProcedureHcondList:
|
|
ProcedureHcond
|
|
{
|
|
$$ = []ast.ErrNode{$1.(ast.ErrNode)}
|
|
}
|
|
| ProcedureHcondList ',' ProcedureHcond
|
|
{
|
|
l := $1.([]ast.ErrNode)
|
|
l = append(l, $3.(ast.ErrNode))
|
|
$$ = l
|
|
}
|
|
|
|
ProcedureHcond:
|
|
ProcedurceCond
|
|
{
|
|
$$ = $1.(ast.ErrNode)
|
|
}
|
|
| "SQLWARNING"
|
|
/* SQLSTATEs 01??? */
|
|
{
|
|
$$ = &ast.ProcedureErrorCon{
|
|
ErrorCon: ast.PROCEDUR_SQLWARNING,
|
|
}
|
|
}
|
|
| "NOT" "FOUND"
|
|
/* SQLSTATEs 02??? */
|
|
{
|
|
$$ = &ast.ProcedureErrorCon{
|
|
ErrorCon: ast.PROCEDUR_NOT_FOUND,
|
|
}
|
|
}
|
|
| "SQLEXCEPTION"
|
|
/* All other SQLSTATEs */
|
|
{
|
|
$$ = &ast.ProcedureErrorCon{
|
|
ErrorCon: ast.PROCEDUR_SQLEXCEPTION,
|
|
}
|
|
}
|
|
|
|
ProcedurceCond:
|
|
NUM
|
|
{
|
|
$$ = &ast.ProcedureErrorVal{
|
|
ErrorNum: getUint64FromNUM($1),
|
|
}
|
|
}
|
|
| "SQLSTATE" optValue stringLit
|
|
{
|
|
$$ = &ast.ProcedureErrorState{
|
|
CodeStatus: $3,
|
|
}
|
|
}
|
|
|
|
optValue:
|
|
{}
|
|
| "VALUE"
|
|
|
|
ProcedureOpenCur:
|
|
"OPEN" identifier
|
|
{
|
|
name := strings.ToLower($2)
|
|
$$ = &ast.ProcedureOpenCur{
|
|
CurName: name,
|
|
}
|
|
}
|
|
|
|
ProcedureFetchInto:
|
|
"FETCH" ProcedureOptFetchNo identifier "INTO" ProcedureFetchList
|
|
{
|
|
name := strings.ToLower($3)
|
|
$$ = &ast.ProcedureFetchInto{
|
|
CurName: name,
|
|
Variables: $5.([]string),
|
|
}
|
|
}
|
|
|
|
ProcedureCloseCur:
|
|
"CLOSE" identifier
|
|
{
|
|
name := strings.ToLower($2)
|
|
$$ = &ast.ProcedureCloseCur{
|
|
CurName: name,
|
|
}
|
|
}
|
|
|
|
ProcedureOptFetchNo:
|
|
|
|
/* Empty */
|
|
| "NEXT" "FROM"
|
|
| "FROM"
|
|
|
|
ProcedureFetchList:
|
|
identifier
|
|
{
|
|
$$ = []string{strings.ToLower($1)}
|
|
}
|
|
| ProcedureFetchList ',' identifier
|
|
{
|
|
l := $1.([]string)
|
|
l = append(l, strings.ToLower($3))
|
|
$$ = l
|
|
}
|
|
|
|
ProcedureDeclsOpt:
|
|
/* Empty */
|
|
{
|
|
$$ = []ast.DeclNode{}
|
|
}
|
|
| ProcedureDecls
|
|
{
|
|
$$ = $1
|
|
}
|
|
|
|
ProcedureDecls:
|
|
ProcedureDecl ';'
|
|
{
|
|
$$ = []ast.DeclNode{$1.(ast.DeclNode)}
|
|
}
|
|
| ProcedureDecls ProcedureDecl ';'
|
|
{
|
|
l := $1.([]ast.DeclNode)
|
|
l = append(l, $2.(ast.DeclNode))
|
|
$$ = l
|
|
}
|
|
|
|
ProcedureProcStmts:
|
|
/* Empty */
|
|
{
|
|
$$ = []ast.StmtNode{}
|
|
}
|
|
| ProcedureProcStmts ProcedureProcStmt ';'
|
|
{
|
|
l := $1.([]ast.StmtNode)
|
|
l = append(l, $2.(ast.StmtNode))
|
|
$$ = l
|
|
}
|
|
|
|
ProcedureProcStmt1s:
|
|
ProcedureProcStmt ';'
|
|
{
|
|
$$ = []ast.StmtNode{$1.(ast.StmtNode)}
|
|
}
|
|
| ProcedureProcStmt1s ProcedureProcStmt ';'
|
|
{
|
|
l := $1.([]ast.StmtNode)
|
|
l = append(l, $2.(ast.StmtNode))
|
|
$$ = l
|
|
}
|
|
|
|
ProcedureBlockContent:
|
|
"BEGIN" ProcedureDeclsOpt ProcedureProcStmts "END"
|
|
{
|
|
x := &ast.ProcedureBlock{
|
|
ProcedureVars: $2.([]ast.DeclNode),
|
|
ProcedureProcStmts: $3.([]ast.StmtNode),
|
|
}
|
|
$$ = x
|
|
}
|
|
|
|
ProcedureIfstmt:
|
|
"IF" ProcedureIf "END" "IF"
|
|
{
|
|
$$ = &ast.ProcedureIfInfo{
|
|
IfBody: $2.(*ast.ProcedureIfBlock),
|
|
}
|
|
}
|
|
|
|
ProcedureIf:
|
|
Expression "THEN" ProcedureProcStmt1s procedurceElseIfs
|
|
{
|
|
ifBlock := &ast.ProcedureIfBlock{
|
|
IfExpr: $1.(ast.ExprNode),
|
|
ProcedureIfStmts: $3.([]ast.StmtNode),
|
|
}
|
|
if $4 != nil {
|
|
ifBlock.ProcedureElseStmt = $4.(ast.StmtNode)
|
|
}
|
|
$$ = ifBlock
|
|
}
|
|
|
|
procedurceElseIfs:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "ELSEIF" ProcedureIf
|
|
{
|
|
$$ = &ast.ProcedureElseIfBlock{
|
|
ProcedureIfStmt: $2.(*ast.ProcedureIfBlock),
|
|
}
|
|
}
|
|
| "ELSE" ProcedureProcStmt1s
|
|
{
|
|
$$ = &ast.ProcedureElseBlock{
|
|
ProcedureIfStmts: $2.([]ast.StmtNode),
|
|
}
|
|
}
|
|
|
|
ProcedureCaseStmt:
|
|
ProcedureSimpleCase
|
|
{
|
|
$$ = $1
|
|
}
|
|
| ProcedureSearchedCase
|
|
{
|
|
$$ = $1
|
|
}
|
|
|
|
SimpleWhenThenList:
|
|
SimpleWhenThen
|
|
{
|
|
$$ = []*ast.SimpleWhenThenStmt{$1.(*ast.SimpleWhenThenStmt)}
|
|
}
|
|
| SimpleWhenThenList SimpleWhenThen
|
|
{
|
|
l := $1.([]*ast.SimpleWhenThenStmt)
|
|
l = append(l, $2.(*ast.SimpleWhenThenStmt))
|
|
$$ = l
|
|
}
|
|
|
|
SearchedWhenThenList:
|
|
SearchWhenThen
|
|
{
|
|
$$ = []*ast.SearchWhenThenStmt{$1.(*ast.SearchWhenThenStmt)}
|
|
}
|
|
| SearchedWhenThenList SearchWhenThen
|
|
{
|
|
l := $1.([]*ast.SearchWhenThenStmt)
|
|
l = append(l, $2.(*ast.SearchWhenThenStmt))
|
|
$$ = l
|
|
}
|
|
|
|
SimpleWhenThen:
|
|
"WHEN" Expression "THEN" ProcedureProcStmt1s
|
|
{
|
|
$$ = &ast.SimpleWhenThenStmt{
|
|
Expr: $2.(ast.ExprNode),
|
|
ProcedureStmts: $4.([]ast.StmtNode),
|
|
}
|
|
}
|
|
|
|
SearchWhenThen:
|
|
"WHEN" Expression "THEN" ProcedureProcStmt1s
|
|
{
|
|
$$ = &ast.SearchWhenThenStmt{
|
|
Expr: $2.(ast.ExprNode),
|
|
ProcedureStmts: $4.([]ast.StmtNode),
|
|
}
|
|
}
|
|
|
|
ElseCaseOpt:
|
|
{
|
|
$$ = nil
|
|
}
|
|
| "ELSE" ProcedureProcStmt1s
|
|
{
|
|
$$ = $2.([]ast.StmtNode)
|
|
}
|
|
|
|
ProcedureSimpleCase:
|
|
"CASE" Expression SimpleWhenThenList ElseCaseOpt "END" "CASE"
|
|
{
|
|
caseStmt := &ast.SimpleCaseStmt{
|
|
Condition: $2.(ast.ExprNode),
|
|
WhenCases: $3.([]*ast.SimpleWhenThenStmt),
|
|
}
|
|
if $4 != nil {
|
|
caseStmt.ElseCases = $4.([]ast.StmtNode)
|
|
}
|
|
$$ = caseStmt
|
|
}
|
|
|
|
ProcedureSearchedCase:
|
|
"CASE" SearchedWhenThenList ElseCaseOpt "END" "CASE"
|
|
{
|
|
caseStmt := &ast.SearchCaseStmt{
|
|
WhenCases: $2.([]*ast.SearchWhenThenStmt),
|
|
}
|
|
if $3 != nil {
|
|
caseStmt.ElseCases = $3.([]ast.StmtNode)
|
|
}
|
|
$$ = caseStmt
|
|
}
|
|
|
|
ProcedureUnlabelLoopBlock:
|
|
ProcedureUnlabelLoopStmt
|
|
{
|
|
$$ = $1
|
|
}
|
|
|
|
ProcedureUnlabelLoopStmt:
|
|
"WHILE" Expression "DO" ProcedureProcStmt1s "END" "WHILE"
|
|
{
|
|
$$ = &ast.ProcedureWhileStmt{
|
|
Condition: $2.(ast.ExprNode),
|
|
Body: $4.([]ast.StmtNode),
|
|
}
|
|
}
|
|
| "REPEAT" ProcedureProcStmt1s "UNTIL" Expression "END" "REPEAT"
|
|
{
|
|
$$ = &ast.ProcedureRepeatStmt{
|
|
Body: $2.([]ast.StmtNode),
|
|
Condition: $4.(ast.ExprNode),
|
|
}
|
|
}
|
|
|
|
ProcedureLabeledBlock:
|
|
identifier ':' ProcedureBlockContent ProcedurceLabelOpt
|
|
{
|
|
labelBlock := &ast.ProcedureLabelBlock{
|
|
LabelName: $1,
|
|
Block: $3.(*ast.ProcedureBlock),
|
|
}
|
|
if $4 != "" && ($1 != $4) {
|
|
labelBlock.LabelError = true
|
|
labelBlock.LabelEnd = $4
|
|
}
|
|
$$ = labelBlock
|
|
}
|
|
|
|
ProcedurceLabelOpt:
|
|
/* Empty */
|
|
{
|
|
$$ = ""
|
|
}
|
|
| identifier
|
|
{
|
|
$$ = $1
|
|
}
|
|
|
|
ProcedurelabeledLoopStmt:
|
|
identifier ':' ProcedureUnlabelLoopStmt ProcedurceLabelOpt
|
|
{
|
|
labelLoop := &ast.ProcedureLabelLoop{
|
|
LabelName: $1,
|
|
Block: $3.(ast.StmtNode),
|
|
}
|
|
if $4 != "" && ($1 != $4) {
|
|
labelLoop.LabelError = true
|
|
labelLoop.LabelEnd = $4
|
|
}
|
|
$$ = labelLoop
|
|
}
|
|
|
|
ProcedureIterate:
|
|
"ITERATE" identifier
|
|
{
|
|
$$ = &ast.ProcedureJump{
|
|
Name: $2,
|
|
IsLeave: false,
|
|
}
|
|
}
|
|
|
|
ProcedureLeave:
|
|
"LEAVE" identifier
|
|
{
|
|
$$ = &ast.ProcedureJump{
|
|
Name: $2,
|
|
IsLeave: true,
|
|
}
|
|
}
|
|
|
|
ProcedureProcStmt:
|
|
ProcedureStatementStmt
|
|
| ProcedureUnlabeledBlock
|
|
| ProcedureIfstmt
|
|
| ProcedureCaseStmt
|
|
| ProcedureUnlabelLoopBlock
|
|
| ProcedureOpenCur
|
|
| ProcedureCloseCur
|
|
| ProcedureFetchInto
|
|
| ProcedureLabeledBlock
|
|
| ProcedurelabeledLoopStmt
|
|
| ProcedureIterate
|
|
| ProcedureLeave
|
|
|
|
/********************************************************************************************
|
|
*
|
|
* Create Procedure Statement
|
|
*
|
|
* Example:
|
|
* CREATE
|
|
* [DEFINER = user]
|
|
* PROCEDURE [IF NOT EXISTS] sp_name ([proc_parameter[,...]])
|
|
* routine_body
|
|
* proc_parameter:
|
|
* [ IN | OUT | INOUT ] param_name type
|
|
* func_parameter:
|
|
* param_name type
|
|
* type:
|
|
* Any valid MySQL data type
|
|
* routine_body:
|
|
* Valid SQL routine statement
|
|
********************************************************************************************/
|
|
CreateProcedureStmt:
|
|
"CREATE" "PROCEDURE" IfNotExists TableName '(' OptSpPdparams ')' ProcedureProcStmt
|
|
{
|
|
x := &ast.ProcedureInfo{
|
|
IfNotExists: $3.(bool),
|
|
ProcedureName: $4.(*ast.TableName),
|
|
ProcedureParam: $6.([]*ast.StoreParameter),
|
|
ProcedureBody: $8,
|
|
}
|
|
startOffset := parser.startOffset(&yyS[yypt])
|
|
originStmt := $8
|
|
originStmt.SetText(parser.lexer.client, strings.TrimSpace(parser.src[startOffset:parser.yylval.offset]))
|
|
startOffset = parser.startOffset(&yyS[yypt-3])
|
|
if parser.src[startOffset] == '(' {
|
|
startOffset++
|
|
}
|
|
endOffset := parser.startOffset(&yyS[yypt-1])
|
|
x.ProcedureParamStr = strings.TrimSpace(parser.src[startOffset:endOffset])
|
|
$$ = x
|
|
}
|
|
|
|
/********************************************************************************************
|
|
* DROP PROCEDURE [IF EXISTS] sp_name
|
|
********************************************************************************************/
|
|
DropProcedureStmt:
|
|
"DROP" "PROCEDURE" IfExists TableName
|
|
{
|
|
$$ = &ast.DropProcedureStmt{
|
|
IfExists: $3.(bool),
|
|
ProcedureName: $4.(*ast.TableName),
|
|
}
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* Calibrate Resource Statement
|
|
*
|
|
* CALIBRATE RESOURCE
|
|
*******************************************************************/
|
|
CalibrateResourceStmt:
|
|
"CALIBRATE" "RESOURCE" CalibrateOption
|
|
{
|
|
$$ = $3.(*ast.CalibrateResourceStmt)
|
|
}
|
|
|
|
CalibrateOption:
|
|
{
|
|
$$ = &ast.CalibrateResourceStmt{}
|
|
}
|
|
| DynamicCalibrateOptionList
|
|
{
|
|
$$ = &ast.CalibrateResourceStmt{
|
|
DynamicCalibrateResourceOptionList: $1.([]*ast.DynamicCalibrateResourceOption),
|
|
}
|
|
}
|
|
| CalibrateResourceWorkloadOption
|
|
{
|
|
$$ = &ast.CalibrateResourceStmt{
|
|
Tp: $1.(ast.CalibrateResourceType),
|
|
}
|
|
}
|
|
|
|
DynamicCalibrateOptionList:
|
|
DynamicCalibrateResourceOption
|
|
{
|
|
$$ = []*ast.DynamicCalibrateResourceOption{$1.(*ast.DynamicCalibrateResourceOption)}
|
|
}
|
|
| DynamicCalibrateOptionList DynamicCalibrateResourceOption
|
|
{
|
|
if $1.([]*ast.DynamicCalibrateResourceOption)[0].Tp == $2.(*ast.DynamicCalibrateResourceOption).Tp ||
|
|
(len($1.([]*ast.DynamicCalibrateResourceOption)) > 1 && $1.([]*ast.DynamicCalibrateResourceOption)[1].Tp == $2.(*ast.DynamicCalibrateResourceOption).Tp) {
|
|
yylex.AppendError(yylex.Errorf("Dupliated options specified"))
|
|
return 1
|
|
}
|
|
$$ = append($1.([]*ast.DynamicCalibrateResourceOption), $2.(*ast.DynamicCalibrateResourceOption))
|
|
}
|
|
| DynamicCalibrateOptionList ',' DynamicCalibrateResourceOption
|
|
{
|
|
if $1.([]*ast.DynamicCalibrateResourceOption)[0].Tp == $3.(*ast.DynamicCalibrateResourceOption).Tp ||
|
|
(len($1.([]*ast.DynamicCalibrateResourceOption)) > 1 && $1.([]*ast.DynamicCalibrateResourceOption)[1].Tp == $3.(*ast.DynamicCalibrateResourceOption).Tp) {
|
|
yylex.AppendError(yylex.Errorf("Dupliated options specified"))
|
|
return 1
|
|
}
|
|
$$ = append($1.([]*ast.DynamicCalibrateResourceOption), $3.(*ast.DynamicCalibrateResourceOption))
|
|
}
|
|
|
|
DynamicCalibrateResourceOption:
|
|
"START_TIME" EqOpt Expression
|
|
{
|
|
$$ = &ast.DynamicCalibrateResourceOption{Tp: ast.CalibrateStartTime, Ts: $3.(ast.ExprNode)}
|
|
}
|
|
| "END_TIME" EqOpt Expression
|
|
{
|
|
$$ = &ast.DynamicCalibrateResourceOption{Tp: ast.CalibrateEndTime, Ts: $3.(ast.ExprNode)}
|
|
}
|
|
| "DURATION" EqOpt stringLit
|
|
{
|
|
_, err := duration.ParseDuration($3)
|
|
if err != nil {
|
|
yylex.AppendError(yylex.Errorf("The DURATION option is not a valid duration: %s", err.Error()))
|
|
return 1
|
|
}
|
|
$$ = &ast.DynamicCalibrateResourceOption{Tp: ast.CalibrateDuration, StrValue: $3}
|
|
}
|
|
| "DURATION" EqOpt "INTERVAL" Expression TimeUnit
|
|
{
|
|
$$ = &ast.DynamicCalibrateResourceOption{Tp: ast.CalibrateDuration, Ts: $4.(ast.ExprNode), Unit: $5.(ast.TimeUnitType)}
|
|
}
|
|
|
|
CalibrateResourceWorkloadOption:
|
|
"WORKLOAD" "TPCC"
|
|
{
|
|
$$ = ast.TPCC
|
|
}
|
|
| "WORKLOAD" "OLTP_READ_WRITE"
|
|
{
|
|
$$ = ast.OLTPREADWRITE
|
|
}
|
|
| "WORKLOAD" "OLTP_READ_ONLY"
|
|
{
|
|
$$ = ast.OLTPREADONLY
|
|
}
|
|
| "WORKLOAD" "OLTP_WRITE_ONLY"
|
|
{
|
|
$$ = ast.OLTPWRITEONLY
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* Query Watch Statement
|
|
*
|
|
* Query Watch
|
|
*******************************************************************/
|
|
AddQueryWatchStmt:
|
|
"QUERY" "WATCH" "ADD" QueryWatchOptionList
|
|
{
|
|
$$ = &ast.AddQueryWatchStmt{
|
|
QueryWatchOptionList: $4.([]*ast.QueryWatchOption),
|
|
}
|
|
}
|
|
|
|
QueryWatchOptionList:
|
|
QueryWatchOption
|
|
{
|
|
$$ = []*ast.QueryWatchOption{$1.(*ast.QueryWatchOption)}
|
|
}
|
|
| QueryWatchOptionList QueryWatchOption
|
|
{
|
|
if !ast.CheckQueryWatchAppend($1.([]*ast.QueryWatchOption), $2.(*ast.QueryWatchOption)) {
|
|
yylex.AppendError(yylex.Errorf("Dupliated options specified"))
|
|
return 1
|
|
}
|
|
$$ = append($1.([]*ast.QueryWatchOption), $2.(*ast.QueryWatchOption))
|
|
}
|
|
| QueryWatchOptionList ',' QueryWatchOption
|
|
{
|
|
if !ast.CheckQueryWatchAppend($1.([]*ast.QueryWatchOption), $3.(*ast.QueryWatchOption)) {
|
|
yylex.AppendError(yylex.Errorf("Dupliated options specified"))
|
|
return 1
|
|
}
|
|
$$ = append($1.([]*ast.QueryWatchOption), $3.(*ast.QueryWatchOption))
|
|
}
|
|
|
|
QueryWatchOption:
|
|
"RESOURCE" "GROUP" ResourceGroupName
|
|
{
|
|
$$ = &ast.QueryWatchOption{Tp: ast.QueryWatchResourceGroup, StrValue: model.NewCIStr($3)}
|
|
}
|
|
| "RESOURCE" "GROUP" UserVariable
|
|
{
|
|
$$ = &ast.QueryWatchOption{Tp: ast.QueryWatchResourceGroup, ExprValue: $3}
|
|
}
|
|
| "ACTION" EqOpt ResourceGroupRunawayActionOption
|
|
{
|
|
$$ = &ast.QueryWatchOption{Tp: ast.QueryWatchAction, IntValue: $3.(int32)}
|
|
}
|
|
| QueryWatchTextOption
|
|
{
|
|
$$ = $1.(*ast.QueryWatchOption)
|
|
}
|
|
|
|
QueryWatchTextOption:
|
|
"SQL" "DIGEST" SimpleExpr
|
|
{
|
|
$$ = &ast.QueryWatchOption{Tp: ast.QueryWatchType, IntValue: int32(model.WatchSimilar), ExprValue: $3}
|
|
}
|
|
| "PLAN" "DIGEST" SimpleExpr
|
|
{
|
|
$$ = &ast.QueryWatchOption{Tp: ast.QueryWatchType, IntValue: int32(model.WatchPlan), ExprValue: $3}
|
|
}
|
|
| "SQL" "TEXT" ResourceGroupRunawayWatchOption "TO" SimpleExpr
|
|
{
|
|
$$ = &ast.QueryWatchOption{Tp: ast.QueryWatchType, IntValue: $3.(int32), ExprValue: $5, BoolValue: true}
|
|
}
|
|
|
|
DropQueryWatchStmt:
|
|
"QUERY" "WATCH" "REMOVE" NUM
|
|
{
|
|
$$ = &ast.DropQueryWatchStmt{
|
|
IntValue: $4.(int64),
|
|
}
|
|
}
|
|
%%
|