1 分离词法文件和语法文件 SqlBase.g4 -> IoTDBSqlLexer.g4 + IoTDBSqlParser.g4
划定词法分析器和语法分析器界线:
- 在词法分析器中匹配并丢弃任何语法分析器无需知晓的东西(如注释和空白符)。
- 由词法分析器来匹配类似标识符、关键字、字符串和数字的常见词法符号。语法分析器的层级更高,所以我们不应当让它处理将数字组合成整数这样的事情,这会加重它的负担。
- 将语法分析器无须区分的词法结构归为同一个词法符号类型。例如,如果我们的程序对待整数和浮点数的方式是一致的,那就把它们都归为NUMBER类型的词法符号。
- 将任何语法分析器可以以相同方式处理的实体归为一类。例如在XML中,语法分析器不关心XML标签的内容,词法分析器就可以将尖括号中的所有内容归为一个名为TAG的词法符号类型。
- 另一方面,如果语法分析器需要把一种类型的文本拆开处理,那么词法分析器就应该将它的各组成部分作为独立的词法符号输送给语法分析器。例如,如果语法分析器需要处理 IP 地址中的元素,那么词法分析器就应该把 IP 地址的各组成部分(整数和点)作为独立的词法符号送入语法分析器。
词法分析器(IoTDBSqlLexer)包括:(按照匹配优先级排序)
1. 空白符
WS:[ \t\r\n]+ -> skip;
2. 关键词列表
3.1 一般关键词
- ADD
- AFTER
- ALIAS
- ALIGN
- ALL
- ALTER
- ANY
- AS
- ASC
- ATTRIBUTES
- AUTOREGISTER
- BEFORE
- BEGIN
- BY
- CACHE
- CHILD
- CLEAR
- COMPRESSION
- COMPRESSOR
- CONCAT
- CONFIGURATION
- CONTAIN
- CONTINUOUS
- COUNT
- CQ
- CQS
- CREATE
- DATATYPE
- DEBUG
- DELETE
- DESC
- DESCRIBE (未使用)
- DEVICE
- DEVICES
- DISABLE
- DROP
- ENCODING
- END
- EVERY
- EXPLAIN (未使用)
- FILL
- FLUSH
- FOR
- FROM
- FULL
- FUNCTION
- FUNCTIONS
- GLOBAL
- GRANT
- GROUP
- INDEX(未使用)
- INFO
- INSERT
- INTO
- KILL
- LABEL(未使用)
- LAST
- LATEST
- LEVEL
- LIKE
- LIMIT
- LINEAR
- LINK(未使用)
- LIST
- LOAD
- LOCK
- MERGE
- METADATA(未使用)
- NODES
- NOW
- OF
- OFF(未使用)
- OFFSET
- ON
- ORDER
- PARTITION
- PASSWORD
- PATHS
- PREVIOUS
- PREVIOUSUNTILLAST
- PRIVILEGES
- PROCESSLIST
- PROPERTY (未使用)
- QUERIES
- QUERY
- READONLY
- REGEXP
- REMOVE
- RENAME
- RESAMPLE
- REVOKE
- ROLE
- ROOT
- SCHEMA
- SELECT
- SET
- SGLEVEL
- SHOW
- SLIMIT
- SNAPSHOT
- SOFFSET
- START
- STOP
- STORAGE
- SYSTEM
- TAGS
- TASK(未使用)
- TIME
- TIMESERIES
- TIMESTAMP
- TO
- TOLERANCE
- TOP
- TRACING
- TRIGGER
- TRIGGERS
- TTL
- UNLINK (未使用)
- UNLOAD
- UNSET
- UPDATE(未使用)
- UPSERT
- USER
- USING (未使用)
- VALUES
- VERIFY
- VERSION
- WATERMARK_EMBEDDING
- WHERE
- WITH
- WITHOUT
- WRITABLE
3.2 数据类型(作为整个语法符号返回)
DATATYPE_VALUE
: BOOLEAN | DOUBLE | FLOAT | INT32 | INT64 | TEXT
;
3.3 编码类型(作为整个语法符号返回)
ENCODING_VALE
: DICTIONARY | DIFF | GORILLA | PLAIN | REGULAR | RLE | TS_2DIFF
;
3.4 压缩类型(作为整个语法符号返回)
COMPRESSOR_VALUE
: GZIP | LZ4 | SNAPPY | UNCOMPRESSED
;
3.5 权限类型(作为整个语法符号返回)
PRIVILEGE_VALUE
: ALL | SET_STORAGE_GROUP
| CREATE_TIMESERIES | INSERT_TIMESERIES | READ_TIMESERIES | DELETE_TIMESERIES
| CREATE_USER | DELETE_USER | MODIFY_PASSWORD | LIST_USER
| GRANT_USER_PRIVILEGE | REVOKE_USER_PRIVILEGE | GRANT_USER_ROLE | REVOKE_USER_ROLE
| CREATE_ROLE | DELETE_ROLE | LIST_ROLE | GRANT_ROLE_PRIVILEGE | REVOKE_ROLE_PRIVILEGE
| CREATE_FUNCTION | DROP_FUNCTION | CREATE_TRIGGER | DROP_TRIGGER | START_TRIGGER | STOP_TRIGGER
| CREATE_CONTINUOUS_QUERY | DROP_CONTINUOUS_QUERY
;
4. 操作符
4.1 算术
MINUS : '-';
PLUS : '+';
DIV : '/';
MOD : '%';
4.2 比较
OPERATOR_EQ : '=' | '==';
OPERATOR_GT : '>';
OPERATOR_GTE : '>=';
OPERATOR_LT : '<';
OPERATOR_LTE : '<=';
OPERATOR_NEQ : '!=' | '<>';
OPERATOR_IN : I N;
OPERATOR_AND
: A N D
| '&'
| '&&'
;
OPERATOR_OR
: O R
| '|'
| '||'
;
OPERATOR_NOT
: N O T | '!'
;
OPERATOR_CONTAINS
: C O N T A I N S
;
5. 结构符号
DOT : '.';
COMMA : ',';
SEMI: ';';
STAR: '*';
DOUBLE_STAR: '**';
LR_BRACKET : '(';
RR_BRACKET : ')';
LS_BRACKET : '[';
RS_BRACKET : ']';
6. 字面量
6.1 字符串型:单引号引用表示字符串常量。
```
STRING_LITERAL
: SQUOTE_STRING
;
QUOTED_STRING_LITERAL
: DQUOTE_STRING
| BQUOTE_STRING
;
fragment DQUOTE_STRING
: '"' ('\\' . | ~'"' )*? '"'
;
fragment SQUOTE_STRING
: '\'' ('\\' . | ~'\'' )*? '\''
;
fragment BQUOTE_STRING
: '`' ('\\' . | ~'`' )*? '`'
;
```
6.2 日期时间型
```
DURATION_LITERAL
: (DECIMAL_LITERAL+ (Y|M O|W|D|H|M|S|M S|U S|N S))+
;
DATETIME_LITERAL
: DECIMAL_LITERAL ('-'|'/') DECIMAL_LITERAL ('-'|'/') DECIMAL_LITERAL ((T | WS)
DECIMAL_LITERAL ':' DECIMAL_LITERAL ':' DECIMAL_LITERAL (DOT DECIMAL_LITERAL)?
(('+' | '-') DECIMAL_LITERAL ':' DECIMAL_LITERAL)?)?
| NOW LR_BRACKET RR_BRACKET
;
```
由于语法分析器中对这一部分的使用比较灵活,因此在语法分析器中还设计了datetimeLiteral。后续可以研究一下这一部分是否可以继续优化。
```
datetimeLiteral
: DATETIME_LITERAL
| dateExpression
| INTEGER_LITERAL
;
dateExpression
: DATETIME_LITERAL ((PLUS | MINUS) DURATION_LITERAL)*
;
```
6.3 数字型
```
INTEGER_LITERAL
: DEC_DIGIT+
;
EXPONENT_NUM_PART
: DEC_DIGIT+ ('e'|'E') ('+'|'-')? DEC_DIGIT+
;
fragment DEC_DIGIT: [0-9];
```
另外,实数型字面量定义在语法分析中。这是因为 EXPONENT_NUM_PART 允许出行在路径中(如root.1e-3),后续可以讨论一下路径中节点命名的规范问题,看看这里能不能优化掉。
```
realLiteral
: INTEGER_LITERAL DOT (INTEGER_LITERAL|EXPONENT_NUM_PART)?
| DOT (INTEGER_LITERAL|EXPONENT_NUM_PART)
| EXPONENT_NUM_PART
;
```
6.4 布尔型
```
BOOLEAN_LITERAL
: T R U E
| F A L S E
;
```
6.5 其他类型
```
NULL_LITERAL
: N U L L
;
NAN_LITERAL
: N A N
;
```
7. 标识符
```
ID
: FIRST_NAME_CHAR NAME_CHAR*
;
fragment NAME_CHAR
: 'A'..'Z'
| 'a'..'z'
| '0'..'9'
| '_'
| '-'
| ':'
| '/'
| '@'
| '#'
| '$'
| '%'
| '&'
| '+'
| '{'
| '}'
| CN_CHAR
;
fragment FIRST_NAME_CHAR
: 'A'..'Z'
| 'a'..'z'
| '0'..'9'
| '_'
| '/'
| '@'
| '#'
| '$'
| '%'
| '&'
| '+'
| '{'
| '}'
| CN_CHAR
;
fragment CN_CHAR
: '\u2E80'..'\u9FFF'
;
```
语法分析器(IoTDBSqlParser)包括:(按照匹配优先级排序)
1. 整体结构
```
singleStatement
: DEBUG? statement SEMI? EOF
;
statement
: ddlStatement | dmlStatement | dclStatement | utilityStatement
;
ddlStatement
: setStorageGroup | createStorageGroup | createTimeseries
| createFunction | createTrigger | createContinuousQuery | createSnapshot
| alterTimeseries | deleteStorageGroup | deleteTimeseries | deletePartition
| dropFunction | dropTrigger | dropContinuousQuery
| setTTL | unsetTTL | startTrigger | stopTrigger
| showStorageGroup | showDevices | showTimeseries | showChildPaths | showChildNodes
| showFunctions | showTriggers | showContinuousQueries | showTTL | showAllTTL
| countStorageGroup | countDevices | countTimeseries | countNodes
;
dmlStatement
: selectStatement | insertStatement | deleteStatement;
dclStatement
: createUser | createRole | alterUser | grantUser | grantRole | grantRoleToUser
| revokeUser | revokeRole | revokeRoleFromUser | dropUser | dropRole
| listUser | listRole | listPrivilegesUser | listPrivilegesRole
| listUserPrivileges | listRolePrivileges | listAllRoleOfUser | listAllUserOfRole
;
utilityStatement
: merge | fullMerge | flush | clearCache
| setSystemStatus | showVersion | showFlushInfo | showLockInfo | showMergeInfo
| showQueryProcesslist | killQuery | grantWatermarkEmbedding | revokeWatermarkEmbedding
| loadConfiguration | loadTimeseries | loadFile | removeFile | unloadFile;
```
2. 一些数据库对象的设计
路径
```
fullPath
: ROOT (DOT nodeNameWithoutWildcard)*
;
prefixPath
: ROOT (DOT nodeName)*
;
suffixPath
: nodeName (DOT nodeName)*
;
```
节点命名
```
nodeName
: ID wildcard?
| wildcard
| (ID | OPERATOR_IN)? LS_BRACKET DECIMAL_LITERAL? ID? RS_BRACKET? ID?
| literalCanBeNodeName
| keywordsCanBeNodeName
;
nodeNameWithoutWildcard
: ID
| (ID | OPERATOR_IN)? LS_BRACKET DECIMAL_LITERAL? ID? RS_BRACKET? ID?
| literalCanBeNodeName
| keywordsCanBeNodeName
;
wildcard
: STAR
| DOUBLE_STAR
;
literalCanBeNodeName
: STRING_LITERAL
| datetimeLiteral
| (MINUS|PLUS)? INTEGER_LITERAL
| (MINUS|PLUS)? EXPONENT_NUM_PART
| BOOLEAN_LITERAL
;
keywordsCanBeNodeName
: DATATYPE_VALUE
| ENCODING_VALE
| COMPRESSOR_VALUE
| PRIVILEGE_VALUE
| ... ...
```
常量/字面量
```
constant
: STRING_LITERAL
| dateExpression
| (MINUS|PLUS)? INTEGER_LITERAL
| (MINUS|PLUS)? realLiteral
| BOOLEAN_LITERAL
| NULL_LITERAL
| NAN_LITERAL
;
realLiteral
: DECIMAL_LITERAL DOT (INTEGER_LITERAL|EXPONENT_NUM_PART)?
| DOT (INTEGER_LITERAL|EXPONENT_NUM_PART)
| EXPONENT_NUM_PART
;
datetimeLiteral
: DATETIME_LITERAL
| dateExpression
| INTEGER_LITERAL
;
```
3. 表达式、谓词
```
dateExpression
: DATETIME_LITERAL ((PLUS | MINUS) DURATION_LITERAL)*
;
expression
: LR_BRACKET unaryInBracket=expression RR_BRACKET
| (PLUS | MINUS) unaryAfterSign=expression
| leftExpression=expression (STAR | DIV | MOD) rightExpression=expression
| leftExpression=expression (PLUS | MINUS) rightExpression=expression
| functionName LR_BRACKET expression (COMMA expression)* functionAttribute* RR_BRACKET
| suffixPath
| literal=STRING_LITERAL
;
functionName
: ID
| COUNT
;
functionAttribute
: COMMA functionAttributeKey=STRING_LITERAL OPERATOR_EQ functionAttributeValue=STRING_LITERAL
;
containsExpression
: name=ID OPERATOR_CONTAINS value=propertyValue
;
orExpression
: andExpression (OPERATOR_OR andExpression)*
;
andExpression
: predicate (OPERATOR_AND predicate)*
;
predicate
: (TIME | TIMESTAMP | suffixPath | fullPath) comparisonOperator constant
| (TIME | TIMESTAMP | suffixPath | fullPath) inClause
| OPERATOR_NOT? LR_BRACKET orExpression RR_BRACKET
| (suffixPath | fullPath) (REGEXP | LIKE) STRING_LITERAL
;
comparisonOperator
: type = OPERATOR_GT
| type = OPERATOR_GTE
| type = OPERATOR_LT
| type = OPERATOR_LTE
| type = OPERATOR_EQ
| type = OPERATOR_NEQ
;
inClause
: OPERATOR_NOT? OPERATOR_IN LR_BRACKET constant (COMMA constant)* RR_BRACKET
;
indexPredicateClause
: (suffixPath | fullPath) LIKE sequenceClause
| (suffixPath | fullPath) CONTAIN sequenceClause
WITH TOLERANCE constant (CONCAT sequenceClause WITH TOLERANCE constant)*
;
sequenceClause
: LR_BRACKET constant (COMMA constant)* RR_BRACKET
;
```
另外,语法分析的一点建议书写规范:使用常量和字面量时,应该增加一个“虚语法规则”,增强可读性。
如:
```
unloadFile
: UNLOAD STRING_LITERAL STRING_LITERAL
;
```
更新为:
```
unloadFile
: UNLOAD srcFileName=STRING_LITERAL dstFileDir=STRING_LITERAL
;
```
2 对部分语法进行修订
- 统一部分相近语法描述
SHOW MERGE -> SHOW MERGE INFO
SHOW FLUSH TASK INFO -> SHOW FLUSH INFO
- 删除已经不支持的语法
UPDATE prefixPath setClause whereClause? #updateStatement
SHOW METADATA #showMetadata
DESCRIBE prefixPath #describePath
CREATE INDEX ON prefixPath whereClause? indexWithClause #createIndex
DROP INDEX indexName=ID ON prefixPath #dropIndex
TRACING ON #tracingOn
TRACING OFF #tracingOff
3 需进一步讨论的点
- nodeName 命名规范
- 引用符号的使用