Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1259 lines
29 KiB
1259 lines
29 KiB
%{ |
|
// 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. |
|
|
|
package parser |
|
|
|
import ( |
|
"fmt" |
|
"math" |
|
"strconv" |
|
"strings" |
|
"unicode" |
|
|
|
"github.com/pingcap/tidb/ast" |
|
"github.com/pingcap/tidb/mysql" |
|
"github.com/pingcap/tidb/util/charset" |
|
"github.com/pingcap/tidb/util/stringutil" |
|
) |
|
|
|
type lexer struct { |
|
c int |
|
col int |
|
errs []error |
|
expr ast.ExprNode |
|
i int |
|
inj int |
|
lcol int |
|
line int |
|
list []ast.StmtNode |
|
ncol int |
|
nline int |
|
sc int |
|
src string |
|
val []byte |
|
ungetBuf []byte |
|
root bool |
|
prepare bool |
|
stmtStartPos int |
|
stringLit []byte |
|
|
|
// record token's offset of the input |
|
tokenEndOffset int |
|
tokenStartOffset int |
|
|
|
// Charset information |
|
charset string |
|
collation string |
|
} |
|
|
|
|
|
// NewLexer builds a new lexer. |
|
func NewLexer(src string) (l *lexer) { |
|
l = &lexer{ |
|
src: src, |
|
nline: 1, |
|
ncol: 0, |
|
} |
|
l.next() |
|
return |
|
} |
|
|
|
func (l *lexer) Errors() []error { |
|
return l.errs |
|
} |
|
|
|
func (l *lexer) Stmts() []ast.StmtNode { |
|
return l.list |
|
} |
|
|
|
func (l *lexer) Expr() ast.ExprNode { |
|
return l.expr |
|
} |
|
|
|
func (l *lexer) Inj() int { |
|
return l.inj |
|
} |
|
|
|
func (l *lexer) SetInj(inj int) { |
|
l.inj = inj |
|
} |
|
|
|
func (l *lexer) SetPrepare() { |
|
l.prepare = true |
|
} |
|
|
|
func (l *lexer) IsPrepare() bool { |
|
return l.prepare |
|
} |
|
|
|
func (l *lexer) Root() bool { |
|
return l.root |
|
} |
|
|
|
func (l *lexer) SetRoot(root bool) { |
|
l.root = root |
|
} |
|
|
|
func (l *lexer) SetCharsetInfo(charset, collation string) { |
|
l.charset = charset |
|
l.collation = collation |
|
} |
|
|
|
func (l *lexer) GetCharsetInfo() (string, string) { |
|
return l.charset, l.collation |
|
} |
|
|
|
// The select statement is not at the end of the whole statement, if the last |
|
// field text was set from its offset to the end of the src string, update |
|
// the last field text. |
|
func (l *lexer) SetLastSelectFieldText(st *ast.SelectStmt, lastEnd int) { |
|
lastField := st.Fields.Fields[len(st.Fields.Fields)-1] |
|
if lastField.Offset + len(lastField.Text()) >= len(l.src)-1 { |
|
lastField.SetText(l.src[lastField.Offset:lastEnd]) |
|
} |
|
} |
|
|
|
func (l *lexer) startOffset(offset int) int { |
|
offset-- |
|
for unicode.IsSpace(rune(l.src[offset])) { |
|
offset++ |
|
} |
|
return offset |
|
} |
|
|
|
func (l *lexer) endOffset(offset int) int { |
|
offset-- |
|
for offset > 0 && unicode.IsSpace(rune(l.src[offset-1])) { |
|
offset-- |
|
} |
|
return offset |
|
} |
|
|
|
func (l *lexer) unget(b byte) { |
|
l.ungetBuf = append(l.ungetBuf, b) |
|
l.i-- |
|
l.ncol-- |
|
l.tokenEndOffset-- |
|
} |
|
|
|
func (l *lexer) next() int { |
|
if un := len(l.ungetBuf); un > 0 { |
|
nc := l.ungetBuf[0] |
|
l.ungetBuf = l.ungetBuf[1:] |
|
l.c = int(nc) |
|
return l.c |
|
} |
|
|
|
if l.c != 0 { |
|
l.val = append(l.val, byte(l.c)) |
|
} |
|
l.c = 0 |
|
if l.i < len(l.src) { |
|
l.c = int(l.src[l.i]) |
|
l.i++ |
|
} |
|
switch l.c { |
|
case '\n': |
|
l.lcol = l.ncol |
|
l.nline++ |
|
l.ncol = 0 |
|
default: |
|
l.ncol++ |
|
} |
|
l.tokenEndOffset++ |
|
return l.c |
|
} |
|
|
|
func (l *lexer) err0(ln, c int, arg interface{}) { |
|
var argStr string |
|
if arg != nil { |
|
argStr = fmt.Sprintf(" %v", arg) |
|
} |
|
|
|
err := fmt.Errorf("line %d column %d near \"%s\"%s", ln, c, l.val, argStr) |
|
l.errs = append(l.errs, err) |
|
} |
|
|
|
func (l *lexer) err(arg interface{}) { |
|
l.err0(l.line, l.col, arg) |
|
} |
|
|
|
func (l *lexer) errf(format string, args ...interface{}) { |
|
s := fmt.Sprintf(format, args...) |
|
l.err0(l.line, l.col, s) |
|
} |
|
|
|
func (l *lexer) Error(s string) { |
|
// Notice: ignore origin error info. |
|
l.err(nil) |
|
} |
|
|
|
func (l *lexer) stmtText() string { |
|
endPos := l.i |
|
if l.src[l.i-1] == '\n' { |
|
endPos = l.i-1 // trim new line |
|
} |
|
if l.src[l.stmtStartPos] == '\n' { |
|
l.stmtStartPos++ |
|
} |
|
|
|
text := l.src[l.stmtStartPos:endPos] |
|
|
|
l.stmtStartPos = l.i |
|
return text |
|
} |
|
|
|
|
|
func (l *lexer) Lex(lval *yySymType) (r int) { |
|
defer func() { |
|
lval.line, lval.col, lval.offset = l.line, l.col, l.tokenStartOffset |
|
l.tokenStartOffset = l.tokenEndOffset |
|
}() |
|
const ( |
|
INITIAL = iota |
|
S1 |
|
S2 |
|
S3 |
|
S4 |
|
) |
|
|
|
if n := l.inj; n != 0 { |
|
l.inj = 0 |
|
return n |
|
} |
|
|
|
c0, c := 0, l.c |
|
%} |
|
|
|
int_lit {decimal_lit}|{octal_lit} |
|
decimal_lit [1-9][0-9]* |
|
octal_lit 0[0-7]* |
|
hex_lit 0[xX][0-9a-fA-F]+|[xX]"'"[0-9a-fA-F]+"'" |
|
bit_lit 0[bB][01]+|[bB]"'"[01]+"'" |
|
|
|
float_lit {D}"."{D}?{E}?|{D}{E}|"."{D}{E}? |
|
D [0-9]+ |
|
E [eE][-+]?[0-9]+ |
|
|
|
imaginary_ilit {D}i |
|
imaginary_lit {float_lit}i |
|
|
|
a [aA] |
|
b [bB] |
|
c [cC] |
|
d [dD] |
|
e [eE] |
|
f [fF] |
|
g [gG] |
|
h [hH] |
|
i [iI] |
|
j [jJ] |
|
k [kK] |
|
l [lL] |
|
m [mM] |
|
n [nN] |
|
o [oO] |
|
p [pP] |
|
q [qQ] |
|
r [rR] |
|
s [sS] |
|
t [tT] |
|
u [uU] |
|
v [vV] |
|
w [wW] |
|
x [xX] |
|
y [yY] |
|
z [zZ] |
|
|
|
abs {a}{b}{s} |
|
add {a}{d}{d} |
|
adddate {a}{d}{d}{d}{a}{t}{e} |
|
admin {a}{d}{m}{i}{n} |
|
after {a}{f}{t}{e}{r} |
|
all {a}{l}{l} |
|
alter {a}{l}{t}{e}{r} |
|
and {a}{n}{d} |
|
any {a}{n}{y} |
|
as {a}{s} |
|
asc {a}{s}{c} |
|
auto_increment {a}{u}{t}{o}_{i}{n}{c}{r}{e}{m}{e}{n}{t} |
|
avg {a}{v}{g} |
|
avg_row_length {a}{v}{g}_{r}{o}{w}_{l}{e}{n}{g}{t}{h} |
|
begin {b}{e}{g}{i}{n} |
|
between {b}{e}{t}{w}{e}{e}{n} |
|
both {b}{o}{t}{h} |
|
btree {b}{t}{r}{e}{e} |
|
by {b}{y} |
|
case {c}{a}{s}{e} |
|
cast {c}{a}{s}{t} |
|
character {c}{h}{a}{r}{a}{c}{t}{e}{r} |
|
charset {c}{h}{a}{r}{s}{e}{t} |
|
check {c}{h}{e}{c}{k} |
|
checksum {c}{h}{e}{c}{k}{s}{u}{m} |
|
coalesce {c}{o}{a}{l}{e}{s}{c}{e} |
|
collate {c}{o}{l}{l}{a}{t}{e} |
|
collation {c}{o}{l}{l}{a}{t}{i}{o}{n} |
|
column {c}{o}{l}{u}{m}{n} |
|
columns {c}{o}{l}{u}{m}{n}{s} |
|
comment {c}{o}{m}{m}{e}{n}{t} |
|
commit {c}{o}{m}{m}{i}{t} |
|
committed {c}{o}{m}{m}{i}{t}{t}{e}{d} |
|
compact {c}{o}{m}{p}{a}{c}{t} |
|
compressed {c}{o}{m}{p}{r}{e}{s}{s}{e}{d} |
|
compression {c}{o}{m}{p}{r}{e}{s}{s}{i}{o}{n} |
|
concat {c}{o}{n}{c}{a}{t} |
|
concat_ws {c}{o}{n}{c}{a}{t}_{w}{s} |
|
connection {c}{o}{n}{n}{e}{c}{t}{i}{o}{n} |
|
connection_id {c}{o}{n}{n}{e}{c}{t}{i}{o}{n}_{i}{d} |
|
constraint {c}{o}{n}{s}{t}{r}{a}{i}{n}{t} |
|
convert {c}{o}{n}{v}{e}{r}{t} |
|
count {c}{o}{u}{n}{t} |
|
create {c}{r}{e}{a}{t}{e} |
|
cross {c}{r}{o}{s}{s} |
|
curdate {c}{u}{r}{d}{a}{t}{e} |
|
current_date {c}{u}{r}{r}{e}{n}{t}_{d}{a}{t}{e} |
|
curtime {c}{u}{r}{t}{i}{m}{e} |
|
current_time {c}{u}{r}{r}{e}{n}{t}_{t}{i}{m}{e} |
|
current_user {c}{u}{r}{r}{e}{n}{t}_{u}{s}{e}{r} |
|
database {d}{a}{t}{a}{b}{a}{s}{e} |
|
databases {d}{a}{t}{a}{b}{a}{s}{e}{s} |
|
date_add {d}{a}{t}{e}_{a}{d}{d} |
|
date_sub {d}{a}{t}{e}_{s}{u}{b} |
|
day {d}{a}{y} |
|
dayname {d}{a}{y}{n}{a}{m}{e} |
|
dayofweek {d}{a}{y}{o}{f}{w}{e}{e}{k} |
|
dayofmonth {d}{a}{y}{o}{f}{m}{o}{n}{t}{h} |
|
dayofyear {d}{a}{y}{o}{f}{y}{e}{a}{r} |
|
ddl {d}{d}{l} |
|
deallocate {d}{e}{a}{l}{l}{o}{c}{a}{t}{e} |
|
default {d}{e}{f}{a}{u}{l}{t} |
|
delayed {d}{e}{l}{a}{y}{e}{d} |
|
delay_key_write {d}{e}{l}{a}{y}_{k}{e}{y}_{w}{r}{i}{t}{e} |
|
delete {d}{e}{l}{e}{t}{e} |
|
drop {d}{r}{o}{p} |
|
desc {d}{e}{s}{c} |
|
describe {d}{e}{s}{c}{r}{i}{b}{e} |
|
distinct {d}{i}{s}{t}{i}{n}{c}{t} |
|
div {d}{i}{v} |
|
do {d}{o} |
|
dual {d}{u}{a}{l} |
|
duplicate {d}{u}{p}{l}{i}{c}{a}{t}{e} |
|
dynamic {d}{y}{n}{a}{m}{i}{c} |
|
else {e}{l}{s}{e} |
|
end {e}{n}{d} |
|
engine {e}{n}{g}{i}{n}{e} |
|
engines {e}{n}{g}{i}{n}{e}{s} |
|
escape {e}{s}{c}{a}{p}{e} |
|
execute {e}{x}{e}{c}{u}{t}{e} |
|
exists {e}{x}{i}{s}{t}{s} |
|
explain {e}{x}{p}{l}{a}{i}{n} |
|
extract {e}{x}{t}{r}{a}{c}{t} |
|
fields {f}{i}{e}{l}{d}{s} |
|
first {f}{i}{r}{s}{t} |
|
fixed {f}{i}{x}{e}{d} |
|
for {f}{o}{r} |
|
foreign {f}{o}{r}{e}{i}{g}{n} |
|
found_rows {f}{o}{u}{n}{d}_{r}{o}{w}{s} |
|
from {f}{r}{o}{m} |
|
full {f}{u}{l}{l} |
|
fulltext {f}{u}{l}{l}{t}{e}{x}{t} |
|
global {g}{l}{o}{b}{a}{l} |
|
grant {g}{r}{a}{n}{t} |
|
grants {g}{r}{a}{n}{t}{s} |
|
group {g}{r}{o}{u}{p} |
|
group_concat {g}{r}{o}{u}{p}_{c}{o}{n}{c}{a}{t} |
|
hash {h}{a}{s}{h} |
|
having {h}{a}{v}{i}{n}{g} |
|
high_priority {h}{i}{g}{h}_{p}{r}{i}{o}{r}{i}{t}{y} |
|
hour {h}{o}{u}{r} |
|
identified {i}{d}{e}{n}{t}{i}{f}{i}{e}{d} |
|
if {i}{f} |
|
ifnull {i}{f}{n}{u}{l}{l} |
|
ignore {i}{g}{n}{o}{r}{e} |
|
in {i}{n} |
|
index {i}{n}{d}{e}{x} |
|
inner {i}{n}{n}{e}{r} |
|
insert {i}{n}{s}{e}{r}{t} |
|
interval {i}{n}{t}{e}{r}{v}{a}{l} |
|
into {i}{n}{t}{o} |
|
is {i}{s} |
|
isolation {i}{s}{o}{l}{a}{t}{i}{o}{n} |
|
join {j}{o}{i}{n} |
|
key {k}{e}{y} |
|
key_block_size {k}{e}{y}_{b}{l}{o}{c}{k}_{s}{i}{z}{e} |
|
leading {l}{e}{a}{d}{i}{n}{g} |
|
left {l}{e}{f}{t} |
|
length {l}{e}{n}{g}{t}{h} |
|
level {l}{e}{v}{e}{l} |
|
like {l}{i}{k}{e} |
|
limit {l}{i}{m}{i}{t} |
|
local {l}{o}{c}{a}{l} |
|
locate {l}{o}{c}{a}{t}{e} |
|
lock {l}{o}{c}{k} |
|
lower {l}{o}{w}{e}{r} |
|
low_priority {l}{o}{w}_{p}{r}{i}{o}{r}{i}{t}{y} |
|
max_rows {m}{a}{x}_{r}{o}{w}{s} |
|
microsecond {m}{i}{c}{r}{o}{s}{e}{c}{o}{n}{d} |
|
minute {m}{i}{n}{u}{t}{e} |
|
min_rows {m}{i}{n}_{r}{o}{w}{s} |
|
mod {m}{o}{d} |
|
mode {m}{o}{d}{e} |
|
month {m}{o}{n}{t}{h} |
|
names {n}{a}{m}{e}{s} |
|
national {n}{a}{t}{i}{o}{n}{a}{l} |
|
not {n}{o}{t} |
|
offset {o}{f}{f}{s}{e}{t} |
|
on {o}{n} |
|
only {o}{n}{l}{y} |
|
option {o}{p}{t}{i}{o}{n} |
|
or {o}{r} |
|
order {o}{r}{d}{e}{r} |
|
outer {o}{u}{t}{e}{r} |
|
password {p}{a}{s}{s}{w}{o}{r}{d} |
|
pow {p}{o}{w} |
|
power {p}{o}{w}{e}{r} |
|
prepare {p}{r}{e}{p}{a}{r}{e} |
|
primary {p}{r}{i}{m}{a}{r}{y} |
|
procedure {p}{r}{o}{c}{e}{d}{u}{r}{e} |
|
quarter {q}{u}{a}{r}{t}{e}{r} |
|
quick {q}{u}{i}{c}{k} |
|
rand {r}{a}{n}{d} |
|
read {r}{e}{a}{d} |
|
repeat {r}{e}{p}{e}{a}{t} |
|
repeatable {r}{e}{p}{e}{a}{t}{a}{b}{l}{e} |
|
references {r}{e}{f}{e}{r}{e}{n}{c}{e}{s} |
|
regexp {r}{e}{g}{e}{x}{p} |
|
replace {r}{e}{p}{l}{a}{c}{e} |
|
redundant {r}{e}{d}{u}{n}{d}{a}{n}{t} |
|
right {r}{i}{g}{h}{t} |
|
rlike {r}{l}{i}{k}{e} |
|
rollback {r}{o}{l}{l}{b}{a}{c}{k} |
|
row {r}{o}{w} |
|
row_format {r}{o}{w}_{f}{o}{r}{m}{a}{t} |
|
schema {s}{c}{h}{e}{m}{a} |
|
schemas {s}{c}{h}{e}{m}{a}{s} |
|
second {s}{e}{c}{o}{n}{d} |
|
select {s}{e}{l}{e}{c}{t} |
|
serializable {s}{e}{r}{i}{a}{l}{i}{z}{a}{b}{l}{e} |
|
session {s}{e}{s}{s}{i}{o}{n} |
|
set {s}{e}{t} |
|
share {s}{h}{a}{r}{e} |
|
show {s}{h}{o}{w} |
|
some {s}{o}{m}{e} |
|
start {s}{t}{a}{r}{t} |
|
status {s}{t}{a}{t}{u}{s} |
|
subdate {s}{u}{b}{d}{a}{t}{e} |
|
strcmp {s}{t}{r}{c}{m}{p} |
|
substr {s}{u}{b}{s}{t}{r} |
|
substring {s}{u}{b}{s}{t}{r}{i}{n}{g} |
|
substring_index {s}{u}{b}{s}{t}{r}{i}{n}{g}_{i}{n}{d}{e}{x} |
|
sum {s}{u}{m} |
|
sysdate {s}{y}{s}{d}{a}{t}{e} |
|
table {t}{a}{b}{l}{e} |
|
tables {t}{a}{b}{l}{e}{s} |
|
then {t}{h}{e}{n} |
|
to {t}{o} |
|
trailing {t}{r}{a}{i}{l}{i}{n}{g} |
|
transaction {t}{r}{a}{n}{s}{a}{c}{t}{i}{o}{n} |
|
triggers {t}{r}{i}{g}{g}{e}{r}{s} |
|
trim {t}{r}{i}{m} |
|
truncate {t}{r}{u}{n}{c}{a}{t}{e} |
|
max {m}{a}{x} |
|
min {m}{i}{n} |
|
uncommitted {u}{n}{c}{o}{m}{m}{i}{t}{t}{e}{d} |
|
unknown {u}{n}{k}{n}{o}{w}{n} |
|
union {u}{n}{i}{o}{n} |
|
unique {u}{n}{i}{q}{u}{e} |
|
unlock {u}{n}{l}{o}{c}{k} |
|
nullif {n}{u}{l}{l}{i}{f} |
|
update {u}{p}{d}{a}{t}{e} |
|
upper {u}{p}{p}{e}{r} |
|
value {v}{a}{l}{u}{e} |
|
values {v}{a}{l}{u}{e}{s} |
|
variables {v}{a}{r}{i}{a}{b}{l}{e}{s} |
|
version {v}{e}{r}{s}{i}{o}{n} |
|
warnings {w}{a}{r}{n}{i}{n}{g}{s} |
|
week {w}{e}{e}{k} |
|
weekday {w}{e}{e}{k}{d}{a}{y} |
|
weekofyear {w}{e}{e}{k}{o}{f}{y}{e}{a}{r} |
|
where {w}{h}{e}{r}{e} |
|
when {w}{h}{e}{n} |
|
write {w}{r}{i}{t}{e} |
|
xor {x}{o}{r} |
|
yearweek {y}{e}{a}{r}{w}{e}{e}{k} |
|
|
|
null {n}{u}{l}{l} |
|
false {f}{a}{l}{s}{e} |
|
true {t}{r}{u}{e} |
|
|
|
calc_found_rows {s}{q}{l}_{c}{a}{l}{c}_{f}{o}{u}{n}{d}_{r}{o}{w}{s} |
|
|
|
current_ts {c}{u}{r}{r}{e}{n}{t}_{t}{i}{m}{e}{s}{t}{a}{m}{p} |
|
localtime {l}{o}{c}{a}{l}{t}{i}{m}{e} |
|
localts {l}{o}{c}{a}{l}{t}{i}{m}{e}{s}{t}{a}{m}{p} |
|
now {n}{o}{w} |
|
|
|
bit {b}{i}{t} |
|
tiny {t}{i}{n}{y} |
|
tinyint {t}{i}{n}{y}{i}{n}{t} |
|
smallint {s}{m}{a}{l}{l}{i}{n}{t} |
|
mediumint {m}{e}{d}{i}{u}{m}{i}{n}{t} |
|
int {i}{n}{t} |
|
integer {i}{n}{t}{e}{g}{e}{r} |
|
bigint {b}{i}{g}{i}{n}{t} |
|
real {r}{e}{a}{l} |
|
double {d}{o}{u}{b}{l}{e} |
|
float {f}{l}{o}{a}{t} |
|
decimal {d}{e}{c}{i}{m}{a}{l} |
|
numeric {n}{u}{m}{e}{r}{i}{c} |
|
date {d}{a}{t}{e} |
|
time {t}{i}{m}{e} |
|
timestamp {t}{i}{m}{e}{s}{t}{a}{m}{p} |
|
datetime {d}{a}{t}{e}{t}{i}{m}{e} |
|
year {y}{e}{a}{r} |
|
char {c}{h}{a}{r} |
|
varchar {v}{a}{r}{c}{h}{a}{r} |
|
binary {b}{i}{n}{a}{r}{y} |
|
varbinary {v}{a}{r}{b}{i}{n}{a}{r}{y} |
|
tinyblob {t}{i}{n}{y}{b}{l}{o}{b} |
|
blob {b}{l}{o}{b} |
|
mediumblob {m}{e}{d}{i}{u}{m}{b}{l}{o}{b} |
|
longblob {l}{o}{n}{g}{b}{l}{o}{b} |
|
tinytext {t}{i}{n}{y}{t}{e}{x}{t} |
|
text {t}{e}{x}{t} |
|
mediumtext {m}{e}{d}{i}{u}{m}{t}{e}{x}{t} |
|
longtext {l}{o}{n}{g}{t}{e}{x}{t} |
|
enum {e}{n}{u}{m} |
|
precision {p}{r}{e}{c}{i}{s}{i}{o}{n} |
|
|
|
signed {s}{i}{g}{n}{e}{d} |
|
unsigned {u}{n}{s}{i}{g}{n}{e}{d} |
|
zerofill {z}{e}{r}{o}{f}{i}{l}{l} |
|
|
|
bigrat {b}{i}{g}{r}{a}{t} |
|
bool {b}{o}{o}{l} |
|
boolean {b}{o}{o}{l}{e}{a}{n} |
|
byte {b}{y}{t}{e} |
|
duration {d}{u}{r}{a}{t}{i}{o}{n} |
|
rune {r}{u}{n}{e} |
|
string {s}{t}{r}{i}{n}{g} |
|
use {u}{s}{e} |
|
user {u}{s}{e}{r} |
|
using {u}{s}{i}{n}{g} |
|
|
|
idchar0 [a-zA-Z_] |
|
idchars {idchar0}|[0-9$] // See: https://dev.mysql.com/doc/refman/5.7/en/identifiers.html |
|
ident {idchar0}{idchars}* |
|
|
|
user_var "@"{ident} |
|
sys_var "@@"(({global}".")|({session}".")|{local}".")?{ident} |
|
|
|
second_microsecond {s}{e}{c}{o}{n}{d}_{m}{i}{c}{r}{o}{s}{e}{c}{o}{n}{d} |
|
minute_microsecond {m}{i}{n}{u}{t}{e}_{m}{i}{c}{r}{o}{s}{e}{c}{o}{n}{d} |
|
minute_second {m}{i}{n}{u}{t}{e}_{s}{e}{c}{o}{n}{d} |
|
hour_microsecond {h}{o}{u}{r}_{m}{i}{c}{r}{o}{s}{e}{c}{o}{n}{d} |
|
hour_second {h}{o}{u}{r}_{s}{e}{c}{o}{n}{d} |
|
hour_minute {h}{o}{u}{r}_{m}{i}{n}{u}{t}{e} |
|
day_microsecond {d}{a}{y}_{m}{i}{c}{r}{o}{s}{e}{c}{o}{n}{d} |
|
day_second {d}{a}{y}_{s}{e}{c}{o}{n}{d} |
|
day_minute {d}{a}{y}_{m}{i}{n}{u}{t}{e} |
|
day_hour {d}{a}{y}_{h}{o}{u}{r} |
|
year_month {y}{e}{a}{r}_{m}{o}{n}{t}{h} |
|
|
|
%yyc c |
|
%yyn c = l.next() |
|
%yyt l.sc |
|
|
|
%x S1 S2 S3 S4 |
|
|
|
%% |
|
l.val = l.val[:0] |
|
c0, l.line, l.col = l.c, l.nline, l.ncol |
|
|
|
<*>\0 return 0 |
|
|
|
[ \t\n\r]+ |
|
#.* |
|
\/\/.* |
|
\/\*([^*]|\*+[^*/])*\*+\/ |
|
-- l.sc = S3 |
|
<S3>[ \t]+.* {l.sc = 0} |
|
<S3>[^ \t] { |
|
l.sc = 0 |
|
l.c = '-' |
|
n := len(l.val) |
|
l.unget(l.val[n-1]) |
|
return '-' |
|
} |
|
|
|
{int_lit} return l.int(lval) |
|
{float_lit} return l.float(lval) |
|
{hex_lit} return l.hex(lval) |
|
{bit_lit} return l.bit(lval) |
|
|
|
\" l.sc = S1 |
|
' l.sc = S2 |
|
` l.sc = S4 |
|
|
|
<S1>[^\"\\]* l.stringLit = append(l.stringLit, l.val...) |
|
<S1>\\. l.stringLit = append(l.stringLit, l.val...) |
|
<S1>\"\" l.stringLit = append(l.stringLit, '"') |
|
<S1>\" l.stringLit = append(l.stringLit, '"') |
|
l.sc = 0 |
|
return l.str(lval, "\"") |
|
<S2>[^'\\]* l.stringLit = append(l.stringLit, l.val...) |
|
<S2>\\. l.stringLit = append(l.stringLit, l.val...) |
|
<S2>'' l.stringLit = append(l.stringLit, '\'') |
|
<S2>' l.stringLit = append(l.stringLit, '\'') |
|
l.sc = 0 |
|
return l.str(lval, "'") |
|
<S4>[^`]* l.stringLit = append(l.stringLit, l.val...) |
|
<S4>`` l.stringLit = append(l.stringLit, '`') |
|
<S4>` l.sc = 0 |
|
lval.item = string(l.stringLit) |
|
l.stringLit = l.stringLit[0:0] |
|
return identifier |
|
|
|
"&&" return andand |
|
"&^" return andnot |
|
"<<" return lsh |
|
"<=" return le |
|
"=" return eq |
|
">=" return ge |
|
"!=" return neq |
|
"<>" return neq |
|
"||" return oror |
|
">>" return rsh |
|
"<=>" return nulleq |
|
|
|
"@" return at |
|
"?" return placeholder |
|
|
|
{abs} lval.item = string(l.val) |
|
return abs |
|
{add} return add |
|
{adddate} lval.item = string(l.val) |
|
return addDate |
|
{admin} lval.item = string(l.val) |
|
return admin |
|
{after} lval.item = string(l.val) |
|
return after |
|
{all} return all |
|
{alter} return alter |
|
{and} return and |
|
{any} lval.item = string(l.val) |
|
return any |
|
{asc} return asc |
|
{as} return as |
|
{auto_increment} lval.item = string(l.val) |
|
return autoIncrement |
|
{avg} lval.item = string(l.val) |
|
return avg |
|
{avg_row_length} lval.item = string(l.val) |
|
return avgRowLength |
|
{begin} lval.item = string(l.val) |
|
return begin |
|
{between} return between |
|
{both} return both |
|
{btree} lval.item = string(l.val) |
|
return btree |
|
{by} return by |
|
{case} return caseKwd |
|
{cast} lval.item = string(l.val) |
|
return cast |
|
{character} return character |
|
{charset} lval.item = string(l.val) |
|
return charsetKwd |
|
{check} return check |
|
{checksum} lval.item = string(l.val) |
|
return checksum |
|
{coalesce} lval.item = string(l.val) |
|
return coalesce |
|
{collate} return collate |
|
{collation} lval.item = string(l.val) |
|
return collation |
|
{column} return column |
|
{columns} lval.item = string(l.val) |
|
return columns |
|
{comment} lval.item = string(l.val) |
|
return comment |
|
{commit} lval.item = string(l.val) |
|
return commit |
|
{committed} lval.item = string(l.val) |
|
return committed |
|
{compact} lval.item = string(l.val) |
|
return compact |
|
{compressed} lval.item = string(l.val) |
|
return compressed |
|
{compression} lval.item = string(l.val) |
|
return compression |
|
{concat} lval.item = string(l.val) |
|
return concat |
|
{concat_ws} lval.item = string(l.val) |
|
return concatWs |
|
{connection} lval.item = string(l.val) |
|
return connection |
|
{connection_id} lval.item = string(l.val) |
|
return connectionID |
|
{constraint} return constraint |
|
{convert} lval.item = string(l.val) |
|
return convert |
|
{count} lval.item = string(l.val) |
|
return count |
|
{create} return create |
|
{cross} return cross |
|
{curdate} lval.item = string(l.val) |
|
return curDate |
|
{current_date} lval.item = string(l.val) |
|
return currentDate |
|
{curtime} lval.item = string(l.val) |
|
return curTime |
|
{current_time} lval.item = string(l.val) |
|
return currentTime |
|
{current_user} lval.item = string(l.val) |
|
return currentUser |
|
{database} lval.item = string(l.val) |
|
return database |
|
{databases} return databases |
|
{date_add} lval.item = string(l.val) |
|
return dateAdd |
|
{date_sub} lval.item = string(l.val) |
|
return dateSub |
|
{day} lval.item = string(l.val) |
|
return day |
|
{dayname} lval.item = string(l.val) |
|
return dayname |
|
{dayofweek} lval.item = string(l.val) |
|
return dayofweek |
|
{dayofmonth} lval.item = string(l.val) |
|
return dayofmonth |
|
{dayofyear} lval.item = string(l.val) |
|
return dayofyear |
|
{day_hour} lval.item = string(l.val) |
|
return dayHour |
|
{day_microsecond} lval.item = string(l.val) |
|
return dayMicrosecond |
|
{day_minute} lval.item = string(l.val) |
|
return dayMinute |
|
{day_second} lval.item = string(l.val) |
|
return daySecond |
|
{ddl} return ddl |
|
{deallocate} lval.item = string(l.val) |
|
return deallocate |
|
{default} return defaultKwd |
|
{delayed} return delayed |
|
{delay_key_write} lval.item = string(l.val) |
|
return delayKeyWrite |
|
{delete} return deleteKwd |
|
{desc} return desc |
|
{describe} return describe |
|
{drop} return drop |
|
{distinct} return distinct |
|
{div} return div |
|
{do} lval.item = string(l.val) |
|
return do |
|
{dual} return dual |
|
{duplicate} lval.item = string(l.val) |
|
return duplicate |
|
{dynamic} lval.item = string(l.val) |
|
return dynamic |
|
{else} return elseKwd |
|
{end} lval.item = string(l.val) |
|
return end |
|
{engine} lval.item = string(l.val) |
|
return engine |
|
{engines} lval.item = string(l.val) |
|
return engines |
|
{execute} lval.item = string(l.val) |
|
return execute |
|
{enum} return enum |
|
{escape} lval.item = string(l.val) |
|
return escape |
|
{exists} return exists |
|
{explain} return explain |
|
{extract} lval.item = string(l.val) |
|
return extract |
|
{fields} lval.item = string(l.val) |
|
return fields |
|
{first} lval.item = string(l.val) |
|
return first |
|
{fixed} lval.item = string(l.val) |
|
return fixed |
|
{for} return forKwd |
|
{foreign} return foreign |
|
{found_rows} lval.item = string(l.val) |
|
return foundRows |
|
{from} return from |
|
{full} lval.item = string(l.val) |
|
return full |
|
{fulltext} return fulltext |
|
{grant} return grant |
|
{grants} lval.item = string(l.val) |
|
return grants |
|
{group} return group |
|
{group_concat} lval.item = string(l.val) |
|
return groupConcat |
|
{hash} lval.item = string(l.val) |
|
return hash |
|
{having} return having |
|
{high_priority} return highPriority |
|
{hour} lval.item = string(l.val) |
|
return hour |
|
{hour_microsecond} lval.item = string(l.val) |
|
return hourMicrosecond |
|
{hour_minute} lval.item = string(l.val) |
|
return hourMinute |
|
{hour_second} lval.item = string(l.val) |
|
return hourSecond |
|
{identified} lval.item = string(l.val) |
|
return identified |
|
{if} lval.item = string(l.val) |
|
return ifKwd |
|
{ifnull} lval.item = string(l.val) |
|
return ifNull |
|
{ignore} return ignore |
|
{index} return index |
|
{inner} return inner |
|
{insert} return insert |
|
{interval} return interval |
|
{into} return into |
|
{in} return in |
|
{is} return is |
|
{isolation} lval.item = string(l.val) |
|
return isolation |
|
{join} return join |
|
{key} return key |
|
{key_block_size} lval.item = string(l.val) |
|
return keyBlockSize |
|
{leading} return leading |
|
{left} lval.item = string(l.val) |
|
return left |
|
{length} lval.item = string(l.val) |
|
return length |
|
{level} lval.item = string(l.val) |
|
return level |
|
{like} return like |
|
{limit} return limit |
|
{local} lval.item = string(l.val) |
|
return local |
|
{locate} lval.item = string(l.val) |
|
return locate |
|
{lock} return lock |
|
{lower} lval.item = string(l.val) |
|
return lower |
|
{low_priority} return lowPriority |
|
{max} lval.item = string(l.val) |
|
return max |
|
{max_rows} lval.item = string(l.val) |
|
return maxRows |
|
{microsecond} lval.item = string(l.val) |
|
return microsecond |
|
{min} lval.item = string(l.val) |
|
return min |
|
{minute} lval.item = string(l.val) |
|
return minute |
|
{minute_microsecond} lval.item = string(l.val) |
|
return minuteMicrosecond |
|
{minute_second} lval.item = string(l.val) |
|
return minuteSecond |
|
{min_rows} lval.item = string(l.val) |
|
return minRows |
|
{mod} return mod |
|
{mode} lval.item = string(l.val) |
|
return mode |
|
{month} lval.item = string(l.val) |
|
return month |
|
{names} lval.item = string(l.val) |
|
return names |
|
{national} lval.item = string(l.val) |
|
return national |
|
{not} return not |
|
{offset} lval.item = string(l.val) |
|
return offset |
|
{on} return on |
|
{only} lval.item = string(l.val) |
|
return only |
|
{option} return option |
|
{order} return order |
|
{or} return or |
|
{outer} return outer |
|
{password} lval.item = string(l.val) |
|
return password |
|
{pow} lval.item = string(l.val) |
|
return pow |
|
{power} lval.item = string(l.val) |
|
return power |
|
{prepare} lval.item = string(l.val) |
|
return prepare |
|
{primary} return primary |
|
{procedure} return procedure |
|
{quarter} lval.item = string(l.val) |
|
return quarter |
|
{quick} lval.item = string(l.val) |
|
return quick |
|
redundant lval.item = string(l.val) |
|
return redundant |
|
{right} return right |
|
{rollback} lval.item = string(l.val) |
|
return rollback |
|
{row} lval.item = string(l.val) |
|
return row |
|
{row_format} lval.item = string(l.val) |
|
return rowFormat |
|
{schema} lval.item = string(l.val) |
|
return schema |
|
{schemas} return schemas |
|
{serializable} lval.item = string(l.val) |
|
return serializable |
|
{session} lval.item = string(l.val) |
|
return session |
|
{some} lval.item = string(l.val) |
|
return some |
|
{start} lval.item = string(l.val) |
|
return start |
|
{status} lval.item = string(l.val) |
|
return status |
|
{global} lval.item = string(l.val) |
|
return global |
|
{rand} lval.item = string(l.val) |
|
return rand |
|
{read} return read |
|
{repeat} lval.item = string(l.val) |
|
return repeat |
|
{repeatable} lval.item = string(l.val) |
|
return repeatable |
|
{regexp} return regexpKwd |
|
{replace} lval.item = string(l.val) |
|
return replace |
|
{references} return references |
|
{rlike} return rlike |
|
|
|
{sys_var} lval.item = string(l.val) |
|
return sysVar |
|
|
|
{user_var} lval.item = string(l.val) |
|
return userVar |
|
{second} lval.item = string(l.val) |
|
return second |
|
{second_microsecond} lval.item= string(l.val) |
|
return secondMicrosecond |
|
{select} return selectKwd |
|
|
|
{set} return set |
|
{share} return share |
|
{show} return show |
|
{subdate} lval.item = string(l.val) |
|
return subDate |
|
{strcmp} lval.item = string(l.val) |
|
return strcmp |
|
{substr} lval.item = string(l.val) |
|
return substring |
|
{substring} lval.item = string(l.val) |
|
return substring |
|
{substring_index} lval.item = string(l.val) |
|
return substringIndex |
|
{sum} lval.item = string(l.val) |
|
return sum |
|
{sysdate} lval.item = string(l.val) |
|
return sysDate |
|
{table} return tableKwd |
|
{tables} lval.item = string(l.val) |
|
return tables |
|
{then} return then |
|
{to} return to |
|
{trailing} return trailing |
|
{transaction} lval.item = string(l.val) |
|
return transaction |
|
{triggers} lval.item = string(l.val) |
|
return triggers |
|
{trim} lval.item = string(l.val) |
|
return trim |
|
{truncate} lval.item = string(l.val) |
|
return truncate |
|
{uncommitted} lval.item = string(l.val) |
|
return uncommitted |
|
{union} return union |
|
{unique} return unique |
|
{unknown} lval.item = string(l.val) |
|
return unknown |
|
{nullif} lval.item = string(l.val) |
|
return nullIf |
|
{unlock} return unlock |
|
{update} return update |
|
{upper} lval.item = string(l.val) |
|
return upper |
|
{use} return use |
|
{user} lval.item = string(l.val) |
|
return user |
|
{using} return using |
|
{value} lval.item = string(l.val) |
|
return value |
|
{values} return values |
|
{variables} lval.item = string(l.val) |
|
return variables |
|
{version} lval.item = string(l.val) |
|
return version |
|
{warnings} lval.item = string(l.val) |
|
return warnings |
|
{week} lval.item = string(l.val) |
|
return week |
|
{weekday} lval.item = string(l.val) |
|
return weekday |
|
{weekofyear} lval.item = string(l.val) |
|
return weekofyear |
|
{when} return when |
|
{where} return where |
|
{write} return write |
|
{xor} return xor |
|
{yearweek} lval.item = string(l.val) |
|
return yearweek |
|
{year_month} lval.item = string(l.val) |
|
return yearMonth |
|
|
|
{signed} lval.item = string(l.val) |
|
return signed |
|
{unsigned} return unsigned |
|
{zerofill} return zerofill |
|
|
|
{null} lval.item = nil |
|
return null |
|
|
|
{false} return falseKwd |
|
|
|
{true} return trueKwd |
|
|
|
{calc_found_rows} lval.item = string(l.val) |
|
return calcFoundRows |
|
|
|
{current_ts} lval.item = string(l.val) |
|
return currentTs |
|
{localtime} return localTime |
|
{localts} return localTs |
|
{now} lval.item = string(l.val) |
|
return now |
|
|
|
{bit} lval.item = string(l.val) |
|
return bitType |
|
|
|
{tiny} lval.item = string(l.val) |
|
return tinyIntType |
|
|
|
{tinyint} lval.item = string(l.val) |
|
return tinyIntType |
|
|
|
{smallint} lval.item = string(l.val) |
|
return smallIntType |
|
|
|
{mediumint} lval.item = string(l.val) |
|
return mediumIntType |
|
|
|
{bigint} lval.item = string(l.val) |
|
return bigIntType |
|
|
|
{decimal} lval.item = string(l.val) |
|
return decimalType |
|
|
|
{numeric} lval.item = string(l.val) |
|
return numericType |
|
|
|
{float} lval.item = string(l.val) |
|
return floatType |
|
|
|
{double} lval.item = string(l.val) |
|
return doubleType |
|
|
|
{precision} lval.item = string(l.val) |
|
return precisionType |
|
|
|
{real} lval.item = string(l.val) |
|
return realType |
|
|
|
{date} lval.item = string(l.val) |
|
return dateType |
|
|
|
{time} lval.item = string(l.val) |
|
return timeType |
|
|
|
{timestamp} lval.item = string(l.val) |
|
return timestampType |
|
|
|
{datetime} lval.item = string(l.val) |
|
return datetimeType |
|
|
|
{year} lval.item = string(l.val) |
|
return yearType |
|
|
|
{char} lval.item = string(l.val) |
|
return charType |
|
|
|
{varchar} lval.item = string(l.val) |
|
return varcharType |
|
|
|
{binary} lval.item = string(l.val) |
|
return binaryType |
|
|
|
{varbinary} lval.item = string(l.val) |
|
return varbinaryType |
|
|
|
{tinyblob} lval.item = string(l.val) |
|
return tinyblobType |
|
|
|
{blob} lval.item = string(l.val) |
|
return blobType |
|
|
|
{mediumblob} lval.item = string(l.val) |
|
return mediumblobType |
|
|
|
{longblob} lval.item = string(l.val) |
|
return longblobType |
|
|
|
{tinytext} lval.item = string(l.val) |
|
return tinytextType |
|
|
|
{mediumtext} lval.item = string(l.val) |
|
return mediumtextType |
|
|
|
{text} lval.item = string(l.val) |
|
return textType |
|
|
|
{longtext} lval.item = string(l.val) |
|
return longtextType |
|
|
|
{bool} lval.item = string(l.val) |
|
return boolType |
|
|
|
{boolean} lval.item = string(l.val) |
|
return booleanType |
|
|
|
{byte} lval.item = string(l.val) |
|
return byteType |
|
|
|
{int} lval.item = string(l.val) |
|
return intType |
|
|
|
{integer} lval.item = string(l.val) |
|
return integerType |
|
|
|
{ident} lval.item = string(l.val) |
|
return l.handleIdent(lval) |
|
|
|
. return c0 |
|
|
|
%% |
|
return int(unicode.ReplacementChar) |
|
} |
|
|
|
func (l *lexer) npos() (line, col int) { |
|
if line, col = l.nline, l.ncol; col == 0 { |
|
line-- |
|
col = l.lcol+1 |
|
} |
|
return |
|
} |
|
|
|
func (l *lexer) str(lval *yySymType, pref string) int { |
|
l.sc = 0 |
|
// TODO: performance issue. |
|
s := string(l.stringLit) |
|
l.stringLit = l.stringLit[0:0] |
|
if pref == "'" { |
|
s = strings.Replace(s, "\\'", "'", -1) |
|
s = strings.TrimSuffix(s, "'") + "\"" |
|
pref = "\"" |
|
} |
|
v := stringutil.RemoveUselessBackslash(pref+s) |
|
v, err := strconv.Unquote(v) |
|
if err != nil { |
|
v = strings.TrimSuffix(s, pref) |
|
} |
|
lval.item = v |
|
return stringLit |
|
} |
|
|
|
func (l *lexer) trimIdent(idt string) string { |
|
idt = strings.TrimPrefix(idt, "`") |
|
idt = strings.TrimSuffix(idt, "`") |
|
return idt |
|
} |
|
|
|
func (l *lexer) int(lval *yySymType) int { |
|
n, err := strconv.ParseUint(string(l.val), 0, 64) |
|
if err != nil { |
|
l.errf("integer literal: %v", err) |
|
return int(unicode.ReplacementChar) |
|
} |
|
|
|
switch { |
|
case n < math.MaxInt64: |
|
lval.item = int64(n) |
|
default: |
|
lval.item = uint64(n) |
|
} |
|
return intLit |
|
} |
|
|
|
func (l *lexer) float(lval *yySymType) int { |
|
n, err := strconv.ParseFloat(string(l.val), 64) |
|
if err != nil { |
|
l.errf("float literal: %v", err) |
|
return int(unicode.ReplacementChar) |
|
} |
|
|
|
lval.item = float64(n) |
|
return floatLit |
|
} |
|
|
|
// https://dev.mysql.com/doc/refman/5.7/en/hexadecimal-literals.html |
|
func (l *lexer) hex(lval *yySymType) int { |
|
s := string(l.val) |
|
h, err := mysql.ParseHex(s) |
|
if err != nil { |
|
l.errf("hexadecimal literal: %v", err) |
|
return int(unicode.ReplacementChar) |
|
} |
|
lval.item = h |
|
return hexLit |
|
} |
|
|
|
// https://dev.mysql.com/doc/refman/5.7/en/bit-type.html |
|
func (l *lexer) bit(lval *yySymType) int { |
|
s := string(l.val) |
|
b, err := mysql.ParseBit(s, -1) |
|
if err != nil { |
|
l.errf("bit literal: %v", err) |
|
return int(unicode.ReplacementChar) |
|
} |
|
lval.item = b |
|
return bitLit |
|
} |
|
|
|
func (l *lexer) handleIdent(lval *yySymType) int { |
|
s := lval.item.(string) |
|
// A character string literal may have an optional character set introducer and COLLATE clause: |
|
// [_charset_name]'string' [COLLATE collation_name] |
|
// See: https://dev.mysql.com/doc/refman/5.7/en/charset-literal.html |
|
if !strings.HasPrefix(s, "_") { |
|
return identifier |
|
} |
|
cs, _, err := charset.GetCharsetInfo(s[1:]) |
|
if err != nil { |
|
return identifier |
|
} |
|
lval.item = cs |
|
return underscoreCS |
|
}
|
|
|