Feat/auto complete (#175)

* feat: update hive grammar to adapt to c3

* feat: support viewName, dbName, fnName autoComplete to hive

* test: add hive suggestion unit test

* test: optimze flink suggestion unit tests
This commit is contained in:
Hayden
2023-10-10 16:37:49 +08:00
committed by GitHub
parent d0ad381833
commit c4030929b2
14 changed files with 9376 additions and 8469 deletions

View File

@ -0,0 +1,19 @@
INSERT INTO db.tb ;
SELECT * FROM db.;
CREATE TABLE db. VALUES;
DROP TABLE IF EXISTS db.a;
CREATE OR REPLACE VIEW db.v;
DROP VIEW db.v ;
CREATE FUNCTION fn1;
SELECT name, calculate_age(birthdate) AS age FROM students;
CREATE DATABASE db;
DROP SCHEMA IF EXISTS sch;

View File

@ -0,0 +1,20 @@
ALTER
;
CREATE
;
DELETE
;
DESCRIBE
;
DROP
;
EXPORT
;
IMPORT
;
INSERT
;
LOAD
;
SHOW
;

View File

@ -0,0 +1,147 @@
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', 'syntaxSuggestion.sql'), 'utf-8');
describe('Hive SQL Syntax Suggestion', () => {
const parser = new HiveSQL();
test('Validate Syntax SQL', () => {
expect(parser.validate(syntaxSql).length).not.toBe(0);
expect(parser.validate(syntaxSql).length).not.toBe(0);
expect(parser.validate(syntaxSql).length).not.toBe(0);
});
test('Insert table ', () => {
const pos: CaretPosition = {
lineNumber: 1,
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', '.', 'tb' ])
});
test('Select table ', () => {
const pos: CaretPosition = {
lineNumber: 3,
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('Create table ', () => {
const pos: CaretPosition = {
lineNumber: 5,
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('DROP table ', () => {
const pos: CaretPosition = {
lineNumber: 7,
column: 26
}
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', '.', 'a' ])
});
test('Create view ', () => {
const pos: CaretPosition = {
lineNumber: 9,
column: 28
}
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
const suggestion = syntaxes?.find(syn => syn.syntaxContextType === SyntaxContextType.VIEW_CREATE);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map(token => token.text))
.toEqual([ 'db', '.', 'v' ])
});
test('Drop view ', () => {
const pos: CaretPosition = {
lineNumber: 11,
column: 15
}
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
const suggestion = syntaxes?.find(syn => syn.syntaxContextType === SyntaxContextType.VIEW);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map(token => token.text))
.toEqual([ 'db', '.', 'v' ])
});
test('Create function ', () => {
const pos: CaretPosition = {
lineNumber: 13,
column: 20
}
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
const suggestion = syntaxes?.find(syn => syn.syntaxContextType === SyntaxContextType.FUNCTION_CREATE);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map(token => token.text))
.toEqual([ 'fn1' ])
});
test('Use function', () => {
const pos: CaretPosition = {
lineNumber: 15,
column: 27
}
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
const suggestion = syntaxes?.find(syn => syn.syntaxContextType === SyntaxContextType.FUNCTION);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map(token => token.text))
.toEqual([ 'calculate_age' ])
});
test('Create database', () => {
const pos: CaretPosition = {
lineNumber: 17,
column: 19
}
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
const suggestion = syntaxes?.find(syn => syn.syntaxContextType === SyntaxContextType.DATABASE_CREATE);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map(token => token.text))
.toEqual([ 'db' ])
});
test('Drop database', () => {
const pos: CaretPosition = {
lineNumber: 19,
column: 26
}
const syntaxes = parser.getSuggestionAtCaretPosition(syntaxSql, pos)?.syntax;
const suggestion = syntaxes?.find(syn => syn.syntaxContextType === SyntaxContextType.DATABASE);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map(token => token.text))
.toEqual([ 'sch' ])
});
})

View File

@ -0,0 +1,232 @@
import fs from "fs";
import path from "path";
import { CaretPosition } from "../../../../src/parser/common/basic-parser-types";
import HiveSQL from "../../../../src/parser/hive";
const tokenSql = fs.readFileSync(
path.join(__dirname, "fixtures", "tokenSuggestion.sql"),
"utf-8"
);
describe("Hive SQL Syntax Suggestion", () => {
const parser = new HiveSQL();
test("After ALTER", () => {
const pos: CaretPosition = {
lineNumber: 1,
column: 7,
};
const suggestion = parser.getSuggestionAtCaretPosition(
tokenSql,
pos
)?.keywords;
expect(suggestion).toEqual([
"APPLICATION",
"GROUP",
"USER",
"POOL",
"TRIGGER",
"RESOURCE",
"SCHEDULED",
"INDEX",
"CONNECTOR",
"DATABASE",
"SCHEMA",
"MATERIALIZED",
"VIEW",
"TABLE",
]);
});
test("After CREATE", () => {
const pos: CaretPosition = {
lineNumber: 3,
column: 8,
};
const suggestion = parser.getSuggestionAtCaretPosition(
tokenSql,
pos
)?.keywords;
expect(suggestion).toEqual([
"CONNECTOR",
"APPLICATION",
"GROUP",
"USER",
"POOL",
"TRIGGER",
"RESOURCE",
"ROLE",
"INDEX",
"TEMPORARY",
"FUNCTION",
"SCHEDULED",
"MATERIALIZED",
"VIEW",
"OR",
"MANAGED",
"TABLE",
"EXTERNAL",
"TRANSACTIONAL",
"REMOTE",
"DATABASE",
"SCHEMA",
]);
});
test("After DELETE", () => {
const pos: CaretPosition = {
lineNumber: 5,
column: 8,
};
const suggestion = parser.getSuggestionAtCaretPosition(
tokenSql,
pos
)?.keywords;
expect(suggestion).toEqual(['FROM']);
});
test("After DESCRIBE", () => {
const pos: CaretPosition = {
lineNumber: 7,
column: 10,
};
const suggestion = parser.getSuggestionAtCaretPosition(
tokenSql,
pos
)?.keywords;
expect(suggestion).toEqual([
"EXTENDED",
"FORMATTED",
"FUNCTION",
"CONNECTOR",
"DATABASE",
"SCHEMA",
]);
});
test("After DROP", () => {
const pos: CaretPosition = {
lineNumber: 9,
column: 6,
};
const suggestion = parser.getSuggestionAtCaretPosition(
tokenSql,
pos
)?.keywords;
expect(suggestion).toEqual([
"CONNECTOR",
"APPLICATION",
"GROUP",
"USER",
"POOL",
"TRIGGER",
"RESOURCE",
"ROLE",
"INDEX",
"TEMPORARY",
"FUNCTION",
"MATERIALIZED",
"VIEW",
"SCHEDULED",
"TABLE",
"DATABASE",
"SCHEMA",
]);
});
test("After EXPORT", () => {
const pos: CaretPosition = {
lineNumber: 11,
column: 8,
};
const suggestion = parser.getSuggestionAtCaretPosition(
tokenSql,
pos
)?.keywords;
expect(suggestion).toEqual(['TABLE']);
});
test("After IMPORT", () => {
const pos: CaretPosition = {
lineNumber: 13,
column: 8,
};
const suggestion = parser.getSuggestionAtCaretPosition(
tokenSql,
pos
)?.keywords;
expect(suggestion).toEqual([
"FROM",
"TABLE",
"EXTERNAL",
]);
});
test("After INSERT", () => {
const pos: CaretPosition = {
lineNumber: 15,
column: 8,
};
const suggestion = parser.getSuggestionAtCaretPosition(
tokenSql,
pos
)?.keywords;
expect(suggestion).toEqual([
"INTO",
"OVERWRITE",
]);
});
test("After LOAD", () => {
const pos: CaretPosition = {
lineNumber: 17,
column: 6,
};
const suggestion = parser.getSuggestionAtCaretPosition(
tokenSql,
pos
)?.keywords;
expect(suggestion).toEqual(["DATA"
]);
});
test("After SHOW", () => {
const pos: CaretPosition = {
lineNumber: 19,
column: 6,
};
const suggestion = parser.getSuggestionAtCaretPosition(
tokenSql,
pos
)?.keywords;
expect(suggestion).toEqual([
"CURRENT",
"ROLES",
"PRINCIPALS",
"ROLE",
"GRANT",
"INDEX",
"INDEXES",
"FORMATTED",
"CONNECTORS",
"RESOURCE",
"CONF",
"TRANSACTIONS",
"COMPACTIONS",
"LOCKS",
"TBLPROPERTIES",
"TABLE",
"CREATE",
"PARTITIONS",
"FUNCTIONS",
"COLUMNS",
"SORTED",
"MATERIALIZED",
"VIEWS",
"TABLES",
"EXTENDED",
"DATABASES",
"SCHEMAS",
]);
});
});