Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CBRD-25749] Add [NOT DETERMINISTIC | DETERMINISTIC] Keywords to the CREATE FUNCTION Statement #5725

Merged
merged 11 commits into from
Jan 2, 2025
Merged
1 change: 1 addition & 0 deletions pl_engine/pl_server/src/main/antlr/PlcLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ DECIMAL: D E C I M A L ;
DECLARE: D E C L A R E ;
DEFAULT: D E F A U L T ;
DEFINER: D E F I N E R ;
DETERMINISTIC: D E T E R M I N I S T I C;
DIV: D I V ;
DOUBLE: D O U B L E ;
ELSE: E L S E ;
Expand Down
7 changes: 6 additions & 1 deletion pl_engine/pl_server/src/main/antlr/PlcParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ create_routine

routine_definition
: (PROCEDURE | FUNCTION) routine_uniq_name ( (LPAREN parameter_list RPAREN)? | LPAREN RPAREN ) (RETURN type_spec)?
(authid_spec)? (IS | AS) (LANGUAGE PLCSQL)? seq_of_declare_specs? body (SEMICOLON)?
(authid_spec)? (deterministic_spec)? (IS | AS) (LANGUAGE PLCSQL)? seq_of_declare_specs? body (SEMICOLON)?
jongmin-won marked this conversation as resolved.
Show resolved Hide resolved
;

routine_uniq_name
Expand All @@ -62,6 +62,11 @@ authid_spec
| AUTHID (CALLER | CURRENT_USER) # authid_caller
;

deterministic_spec
: NOT DETERMINISTIC
| DETERMINISTIC
;

default_value_part
: (':=' | DEFAULT) expression
;
Expand Down
13 changes: 13 additions & 0 deletions src/executables/unload_schema.c
Original file line number Diff line number Diff line change
Expand Up @@ -4531,6 +4531,19 @@ emit_stored_procedure_pre (extract_context & ctxt, print_output & output_ctx)
output_ctx ("AUTHID OWNER ");
}

// dtrm_type
if (sp_type == SP_TYPE_FUNCTION)
{
if (directive & SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_DETERMINISTIC)
{
output_ctx ("DETERMINISTIC ");
}
else
{
output_ctx ("NOT DETERMINISTIC ");
}
}

