|
| 1 | +import { expandPhrases } from 'src/expandPhrases'; |
| 2 | +import Formatter from 'src/formatter/Formatter'; |
| 3 | +import Tokenizer from 'src/lexer/Tokenizer'; |
| 4 | +import { EOF_TOKEN, isToken, type Token, TokenType } from 'src/lexer/token'; |
| 5 | +import { keywords } from './singlestoredb.keywords'; |
| 6 | +import { functions } from './singlestoredb.functions'; |
| 7 | + |
| 8 | +const reservedCommands = expandPhrases([ |
| 9 | + // queries |
| 10 | + 'WITH', |
| 11 | + 'SELECT [ALL | DISTINCT | DISTINCTROW]', |
| 12 | + 'FROM', |
| 13 | + 'WHERE', |
| 14 | + 'GROUP BY', |
| 15 | + 'HAVING', |
| 16 | + 'ORDER BY', |
| 17 | + 'LIMIT', |
| 18 | + 'OFFSET', |
| 19 | + // Data manipulation |
| 20 | + // - insert: |
| 21 | + 'INSERT [IGNORE] [INTO]', |
| 22 | + 'VALUES', |
| 23 | + 'REPLACE [INTO]', |
| 24 | + // - update: |
| 25 | + 'UPDATE', |
| 26 | + 'SET', |
| 27 | + // - delete: |
| 28 | + 'DELETE [FROM]', |
| 29 | + // - truncate: |
| 30 | + 'TRUNCATE [TABLE]', |
| 31 | + // Data definition |
| 32 | + 'CREATE VIEW', |
| 33 | + 'CREATE [ROWSTORE] [REFERENCE | TEMPORARY | GLOBAL TEMPORARY] TABLE [IF NOT EXISTS]', |
| 34 | + 'CREATE [OR REPLACE] [TEMPORARY] PROCEDURE [IF NOT EXISTS]', |
| 35 | + 'CREATE [OR REPLACE] [EXTERNAL] FUNCTION', |
| 36 | + 'DROP [TEMPORARY] TABLE [IF EXISTS]', |
| 37 | + // - alter table: |
| 38 | + 'ALTER [ONLINE] TABLE', |
| 39 | + 'ADD [COLUMN]', |
| 40 | + 'ADD [UNIQUE] {INDEX | KEY}', |
| 41 | + 'DROP [COLUMN]', |
| 42 | + 'MODIFY [COLUMN]', |
| 43 | + 'CHANGE', |
| 44 | + 'RENAME [TO | AS]', |
| 45 | + |
| 46 | + // https://docs.singlestore.com/managed-service/en/reference/sql-reference.html |
| 47 | + 'ADD AGGREGATOR', |
| 48 | + 'ADD LEAF', |
| 49 | + 'AGGREGATOR SET AS MASTER', |
| 50 | + 'ALTER DATABASE', |
| 51 | + 'ALTER PIPELINE', |
| 52 | + 'ALTER RESOURCE POOL', |
| 53 | + 'ALTER USER', |
| 54 | + 'ALTER VIEW', |
| 55 | + 'ANALYZE TABLE', |
| 56 | + 'ATTACH DATABASE', |
| 57 | + 'ATTACH LEAF', |
| 58 | + 'ATTACH LEAF ALL', |
| 59 | + 'BACKUP DATABASE', |
| 60 | + 'BINLOG', |
| 61 | + 'BOOTSTRAP AGGREGATOR', |
| 62 | + 'CACHE INDEX', |
| 63 | + 'CALL', |
| 64 | + 'CHANGE', |
| 65 | + 'CHANGE MASTER TO', |
| 66 | + 'CHANGE REPLICATION FILTER', |
| 67 | + 'CHANGE REPLICATION SOURCE TO', |
| 68 | + 'CHECK BLOB CHECKSUM', |
| 69 | + 'CHECK TABLE', |
| 70 | + 'CHECKSUM TABLE', |
| 71 | + 'CLEAR ORPHAN DATABASES', |
| 72 | + 'CLONE', |
| 73 | + 'COMMIT', |
| 74 | + 'CREATE DATABASE', |
| 75 | + 'CREATE GROUP', |
| 76 | + 'CREATE INDEX', |
| 77 | + 'CREATE LINK', |
| 78 | + 'CREATE MILESTONE', |
| 79 | + 'CREATE PIPELINE', |
| 80 | + 'CREATE RESOURCE POOL', |
| 81 | + 'CREATE ROLE', |
| 82 | + 'CREATE USER', |
| 83 | + 'DEALLOCATE PREPARE', |
| 84 | + 'DESCRIBE', |
| 85 | + 'DETACH DATABASE', |
| 86 | + 'DETACH PIPELINE', |
| 87 | + 'DO', |
| 88 | + 'DROP DATABASE', |
| 89 | + 'DROP FUNCTION', |
| 90 | + 'DROP INDEX', |
| 91 | + 'DROP LINK', |
| 92 | + 'DROP PIPELINE', |
| 93 | + 'DROP PROCEDURE', |
| 94 | + 'DROP RESOURCE POOL', |
| 95 | + 'DROP ROLE', |
| 96 | + 'DROP USER', |
| 97 | + 'DROP VIEW', |
| 98 | + 'EXECUTE', |
| 99 | + 'EXPLAIN', |
| 100 | + 'FLUSH', |
| 101 | + 'FORCE', |
| 102 | + 'GRANT', |
| 103 | + 'HANDLER', |
| 104 | + 'HELP', |
| 105 | + 'KILL CONNECTION', |
| 106 | + 'KILLALL QUERIES', |
| 107 | + 'LOAD DATA', |
| 108 | + 'LOAD INDEX INTO CACHE', |
| 109 | + 'LOAD XML', |
| 110 | + 'LOCK INSTANCE FOR BACKUP', |
| 111 | + 'LOCK TABLES', |
| 112 | + 'MASTER_POS_WAIT', |
| 113 | + 'OPTIMIZE TABLE', |
| 114 | + 'PREPARE', |
| 115 | + 'PURGE BINARY LOGS', |
| 116 | + 'REBALANCE PARTITIONS', |
| 117 | + 'RELEASE SAVEPOINT', |
| 118 | + 'REMOVE AGGREGATOR', |
| 119 | + 'REMOVE LEAF', |
| 120 | + 'REPAIR TABLE', |
| 121 | + 'REPLACE', |
| 122 | + 'REPLICATE DATABASE', |
| 123 | + 'RESET', |
| 124 | + 'RESET MASTER', |
| 125 | + 'RESET PERSIST', |
| 126 | + 'RESET REPLICA', |
| 127 | + 'RESET SLAVE', |
| 128 | + 'RESTART', |
| 129 | + 'RESTORE DATABASE', |
| 130 | + 'RESTORE REDUNDANCY', |
| 131 | + 'REVOKE', |
| 132 | + 'ROLLBACK', |
| 133 | + 'ROLLBACK TO SAVEPOINT', |
| 134 | + 'SAVEPOINT', |
| 135 | + 'SET CHARACTER SET', |
| 136 | + 'SET DEFAULT ROLE', |
| 137 | + 'SET NAMES', |
| 138 | + 'SET PASSWORD', |
| 139 | + 'SET RESOURCE GROUP', |
| 140 | + 'SET ROLE', |
| 141 | + 'SET TRANSACTION', |
| 142 | + 'SHOW', |
| 143 | + 'SHOW CHARACTER SET', |
| 144 | + 'SHOW COLLATION', |
| 145 | + 'SHOW COLUMNS', |
| 146 | + 'SHOW CREATE DATABASE', |
| 147 | + 'SHOW CREATE FUNCTION', |
| 148 | + 'SHOW CREATE PIPELINE', |
| 149 | + 'SHOW CREATE PROCEDURE', |
| 150 | + 'SHOW CREATE TABLE', |
| 151 | + 'SHOW CREATE USER', |
| 152 | + 'SHOW CREATE VIEW', |
| 153 | + 'SHOW DATABASES', |
| 154 | + 'SHOW ENGINE', |
| 155 | + 'SHOW ENGINES', |
| 156 | + 'SHOW ERRORS', |
| 157 | + 'SHOW FUNCTION CODE', |
| 158 | + 'SHOW FUNCTION STATUS', |
| 159 | + 'SHOW GRANTS', |
| 160 | + 'SHOW INDEX', |
| 161 | + 'SHOW MASTER STATUS', |
| 162 | + 'SHOW OPEN TABLES', |
| 163 | + 'SHOW PLUGINS', |
| 164 | + 'SHOW PRIVILEGES', |
| 165 | + 'SHOW PROCEDURE CODE', |
| 166 | + 'SHOW PROCEDURE STATUS', |
| 167 | + 'SHOW PROCESSLIST', |
| 168 | + 'SHOW PROFILE', |
| 169 | + 'SHOW PROFILES', |
| 170 | + 'SHOW RELAYLOG EVENTS', |
| 171 | + 'SHOW REPLICA STATUS', |
| 172 | + 'SHOW REPLICAS', |
| 173 | + 'SHOW SLAVE', |
| 174 | + 'SHOW SLAVE HOSTS', |
| 175 | + 'SHOW STATUS', |
| 176 | + 'SHOW TABLE STATUS', |
| 177 | + 'SHOW TABLES', |
| 178 | + 'SHOW VARIABLES', |
| 179 | + 'SHOW WARNINGS', |
| 180 | + 'SHUTDOWN', |
| 181 | + 'SNAPSHOT DATABASE', |
| 182 | + 'SOURCE_POS_WAIT', |
| 183 | + 'START GROUP_REPLICATION', |
| 184 | + 'START PIPELINE', |
| 185 | + 'START REPLICA', |
| 186 | + 'START SLAVE', |
| 187 | + 'START TRANSACTION', |
| 188 | + 'STOP GROUP_REPLICATION', |
| 189 | + 'STOP PIPELINE', |
| 190 | + 'STOP REPLICA', |
| 191 | + 'STOP REPLICATING', |
| 192 | + 'STOP SLAVE', |
| 193 | + 'TEST PIPELINE', |
| 194 | + 'TRUNCATE TABLE', |
| 195 | + 'UNLOCK INSTANCE', |
| 196 | + 'UNLOCK TABLES', |
| 197 | + 'USE', |
| 198 | + 'XA', |
| 199 | + // flow control |
| 200 | + 'ITERATE', |
| 201 | + 'LEAVE', |
| 202 | + 'LOOP', |
| 203 | + 'REPEAT', |
| 204 | + 'RETURN', |
| 205 | + 'WHILE', |
| 206 | +]); |
| 207 | + |
| 208 | +const reservedSetOperations = expandPhrases([ |
| 209 | + 'UNION [ALL | DISTINCT]', |
| 210 | + 'EXCEPT', |
| 211 | + 'INTERSECT', |
| 212 | + 'MINUS', |
| 213 | +]); |
| 214 | + |
| 215 | +const reservedJoins = expandPhrases([ |
| 216 | + 'JOIN', |
| 217 | + '{LEFT | RIGHT | FULL} [OUTER] JOIN', |
| 218 | + '{INNER | CROSS} JOIN', |
| 219 | + 'NATURAL {LEFT | RIGHT} [OUTER] JOIN', |
| 220 | + // non-standard joins |
| 221 | + 'STRAIGHT_JOIN', |
| 222 | +]); |
| 223 | + |
| 224 | +const reservedPhrases = ['ON DELETE', 'ON UPDATE', 'CHARACTER SET']; |
| 225 | + |
| 226 | +export default class SingleStoreDbFormatter extends Formatter { |
| 227 | + static operators = ['~', ':=', '<=>', '<<', '>>', '&&', '||']; |
| 228 | + |
| 229 | + tokenizer() { |
| 230 | + return new Tokenizer({ |
| 231 | + reservedCommands, |
| 232 | + reservedSetOperations, |
| 233 | + reservedJoins, |
| 234 | + reservedDependentClauses: ['WHEN', 'ELSE', 'ELSEIF'], |
| 235 | + reservedPhrases, |
| 236 | + reservedLogicalOperators: ['AND', 'OR'], |
| 237 | + reservedKeywords: keywords, |
| 238 | + reservedFunctionNames: functions, |
| 239 | + // TODO: support _binary"some string" prefix |
| 240 | + stringTypes: [ |
| 241 | + { quote: "''", prefixes: ['B', 'X'] }, |
| 242 | + { quote: '""', prefixes: ['B', 'X'] }, |
| 243 | + ], |
| 244 | + identTypes: ['``'], |
| 245 | + identChars: { first: '$', rest: '$', allowFirstCharNumber: true }, |
| 246 | + variableTypes: [ |
| 247 | + { regex: '@[A-Za-z0-9_$]+' }, |
| 248 | + { quote: '``', prefixes: ['@'], requirePrefix: true }, |
| 249 | + ], |
| 250 | + lineCommentTypes: ['--', '#'], |
| 251 | + operators: SingleStoreDbFormatter.operators, |
| 252 | + postProcess, |
| 253 | + }); |
| 254 | + } |
| 255 | +} |
| 256 | + |
| 257 | +function postProcess(tokens: Token[]) { |
| 258 | + return tokens.map((token, i) => { |
| 259 | + const nextToken = tokens[i + 1] || EOF_TOKEN; |
| 260 | + if (isToken.SET(token) && nextToken.text === '(') { |
| 261 | + // This is SET datatype, not SET statement |
| 262 | + return { ...token, type: TokenType.RESERVED_FUNCTION_NAME }; |
| 263 | + } |
| 264 | + return token; |
| 265 | + }); |
| 266 | +} |
0 commit comments