Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

1

...

> 划定词法分析器和语法分析器界线的经验法则:
>
> - 在词法分析器中匹配并丢弃任何语法分析器无需知晓的东西(如注释和空白符)。
>
> - 由词法分析器来匹配类似标识符、关键字、字符串和数字的常见词法符号。语法分析器的层级更高,所以我们不应当让它处理将数字组合成整数这样的事情,这会加重它的负担。
>
> - 将语法分析器无须区分的词法结构归为同一个词法符号类型。例如,如果我们的程序对待整数和浮点数的方式是一致的,那就把它们都归为NUMBER类型的词法符号。
>
> - 将任何语法分析器可以以相同方式处理的实体归为一类。例如在XML中,语法分析器不关心XML标签的内容,词法分析器就可以将尖括号中的所有内容归为一个名为TAG的词法符号类型。
>
> - 另一方面,如果语法分析器需要把一种类型的文本拆开处理,那么词法分析器就应该将它的各组成部分作为独立的词法符号输送给语法分析器。例如,如果语法分析器需要处理 IP 地址中的元素,那么词法分析器就应该把 IP 地址的各组成部分(整数和点)作为独立的词法符号送入语法分析器。
>
>   ——摘自《ANTLR 4 权威指南》

...

分离词法文件和语法文件  SqlBase.g4 -> IoTDBSqlLexer.g4 + IoTDBSqlParser.g4

...


划定词法分析器和语法分析器界线:

  • 在词法分析器中匹配并丢弃任何语法分析器无需知晓的东西(如注释和空白符)。
  • 由词法分析器来匹配类似标识符、关键字、字符串和数字的常见词法符号。语法分析器的层级更高,所以我们不应当让它处理将数字组合成整数这样的事情,这会加重它的负担。
  • 将语法分析器无须区分的词法结构归为同一个词法符号类型。例如,如果我们的程序对待整数和浮点数的方式是一致的,那就把它们都归为NUMBER类型的词法符号。
  • 将任何语法分析器可以以相同方式处理的实体归为一类。例如在XML中,语法分析器不关心XML标签的内容,词法分析器就可以将尖括号中的所有内容归为一个名为TAG的词法符号类型。
  • 另一方面,如果语法分析器需要把一种类型的文本拆开处理,那么词法分析器就应该将它的各组成部分作为独立的词法符号输送给语法分析器。例如,如果语法分析器需要处理 IP 地址中的元素,那么词法分析器就应该把 IP 地址的各组成部分(整数和点)作为独立的词法符号送入语法分析器。

词法分析器(IoTDBSqlLexer)包括:(按照匹配优先级排序)

1. 空白符

WS:[ \t\r\n]+ -> skip;

2. 关键词列表

**词法分析器(IoTDBSqlLexer)包括:**(按照匹配优先级排序)

1. 空白符

   ```
   WS
       :
       [ \t\r\n]+ -> skip
       ;
   ```

2. 关键词词组:尝试作为整个词法符号返回给语法分析器。

   - ALIGN BY DEVICE
   - CONTINUOUS QUERY
   - DISABLE ALIGN
   - GROUP BY DEVICE

