feat: optimize suggestion (#231)
* feat: optimize the strategy of finding the right range * test: apply commentOtherLine util to all suggestion tests * test: decomment suggestion test cases * test: add suggestion test cases in multiple statements * chore: improve comments * test: update log info in test
This commit is contained in:
parent
fd50c09a86
commit
3c7c59fb70
@ -277,55 +277,74 @@ export default abstract class BasicParser<
|
||||
|
||||
/**
|
||||
* Split sql by statement.
|
||||
* Try to collect candidates from the caret statement only.
|
||||
* Try to collect candidates in as small a range as possible.
|
||||
*/
|
||||
this.listen(splitListener, this._parseTree);
|
||||
const statementCount = splitListener.statementsContext?.length;
|
||||
const statementsContext = splitListener.statementsContext;
|
||||
|
||||
// If there are multiple statements.
|
||||
if (splitListener.statementsContext.length > 1) {
|
||||
// find statement rule context where caretPosition is located.
|
||||
const caretStatementContext = splitListener?.statementsContext.find((ctx) => {
|
||||
return (
|
||||
caretTokenIndex <= ctx.stop?.tokenIndex &&
|
||||
caretTokenIndex >= ctx.start.tokenIndex
|
||||
);
|
||||
});
|
||||
if (statementCount > 1) {
|
||||
/**
|
||||
* Find a minimum valid range, reparse the fragment, and provide a new parse tree to C3.
|
||||
* The boundaries of this range must be statements with no syntax errors.
|
||||
* This can ensure the stable performance of the C3.
|
||||
*/
|
||||
let startStatement: ParserRuleContext;
|
||||
let stopStatement: ParserRuleContext;
|
||||
|
||||
for (let index = 0; index < statementCount; index++) {
|
||||
const ctx = statementsContext[index];
|
||||
const isCurrentCtxValid = !ctx.exception;
|
||||
if (!isCurrentCtxValid) continue;
|
||||
|
||||
if (caretStatementContext) {
|
||||
c3Context = caretStatementContext;
|
||||
} else {
|
||||
const lastStatementToken =
|
||||
splitListener.statementsContext[splitListener?.statementsContext.length - 1]
|
||||
.start;
|
||||
/**
|
||||
* If caretStatementContext is not found and it follows all statements.
|
||||
* Reparses part of the input following the penultimate statement.
|
||||
* And c3 will collect candidates in the new parseTreeContext.
|
||||
* Ensure that the statementContext before the left boundary
|
||||
* and the last statementContext on the right boundary are qualified SQL statements.
|
||||
*/
|
||||
if (caretTokenIndex > lastStatementToken?.tokenIndex) {
|
||||
/**
|
||||
* Save offset of the tokenIndex in the partInput
|
||||
* compared to the tokenIndex in the whole input
|
||||
*/
|
||||
tokenIndexOffset = lastStatementToken?.tokenIndex;
|
||||
// Correct caretTokenIndex
|
||||
caretTokenIndex = caretTokenIndex - tokenIndexOffset;
|
||||
const isPrevCtxValid = index === 0 || !statementsContext[index - 1]?.exception;
|
||||
const isNextCtxValid =
|
||||
index === statementCount - 1 || !statementsContext[index + 1]?.exception;
|
||||
|
||||
const inputSlice = input.slice(lastStatementToken.startIndex);
|
||||
const lexer = this.createLexer(inputSlice);
|
||||
lexer.removeErrorListeners();
|
||||
if (ctx.stop.tokenIndex < caretTokenIndex && isPrevCtxValid) {
|
||||
startStatement = ctx;
|
||||
}
|
||||
|
||||
const tokenStream = new CommonTokenStream(lexer);
|
||||
tokenStream.fill();
|
||||
const parser = this.createParserFromTokenStream(tokenStream);
|
||||
parser.removeErrorListeners();
|
||||
parser.buildParseTree = true;
|
||||
parser.errorHandler = new ErrorStrategy();
|
||||
|
||||
sqlParserIns = parser;
|
||||
c3Context = parser.program();
|
||||
if (!stopStatement && ctx.start.tokenIndex > caretTokenIndex && isNextCtxValid) {
|
||||
stopStatement = ctx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// A boundary consisting of the index of the input.
|
||||
const startIndex = startStatement?.start?.startIndex ?? 0;
|
||||
const stopIndex = stopStatement?.stop?.stopIndex ?? input.length - 1;
|
||||
|
||||
/**
|
||||
* Save offset of the tokenIndex in the range of input
|
||||
* compared to the tokenIndex in the whole input
|
||||
*/
|
||||
tokenIndexOffset = startStatement?.start?.tokenIndex ?? 0;
|
||||
caretTokenIndex = caretTokenIndex - tokenIndexOffset;
|
||||
|
||||
/**
|
||||
* Reparse the input fragment,
|
||||
* and c3 will collect candidates in the newly generated parseTree.
|
||||
*/
|
||||
const inputSlice = input.slice(startIndex, stopIndex);
|
||||
|
||||
const lexer = this.createLexer(inputSlice);
|
||||
lexer.removeErrorListeners();
|
||||
const tokenStream = new CommonTokenStream(lexer);
|
||||
tokenStream.fill();
|
||||
|
||||
const parser = this.createParserFromTokenStream(tokenStream);
|
||||
parser.removeErrorListeners();
|
||||
parser.buildParseTree = true;
|
||||
parser.errorHandler = new ErrorStrategy();
|
||||
|
||||
sqlParserIns = parser;
|
||||
c3Context = parser.program();
|
||||
}
|
||||
|
||||
const core = new CodeCompletionCore(sqlParserIns);
|
||||
|
@ -1,19 +0,0 @@
|
||||
CREATE TABLE orders (
|
||||
order_uid BIGINT,
|
||||
product_id BIGINT,
|
||||
price DECIMAL(32, 2),
|
||||
order_time TIMESTAMP(3)
|
||||
) WITH (
|
||||
'connector' = 'datagen'
|
||||
);
|
||||
|
||||
CREATE TABLE orders (
|
||||
order_uid BIGINT,
|
||||
product_id BIGINT,
|
||||
price DECIMAL(32, 2),
|
||||
order_time TIMESTAMP(3)
|
||||
) WITH (
|
||||
'connector' = 'datagen'
|
||||
);
|
||||
|
||||
use cat1.
|
@ -0,0 +1,31 @@
|
||||
SELECT * FROM -- unfinished
|
||||
|
||||
CREATE TEMPORARY VIEW IF NOT EXISTS v AS SELECT col1 FROM tbl;
|
||||
|
||||
CREATE TEMPORARY TABLE client_errors (
|
||||
log_time TIMESTAMP(3),
|
||||
request_line STRING,
|
||||
status_code STRING,
|
||||
size INT
|
||||
) WITH (
|
||||
'connector' = 'stream-x'
|
||||
);
|
||||
|
||||
ALTER VIEW v1 RENAME TO v2;
|
||||
|
||||
CREATE TABLE db. ; -- unfinished
|
||||
|
||||
LOAD MODULE CORE;
|
||||
|
||||
REMOVE JAR '<path_to_filename>.jar'
|
||||
|
||||
INSERT INTO VALUES (100, 99.9 / 10, 'abc', true, now ()); -- unfinished
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS dataApi COMMENT 'test create database' WITH ('key1' = 'value1', 'key2.a' = 'value2.a');
|
||||
|
||||
DROP DATABASE IF EXISTS Orders RESTRICT;
|
||||
|
||||
INSERT INTO country_page_view
|
||||
SELECT `user`,
|
||||
cnt
|
||||
FROM db. ; -- unfinished
|
69
test/parser/flinksql/suggestion/multipleStatement.test.ts
Normal file
69
test/parser/flinksql/suggestion/multipleStatement.test.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { CaretPosition, SyntaxContextType } from '../../../../src/parser/common/basic-parser-types';
|
||||
import FlinkSQL from '../../../../src/parser/flinksql';
|
||||
|
||||
const syntaxSql = fs.readFileSync(
|
||||
path.join(__dirname, 'fixtures', 'multipleStatement.sql'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
describe('FlinkSQL Multiple Statements Syntax Suggestion', () => {
|
||||
const parser = new FlinkSQL();
|
||||
|
||||
test('Select from table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 1,
|
||||
column: 15,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Create table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 16,
|
||||
column: 17,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE_CREATE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
|
||||
test('Insert into table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 22,
|
||||
column: 13,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Insert into select from table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 31,
|
||||
column: 9,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
});
|
@ -8,7 +8,6 @@ const syntaxSql = fs.readFileSync(
|
||||
path.join(__dirname, 'fixtures', 'syntaxSuggestion.sql'),
|
||||
'utf-8'
|
||||
);
|
||||
const multipleSql = fs.readFileSync(path.join(__dirname, 'fixtures', 'multipleSql.sql'), 'utf-8');
|
||||
|
||||
describe('Flink SQL Syntax Suggestion', () => {
|
||||
const parser = new FlinkSQL();
|
||||
@ -19,20 +18,6 @@ describe('Flink SQL Syntax Suggestion', () => {
|
||||
expect(parser.validate(syntaxSql).length).not.toBe(0);
|
||||
});
|
||||
|
||||
test('Multiple SQL use database', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 19,
|
||||
column: 10,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(multipleSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.DATABASE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['cat1', '.']);
|
||||
});
|
||||
|
||||
test('Drop catalog', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 1,
|
||||
|
@ -2,6 +2,7 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { CaretPosition } from '../../../../src/parser/common/basic-parser-types';
|
||||
import FlinkSQL from '../../../../src/parser/flinksql';
|
||||
import { commentOtherLine } from '../../../helper';
|
||||
|
||||
const tokenSql = fs.readFileSync(path.join(__dirname, 'fixtures', 'tokenSuggestion.sql'), 'utf-8');
|
||||
|
||||
@ -13,7 +14,10 @@ describe('Flink SQL Token Suggestion', () => {
|
||||
lineNumber: 3,
|
||||
column: 5,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual(['MODULES', 'CATALOG']);
|
||||
});
|
||||
@ -23,7 +27,10 @@ describe('Flink SQL Token Suggestion', () => {
|
||||
lineNumber: 5,
|
||||
column: 8,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual([
|
||||
'CATALOG',
|
||||
@ -40,7 +47,10 @@ describe('Flink SQL Token Suggestion', () => {
|
||||
lineNumber: 7,
|
||||
column: 6,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual([
|
||||
'MODULES',
|
||||
|
21
test/parser/hive/suggestion/fixtures/multipleStatement.sql
Normal file
21
test/parser/hive/suggestion/fixtures/multipleStatement.sql
Normal file
@ -0,0 +1,21 @@
|
||||
SELECT * FROM -- unfinished
|
||||
|
||||
CREATE VIEW mydb.bro_view AS SELECT * FROM mydb.sale_tbl;
|
||||
|
||||
CREATE TEMPORARY EXTERNAL TABLE list_bucket_multiple (col1 STRING, col2 INT, col3 STRING);
|
||||
|
||||
ALTER VIEW myview1 SET TBLPROPERTIES ('author'='hayden','date'='2023-09-04')
|
||||
|
||||
CREATE TABLE db. ; -- unfinished
|
||||
|
||||
DROP CONNECTOR connector1;
|
||||
|
||||
SET ROLE `admin`;
|
||||
|
||||
INSERT INTO VALUES (100, 99.9 / 10, 'abc', true, now ()); -- unfinished
|
||||
|
||||
ALTER TABLE tbl1 RENAME TO tbl2;
|
||||
|
||||
ALTER SCHEMA database_name SET OWNER USER `admin`;
|
||||
|
||||
INSERT OVERWRITE LOCAL DIRECTORY '/path/to/output' SELECT col1, col2 FROM ; -- unfinished
|
69
test/parser/hive/suggestion/multipleStatement.test.ts
Normal file
69
test/parser/hive/suggestion/multipleStatement.test.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { CaretPosition, SyntaxContextType } from '../../../../src/parser/common/basic-parser-types';
|
||||
import HiveSQL from '../../../../src/parser/hive';
|
||||
|
||||
const syntaxSql = fs.readFileSync(
|
||||
path.join(__dirname, 'fixtures', 'multipleStatement.sql'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
describe('HiveSQL Multiple Statements Syntax Suggestion', () => {
|
||||
const parser = new HiveSQL();
|
||||
|
||||
test('Select from table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 1,
|
||||
column: 15,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Create table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 9,
|
||||
column: 17,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE_CREATE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
|
||||
test('Insert into table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 15,
|
||||
column: 13,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Insert into select from table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 21,
|
||||
column: 75,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
});
|
@ -2,6 +2,7 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { CaretPosition } from '../../../../src/parser/common/basic-parser-types';
|
||||
import HiveSQL from '../../../../src/parser/hive';
|
||||
import { commentOtherLine } from '../../../helper';
|
||||
|
||||
const tokenSql = fs.readFileSync(path.join(__dirname, 'fixtures', 'tokenSuggestion.sql'), 'utf-8');
|
||||
|
||||
@ -13,7 +14,10 @@ describe('Hive SQL Token Suggestion', () => {
|
||||
lineNumber: 1,
|
||||
column: 7,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
expect(suggestion).toEqual([
|
||||
'APPLICATION',
|
||||
'GROUP',
|
||||
@ -37,7 +41,10 @@ describe('Hive SQL Token Suggestion', () => {
|
||||
lineNumber: 3,
|
||||
column: 8,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
expect(suggestion).toEqual([
|
||||
'CONNECTOR',
|
||||
'APPLICATION',
|
||||
@ -69,7 +76,10 @@ describe('Hive SQL Token Suggestion', () => {
|
||||
lineNumber: 5,
|
||||
column: 8,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
expect(suggestion).toEqual(['FROM']);
|
||||
});
|
||||
|
||||
@ -78,7 +88,10 @@ describe('Hive SQL Token Suggestion', () => {
|
||||
lineNumber: 7,
|
||||
column: 10,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
expect(suggestion).toEqual([
|
||||
'EXTENDED',
|
||||
'FORMATTED',
|
||||
@ -94,7 +107,10 @@ describe('Hive SQL Token Suggestion', () => {
|
||||
lineNumber: 9,
|
||||
column: 6,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
expect(suggestion).toEqual([
|
||||
'CONNECTOR',
|
||||
'APPLICATION',
|
||||
@ -121,7 +137,10 @@ describe('Hive SQL Token Suggestion', () => {
|
||||
lineNumber: 11,
|
||||
column: 8,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
expect(suggestion).toEqual(['TABLE']);
|
||||
});
|
||||
|
||||
@ -130,7 +149,10 @@ describe('Hive SQL Token Suggestion', () => {
|
||||
lineNumber: 13,
|
||||
column: 8,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
expect(suggestion).toEqual(['FROM', 'TABLE', 'EXTERNAL']);
|
||||
});
|
||||
|
||||
@ -139,7 +161,10 @@ describe('Hive SQL Token Suggestion', () => {
|
||||
lineNumber: 15,
|
||||
column: 8,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
expect(suggestion).toEqual(['INTO', 'OVERWRITE']);
|
||||
});
|
||||
|
||||
@ -148,7 +173,10 @@ describe('Hive SQL Token Suggestion', () => {
|
||||
lineNumber: 17,
|
||||
column: 6,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
expect(suggestion).toEqual(['DATA']);
|
||||
});
|
||||
|
||||
@ -157,7 +185,10 @@ describe('Hive SQL Token Suggestion', () => {
|
||||
lineNumber: 19,
|
||||
column: 6,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
expect(suggestion).toEqual([
|
||||
'CURRENT',
|
||||
'ROLES',
|
||||
|
21
test/parser/impala/suggestion/fixtures/multipleStatement.sql
Normal file
21
test/parser/impala/suggestion/fixtures/multipleStatement.sql
Normal file
@ -0,0 +1,21 @@
|
||||
SELECT * FROM -- unfinished
|
||||
|
||||
CREATE VIEW my_view AS SELECT * FROM my_table;
|
||||
|
||||
create table census (name string, census_year int) partitioned by (year int);
|
||||
|
||||
ALTER VIEW v1 RENAME TO db2.v2;
|
||||
|
||||
CREATE TABLE db. ; -- unfinished
|
||||
|
||||
INSERT INTO target_table (col1, col2, col3) PARTITION (year = 2016, month IN (10, 11, 12)) SELECT * FROM dual;
|
||||
|
||||
EXPLAIN INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three');
|
||||
|
||||
INSERT INTO VALUES (100, 99.9 / 10, 'abc', true, now ()); -- unfinished
|
||||
|
||||
ALTER TABLE my_table REPLACE COLUMNS (age INT COMMENT 'Updated Age');
|
||||
|
||||
ALTER DATABASE my_db SET OWNER USER 'impala';
|
||||
|
||||
INSERT INTO t2 (c1) SELECT c1 FROM t1.; -- unfinished
|
69
test/parser/impala/suggestion/multipleStatement.test.ts
Normal file
69
test/parser/impala/suggestion/multipleStatement.test.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { CaretPosition, SyntaxContextType } from '../../../../src/parser/common/basic-parser-types';
|
||||
import ImpalaSQL from '../../../../src/parser/impala';
|
||||
|
||||
const syntaxSql = fs.readFileSync(
|
||||
path.join(__dirname, 'fixtures', 'multipleStatement.sql'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
describe('ImpalaSQL Multiple Statements Syntax Suggestion', () => {
|
||||
const parser = new ImpalaSQL();
|
||||
|
||||
test('Select from table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 1,
|
||||
column: 15,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Create table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 9,
|
||||
column: 17,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE_CREATE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
|
||||
test('Insert into table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 15,
|
||||
column: 13,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Insert into select from table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 21,
|
||||
column: 39,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['t1', '.']);
|
||||
});
|
||||
});
|
@ -2,6 +2,7 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { CaretPosition, SyntaxContextType } from '../../../../src/parser/common/basic-parser-types';
|
||||
import ImpalaSQL from '../../../../src/parser/impala';
|
||||
import { commentOtherLine } from '../../../helper';
|
||||
|
||||
const syntaxSql = fs.readFileSync(
|
||||
path.join(__dirname, 'fixtures', 'syntaxSuggestion.sql'),
|
||||
@ -16,7 +17,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 1,
|
||||
column: 20,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
@ -30,7 +34,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 3,
|
||||
column: 27,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.FUNCTION
|
||||
);
|
||||
@ -44,7 +51,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 5,
|
||||
column: 19,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.DATABASE
|
||||
);
|
||||
@ -58,7 +68,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 7,
|
||||
column: 21,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
@ -72,7 +85,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 7,
|
||||
column: 39,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.COLUMN
|
||||
);
|
||||
@ -86,7 +102,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 9,
|
||||
column: 19,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.VIEW
|
||||
);
|
||||
@ -100,7 +119,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 11,
|
||||
column: 12,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.VIEW
|
||||
);
|
||||
@ -114,7 +136,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 13,
|
||||
column: 20,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.DATABASE
|
||||
);
|
||||
@ -128,7 +153,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 15,
|
||||
column: 20,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
@ -142,7 +170,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 17,
|
||||
column: 22,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.FUNCTION
|
||||
);
|
||||
@ -156,7 +187,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 19,
|
||||
column: 21,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
@ -170,7 +204,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 21,
|
||||
column: 15,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.VIEW_CREATE
|
||||
);
|
||||
@ -184,7 +221,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 23,
|
||||
column: 20,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE_CREATE
|
||||
);
|
||||
@ -198,7 +238,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 25,
|
||||
column: 20,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.FUNCTION_CREATE
|
||||
);
|
||||
@ -212,7 +255,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 27,
|
||||
column: 25,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.DATABASE_CREATE
|
||||
);
|
||||
@ -226,7 +272,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 29,
|
||||
column: 19,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
@ -240,7 +289,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 31,
|
||||
column: 22,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
@ -254,7 +306,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 33,
|
||||
column: 22,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
@ -268,7 +323,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 35,
|
||||
column: 20,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.VIEW
|
||||
);
|
||||
@ -282,7 +340,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 37,
|
||||
column: 22,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.COLUMN
|
||||
);
|
||||
@ -296,7 +357,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 39,
|
||||
column: 22,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.COLUMN
|
||||
);
|
||||
@ -310,7 +374,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 41,
|
||||
column: 36,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.COLUMN_CREATE
|
||||
);
|
||||
@ -324,7 +391,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 43,
|
||||
column: 36,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.COLUMN_CREATE
|
||||
);
|
||||
@ -338,7 +408,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 45,
|
||||
column: 45,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.COLUMN_CREATE
|
||||
);
|
||||
@ -352,7 +425,10 @@ describe('Impala SQL Syntax Suggestion', () => {
|
||||
lineNumber: 47,
|
||||
column: 49,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.COLUMN_CREATE
|
||||
);
|
||||
|
@ -14,7 +14,10 @@ describe('Impala SQL Token Suggestion', () => {
|
||||
lineNumber: 1,
|
||||
column: 7,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual(['TABLE', 'VIEW', 'DATABASE']);
|
||||
});
|
||||
|
21
test/parser/mysql/suggestion/fixtures/multipleStatement.sql
Normal file
21
test/parser/mysql/suggestion/fixtures/multipleStatement.sql
Normal file
@ -0,0 +1,21 @@
|
||||
SELECT * FROM -- unfinished
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS db_name DEFAULT ENCRYPTION 'Y';
|
||||
|
||||
CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (a), KEY(b)) ENGINE=InnoDB SELECT b,c FROM test2;
|
||||
|
||||
ALTER LOGFILE GROUP lg_3 ADD UNDOFILE 'undo_10.dat' INITIAL_SIZE=32M ENGINE=NDBCLUSTER;
|
||||
|
||||
CREATE TABLE db. LIKE orig_tbl; -- unfinished
|
||||
|
||||
INSERT HIGH_PRIORITY IGNORE INTO tbl_temp2 (fld_id) VALUES ROW(1,-2,3), ROW(5,7,9), ROW(4,6,8);
|
||||
|
||||
CHANGE REPLICATION FILTER REPLICATE_DO_DB = (db3, db4);
|
||||
|
||||
INSERT INTO VALUES (1,2,3),(4,5,6) ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b); -- unfinished
|
||||
|
||||
ALTER FUNCTION function_name LANGUAGE SQL;
|
||||
|
||||
ALTER FUNCTION function_name NOT DETERMINISTIC;
|
||||
|
||||
INSERT LOW_PRIORITY IGNORE INTO tbl_temp2 (fld_id) SELECT tbl_temp1.fld_order_id FROM -- unfinished
|
69
test/parser/mysql/suggestion/multipleStatement.test.ts
Normal file
69
test/parser/mysql/suggestion/multipleStatement.test.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { CaretPosition, SyntaxContextType } from '../../../../src/parser/common/basic-parser-types';
|
||||
import MySQL from '../../../../src/parser/mysql';
|
||||
|
||||
const syntaxSql = fs.readFileSync(
|
||||
path.join(__dirname, 'fixtures', 'multipleStatement.sql'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
describe('MySQL Multiple Statements Syntax Suggestion', () => {
|
||||
const parser = new MySQL();
|
||||
|
||||
test('Select from table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 1,
|
||||
column: 15,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Create table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 9,
|
||||
column: 17,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE_CREATE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
|
||||
test('Insert into table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 15,
|
||||
column: 13,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Insert into select from table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 21,
|
||||
column: 87,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
});
|
@ -50,23 +50,22 @@ describe('MySQL Syntax Suggestion', () => {
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
|
||||
// TODO: fix bug of basic parser and decomment following test
|
||||
// test('Create table ', () => {
|
||||
// const pos: CaretPosition = {
|
||||
// lineNumber: 5,
|
||||
// column: 17,
|
||||
// };
|
||||
// const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
// commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
// pos
|
||||
// )?.syntax;
|
||||
// const suggestion = syntaxes?.find(
|
||||
// (syn) => syn.syntaxContextType === SyntaxContextType.TABLE_CREATE
|
||||
// );
|
||||
test('Create table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 5,
|
||||
column: 17,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE_CREATE
|
||||
);
|
||||
|
||||
// expect(suggestion).not.toBeUndefined();
|
||||
// expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
// });
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
|
||||
test('DROP table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
|
@ -42,7 +42,7 @@ describe('MySQL Database Administration Syntax Tests', () => {
|
||||
it(sql, () => {
|
||||
const result = parser.validate(sql);
|
||||
if (result.length) {
|
||||
console.log(result, `\n请检查 sql: ${sql}`);
|
||||
console.log(result, `\nPlease check sql: ${sql}`);
|
||||
}
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
|
@ -49,7 +49,7 @@ describe('MySQL DDL Syntax Tests', () => {
|
||||
it(sql, () => {
|
||||
const result = parser.validate(sql);
|
||||
if (result.length) {
|
||||
console.log(result, `\n请检查 sql: ${sql}`);
|
||||
console.log(result, `\nPlease check sql: ${sql}`);
|
||||
}
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
|
@ -33,7 +33,7 @@ describe('MySQL DML Syntax Tests', () => {
|
||||
it(sql, () => {
|
||||
const result = parser.validate(sql);
|
||||
if (result.length) {
|
||||
console.log(result, `\n请检查 sql: ${sql}`);
|
||||
console.log(result, `\nPlease check sql: ${sql}`);
|
||||
}
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
|
@ -27,7 +27,7 @@ describe('MySQL Transactional and Locking, Replication, Prepared Compound and Ut
|
||||
it(sql, () => {
|
||||
const result = parser.validate(sql);
|
||||
if (result.length) {
|
||||
console.log(result, `\n请检查 sql: ${sql}`);
|
||||
console.log(result, `\nPlease check sql: ${sql}`);
|
||||
}
|
||||
expect(result.length).toBe(0);
|
||||
});
|
||||
|
21
test/parser/pgsql/suggestion/fixtures/multipleStatement.sql
Normal file
21
test/parser/pgsql/suggestion/fixtures/multipleStatement.sql
Normal file
@ -0,0 +1,21 @@
|
||||
CREATE TABLE VALUES -- unfinished
|
||||
|
||||
CREATE UNLOGGED TABLE table1 (col1 int) INHERITS (table_parent) WITHOUT OIDS ON COMMIT DROP;
|
||||
|
||||
CREATE SCHEMA schemaname AUTHORIZATION username;
|
||||
|
||||
ALTER TABLE products ADD FOREIGN KEY (product_group_id) REFERENCES product_groups;
|
||||
|
||||
SELECT * FROM db. ; -- unfinished
|
||||
|
||||
INSERT INTO weather (date, city, temp_hi, temp_lo) VALUES ('1994-11-29', 'Hayward', 54, 37);
|
||||
|
||||
ANALYZE VERBOSE table_name ( column_name, column_name2);
|
||||
|
||||
INSERT INTO weather (date, city, temp_hi, temp_lo) VALUES ('1994-11-29', 'Hayward', 54, 37); -- unfinished
|
||||
|
||||
DROP TABLE products CASCADE;
|
||||
|
||||
DROP AGGREGATE aggname2(int);
|
||||
|
||||
INSERT INTO products (product_no, name, price) SELECT * FROM db. ; -- unfinished
|
69
test/parser/pgsql/suggestion/multipleStatement.test.ts
Normal file
69
test/parser/pgsql/suggestion/multipleStatement.test.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { CaretPosition, SyntaxContextType } from '../../../../src/parser/common/basic-parser-types';
|
||||
import PgSQL from '../../../../src/parser/pgsql';
|
||||
|
||||
const syntaxSql = fs.readFileSync(
|
||||
path.join(__dirname, 'fixtures', 'multipleStatement.sql'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
describe('PgSQL Multiple Statements Syntax Suggestion', () => {
|
||||
const parser = new PgSQL();
|
||||
|
||||
test('Create table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 1,
|
||||
column: 14,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE_CREATE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Select from table', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 9,
|
||||
column: 18,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
|
||||
test('Insert into table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 15,
|
||||
column: 13,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Insert into select from table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 21,
|
||||
column: 65,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
});
|
@ -638,29 +638,28 @@ describe('Postgre SQL Syntax Suggestion', () => {
|
||||
lineNumber: 59,
|
||||
column: 48,
|
||||
};
|
||||
// const pos1: CaretPosition = {
|
||||
// lineNumber: 59,
|
||||
// column: 93,
|
||||
// };
|
||||
const pos1: CaretPosition = {
|
||||
lineNumber: 59,
|
||||
column: 93,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos.lineNumber),
|
||||
pos
|
||||
)?.syntax;
|
||||
// const syntaxes1 = parser.getSuggestionAtCaretPosition(
|
||||
// commentOtherLine(syntaxSql, pos1.lineNumber),
|
||||
// pos1
|
||||
// )?.syntax;
|
||||
const syntaxes1 = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(syntaxSql, pos1.lineNumber),
|
||||
pos1
|
||||
)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.COLUMN
|
||||
);
|
||||
// const suggestion1 = syntaxes1?.find(
|
||||
// (syn) => syn.syntaxContextType === SyntaxContextType.FUNCTION
|
||||
// );
|
||||
const suggestion1 = syntaxes1?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.FUNCTION
|
||||
);
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['column_name']);
|
||||
// TODO: fix bug of basic parser and decomment following case
|
||||
// expect(suggestion1).not.toBeUndefined();
|
||||
// expect(suggestion1?.wordRanges.map((token) => token.text)).toEqual(['function_name']);
|
||||
expect(suggestion1).not.toBeUndefined();
|
||||
expect(suggestion1?.wordRanges.map((token) => token.text)).toEqual(['function_name']);
|
||||
});
|
||||
|
||||
test('GRANT With Column', () => {
|
||||
|
21
test/parser/spark/suggestion/fixtures/multipleStatement.sql
Normal file
21
test/parser/spark/suggestion/fixtures/multipleStatement.sql
Normal file
@ -0,0 +1,21 @@
|
||||
CREATE TABLE VALUES -- unfinished
|
||||
|
||||
CREATE TABLE student (id INT, name STRING, age INT) STORED AS ORC;
|
||||
|
||||
CREATE SCHEMA customer_db WITH DBPROPERTIES (ID=001, Name='John');
|
||||
|
||||
ALTER TABLE StudentInfo ADD COLUMNS (LastName string, DOB timestamp);
|
||||
|
||||
SELECT * FROM db. ; -- unfinished
|
||||
|
||||
INSERT INTO weather (date, city, temp_hi, temp_lo) VALUES ('1994-11-29', 'Hayward', 54, 37);
|
||||
|
||||
DESC EXTENDED students name;
|
||||
|
||||
INSERT INTO weather (date, city, temp_hi, temp_lo) VALUES ('1994-11-29', 'Hayward', 54, 37); -- unfinished
|
||||
|
||||
DROP TABLE IF EXISTS employable;
|
||||
|
||||
DROP TEMPORARY FUNCTION test_avg;
|
||||
|
||||
INSERT INTO products (product_no, name, price) SELECT * FROM db. ; -- unfinished
|
69
test/parser/spark/suggestion/multipleStatement.test.ts
Normal file
69
test/parser/spark/suggestion/multipleStatement.test.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { CaretPosition, SyntaxContextType } from '../../../../src/parser/common/basic-parser-types';
|
||||
import SparkSQL from '../../../../src/parser/spark';
|
||||
|
||||
const syntaxSql = fs.readFileSync(
|
||||
path.join(__dirname, 'fixtures', 'multipleStatement.sql'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
describe('SparkSQL Multiple Statements Syntax Suggestion', () => {
|
||||
const parser = new SparkSQL();
|
||||
|
||||
test('Create table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 1,
|
||||
column: 14,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE_CREATE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Select from table', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 9,
|
||||
column: 18,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
|
||||
test('Insert into table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 15,
|
||||
column: 13,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Insert into select from table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 21,
|
||||
column: 65,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
});
|
@ -2,6 +2,7 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { CaretPosition } from '../../../../src/parser/common/basic-parser-types';
|
||||
import SparkSQL from '../../../../src/parser/spark';
|
||||
import { commentOtherLine } from '../../../helper';
|
||||
|
||||
const tokenSql = fs.readFileSync(path.join(__dirname, 'fixtures', 'tokenSuggestion.sql'), 'utf-8');
|
||||
|
||||
@ -13,7 +14,10 @@ describe('Spark SQL Token Suggestion', () => {
|
||||
lineNumber: 1,
|
||||
column: 7,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual(['TABLE', 'INDEX', 'VIEW', 'DATABASE', 'NAMESPACE', 'SCHEMA']);
|
||||
});
|
||||
@ -23,7 +27,10 @@ describe('Spark SQL Token Suggestion', () => {
|
||||
lineNumber: 3,
|
||||
column: 8,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual([
|
||||
'TEMPORARY',
|
||||
@ -46,7 +53,10 @@ describe('Spark SQL Token Suggestion', () => {
|
||||
lineNumber: 5,
|
||||
column: 8,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual(['FROM']);
|
||||
});
|
||||
@ -56,7 +66,10 @@ describe('Spark SQL Token Suggestion', () => {
|
||||
lineNumber: 7,
|
||||
column: 10,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual([
|
||||
'WITH',
|
||||
@ -79,7 +92,10 @@ describe('Spark SQL Token Suggestion', () => {
|
||||
lineNumber: 9,
|
||||
column: 6,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual([
|
||||
'TEMPORARY',
|
||||
@ -99,7 +115,10 @@ describe('Spark SQL Token Suggestion', () => {
|
||||
lineNumber: 11,
|
||||
column: 8,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual(['OVERWRITE', 'INTO']);
|
||||
});
|
||||
@ -109,7 +128,10 @@ describe('Spark SQL Token Suggestion', () => {
|
||||
lineNumber: 13,
|
||||
column: 6,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual(['DATA']);
|
||||
});
|
||||
@ -119,7 +141,10 @@ describe('Spark SQL Token Suggestion', () => {
|
||||
lineNumber: 15,
|
||||
column: 6,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual([
|
||||
'LOCKS',
|
||||
@ -154,7 +179,10 @@ describe('Spark SQL Token Suggestion', () => {
|
||||
lineNumber: 17,
|
||||
column: 8,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual(['TABLE']);
|
||||
});
|
||||
|
@ -0,0 +1,22 @@
|
||||
CREATE TABLE VALUES -- unfinished
|
||||
|
||||
ALTER SCHEMA foo RENAME TO bar;
|
||||
|
||||
DELETE FROM t;
|
||||
|
||||
DENY SELECT ON SCHEMA s TO USER u;
|
||||
|
||||
SELECT ids FROM db. ; -- unfinished
|
||||
|
||||
INSERT INTO weather (date, city, temp_hi, temp_lo) VALUES ('1994-11-29', 'Hayward', 54, 37);
|
||||
|
||||
EXPLAIN ANALYZE VERBOSE SELECT * FROM t;
|
||||
|
||||
INSERT INTO weather (date, city, temp_hi, temp_lo) VALUES ('1994-11-29', 'Hayward', 54, 37); -- unfinished
|
||||
|
||||
DENY SELECT ON SCHEMA s TO USER u;
|
||||
|
||||
CALL catalog.schema.test();
|
||||
|
||||
INSERT INTO products (product_no, name, price) SELECT * FROM db. ; -- unfinished
|
||||
|
69
test/parser/trinosql/suggestion/multipleStatement.test.ts
Normal file
69
test/parser/trinosql/suggestion/multipleStatement.test.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { CaretPosition, SyntaxContextType } from '../../../../src/parser/common/basic-parser-types';
|
||||
import TrinoSQL from '../../../../src/parser/trinosql';
|
||||
|
||||
const syntaxSql = fs.readFileSync(
|
||||
path.join(__dirname, 'fixtures', 'multipleStatement.sql'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
describe('TrinoSQL Multiple Statements Syntax Suggestion', () => {
|
||||
const parser = new TrinoSQL();
|
||||
|
||||
test('Create table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 1,
|
||||
column: 14,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE_CREATE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Select from table', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 9,
|
||||
column: 20,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
|
||||
test('Insert into table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 15,
|
||||
column: 13,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual([]);
|
||||
});
|
||||
|
||||
test('Insert into select from table ', () => {
|
||||
const pos: CaretPosition = {
|
||||
lineNumber: 21,
|
||||
column: 65,
|
||||
};
|
||||
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
|
||||
const suggestion = syntaxes?.find(
|
||||
(syn) => syn.syntaxContextType === SyntaxContextType.TABLE
|
||||
);
|
||||
|
||||
expect(suggestion).not.toBeUndefined();
|
||||
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
|
||||
});
|
||||
});
|
@ -14,7 +14,10 @@ describe('Trino SQL Token Suggestion', () => {
|
||||
lineNumber: 1,
|
||||
column: 7,
|
||||
};
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(tokenSql, pos)?.keywords;
|
||||
const suggestion = parser.getSuggestionAtCaretPosition(
|
||||
commentOtherLine(tokenSql, pos.lineNumber),
|
||||
pos
|
||||
)?.keywords;
|
||||
|
||||
expect(suggestion).toEqual(['VIEW', 'MATERIALIZED', 'TABLE', 'SCHEMA']);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user