int sp_lang = db_get_int (&lang_val);
if (sp_lang == SP_LANG_PLCSQL)
{
Expand Down
1 change: 1 addition & 0 deletions src/object/schema_system_catalog_install.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1815,6 +1815,7 @@ namespace cubschema
{"arg_count", "integer"},
{"lang", "varchar(16)"},
{"authid", "varchar(16)"},
{"dtrm_type", "varchar(20)"},
jongmin-won marked this conversation as resolved.
Show resolved Hide resolved
{"target", "varchar(4096)"},
{"owner", "varchar(256)"},
{"code", format_varchar (1073741823)},
Expand Down
1 change: 1 addition & 0 deletions src/object/schema_system_catalog_install_query_spec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,7 @@ sm_define_view_stored_procedure_spec (void)
"[sp].[arg_count] AS [arg_count], "
"CASE [sp].[lang] WHEN 0 THEN 'PLCSQL' WHEN 1 THEN 'JAVA' ELSE 'UNKNOWN' END AS [lang], "
"CASE [sp].[directive] & 1 WHEN 0 THEN 'DEFINER' ELSE 'CURRENT_USER' END AS [authid], "
"CASE [sp].[directive] & 2 WHEN 0 THEN 'NOT DETERMINISTIC' ELSE 'DETERMINISTIC' END AS [dtrm_type], "
"CONCAT ([sp].[target_class], '.', [sp].[target_method]) AS [target], "
"CAST ([sp].[owner].[name] AS VARCHAR(255)) AS [owner], " /* string -> varchar(255) */
"[sp_code].[scode] AS [code], "
Expand Down
64 changes: 49 additions & 15 deletions src/parser/csql_grammar.y
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,7 @@ static int g_plcsql_text_pos;
%type <number> deduplicate_key_mod_level
%type <number> opt_index_with_clause_no_online
%type <number> opt_authid
%type <number> opt_deterministic
/*}}}*/

/* define rule type (node) */
Expand Down Expand Up @@ -1553,6 +1554,7 @@ static int g_plcsql_text_pos;
%token <cptr> DECREMENT
%token <cptr> DEFINER
%token <cptr> DENSE_RANK
%token <cptr> DETERMINISTIC
%token <cptr> DONT_REUSE_OID
%token <cptr> ELT
%token <cptr> EMPTY
Expand Down Expand Up @@ -3129,14 +3131,15 @@ create_stmt
opt_sp_param_list /* 6 */
RETURN sp_return_type /* 7, 8 */
opt_authid /* 9 */
is_or_as pl_language_spec /* 10, 11 */
opt_comment_spec /* 12 */
opt_deterministic /* 10 */
jongmin-won marked this conversation as resolved.
Show resolved Hide resolved
is_or_as pl_language_spec /* 11, 12 */
opt_comment_spec /* 13 */
{ pop_msg(); }
{{ DBG_TRACE_GRAMMAR(create_stmt, | CREATE opt_or_replace FUNCTION~);
PT_NODE *node = parser_pop_hint_node ();
if (node)
{
PT_NODE* body = $11;
PT_NODE* body = $12;
if (body->info.sp_body.lang == SP_LANG_PLCSQL && body->info.sp_body.impl == NULL)
{
// In particular, this happens for two cases:
Expand All @@ -3148,8 +3151,8 @@ create_stmt
assert(this_parser->file);

int start = @1.buffer_pos - 6; // 6 : length of "create"
int spec_start = @10.buffer_pos; // right after is_or_as
int spec_end = @11.buffer_pos;
int spec_start = @11.buffer_pos; // right after is_or_as
int spec_end = @12.buffer_pos;
int end = @$.buffer_pos;
if (pt_set_plcsql_body_impl(node, body, start, spec_start, spec_end, end) < 0) {
PT_ERROR (this_parser, node, "failed to get the user SQL from the input file");
Expand All @@ -3160,11 +3163,12 @@ create_stmt
node->info.sp.name = $5;
node->info.sp.type = PT_SP_FUNCTION;
node->info.sp.auth_id = $9;
node->info.sp.dtrm_type = $10;
node->info.sp.param_list = $6;
node->info.sp.ret_type = (int) TO_NUMBER(CONTAINER_AT_0($8));
node->info.sp.ret_data_type = CONTAINER_AT_1($8);
node->info.sp.body = $11;
node->info.sp.comment = $12;
node->info.sp.body = $12;
node->info.sp.comment = $13;
}

$$ = node;
Expand Down Expand Up @@ -12833,25 +12837,54 @@ sp_return_type

opt_authid
: /* empty */
{{ $$ = PT_AUTHID_OWNER; }}
{{ DBG_TRACE_GRAMMAR(opt_authid, : );
$$ = PT_AUTHID_OWNER;
DBG_PRINT}}
| AUTHID DEFINER
{{ $$ = PT_AUTHID_OWNER; }}
{{ DBG_TRACE_GRAMMAR(opt_authid, : AUTHID DEFINER);
$$ = PT_AUTHID_OWNER;
DBG_PRINT}}
| AUTHID OWNER
{{ $$ = PT_AUTHID_OWNER; }}
{{ DBG_TRACE_GRAMMAR(opt_authid, : AUTHID OWNER);
$$ = PT_AUTHID_OWNER;
DBG_PRINT}}
| AUTHID CALLER
{{ $$ = PT_AUTHID_CALLER; }}
{{ DBG_TRACE_GRAMMAR(opt_authid, : AUTHID CALLER);
$$ = PT_AUTHID_CALLER;
DBG_PRINT}}
| AUTHID CURRENT_USER
{{ $$ = PT_AUTHID_CALLER; }}
{{ DBG_TRACE_GRAMMAR(opt_authid, : AUTHID CURRENT_USER);
$$ = PT_AUTHID_CALLER;
DBG_PRINT}}
;

opt_deterministic
: /* empty */
{{ DBG_TRACE_GRAMMAR(opt_deterministic, : );
$$ = PT_NOT_DETERMINISTIC;
DBG_PRINT}}
| NOT DETERMINISTIC
{{ DBG_TRACE_GRAMMAR(opt_deterministic, : NOT DETERMINISTIC);
$$ = PT_NOT_DETERMINISTIC;
DBG_PRINT}}
| DETERMINISTIC
{{ DBG_TRACE_GRAMMAR(opt_deterministic, : DETERMINISTIC);
$$ = PT_DETERMINISTIC;
DBG_PRINT}}
;

is_or_as
: IS
| AS
: IS
{ DBG_TRACE_GRAMMAR(is_or_as, : IS); DBG_PRINT}
| AS
{ DBG_TRACE_GRAMMAR(is_or_as, : AS); DBG_PRINT}
;

opt_lang_plcsql
: /* empty */
: /* empty */
{ DBG_TRACE_GRAMMAR(opt_lang_plcsql, : ); DBG_PRINT}
| LANGUAGE PLCSQL
{ DBG_TRACE_GRAMMAR(opt_lang_plcsql, : LANGUAGE PLCSQL); DBG_PRINT}
;

pl_language_spec
Expand Down Expand Up @@ -23217,6 +23250,7 @@ identifier
| DEFINER {{ DBG_TRACE_GRAMMAR(identifier, | DEFINER ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }}
| DEDUPLICATE_ {{ DBG_TRACE_GRAMMAR(identifier, | DEDUPLICATE_ ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }}
| DENSE_RANK {{ DBG_TRACE_GRAMMAR(identifier, | DENSE_RANK ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }}
| DETERMINISTIC {{ DBG_TRACE_GRAMMAR(identifier, | DETERMINISTIC ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }}
| DISK_SIZE {{ DBG_TRACE_GRAMMAR(identifier, | DISK_SIZE ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }}
| DONT_REUSE_OID {{ DBG_TRACE_GRAMMAR(identifier, | DONT_REUSE_OID ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }}
| ELT {{ DBG_TRACE_GRAMMAR(identifier, | ELT ); SET_CPTR_2_PTNAME($$, $1, @$.buffer_pos); }}
Expand Down
7 changes: 5 additions & 2 deletions src/parser/csql_lexer.l
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,9 @@ IDL [a-zA-Z0-9_]
[dD][eE][sS][cC] { begin_token(yytext); return DESC; }
[dD][eE][sS][cC][rR][iI][bB][eE] { begin_token(yytext); return DESCRIBE; }
[dD][eE][sS][cC][rR][iI][pP][tT][oO][rR] { begin_token(yytext); return DESCRIPTOR; }
[dD][eE][tT][eE][rR][mM][iI][nN][iI][sS][tT][iI][cC] { begin_token(yytext);
csql_yylval.cptr = pt_makename(yytext);
return DETERMINISTIC; }
[dD][iI][aA][gG][nN][oO][sS][tT][iI][cC][sS] { begin_token(yytext); return DIAGNOSTICS; }
[dD][iI][fF][fF][eE][rR][eE][nN][cC][eE] { begin_token(yytext); return DIFFERENCE_; }
[dD][iI][sS][cC][oO][nN][nN][eE][cC][tT] { begin_token(yytext); return DISCONNECT; }
Expand Down Expand Up @@ -722,8 +725,8 @@ IDL [a-zA-Z0-9_]
[oO][vV][eE][rR] { begin_token(yytext); return OVER; }
[oO][vV][eE][rR][lL][aA][pP][sS] { begin_token(yytext); return OVERLAPS; }
[oO][wW][nN][eE][rR] { begin_token(yytext);
csql_yylval.cptr = pt_makename(yytext);
return OWNER; }
csql_yylval.cptr = pt_makename(yytext);
return OWNER; }
[pP][aA][gG][eE] { begin_token(yytext);
csql_yylval.cptr = pt_makename(yytext);
return PAGE; }
Expand Down
1 change: 1 addition & 0 deletions src/parser/keyword.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ static KEYWORD_RECORD keywords[] = {
{DESC, "DESC", 0},
{DESCRIBE, "DESCRIBE", 0},
{DESCRIPTOR, "DESCRIPTOR", 0},
{DETERMINISTIC, "DETERMINISTIC", 1},
{DIAGNOSTICS, "DIAGNOSTICS", 0},
{DIFFERENCE_, "DIFFERENCE", 0},
{DISCONNECT, "DISCONNECT", 0},
Expand Down
5 changes: 4 additions & 1 deletion src/parser/parse_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1350,7 +1350,9 @@ typedef enum
PT_SYNONYM,

PT_AUTHID_OWNER,
PT_AUTHID_CALLER
PT_AUTHID_CALLER,
PT_NOT_DETERMINISTIC,
PT_DETERMINISTIC
// todo: separate into relevant enumerations
} PT_MISC_TYPE;

Expand Down Expand Up @@ -3402,6 +3404,7 @@ struct pt_stored_proc_info
PT_NODE *comment;
PT_NODE *owner; /* for ALTER PROCEDURE/FUNCTION name OWNER TO new_owner */
PT_MISC_TYPE auth_id; /* PT_AUTHID_OWNER, PT_AUTHID_CALLER */
PT_MISC_TYPE dtrm_type; /* PT_NOT_DETERMINISTIC, PT_DETERMINISTIC */
PT_MISC_TYPE type;
unsigned or_replace:1; /* OR REPLACE clause */
PT_TYPE_ENUM ret_type;
Expand Down
12 changes: 12 additions & 0 deletions src/parser/parse_tree_cl.c
Original file line number Diff line number Diff line change
Expand Up @@ -7655,6 +7655,18 @@ pt_print_create_stored_procedure (PARSER_CONTEXT * parser, PT_NODE * p)
{
q = pt_append_nulstring (parser, q, " AUTHID CALLER");
}

if (p->info.sp.type == PT_SP_FUNCTION)
{
if (p->info.sp.dtrm_type == PT_NOT_DETERMINISTIC)
{
q = pt_append_nulstring (parser, q, " NOT DETERMINISTIC");
}
else
{
q = pt_append_nulstring (parser, q, " DETERMINISTIC");
}
}
}

r3 = pt_print_bytes (parser, p->info.sp.body);
Expand Down
13 changes: 13 additions & 0 deletions src/parser/xasl_generation.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#include "jsp_cl.h"
#include "subquery_cache.h"
#include "pl_signature.hpp"
#include "sp_catalog.hpp"

#if defined(WINDOWS)
#include "wintcp.h"
Expand Down Expand Up @@ -27624,6 +27625,18 @@ pt_make_sq_cache_key_struct (QPROC_DB_VALUE_LIST key_struct, void *p, int type)
break;
case TYPE_SP:
regu_var_list_p = regu_src->value.sp_ptr->args;

/* The value of regu_src->value.sp_ptr->sig->is_deterministic is interpreted as follows
* 0: PT_AUTHID_OWNER + PT_NOT_DETERMINISTIC
* 1: PT_AUTHID_CALLER + PT_NOT_DETERMINISTIC
* 2: PT_AUTHID_OWNER + PT_DETERMINISTIC
* 3: PT_AUTHID_CALLER + PT_DETERMINISTIC
*/
if (regu_src->value.sp_ptr->sig->is_deterministic == false)
{
return ER_FAILED;
jongmin-won marked this conversation as resolved.
Show resolved Hide resolved
jongmin-won marked this conversation as resolved.
Show resolved Hide resolved
}

while (regu_var_list_p)
{
regu_src = &regu_var_list_p->value;
Expand Down
33 changes: 31 additions & 2 deletions src/sp/jsp_cl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@
#define PT_NODE_SP_AUTHID(node) \
((node)->info.sp.auth_id)

#define PT_NODE_SP_DETERMINISTIC_TYPE(node) \
((node)->info.sp.dtrm_type)

#define PT_NODE_SP_COMMENT(node) \
(((node)->info.sp.comment == NULL) ? "" : \
(char *) (node)->info.sp.comment->info.value.data_value.str->bytes)
Expand All @@ -124,6 +127,7 @@ static SP_TYPE_ENUM jsp_map_pt_misc_to_sp_type (PT_MISC_TYPE pt_enum);
static SP_MODE_ENUM jsp_map_pt_misc_to_sp_mode (PT_MISC_TYPE pt_enum);
static PT_MISC_TYPE jsp_map_sp_type_to_pt_misc (SP_TYPE_ENUM sp_type);
static SP_DIRECTIVE_ENUM jsp_map_pt_to_sp_authid (PT_MISC_TYPE pt_authid);
static SP_DIRECTIVE_ENUM jsp_map_pt_to_sp_dtrm_type (PT_MISC_TYPE pt_dtrm_type, SP_DIRECTIVE_ENUM directive);

static char *jsp_check_stored_procedure_name (const char *str);
static int jsp_check_overflow_args (PARSER_CONTEXT *parser, PT_NODE *node, int num_params, int num_args);
Expand Down Expand Up @@ -1012,6 +1016,8 @@ jsp_create_stored_procedure (PARSER_CONTEXT *parser, PT_NODE *statement)
if (sp_info.sp_type == SP_TYPE_FUNCTION)
{
sp_info.return_type = pt_type_enum_to_db (statement->info.sp.ret_type);
// check the deterministic_type of function
sp_info.directive = jsp_map_pt_to_sp_dtrm_type (PT_NODE_SP_DETERMINISTIC_TYPE (statement), sp_info.directive);
}
else
{
Expand Down Expand Up @@ -1477,6 +1483,20 @@ jsp_map_pt_to_sp_authid (PT_MISC_TYPE pt_authid)
SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_CALLER);
}

static SP_DIRECTIVE_ENUM
jsp_map_pt_to_sp_dtrm_type (PT_MISC_TYPE pt_dtrm_type, SP_DIRECTIVE_ENUM directive)
{
assert (pt_dtrm_type == PT_NOT_DETERMINISTIC || pt_dtrm_type == PT_DETERMINISTIC);

if (pt_dtrm_type == PT_DETERMINISTIC)
{
directive = static_cast<SP_DIRECTIVE_ENUM> (static_cast<int> (directive) | static_cast<int>
(SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_DETERMINISTIC));
}

return directive;
}

/*
* jsp_check_stored_procedure_name -
* return: java stored procedure name
Expand Down Expand Up @@ -2074,7 +2094,7 @@ jsp_make_pl_signature (PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *subquery_

/* semantic check */
int directive = db_get_int (&entry.vals[SP_ATTR_INDEX_DIRECTIVE]);
const char *auth_name = (directive == SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_OWNER ? jsp_get_owner_name (
const char *auth_name = (! (directive & SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_CALLER) ? jsp_get_owner_name (
name, user_name_buffer, DB_MAX_USER_LENGTH) : au_get_current_user_name ());

int result_type = db_get_int (&entry.vals[SP_ATTR_INDEX_RETURN_TYPE]);
Expand All @@ -2094,8 +2114,17 @@ jsp_make_pl_signature (PARSER_CONTEXT *parser, PT_NODE *node, PT_NODE *subquery_
}

sig.auth = db_private_strdup (NULL, auth_name);
if ((directive & SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_DETERMINISTIC))
jongmin-won marked this conversation as resolved.
Show resolved Hide resolved
{
sig.is_deterministic = true;
}
else
{
sig.is_deterministic = false;
}

sig.result_type = result_type;
if (directive == SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_OWNER)
if (! (directive & SP_DIRECTIVE_ENUM::SP_DIRECTIVE_RIGHTS_CALLER))
{
jsp_get_owner_name (name, user_name_buffer, DB_MAX_USER_LENGTH);
sig.auth = db_private_strndup (NULL, user_name_buffer, DB_MAX_USER_LENGTH);
Expand Down
1 change: 1 addition & 0 deletions src/sp/pl_signature.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ namespace cubpl
int type; // PL_TYPE
char *name;
char *auth;
bool is_deterministic; // DETERMINISTIC
jongmin-won marked this conversation as resolved.
Show resolved Hide resolved
int result_type; // DB_TYPE

pl_arg arg;
Expand Down
1 change: 1 addition & 0 deletions src/sp/sp_catalog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ enum sp_directive : int
{
SP_DIRECTIVE_RIGHTS_OWNER = 0x00,
SP_DIRECTIVE_RIGHTS_CALLER = (0x01 << 0),
SP_DIRECTIVE_RIGHTS_DETERMINISTIC = (0x01 << 1),
jongmin-won marked this conversation as resolved.
Show resolved Hide resolved
};
typedef sp_directive SP_DIRECTIVE_ENUM;

Expand Down
Loading