feat: support pgsql code completion (#205)

* feat: pgsql: complete sql, upgrade syntax file and complete autoImprove

* feat: pgsql: complete unit test

* feat: pgsql: update unit test for autocomplete

* feat(pgsql: update split's context type ): pgsql: update split's context type

* feat(pgsql: update schema, table, procedure, tablespace, function, view,database's rule name): pgsql

* feat: pgsql: update usualName's rule realize

* feat: pgsql:update funcName's using

---------

Co-authored-by: zhaoge <>
This commit is contained in:
XCynthia
2023-11-15 15:34:42 +08:00
committed by GitHub
parent 2e6d18e7dc
commit cbb1279f9e
24 changed files with 36285 additions and 23896 deletions

View File

@ -0,0 +1,31 @@
CREATE TABLE db. ();
INSERT INTO db.tb ;
SELECT * FROM db. ;
ALTER TABLE db ;
CREATE OR REPLACE VIEW db.v;
ALTER VIEW db.v ;
DROP VIEW db. ;
CREATE FUNCTION fn1;
DROP FUNCTION fn1;
CREATE DATABASE db;
DROP DATABASE db ;
ALTER DATABASE db ;
CREATE SCHEMA IF NOT EXISTS schema_name;
DROP SCHEMA IF EXISTS sch;
ALTER SCHEMA name RENAME TO new_name;

View File

@ -0,0 +1,12 @@
DROP ;
ALTER ;
INSERT ;
DELETE ;
CREATE ;

View File

@ -0,0 +1,275 @@
import fs from 'fs';
import path from 'path';
import { CaretPosition, SyntaxContextType } from '../../../../src/parser/common/basic-parser-types';
import PgSQL from '../../../../src/parser/pgsql';
import { commentOtherLine } from '../../../helper';
const syntaxSql = fs.readFileSync(
path.join(__dirname, 'fixtures', 'syntaxSuggestion.sql'),
'utf-8'
);
describe('Postgre SQL Syntax Suggestion', () => {
const parser = new PgSQL();
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: 3,
column: 18,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
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('Alter table ', () => {
const pos: CaretPosition = {
lineNumber: 7,
column: 15,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
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('Select table ', () => {
const pos: CaretPosition = {
lineNumber: 5,
column: 18,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
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: 1,
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', '.']);
});
test('Create view ', () => {
const pos: CaretPosition = {
lineNumber: 9,
column: 28,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
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: 13,
column: 14,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
pos
)?.syntax;
const suggestion = syntaxes?.find(
(syn) => syn.syntaxContextType === SyntaxContextType.VIEW
);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db', '.']);
});
test('Alter view ', () => {
const pos: CaretPosition = {
lineNumber: 11,
column: 16,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
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: 15,
column: 20,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
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('Drop function', () => {
const pos: CaretPosition = {
lineNumber: 17,
column: 18,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
pos
)?.syntax;
const suggestion = syntaxes?.find(
(syn) => syn.syntaxContextType === SyntaxContextType.FUNCTION
);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['fn1']);
});
test('Create database', () => {
const pos: CaretPosition = {
lineNumber: 19,
column: 19,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
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: 21,
column: 17,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
pos
)?.syntax;
const suggestion = syntaxes?.find(
(syn) => syn.syntaxContextType === SyntaxContextType.DATABASE
);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db']);
});
test('Alter database', () => {
const pos: CaretPosition = {
lineNumber: 23,
column: 18,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
pos
)?.syntax;
const suggestion = syntaxes?.find(
(syn) => syn.syntaxContextType === SyntaxContextType.DATABASE
);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['db']);
});
test('Create schema', () => {
const pos: CaretPosition = {
lineNumber: 25,
column: 40,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
pos
)?.syntax;
const suggestion = syntaxes?.find(
(syn) => syn.syntaxContextType === SyntaxContextType.DATABASE_CREATE
);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['schema_name']);
});
test('Drop schema', () => {
const pos: CaretPosition = {
lineNumber: 27,
column: 26,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
pos
)?.syntax;
const suggestion = syntaxes?.find(
(syn) => syn.syntaxContextType === SyntaxContextType.DATABASE
);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['sch']);
});
test('Alter schema', () => {
const pos: CaretPosition = {
lineNumber: 29,
column: 18,
};
const syntaxes = parser.getSuggestionAtCaretPosition(
commentOtherLine(syntaxSql, pos.lineNumber),
pos
)?.syntax;
const suggestion = syntaxes?.find(
(syn) => syn.syntaxContextType === SyntaxContextType.DATABASE
);
expect(suggestion).not.toBeUndefined();
expect(suggestion?.wordRanges.map((token) => token.text)).toEqual(['name']);
});
});

View File

@ -0,0 +1,193 @@
import fs from 'fs';
import path from 'path';
import { CaretPosition } from '../../../../src/parser/common/basic-parser-types';
import PostgresSQL from '../../../../src/parser/pgsql';
import { commentOtherLine } from '../../../helper';
const tokenSql = fs.readFileSync(path.join(__dirname, 'fixtures', 'tokenSuggestion.sql'), 'utf-8');
describe('Postgres SQL Token Suggestion', () => {
const parser = new PostgresSQL();
test('After ALTER', () => {
const pos: CaretPosition = {
lineNumber: 3,
column: 7,
};
const suggestion = parser.getSuggestionAtCaretPosition(
commentOtherLine(tokenSql, pos.lineNumber),
pos
)?.keywords;
expect(suggestion).toEqual([
'TYPE',
'TEXT',
'STATISTICS',
'TABLESPACE',
'USER',
'ROLE',
'EVENT',
'TRIGGER',
'RULE',
'FOREIGN',
'TABLE',
'MATERIALIZED',
'VIEW',
'INDEX',
'SEQUENCE',
'SUBSCRIPTION',
'SERVER',
'SCHEMA',
'ROUTINE',
'PUBLICATION',
'PROCEDURE',
'POLICY',
'OPERATOR',
'LANGUAGE',
'PROCEDURAL',
'GROUP',
'FUNCTION',
'DOMAIN',
'DATABASE',
'CONVERSION',
'COLLATION',
'AGGREGATE',
'SYSTEM',
'LARGE',
'EXTENSION',
'DEFAULT',
]);
});
test('After CREATE', () => {
const pos: CaretPosition = {
lineNumber: 9,
column: 8,
};
const suggestion = parser.getSuggestionAtCaretPosition(
commentOtherLine(tokenSql, pos.lineNumber),
pos
)?.keywords;
expect(suggestion).toEqual([
'RECURSIVE',
'VIEW',
'TEMPORARY',
'TEMP',
'LOCAL',
'GLOBAL',
'UNLOGGED',
'OR',
'RULE',
'INDEX',
'UNIQUE',
'TABLE',
'COLLATION',
'TEXT',
'TYPE',
'OPERATOR',
'AGGREGATE',
'DATABASE',
'USER',
'ROLE',
'EVENT',
'TRIGGER',
'CONSTRAINT',
'TRANSFORM',
'TABLESPACE',
'STATISTICS',
'SUBSCRIPTION',
'SEQUENCE',
'SCHEMA',
'LANGUAGE',
'PROCEDURAL',
'TRUSTED',
'POLICY',
'PUBLICATION',
'MATERIALIZED',
'GROUP',
'PROCEDURE',
'FUNCTION',
'FOREIGN',
'SERVER',
'EXTENSION',
'DOMAIN',
'CONVERSION',
'DEFAULT',
'CAST',
'ASSERTION',
'ACCESS',
]);
});
test('After DELETE', () => {
const pos: CaretPosition = {
lineNumber: 7,
column: 8,
};
const suggestion = parser.getSuggestionAtCaretPosition(
commentOtherLine(tokenSql, pos.lineNumber),
pos
)?.keywords;
expect(suggestion).toEqual(['FROM']);
});
test('After DROP', () => {
const pos: CaretPosition = {
lineNumber: 1,
column: 6,
};
const suggestion = parser.getSuggestionAtCaretPosition(
commentOtherLine(tokenSql, pos.lineNumber),
pos
)?.keywords;
expect(suggestion).toEqual([
'OPERATOR',
'ROUTINE',
'PROCEDURE',
'FUNCTION',
'AGGREGATE',
'DATABASE',
'USER',
'GROUP',
'ROLE',
'TRANSFORM',
'TABLESPACE',
'SUBSCRIPTION',
'INDEX',
'DOMAIN',
'TYPE',
'RULE',
'TRIGGER',
'POLICY',
'SCHEMA',
'ACCESS',
'EVENT',
'EXTENSION',
'FOREIGN',
'PROCEDURAL',
'LANGUAGE',
'PUBLICATION',
'SERVER',
'TABLE',
'SEQUENCE',
'VIEW',
'MATERIALIZED',
'COLLATION',
'CONVERSION',
'STATISTICS',
'TEXT',
'OWNED',
'CAST',
]);
});
test('After INSERT', () => {
const pos: CaretPosition = {
lineNumber: 5,
column: 8,
};
const suggestion = parser.getSuggestionAtCaretPosition(
commentOtherLine(tokenSql, pos.lineNumber),
pos
)?.keywords;
expect(suggestion).toEqual(['INTO']);
});
});