Skip to content

Commit

Permalink
Merge pull request #336 from liuxy0551/feat_mysql
Browse files Browse the repository at this point in the history
mysql grammar correct
  • Loading branch information
Cythia828 authored Aug 1, 2024
2 parents 24b392d + 5d6ff46 commit 6176339
Show file tree
Hide file tree
Showing 14 changed files with 11,625 additions and 10,547 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ coverage
.idea
gen/
src/**/*.iml
benchmark/reports/*
benchmark/reports/*
*.tgz
47 changes: 24 additions & 23 deletions src/grammar/mysql/MySqlParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ ddlStatement
| createLogfileGroup
| createProcedure
| createFunction
| createFunctionLoadable
| createServer
| createTable
| createTablespaceInnodb
Expand Down Expand Up @@ -266,6 +267,22 @@ createProcedure
)* ')' routineOption* routineBody
;

createFunction
: KW_CREATE ownerStatement? KW_AGGREGATE? KW_FUNCTION ifNotExists? functionNameCreate '(' functionParameter? (
',' functionParameter
)* ')' KW_RETURNS dataType routineOption* (routineBody | returnStatement)
;

// https://dev.mysql.com/doc/refman/8.0/en/create-function-loadable.html
createFunctionLoadable
: KW_CREATE KW_AGGREGATE? KW_FUNCTION ifNotExists? functionNameCreate KW_RETURNS returnType=(
KW_STRING
| KW_INTEGER
| KW_REAL
| KW_DECIMAL
) KW_SONAME STRING_LITERAL
;

createRole
: KW_CREATE KW_ROLE ifNotExists? userOrRoleNames
;
Expand Down Expand Up @@ -310,7 +327,7 @@ createTablespaceNdb
;

createTrigger
: KW_CREATE ownerStatement? KW_TRIGGER ifNotExists? trigger_name=fullId triggerTime=(
: KW_CREATE ownerStatement? ifNotExists? KW_TRIGGER ifNotExists? trigger_name=fullId triggerTime=(
KW_BEFORE
| KW_AFTER
) triggerEvent=(KW_INSERT | KW_UPDATE | KW_DELETE) KW_ON tableName KW_FOR KW_EACH KW_ROW (
Expand Down Expand Up @@ -420,6 +437,10 @@ procedureParameter
: direction=(KW_IN | KW_OUT | KW_INOUT)? paramName=uid dataType
;

functionParameter
: paramName=uid dataType
;

routineOption
: KW_COMMENT STRING_LITERAL # routineComment
| KW_LANGUAGE KW_SQL # routineLanguage
Expand Down Expand Up @@ -907,19 +928,6 @@ replaceStatement
)? (('(' columnNames ')')? replaceStatementValuesOrSelectOrTable | setAssignmentList)
;

// selectStatement
// : querySpecification lockClause? # simpleSelect
// | querySpecificationNointo lockClause? intoClause? # simpleSelect
// | queryExpression lockClause? # parenthesisSelect
// | querySpecificationNointo unionStatement+ (
// KW_UNION unionType=(KW_ALL | KW_DISTINCT)? (querySpecification | queryExpression)
// )? orderByClause? limitClause? lockClause? # unionSelect
// | queryExpressionNointo unionParenthesis+ (
// KW_UNION unionType=(KW_ALL | KW_DISTINCT)? queryExpression
// )? orderByClause? limitClause? lockClause? # unionParenthesisSelect
// | querySpecificationNointo (',' lateralStatement)+ # withLateralStatement
// ;

// TODO: Simplify the rules to fit SLL(*) Mode
selectStatement
: querySpecification unionStatement* (
Expand Down Expand Up @@ -1127,6 +1135,7 @@ queryExpression
*/
querySpecification
: KW_SELECT selectSpec* selectElements intoClause? fromClause groupByClause? havingClause? windowClause? orderByClause? limitClause? intoClause?
unionStatement?
;

unionStatement
Expand Down Expand Up @@ -1996,15 +2005,6 @@ checkTableOption
| KW_CHANGED
;

createFunction
: KW_CREATE KW_AGGREGATE? KW_FUNCTION ifNotExists? functionNameCreate KW_RETURNS returnType=(
KW_STRING
| KW_INTEGER
| KW_REAL
| KW_DECIMAL
) KW_SONAME STRING_LITERAL
;

