diff --git a/src/common/backend/nodes/copyfuncs.cpp b/src/common/backend/nodes/copyfuncs.cpp index 37f1ff0c7..758080d74 100644 --- a/src/common/backend/nodes/copyfuncs.cpp +++ b/src/common/backend/nodes/copyfuncs.cpp @@ -5184,6 +5184,8 @@ static CreatePackageStmt* _copyCreatePackageStmt(const CreatePackageStmt* from) COPY_NODE_FIELD(pkgname); COPY_SCALAR_FIELD(pkgsecdef); COPY_STRING_FIELD(pkgspec); + COPY_SCALAR_FIELD(pkgspec_location); + COPY_SCALAR_FIELD(pkgspec_prefix_len); return newnode; } diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index a45086d59..f6a383098 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -13487,6 +13487,7 @@ CreatePackageStmt: CREATE opt_or_replace PACKAGE pkg_name invoker_rights as_is {pg_yyget_extra(yyscanner)->core_yy_extra.include_ora_comment = true;} { u_sess->plsql_cxt.package_as_line = GetLineNumber(t_thrd.postgres_cxt.debug_query_string, @6); + CreatePackageStmt *n = makeNode(CreatePackageStmt); char *pkgNameBegin = NULL; char *pkgNameEnd = NULL; char *pkgName = NULL; @@ -13519,7 +13520,7 @@ CreatePackageStmt: tok = yychar; yychar = YYEMPTY; } - int proc_start_pos = yylloc; + int proc_start_pos = n->pkgspec_location = yylloc; u_sess->plsql_cxt.package_first_line = GetLineNumber(t_thrd.postgres_cxt.debug_query_string, yylloc); // Scan whole stmt. @@ -13586,6 +13587,8 @@ CreatePackageStmt: initStringInfo(&content_info); appendStringInfo(&content_info, "%s", PACKAGE_STR); appendStringInfo(&content_info, "%s", DECLARE_STR); + n->pkgspec_prefix_len = content_info.len; + n->pkgspec_location -= 1; appendBinaryStringInfo(&content_info, yyextra->core_yy_extra.scanbuf + proc_start_pos - 1, name_start_pos - proc_start_pos + 1); char* pkg_spec_str = content_info.data; @@ -13627,7 +13630,6 @@ CreatePackageStmt: parser_yyerror("package name end is not match the one begin!"); } #endif - CreatePackageStmt *n = makeNode(CreatePackageStmt); n->replace = $2; n->pkgname = $4; n->pkgspec = pkg_spec_str; diff --git a/src/common/pl/plpgsql/src/gram.y b/src/common/pl/plpgsql/src/gram.y index 19f96bad6..f4cf7e320 100755 --- a/src/common/pl/plpgsql/src/gram.y +++ b/src/common/pl/plpgsql/src/gram.y @@ -211,11 +211,11 @@ static PLpgSQL_expr *read_cursor_args(PLpgSQL_var *cursor, int until, const char *expected); static List *read_raise_options(void); static int errstate = ERROR; -static char* get_proc_str(int tok); +static DefElem* get_proc_str(int tok); static char* get_init_proc(int tok); static char* get_attrname(int tok); static AttrNumber get_assign_attrno(PLpgSQL_datum* target, char* attrname); -static void raw_parse_package_function(char* proc_str); +static void raw_parse_package_function(char* proc_str, int location, int leaderlen); static void checkFuncName(List* funcname); static void IsInPublicNamespace(char* varname); static void SetErrorState(); @@ -317,6 +317,7 @@ static void processFunctionRecordOutParam(int varno, Oid funcoid, int* outparam) PLpgSQL_case_when *casewhen; PLpgSQL_rec_attr *recattr; Node *plnode; + DefElem *def; } %type assign_el @@ -340,7 +341,8 @@ static void processFunctionRecordOutParam(int varno, Oid funcoid, int* outparam) %type for_variable %type for_control forall_control -%type any_identifier opt_block_label opt_label goto_block_label label_name spec_proc init_proc +%type spec_proc +%type any_identifier opt_block_label opt_label goto_block_label label_name init_proc %type opt_rollback_to opt_savepoint_name savepoint_name attr_name %type proc_sect proc_stmts stmt_elsifs stmt_else forall_body @@ -1476,20 +1478,22 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no } | K_FUNCTION {u_sess->parser_cxt.is_procedure=false;} spec_proc { + DefElem *def = $3; u_sess->plsql_cxt.procedure_start_line = GetLineNumber(u_sess->plsql_cxt.curr_compile_context->core_yy->scanbuf, @1); u_sess->plsql_cxt.plpgsql_yylloc = @1; u_sess->plsql_cxt.isCreateFunction = true; - raw_parse_package_function($3); + raw_parse_package_function(def->defname, def->location, def->begin_location); u_sess->plsql_cxt.isCreateFunction = false; u_sess->plsql_cxt.procedure_start_line = 0; u_sess->plsql_cxt.plpgsql_yylloc = 0; } | K_PROCEDURE {u_sess->parser_cxt.is_procedure=true;} spec_proc { + DefElem *def = $3; u_sess->plsql_cxt.procedure_start_line = GetLineNumber(u_sess->plsql_cxt.curr_compile_context->core_yy->scanbuf, @1); u_sess->plsql_cxt.plpgsql_yylloc = plpgsql_yylloc; u_sess->plsql_cxt.isCreateFunction = true; - raw_parse_package_function($3); + raw_parse_package_function(def->defname, def->location, def->begin_location); u_sess->plsql_cxt.isCreateFunction = false; u_sess->plsql_cxt.procedure_start_line = 0; u_sess->plsql_cxt.plpgsql_yylloc = 0; @@ -8174,15 +8178,18 @@ read_sql_construct(int until, /* * get function declare or definition string in package. */ -static char * +static DefElem* get_proc_str(int tok) { int blocklevel = 0; int pre_tok = 0; + DefElem *def; if (u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package == NULL) { yyerror("not allowed create procedure in function or procedure."); } - tok = yylex(); + tok = yylex(); + def = makeDefElem(NULL, NULL); /* make an empty DefElem */ + def->location = yylloc; StringInfoData ds; bool is_defining_proc = false; char * spec_proc_str = NULL; @@ -8196,6 +8203,7 @@ get_proc_str(int tok) } else { appendStringInfoString(&ds, " CREATE OR REPLACE PROCEDURE "); } + def->begin_location = ds.len; u_sess->parser_cxt.in_package_function_compile = true; while(true) { @@ -8270,9 +8278,10 @@ get_proc_str(int tok) u_sess->parser_cxt.isFunctionDeclare = false; } + def->defname = pstrdup(ds.data); spec_proc_str = pstrdup(ds.data); pfree_ext(ds.data); - return spec_proc_str; + return def; } static char* get_init_proc(int tok) { @@ -12081,14 +12090,39 @@ parse_lob_open_close(int location) return NULL; } -static void raw_parse_package_function(char* proc_str) +static void raw_parse_package_function_callback(void *arg) +{ + sql_error_callback_arg *cbarg = (sql_error_callback_arg*)arg; + int cur_pos = geterrposition(); + + if (cur_pos > cbarg->leaderlen) + { + cur_pos += cbarg->location - cbarg->leaderlen; + errposition(cur_pos); + } +} + +static void raw_parse_package_function(char* proc_str, int location, int leaderlen) { if (u_sess->plsql_cxt.curr_compile_context->plpgsql_curr_compile_package != NULL) { + sql_error_callback_arg cbarg; + ErrorContextCallback syntax_errcontext; List* raw_parsetree_list = NULL; u_sess->plsql_cxt.plpgsql_yylloc = plpgsql_yylloc; u_sess->plsql_cxt.rawParsePackageFunction = true; + + cbarg.location = location; + cbarg.leaderlen = leaderlen; + + syntax_errcontext.callback = raw_parse_package_function_callback; + syntax_errcontext.arg = &cbarg; + syntax_errcontext.previous = t_thrd.log_cxt.error_context_stack; + t_thrd.log_cxt.error_context_stack = &syntax_errcontext; raw_parsetree_list = raw_parser(proc_str); + /* Restore former ereport callback */ + t_thrd.log_cxt.error_context_stack = syntax_errcontext.previous; + CreateFunctionStmt* stmt; u_sess->plsql_cxt.rawParsePackageFunction = false; int rc = 0; diff --git a/src/gausskernel/optimizer/commands/packagecmds.cpp b/src/gausskernel/optimizer/commands/packagecmds.cpp index c6e6d8486..a9bf5449e 100644 --- a/src/gausskernel/optimizer/commands/packagecmds.cpp +++ b/src/gausskernel/optimizer/commands/packagecmds.cpp @@ -60,6 +60,22 @@ #include "tcop/utility.h" +static void create_package_error_callback(void *arg) +{ + CreatePackageStmt* stmt = (CreatePackageStmt*)arg; + int cur_pos; + + if (stmt->pkgspec_location <= 0) + return; + + cur_pos = geterrposition(); + if (cur_pos > 0) + { + cur_pos += (stmt->pkgspec_location - stmt->pkgspec_prefix_len); + errposition(cur_pos); + } +} + void CreatePackageCommand(CreatePackageStmt* stmt, const char* queryString) { #ifdef ENABLE_MULTIPLE_NODES @@ -72,6 +88,7 @@ void CreatePackageCommand(CreatePackageStmt* stmt, const char* queryString) char* pkgname = NULL; char* pkgspecsrc = NULL; Oid pkgOwner; + ErrorContextCallback err_context; /* Convert list of names to a name and namespace */ namespaceId = QualifiedNameGetCreationNamespace(stmt->pkgname, &pkgname); @@ -122,7 +139,13 @@ void CreatePackageCommand(CreatePackageStmt* stmt, const char* queryString) errcause("package name is null"), erraction("rename package"))); } + + err_context.arg = (void*)stmt; + err_context.previous = t_thrd.log_cxt.error_context_stack; + err_context.callback = create_package_error_callback; + t_thrd.log_cxt.error_context_stack = &err_context; packageId = PackageSpecCreate(namespaceId, pkgname, pkgOwner, pkgspecsrc, stmt->replace, stmt->pkgsecdef); + t_thrd.log_cxt.error_context_stack = err_context.previous; /* Advance cmd counter to make the package visible */ if (OidIsValid(packageId)) { diff --git a/src/include/nodes/parsenodes_common.h b/src/include/nodes/parsenodes_common.h index 6a89947af..c1059597a 100644 --- a/src/include/nodes/parsenodes_common.h +++ b/src/include/nodes/parsenodes_common.h @@ -2150,6 +2150,8 @@ typedef struct CreatePackageStmt { List* pkgname; /* qualified name of function to create */ bool pkgsecdef; /* package security definer or invoker */ char* pkgspec; /* content of package spec */ + int pkgspec_location; /* pkgspec start location */ + int pkgspec_prefix_len; /* inserted string length in pkgspec */ } CreatePackageStmt; typedef struct CreatePackageBodyStmt { diff --git a/src/test/regress/expected/pldeveloper_gs_source.out b/src/test/regress/expected/pldeveloper_gs_source.out index 994dfdf4d..b037b5304 100644 --- a/src/test/regress/expected/pldeveloper_gs_source.out +++ b/src/test/regress/expected/pldeveloper_gs_source.out @@ -290,7 +290,7 @@ end pkg1; / NOTICE: syntax error at or near "F" LINE 3: procedure proc1(c ff%F); - ^ + ^ CONTEXT: compilation of PL/pgSQL package near line 1 ERROR: Debug mod,create procedure has error. DETAIL: N/A diff --git a/src/test/regress/expected/plsql_show_all_error.out b/src/test/regress/expected/plsql_show_all_error.out index dafff71ba..8145f4f6b 100644 --- a/src/test/regress/expected/plsql_show_all_error.out +++ b/src/test/regress/expected/plsql_show_all_error.out @@ -390,167 +390,167 @@ end AA; / NOTICE: syntax error at or near "json" LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 4: procedure aa_bb(p_self in out nocopy json, pair_name varch... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 5: procedure aa_bb(p_self in out nocopy json, pair_name varch... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 6: procedure aa_bb(p_self in out nocopy json, pair_name varch... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 7: procedure aa_bb(p_self in out nocopy json, pair_name varch... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 8: ...procedure aa_check_duplicate(p_self in out nocopy json, v_se... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 9: procedure aa_remove_duplicates(p_self in out nocopy json); + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 11: procedure aa_bb(p_self in out nocopy json, pair_name varch... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 12: procedure aa_bb(p_self in out nocopy json, pair_name varch... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "position" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 16: function aa_get(p_self in json, position pls_integer) retu... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "clob" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 21: ...dure aa_to_clob(p_self in json, buf in out nocopy clob, spac... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 28: procedure aa_path_bb(p_self in out nocopy json, json_path ... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 29: procedure aa_path_bb(p_self in out nocopy json, json_path ... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 30: procedure aa_path_bb(p_self in out nocopy json, json_path ... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 31: procedure aa_path_bb(p_self in out nocopy json, json_path ... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 32: procedure aa_path_bb(p_self in out nocopy json, json_path ... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 33: procedure aa_path_bb(p_self in out nocopy json, json_path ... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 35: procedure aa_path_remove(p_self in out nocopy json, json_p... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 41: procedure aa_append(p_self in out nocopy json_list, elem j... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 42: procedure aa_append(p_self in out nocopy json_list, elem v... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 43: procedure aa_append(p_self in out nocopy json_list, elem n... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 44: procedure aa_append(p_self in out nocopy json_list, elem b... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 45: procedure aa_append(p_self in out nocopy json_list, elem j... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 47: procedure aa_replace(p_self in out nocopy json_list, posit... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 48: procedure aa_replace(p_self in out nocopy json_list, posit... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 49: procedure aa_replace(p_self in out nocopy json_list, posit... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 50: procedure aa_replace(p_self in out nocopy json_list, posit... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 51: procedure aa_replace(p_self in out nocopy json_list, posit... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 54: procedure aa_remove(p_self in out nocopy json_list, positi... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ -CONTEXT: compilation of PL/pgSQL package near line 1 -NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ -CONTEXT: compilation of PL/pgSQL package near line 1 -NOTICE: syntax error at or near "position" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ -CONTEXT: compilation of PL/pgSQL package near line 1 -NOTICE: syntax error at or near "clob" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ -CONTEXT: compilation of PL/pgSQL package near line 1 -NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ -CONTEXT: compilation of PL/pgSQL package near line 1 -NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ -CONTEXT: compilation of PL/pgSQL package near line 1 -NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ -CONTEXT: compilation of PL/pgSQL package near line 1 -NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ -CONTEXT: compilation of PL/pgSQL package near line 1 -NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ -CONTEXT: compilation of PL/pgSQL package near line 1 -NOTICE: syntax error at or near "json_list" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ -CONTEXT: compilation of PL/pgSQL package near line 1 -NOTICE: syntax error at or near "clob" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... +LINE 55: procedure aa_remove_first(p_self in out nocopy json_list); ^ CONTEXT: compilation of PL/pgSQL package near line 1 +NOTICE: syntax error at or near "json_list" +LINE 56: procedure aa_remove_last(p_self in out nocopy json_list); + ^ +CONTEXT: compilation of PL/pgSQL package near line 1 +NOTICE: syntax error at or near "position" +LINE 57: function aa_get(p_self in json_list, position pls_integer)... + ^ +CONTEXT: compilation of PL/pgSQL package near line 1 NOTICE: syntax error at or near "clob" -LINE 3: procedure aa_remove(p_self in out nocopy json, pair_name v... - ^ +LINE 63: ...aa_to_clob(p_self in json_list, buf in out nocopy clob, spac... + ^ +CONTEXT: compilation of PL/pgSQL package near line 1 +NOTICE: syntax error at or near "json_list" +LINE 68: procedure aa_path_bb(p_self in out nocopy json_list, json_... + ^ +CONTEXT: compilation of PL/pgSQL package near line 1 +NOTICE: syntax error at or near "json_list" +LINE 69: procedure aa_path_bb(p_self in out nocopy json_list, json_... + ^ +CONTEXT: compilation of PL/pgSQL package near line 1 +NOTICE: syntax error at or near "json_list" +LINE 70: procedure aa_path_bb(p_self in out nocopy json_list, json_... + ^ +CONTEXT: compilation of PL/pgSQL package near line 1 +NOTICE: syntax error at or near "json_list" +LINE 71: procedure aa_path_bb(p_self in out nocopy json_list, json_... + ^ +CONTEXT: compilation of PL/pgSQL package near line 1 +NOTICE: syntax error at or near "json_list" +LINE 72: procedure aa_path_bb(p_self in out nocopy json_list, json_... + ^ +CONTEXT: compilation of PL/pgSQL package near line 1 +NOTICE: syntax error at or near "json_list" +LINE 74: procedure aa_path_remove(p_self in out nocopy json_list, j... + ^ +CONTEXT: compilation of PL/pgSQL package near line 1 +NOTICE: syntax error at or near "clob" +LINE 83: ...aa_get_string(p_self in json_value, buf in out nocopy clob); + ^ +CONTEXT: compilation of PL/pgSQL package near line 1 +NOTICE: syntax error at or near "clob" +LINE 96: ...a_to_clob(p_self in json_value, buf in out nocopy clob, spac... + ^ CONTEXT: compilation of PL/pgSQL package near line 1 ERROR: Debug mod,create procedure has error. DETAIL: N/A