diff --git a/contrib/shark/expected/test_dbcc.out b/contrib/shark/expected/test_dbcc.out index 19bf43b16540885957f9b0fba17cf7e26b4a95b1..c56f76a98730bb4cd2a6e3572beb08ba797173e3 100644 --- a/contrib/shark/expected/test_dbcc.out +++ b/contrib/shark/expected/test_dbcc.out @@ -555,6 +555,66 @@ CONTEXT: referenced column: dbcc_check_ident_no_reseed (1 row) drop table Employees1; +-- ANONYMOUS BLOCK +CREATE TABLE Employees (EmployeeID serial ,Name VARCHAR(100) NOT NULL); +NOTICE: CREATE TABLE will create implicit sequence "employees_employeeid_seq" for serial column "employees.employeeid" +insert into Employees(Name) values ('zhangsan'); +insert into Employees(Name) values ('lisi'); +begin + DBCC CHECKIDENT ('Employees', NORESEED); +end; +/ +NOTICE: "Checking identity information: current identity value '2', current column value '2'." +CONTEXT: referenced column: dbcc_check_ident_no_reseed +SQL statement "DBCC CHECKIDENT ('Employees', NORESEED)" +PL/pgSQL function inline_code_block line 2 at PERFORM +begin + DBCC CHECKIDENT ('Employees', RESEED, 5); +end; +/ +NOTICE: "Checking identity information: current identity value '2'." +CONTEXT: referenced column: dbcc_check_ident_reseed +SQL statement "DBCC CHECKIDENT ('Employees', RESEED, 5)" +PL/pgSQL function inline_code_block line 2 at PERFORM +CREATE FUNCTION func_20_1() RETURN integer +AS +BEGIN + DBCC CHECKIDENT ('Employees', NORESEED); + RETURN 0; +END; +/ +select func_20_1(); +NOTICE: "Checking identity information: current identity value '5', current column value '2'." +CONTEXT: referenced column: dbcc_check_ident_no_reseed +SQL statement "DBCC CHECKIDENT ('Employees', NORESEED)" +PL/pgSQL function func_20_1() line 2 at PERFORM +referenced column: func_20_1 + func_20_1 +----------- + 0 +(1 row) + +CREATE FUNCTION func_20_2() RETURN integer +AS +BEGIN + DBCC CHECKIDENT ('Employees', RESEED, 5); + RETURN 0; +END; +/ +select func_20_2(); +NOTICE: "Checking identity information: current identity value '5'." +CONTEXT: referenced column: dbcc_check_ident_reseed +SQL statement "DBCC CHECKIDENT ('Employees', RESEED, 5)" +PL/pgSQL function func_20_2() line 2 at PERFORM +referenced column: func_20_2 + func_20_2 +----------- + 0 +(1 row) + +drop TABLE Employees; +drop FUNCTION func_20_2(); +drop FUNCTION func_20_1(); -- create table as create table t2(id int, name int); insert into t2 values (1, 1); diff --git a/contrib/shark/shark--1.0.sql b/contrib/shark/shark--1.0.sql index 5ce296042b9bdc9ecdabc42aab292e4d579f10a7..dd91971d4f180d1f5cf46d57e71a3c0b6932b217 100644 --- a/contrib/shark/shark--1.0.sql +++ b/contrib/shark/shark--1.0.sql @@ -11,6 +11,13 @@ create function pltsql_validator(oid) create function pltsql_inline_handler(internal) returns void as 'MODULE_PATHNAME' language C; +create trusted language pltsql + handler pltsql_call_handler + inline pltsql_inline_handler + validator pltsql_validator; + +grant usage on language pltsql to public; + CREATE OR REPLACE FUNCTION sys.day (timestamptz) RETURNS float8 LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_part(''day'', $1)'; CREATE OR REPLACE FUNCTION sys.day (abstime) RETURNS float8 LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_part(''day'', $1)'; CREATE OR REPLACE FUNCTION sys.day (date) RETURNS float8 LANGUAGE SQL IMMUTABLE STRICT as 'select pg_catalog.date_part(''day'', $1)'; @@ -44,16 +51,8 @@ RETURNS INT AS '$libdir/shark', 'objectproperty_internal' LANGUAGE C STABLE; -create trusted language pltsql - handler pltsql_call_handler - inline pltsql_inline_handler - validator pltsql_validator; - - CREATE FUNCTION dbcc_check_ident_no_reseed(varchar, boolean, boolean) RETURNS varchar as 'MODULE_PATHNAME', 'dbcc_check_ident_no_reseed' LANGUAGE C STRICT STABLE; CREATE FUNCTION dbcc_check_ident_reseed(varchar, bigint, boolean) RETURNS varchar as 'MODULE_PATHNAME', 'dbcc_check_ident_reseed' LANGUAGE C STABLE; - -grant usage on language pltsql to public; create function fetch_status() returns int as 'MODULE_PATHNAME' language C; diff --git a/contrib/shark/sql/test_dbcc.sql b/contrib/shark/sql/test_dbcc.sql index 5f7a61d1b972cf6c7ac51004b98a73c3bd4239e7..1bed7f0bdbfecf297d44825f2f732cff60c19893 100644 --- a/contrib/shark/sql/test_dbcc.sql +++ b/contrib/shark/sql/test_dbcc.sql @@ -289,6 +289,44 @@ DBCC CHECKIDENT ('Employees1', NORESEED); drop table Employees1; + +-- ANONYMOUS BLOCK +CREATE TABLE Employees (EmployeeID serial ,Name VARCHAR(100) NOT NULL); +insert into Employees(Name) values ('zhangsan'); +insert into Employees(Name) values ('lisi'); + +begin + DBCC CHECKIDENT ('Employees', NORESEED); +end; +/ + +begin + DBCC CHECKIDENT ('Employees', RESEED, 5); +end; +/ + +CREATE FUNCTION func_20_1() RETURN integer +AS +BEGIN + DBCC CHECKIDENT ('Employees', NORESEED); + RETURN 0; +END; +/ +select func_20_1(); + +CREATE FUNCTION func_20_2() RETURN integer +AS +BEGIN + DBCC CHECKIDENT ('Employees', RESEED, 5); + RETURN 0; +END; +/ +select func_20_2(); + +drop TABLE Employees; +drop FUNCTION func_20_2(); +drop FUNCTION func_20_1(); + -- create table as create table t2(id int, name int); insert into t2 values (1, 1); diff --git a/contrib/shark/src/backend_parser/gram-tsql-decl.y b/contrib/shark/src/backend_parser/gram-tsql-decl.y index b284521b6a4f71397ad660e0733d34d142aa6ede..c7a876f72e8f8eb297b028332658a0e6efb5c05c 100644 --- a/contrib/shark/src/backend_parser/gram-tsql-decl.y +++ b/contrib/shark/src/backend_parser/gram-tsql-decl.y @@ -5,7 +5,7 @@ %type tsql_opt_clustered tsql_opt_columnstore %token TSQL_ATAT_IDENT %type opt_with_no_infomsgs -%type TSQL_computed_column +%type TSQL_computed_column TSQL_AnonyBlockStmt TSQL_CreateFunctionStmt %type tsql_top_clause tsql_select_top_value %type tsql_opt_ties tsql_opt_percent %type DirectColLabel diff --git a/contrib/shark/src/backend_parser/gram-tsql-epilogue.y.cpp b/contrib/shark/src/backend_parser/gram-tsql-epilogue.y.cpp index 122b724fdf716f1b55b1a775926333ea67198bd2..fdf977b494418d3b7b0657cce4097e803008fc62 100644 --- a/contrib/shark/src/backend_parser/gram-tsql-epilogue.y.cpp +++ b/contrib/shark/src/backend_parser/gram-tsql-epilogue.y.cpp @@ -67,5 +67,47 @@ static char* quote_identifier_wrapper(char* ident, core_yyscan_t yyscanner) } } +// To make a node for anonymous block +static Node * +TsqlMakeAnonyBlockFuncStmt(int flag, const char *str) +{ + DoStmt *n = makeNode(DoStmt); + char *str_body = NULL; + DefElem * body = NULL; + errno_t rc = EOK; + + if (BEGIN_P == flag) + { + int len1 = strlen("DECLARE \nBEGIN "); + int len2 = strlen(str); + str_body = (char *)palloc(len1 + len2 + 1); + rc = strncpy_s(str_body, len1 + len2 + 1, "DECLARE \nBEGIN ",len1); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(str_body + len1, len2 + 1, str); + securec_check(rc, "\0", "\0"); + } + else + { + int len1 = strlen("DECLARE "); + int len2 = strlen(str); + str_body = (char *)palloc(len1 + len2 + 1); + rc = strncpy_s(str_body, len1 + len2 + 1, "DECLARE ", len1); + securec_check(rc, "\0", "\0"); + rc = strcpy_s(str_body + len1, len2 + 1, str); + securec_check(rc, "\0", "\0"); + } + + body = makeDefElem("as", (Node*)makeString(str_body)); + if (get_language_oid("pltsql", true) != InvalidOid) { + n->args = list_make1(makeDefElem("language", (Node *)makeString("pltsql"))); + } else { + n->args = list_make1(makeDefElem("language", (Node *)makeString("plpgsql"))); + } + + n->args = lappend( n->args, body); + + return (Node*)n; +} + #include "scan-backend.inc" #undef SCANINC diff --git a/contrib/shark/src/backend_parser/gram-tsql-prologue.y.h b/contrib/shark/src/backend_parser/gram-tsql-prologue.y.h index 53123d6cecaee25943f94f22ed38ba20800addc2..dc3c7cc60f405e634ac399552797b5e0c9306e54 100644 --- a/contrib/shark/src/backend_parser/gram-tsql-prologue.y.h +++ b/contrib/shark/src/backend_parser/gram-tsql-prologue.y.h @@ -3,4 +3,6 @@ List *TsqlSystemFuncName2(char *name); static List* make_no_reseed_func(char* table_name, bool with_no_msgs, bool reseed_to_max); static List* make_reseed_func(char* table_name, Node* new_seed, bool with_no_msgs); static List* make_func_call_func(List* funcname, List* args); -static char* quote_identifier_wrapper(char* ident, core_yyscan_t yyscanner); \ No newline at end of file +static char* quote_identifier_wrapper(char* ident, core_yyscan_t yyscanner); +static Node* TsqlMakeAnonyBlockFuncStmt(int flag, const char *str); +extern Oid get_language_oid(const char* langname, bool missing_ok); \ No newline at end of file diff --git a/contrib/shark/src/backend_parser/gram-tsql-rule.y b/contrib/shark/src/backend_parser/gram-tsql-rule.y index 5e032592c92f27db952e54b6c94a47815c176d5f..2c11055c814c5a95d2ffc3bd1f9a84221da82960 100644 --- a/contrib/shark/src/backend_parser/gram-tsql-rule.y +++ b/contrib/shark/src/backend_parser/gram-tsql-rule.y @@ -573,6 +573,127 @@ DBCCStmt: DBCCCheckIdentStmt } ; +TSQL_AnonyBlockStmt: + DECLARE { u_sess->parser_cxt.eaten_declare = true; u_sess->parser_cxt.eaten_begin = false; } subprogram_body + { + $$ = (Node *)TsqlMakeAnonyBlockFuncStmt(DECLARE, ((FunctionSources*)$3)->bodySrc); + } + | BEGIN_P { u_sess->parser_cxt.eaten_declare = true; u_sess->parser_cxt.eaten_begin = true; } subprogram_body + { + $$ = (Node *)TsqlMakeAnonyBlockFuncStmt(BEGIN_P, ((FunctionSources*)$3)->bodySrc); + } + ; + + +TSQL_CreateFunctionStmt: + CREATE opt_or_replace definer_user FUNCTION func_name_opt_arg proc_args + RETURNS func_return createfunc_opt_list opt_definition + { + set_function_style_pg(); + CreateFunctionStmt *n = makeNode(CreateFunctionStmt); + n->isOraStyle = false; + n->isPrivate = false; + n->replace = $2; + n->definer = $3; + if (n->replace && NULL != n->definer) { + parser_yyerror("not support DEFINER function"); + } + n->funcname = $5; + n->parameters = $6; + n->returnType = $8; + n->options = $9; + n->withClause = $10; + n->isProcedure = false; + $$ = (Node *)n; + } + | CREATE opt_or_replace definer_user FUNCTION func_name_opt_arg proc_args + RETURNS TABLE '(' table_func_column_list ')' createfunc_opt_list opt_definition + { + set_function_style_pg(); + CreateFunctionStmt *n = makeNode(CreateFunctionStmt); + n->isOraStyle = false; + n->isPrivate = false; + n->replace = $2; + n->definer = $3; + if (n->replace && NULL != n->definer) { + parser_yyerror("not support DEFINER function"); + } + n->funcname = $5; + n->parameters = mergeTableFuncParameters($6, $10); + n->returnType = TableFuncTypeName($10); + n->returnType->location = @8; + n->options = $12; + n->withClause = $13; + n->isProcedure = false; + $$ = (Node *)n; + } + | CREATE opt_or_replace definer_user FUNCTION func_name_opt_arg proc_args + createfunc_opt_list opt_definition + { + set_function_style_pg(); + CreateFunctionStmt *n = makeNode(CreateFunctionStmt); + n->isOraStyle = false; + n->isPrivate = false; + n->replace = $2; + n->definer = $3; + if (n->replace && NULL != n->definer) { + parser_yyerror("not support DEFINER function"); + } + n->funcname = $5; + n->parameters = $6; + n->returnType = NULL; + n->options = $7; + n->withClause = $8; + n->isProcedure = false; + $$ = (Node *)n; + } + | CREATE opt_or_replace definer_user FUNCTION func_name_opt_arg proc_args + RETURN func_return opt_createproc_opt_list as_is { + u_sess->parser_cxt.eaten_declare = false; + u_sess->parser_cxt.eaten_begin = false; + pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true; + u_sess->parser_cxt.isCreateFuncOrProc = true; + if (set_is_create_plsql_type()) { + set_create_plsql_type_start(); + set_function_style_a(); + } + } subprogram_body + { + int rc = 0; + rc = CompileWhich(); + if (rc == PLPGSQL_COMPILE_PROC || rc == PLPGSQL_COMPILE_NULL) { + u_sess->plsql_cxt.procedure_first_line = GetLineNumber(t_thrd.postgres_cxt.debug_query_string, @10); + } + CreateFunctionStmt *n = makeNode(CreateFunctionStmt); + FunctionSources *funcSource = (FunctionSources *)$12; + n->isOraStyle = true; + n->isPrivate = false; + n->replace = $2; + n->definer = $3; + if (n->replace && NULL != n->definer) { + parser_yyerror("not support DEFINER function"); + } + n->funcname = $5; + n->parameters = $6; + n->inputHeaderSrc = FormatFuncArgType(yyscanner, funcSource->headerSrc, n->parameters); + if (enable_plpgsql_gsdependency_guc()) { + n->funcHeadSrc = ParseFuncHeadSrc(yyscanner); + } + n->returnType = $8; + n->options = $9; + n->options = lappend(n->options, makeDefElem("as", + (Node *)list_make1(makeString(funcSource->bodySrc)))); + n->options = lappend(n->options, makeDefElem("language", + (Node *)makeString("pltsql"))); + + n->withClause = NIL; + n->withClause = NIL; + n->isProcedure = false; + u_sess->parser_cxt.isCreateFuncOrProc = false; + $$ = (Node *)n; + } + ; + tsql_stmt : AlterAppWorkloadGroupMappingStmt @@ -617,7 +738,7 @@ tsql_stmt : | AlterUserStmt | AlterWorkloadGroupStmt | AnalyzeStmt - | AnonyBlockStmt + | TSQL_AnonyBlockStmt | BarrierStmt | CreateAppWorkloadGroupMappingStmt | CallFuncStmt @@ -644,7 +765,7 @@ tsql_stmt : | CreateForeignServerStmt | CreateForeignTableStmt | CreateDataSourceStmt - | CreateFunctionStmt + | TSQL_CreateFunctionStmt | CreateEventStmt | AlterEventStmt | DropEventStmt