3. 关键词列表(其中保留字用**“R”**标记)

   3.1 一般关键词

   - ADD
   - AFTER
   - ALIAS
   - ALIGN
   - ALL
   - ALTER **(R)**
   - ANY
   - AS
   - ASC
   - ATTRIBUTES
   - AUTOREGISTER
   - BEFORE
   - BEGIN
   - BY
   - CACHE
   - CHILD
   - CLEAR **(R)**
   - COMPRESSION
   - COMPRESSOR
   - CONCAT
   - CONFIGURATION
   - CONTAIN
   - CONTINUOUS
   - COUNT **(R)**
   - CQ
   - CQS
   - CREATE **(R)**CREATE
   - DATATYPE
   - DEBUG **(R)**
   - DELETE **(R)**
   - DESC
   - DESCRIBE (拟去除)(未使用)
   - DEVICE
   - DEVICES
   - DISABLE
   - DROP **(R)**
   - ENCODING
   - END
   - EVERY
   - EXPLAIN (拟去除)(未使用)
   - FILL
   - FLUSH **(R)**
   - FOR
   - FROM **(R)**
   - FULL **(R)**
   - FUNCTION
   - FUNCTIONS
   - GLOBAL
   - GRANT **(R)**
   - GROUP
   - INDEX (拟去除)INDEX(未使用)
   - INFO
   - INSERT **(R)**
   - INTO **(R)**INTO
   - KILL **(R)**
   - LABEL (拟去除)LABEL(未使用)
   - LAST
   - LATEST
   - LEVEL
   - LIKE
   - LIMIT **(R)**
   - LINEAR
   - LINK (拟去除)LINK(未使用)
   - LIST **(R)**
   - LOAD **(R)**
   - LOCK
   - MERGE **(R)**
   - METADATA (拟去除)METADATA(未使用)
   - NODES
   - NOW **(R)**
   - OF
   - OFF (拟去除)OFF(未使用)
   - OFFSET **(R)**
   - ON **(R)**- ON
   - ORDER
   - PARTITION
   - PASSWORD
   - PATHS
   - PREVIOUS
   - PREVIOUSUNTILLAST
   - PRIVILEGES
   - PROCESSLIST
   - PROPERTY (拟去除)(未使用)
   - QUERIES
   - QUERY
   - READONLY
   - REGEXP
   - REMOVE
   - RENAME
   - RESAMPLE
   - REVOKE **(R)**
   - ROLE
   - ROOT **(R)**
   - SCHEMA
   - SELECT **(R)**
   - SET **(R)**
   - SGLEVEL
   - SHOW **(R)**
   - SLIMIT
   - SNAPSHOT
   - SOFFSET
   - START **(R)**
   - STOP **(R)**
   - STORAGE
   - SYSTEM
   - TAGS
   - TASK (拟去除)TASK(未使用)
   - TIME **(R)**
   - TIMESERIES
   - TIMESTAMP **(R)**- TIMESTAMP
   - TO **(R)**
   - TOLERANCE
   - TOP
   - TRACING **(R)**
   - TRIGGER
   - TRIGGERS
   - TTL
   - UNLINK (拟去除)(未使用)
   - UNLOAD **(R)**
   - UNSET
   - UPDATE (拟去除)UPDATE(未使用)
   - UPSERT
   - USER
   - USING (拟去除)(未使用)
   - VALUES **(R)**
   - VERIFY
   - VERSION
   - WATERMARK_EMBEDDING
   - WHERE **(R)**
   - WITH **(R)**
   - WITHOUT
   - WRITABLE

   3.2 数据类型(作为整个语法符号返回)   ```
   DATATYPE

  DATATYPE_VALUE
       : BOOLEAN | DOUBLE | FLOAT | INT32 | INT64 | TEXT
   

...

  ;

   ```   3.3 编码类型(作为整个语法符号返回)   ```
   ENCODING

  ENCODING_VALE
       : DICTIONARY | DIFF | GORILLA | PLAIN | REGULAR | RLE | TS_2DIFF
     

...

;

...

   3.4 压缩类型(作为整个语法符号返回)   ```
   COMPRESSOR

  COMPRESSOR_VALUE
       : GZIP | LZ4 | SNAPPY | UNCOMPRESSED
   

...

  ;

...

   3.5 权限类型(作为整个语法符号返回)   ```
   PRIVILEGE

  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 :

  MINUS : '-';

...

  PLUS : '+';

...

  DIV : '/';

...

  MOD : '%';

...

   4.2 比较   ```
   OPERATOR

  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 :

  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

...

    : (INTEGER_LITERAL+ (Y|M O|W|D|H|M|S|M S|U S|N S))+

...

    ;

...


DATETIME_LITERAL

...

    : INTEGER_LITERAL ('-'|'/')

...

 INTEGER_LITERAL ('-'|'/')

...

 INTEGER_LITERAL ((T | WS)

...

      INTEGER_LITERAL ':'

...

 INTEGER_LITERAL ':'

...

 INTEGER_LITERAL (DOT

...

 INTEGER_LITERAL)?

...

      (('+' | '-')

...

 INTEGER_LITERAL ':'

...

 INTEGER_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 另外,实数型字面量定义在语法分析中。这是因为 EXPONENT_NUM_PART允许出行在路径中,后续可以讨论一下路径中节点命名的规范问题,看看这里能不能优化掉。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 | settle
       | 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
     

...

 : QUOTED_STRING_LITERAL
       | datetimeLiteral

...

        | (MINUS|PLUS)?

...

 INTEGER_LITERAL
       | (MINUS|PLUS)? EXPONENT_NUM_PART
       | BOOLEAN_LITERAL
       ;
   
   keywordsCanBeNodeName
       : DATATYPE_VALUE
       | ENCODING_VALE
     

...

 | COMPRESSOR_VALUE
 

...

      | ASC
| DESC
| DEVICE
;

   ```

   常量 & /字面量

   ```
   constant
       : STRING_LITERAL
       | dateExpression
     

...

 | (MINUS|PLUS)?

...

 INTEGER_LITERAL
       | (MINUS|PLUS)? realLiteral
       | BOOLEAN_LITERAL
       | NULL_LITERAL
       | NAN_LITERAL
       ;
   
   realLiteral
     

...

 :

...

 INTEGER_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

2. 字符串支持单引号、双引号、反引号三种符号支持。

3. 删除已经不支持的语法

   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

4. 整理了关键词和保留字列表,对于非保留字的关键词,需加入语法分析器的 keywordsCanBeNodeName 语法项中。(目前仅放了跟测试有关的几个,待讨论确认后更新)

## 3 需进一步讨论的点

1. 明确 nodeName 的命名规范。
2. 是否有其他语法建议修订,如:
   - 按照设备对齐查询去除:GROUP BY DEVICE
   - 创建存储组是否考虑只保留 CREATE?(这个改动可能比较多,需谨慎)
3. 明确关键词中哪些为保留字(上面的列表为初步设计)。
4. 引用机制的设计(宇荣)。

     SHOW LOCK 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 命名规范:

  • 引用符号的使用:

4 语法解析效率测试

实验结果:重构后与重构前性能基本不变(略有提升)

View file
nameJDBCExample.java
height250
View file
namePlannerTest.java
height250
## 4 语法解析效率测试工具的设计(尚未开始)