installComponent
: KW_INSTALL KW_COMPONENT component_name=uid (',' component_name=uid)* (
KW_SET variableExpr (',' variableExpr)*
Expand Down Expand Up @@ -3421,6 +3421,7 @@ keywordsCanBeId
| KW_RESOURCE_GROUP_USER
| KW_RESUME
| KW_RETURNED_SQLSTATE
| KW_RETURNING
| KW_RETURNS
| KW_REUSE
| KW_ROLE
Expand Down
6 changes: 4 additions & 2 deletions src/lib/mysql/MySqlParser.interp

Large diffs are not rendered by default.

21,948 changes: 11,453 additions & 10,495 deletions src/lib/mysql/MySqlParser.ts

Large diffs are not rendered by default.

44 changes: 33 additions & 11 deletions src/lib/mysql/MySqlParserListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { CreateEventContext } from "./MySqlParser.js";
import { CreateIndexContext } from "./MySqlParser.js";
import { CreateLogfileGroupContext } from "./MySqlParser.js";
import { CreateProcedureContext } from "./MySqlParser.js";
import { CreateFunctionContext } from "./MySqlParser.js";
import { CreateFunctionLoadableContext } from "./MySqlParser.js";
import { CreateRoleContext } from "./MySqlParser.js";
import { CreateServerContext } from "./MySqlParser.js";
import { QueryCreateTableContext } from "./MySqlParser.js";
Expand All @@ -49,6 +51,7 @@ import { EnableTypeContext } from "./MySqlParser.js";
import { IndexTypeContext } from "./MySqlParser.js";
import { IndexOptionContext } from "./MySqlParser.js";
import { ProcedureParameterContext } from "./MySqlParser.js";
import { FunctionParameterContext } from "./MySqlParser.js";
import { RoutineCommentContext } from "./MySqlParser.js";
import { RoutineLanguageContext } from "./MySqlParser.js";
import { RoutineBehaviorContext } from "./MySqlParser.js";
Expand Down Expand Up @@ -444,7 +447,6 @@ import { OptimizeTableContext } from "./MySqlParser.js";
import { RepairTableContext } from "./MySqlParser.js";
import { TableActionOptionContext } from "./MySqlParser.js";
import { CheckTableOptionContext } from "./MySqlParser.js";
import { CreateFunctionContext } from "./MySqlParser.js";
import { InstallComponentContext } from "./MySqlParser.js";
import { VariableExprContext } from "./MySqlParser.js";
import { UninstallComponentContext } from "./MySqlParser.js";
Expand Down Expand Up @@ -854,6 +856,26 @@ export class MySqlParserListener implements ParseTreeListener {
* @param ctx the parse tree
*/
exitCreateProcedure?: (ctx: CreateProcedureContext) => void;
/**
* Enter a parse tree produced by `MySqlParser.createFunction`.
* @param ctx the parse tree
*/
enterCreateFunction?: (ctx: CreateFunctionContext) => void;
/**
* Exit a parse tree produced by `MySqlParser.createFunction`.
* @param ctx the parse tree
*/
exitCreateFunction?: (ctx: CreateFunctionContext) => void;
/**
* Enter a parse tree produced by `MySqlParser.createFunctionLoadable`.
* @param ctx the parse tree
*/
enterCreateFunctionLoadable?: (ctx: CreateFunctionLoadableContext) => void;
/**
* Exit a parse tree produced by `MySqlParser.createFunctionLoadable`.
* @param ctx the parse tree
*/
exitCreateFunctionLoadable?: (ctx: CreateFunctionLoadableContext) => void;
/**
* Enter a parse tree produced by `MySqlParser.createRole`.
* @param ctx the parse tree
Expand Down Expand Up @@ -1104,6 +1126,16 @@ export class MySqlParserListener implements ParseTreeListener {
* @param ctx the parse tree
*/
exitProcedureParameter?: (ctx: ProcedureParameterContext) => void;
/**
* Enter a parse tree produced by `MySqlParser.functionParameter`.
* @param ctx the parse tree
*/
enterFunctionParameter?: (ctx: FunctionParameterContext) => void;
/**
* Exit a parse tree produced by `MySqlParser.functionParameter`.
* @param ctx the parse tree
*/
exitFunctionParameter?: (ctx: FunctionParameterContext) => void;
/**
* Enter a parse tree produced by the `routineComment`
* labeled alternative in `MySqlParser.routineOption`.
Expand Down Expand Up @@ -5440,16 +5472,6 @@ export class MySqlParserListener implements ParseTreeListener {
* @param ctx the parse tree
*/
exitCheckTableOption?: (ctx: CheckTableOptionContext) => void;
/**
* Enter a parse tree produced by `MySqlParser.createFunction`.
* @param ctx the parse tree
*/
enterCreateFunction?: (ctx: CreateFunctionContext) => void;
/**
* Exit a parse tree produced by `MySqlParser.createFunction`.
* @param ctx the parse tree
*/
exitCreateFunction?: (ctx: CreateFunctionContext) => void;
/**
* Enter a parse tree produced by `MySqlParser.installComponent`.
* @param ctx the parse tree
Expand Down
28 changes: 21 additions & 7 deletions src/lib/mysql/MySqlParserVisitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { CreateEventContext } from "./MySqlParser.js";
import { CreateIndexContext } from "./MySqlParser.js";
import { CreateLogfileGroupContext } from "./MySqlParser.js";
import { CreateProcedureContext } from "./MySqlParser.js";
import { CreateFunctionContext } from "./MySqlParser.js";
import { CreateFunctionLoadableContext } from "./MySqlParser.js";
import { CreateRoleContext } from "./MySqlParser.js";
import { CreateServerContext } from "./MySqlParser.js";
import { QueryCreateTableContext } from "./MySqlParser.js";
Expand All @@ -49,6 +51,7 @@ import { EnableTypeContext } from "./MySqlParser.js";
import { IndexTypeContext } from "./MySqlParser.js";
import { IndexOptionContext } from "./MySqlParser.js";
import { ProcedureParameterContext } from "./MySqlParser.js";
import { FunctionParameterContext } from "./MySqlParser.js";
import { RoutineCommentContext } from "./MySqlParser.js";
import { RoutineLanguageContext } from "./MySqlParser.js";
import { RoutineBehaviorContext } from "./MySqlParser.js";
Expand Down Expand Up @@ -444,7 +447,6 @@ import { OptimizeTableContext } from "./MySqlParser.js";
import { RepairTableContext } from "./MySqlParser.js";
import { TableActionOptionContext } from "./MySqlParser.js";
import { CheckTableOptionContext } from "./MySqlParser.js";
import { CreateFunctionContext } from "./MySqlParser.js";
import { InstallComponentContext } from "./MySqlParser.js";
import { VariableExprContext } from "./MySqlParser.js";
import { UninstallComponentContext } from "./MySqlParser.js";
Expand Down Expand Up @@ -789,6 +791,18 @@ export class MySqlParserVisitor<Result> extends AbstractParseTreeVisitor<Result>
* @return the visitor result
*/
visitCreateProcedure?: (ctx: CreateProcedureContext) => Result;
/**
* Visit a parse tree produced by `MySqlParser.createFunction`.
* @param ctx the parse tree
* @return the visitor result
*/
visitCreateFunction?: (ctx: CreateFunctionContext) => Result;
/**
* Visit a parse tree produced by `MySqlParser.createFunctionLoadable`.
* @param ctx the parse tree
* @return the visitor result
*/
visitCreateFunctionLoadable?: (ctx: CreateFunctionLoadableContext) => Result;
/**
* Visit a parse tree produced by `MySqlParser.createRole`.
* @param ctx the parse tree
Expand Down Expand Up @@ -938,6 +952,12 @@ export class MySqlParserVisitor<Result> extends AbstractParseTreeVisitor<Result>
* @return the visitor result
*/
visitProcedureParameter?: (ctx: ProcedureParameterContext) => Result;
/**
* Visit a parse tree produced by `MySqlParser.functionParameter`.
* @param ctx the parse tree
* @return the visitor result
*/
visitFunctionParameter?: (ctx: FunctionParameterContext) => Result;
/**
* Visit a parse tree produced by the `routineComment`
* labeled alternative in `MySqlParser.routineOption`.
Expand Down Expand Up @@ -3501,12 +3521,6 @@ export class MySqlParserVisitor<Result> extends AbstractParseTreeVisitor<Result>
* @return the visitor result
*/
visitCheckTableOption?: (ctx: CheckTableOptionContext) => Result;
/**
* Visit a parse tree produced by `MySqlParser.createFunction`.
* @param ctx the parse tree
* @return the visitor result
*/
visitCreateFunction?: (ctx: CreateFunctionContext) => Result;
/**
* Visit a parse tree produced by `MySqlParser.installComponent`.
* @param ctx the parse tree
Expand Down
9 changes: 9 additions & 0 deletions src/parser/mysql/mysqlEntityCollector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
CopyCreateTableContext,
CreateDatabaseContext,
CreateFunctionContext,
CreateFunctionLoadableContext,
CreateViewContext,
DatabaseNameContext,
DatabaseNameCreateContext,
Expand Down Expand Up @@ -143,4 +144,12 @@ export class MySqlEntityCollector extends EntityCollector implements MySqlParser
exitCreateFunction(ctx: CreateFunctionContext) {
this.popStmt();
}

enterCreateFunctionLoadable(ctx: CreateFunctionLoadableContext) {
this.pushStmt(ctx, StmtContextType.CREATE_FUNCTION_STMT);
}

exitCreateFunctionLoadable(ctx: CreateFunctionLoadableContext) {
this.popStmt();
}
}
54 changes: 46 additions & 8 deletions test/parser/mysql/contextCollect/entityCollector.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('MySQL entity collector tests', () => {
});

test('split results', () => {
expect(splitListener.statementsContext.length).toBe(15);
expect(splitListener.statementsContext.length).toBe(16);
});

test('create table by columns', () => {
Expand Down Expand Up @@ -468,21 +468,21 @@ describe('MySQL entity collector tests', () => {
const functionEntity = allEntities[0];

expect(functionEntity.entityContextType).toBe(EntityContextType.FUNCTION_CREATE);
expect(functionEntity.text).toBe('my_concat_ws');
expect(functionEntity.text).toBe('hello');
expect(functionEntity.position).toEqual({
endColumn: 43,
endIndex: 982,
endColumn: 39,
endIndex: 978,
line: 39,
startColumn: 31,
startIndex: 971,
startColumn: 34,
startIndex: 974,
});

expect(functionEntity.belongStmt.stmtContextType).toBe(
StmtContextType.CREATE_FUNCTION_STMT
);
expect(functionEntity.belongStmt.position).toEqual({
endColumn: 87,
endIndex: 1026,
endColumn: 114,
endIndex: 1053,
endLine: 39,
startColumn: 1,
startIndex: 941,
Expand All @@ -492,4 +492,42 @@ describe('MySQL entity collector tests', () => {
expect(functionEntity.columns).toBeNull();
expect(functionEntity.relatedEntities).toBeNull();
});

test('create function loadable', () => {
const functionCreateContext = splitListener.statementsContext[15];

const collectListener = new MySqlEntityCollector(commonSql);
mysql.listen(collectListener as ParseTreeListener, functionCreateContext);

const allEntities = collectListener.getEntities();

expect(allEntities.length).toBe(1);

const functionEntity = allEntities[0];

expect(functionEntity.entityContextType).toBe(EntityContextType.FUNCTION_CREATE);
expect(functionEntity.text).toBe('my_concat_ws');
expect(functionEntity.position).toEqual({
endColumn: 43,
endIndex: 1098,
line: 41,
startColumn: 31,
startIndex: 1087,
});

expect(functionEntity.belongStmt.stmtContextType).toBe(
StmtContextType.CREATE_FUNCTION_STMT
);
expect(functionEntity.belongStmt.position).toEqual({
endColumn: 87,
endIndex: 1142,
endLine: 41,
startColumn: 1,
startIndex: 1057,
startLine: 41,
});

expect(functionEntity.columns).toBeNull();
expect(functionEntity.relatedEntities).toBeNull();
});
});
2 changes: 2 additions & 0 deletions test/parser/mysql/contextCollect/fixtures/common.sql
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ SHOW CREATE SCHEMA IF NOT EXISTS db_name;

DROP SCHEMA IF EXISTS db_name;

CREATE DEFINER = 'user' FUNCTION hello (s CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN CONCAT('Hello, ',s,'!');

CREATE FUNCTION IF NOT EXISTS my_concat_ws RETURNS STRING SONAME 'udf_my_concat_ws.so';
1 change: 1 addition & 0 deletions test/parser/mysql/suggestion/tokenSuggestion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ describe('MySQL Token Suggestion', () => {
'ALGORITHM',
'OR',
'TRIGGER',
'IF',
'TABLESPACE',
'UNDO',
'TABLE',
Expand Down
3 changes: 3 additions & 0 deletions test/parser/mysql/syntax/fixtures/alterTable.sql
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,6 @@ ALTER TABLE t1 ALTER COLUMN c1 DROP DEFAULT, DROP CONSTRAINT c2_positive, ALTER
ALTER TABLE t1 ALTER COLUMN c1 DROP DEFAULT, DROP CONSTRAINT c2_positive, ALTER CHECK c2_positive NOT ENFORCED REBUILD PARTITION p0 REBUILD PARTITION ALL;
ALTER TABLE t1 ALTER COLUMN c1 DROP DEFAULT, DROP CONSTRAINT c2_positive, ALTER CHECK c2_positive NOT ENFORCED REPAIR PARTITION p0 REPAIR PARTITION ALL;
ALTER TABLE t1 ALTER COLUMN c1 SET VISIBLE, DROP CONSTRAINT c2_positive, ALTER CHECK c2_positive NOT ENFORCED REMOVE PARTITIONING UPGRADE PARTITIONING;


ALTER TABLE `order` ADD cancelled TINYINT(1) DEFAULT 0 NOT NULL, ADD delivered TINYINT(1) DEFAULT 0 NOT NULL, ADD returning TINYINT(1) DEFAULT 0 NOT NULL;
Loading

0 comments on commit 6176339

Please sign in to comment.