8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 22:43:04 +01:00

Support for PSQL functions (only the DSQL part so far). Still work in progress.

This commit is contained in:
dimitr 2009-12-21 17:23:07 +00:00
parent cf9a6ff9f7
commit 1f3694c903
11 changed files with 984 additions and 388 deletions

File diff suppressed because it is too large Load Diff

View File

@ -24,6 +24,8 @@
#define DSQL_DDL_NODES_H
#include "../jrd/common.h"
#include "../dsql/node.h"
#include "../dsql/make_proto.h"
#include "../dsql/Nodes.h"
#include "../common/classes/array.h"
#include "../common/classes/TriState.h"
@ -145,24 +147,58 @@ private:
};
class CreateAlterFunctionNode : public DdlNode
class CreateAlterFunctionNode;
class FunctionNode : public DdlNode, public BlockNode
{
public:
explicit FunctionNode(MemoryPool& p, const Firebird::string& sqlText)
: DdlNode(p, sqlText)
{
}
public:
virtual void genReturn();
virtual dsql_nod* resolveVariable(const dsql_str* varName);
protected:
virtual CreateAlterFunctionNode* getCreateAlterNode() = 0;
};
class CreateAlterFunctionNode : public FunctionNode
{
public:
explicit CreateAlterFunctionNode(MemoryPool& pool, const Firebird::string& sqlText,
const Firebird::MetaName& aName)
: DdlNode(pool, sqlText),
: FunctionNode(pool, sqlText),
name(pool, aName),
returnType(NULL, NULL),
create(true),
alter(false),
external(NULL),
invariant(false),
parameters(pool),
returnType(NULL, NULL),
variables(pool),
outputVariables(pool),
localDeclList(NULL),
body(NULL),
source(pool),
compiled(false),
invalid(false),
package(pool),
privateScope(false),
source(pool)
packageOwner(pool),
privateScope(false)
{
}
protected:
virtual CreateAlterFunctionNode* getCreateAlterNode()
{
return this;
}
public:
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
@ -172,21 +208,30 @@ protected:
private:
void executeCreate(thread_db* tdbb, jrd_tra* transaction);
bool executeAlter(thread_db* tdbb, jrd_tra* transaction);
bool executeAlter(thread_db* tdbb, jrd_tra* transaction, bool secondPass, bool runTriggers);
void storeArgument(thread_db* tdbb, jrd_tra* transaction,
unsigned pos, const TypeClause& parameter, dsql_nod* legacyDefault);
unsigned pos, const ParameterClause& parameter);
void compile(thread_db* tdbb, jrd_tra* transaction);
public:
Firebird::MetaName name;
TypeClause returnType;
bool create;
bool alter;
ExternalClause* external;
bool invariant;
Firebird::Array<ParameterClause> parameters;
Firebird::MetaName package;
bool privateScope;
TypeClause returnType;
Firebird::Array<dsql_nod*> variables;
Firebird::Array<dsql_nod*> outputVariables;
Firebird::string source;
dsql_nod* localDeclList;
dsql_nod* body;
bool compiled;
bool invalid;
Firebird::MetaName package;
Firebird::string packageOwner;
bool privateScope;
};
@ -202,10 +247,17 @@ public:
{
}
public:
static void dropArguments(thread_db* tdbb, jrd_tra* transaction,
const Firebird::MetaName& functionName, const Firebird::MetaName& packageName);
public:
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
protected:
virtual DdlNode* internalDsqlPass();
public:
Firebird::MetaName name;
bool silent;
@ -213,6 +265,37 @@ public:
};
class RecreateFunctionNode : public FunctionNode
{
public:
explicit RecreateFunctionNode(MemoryPool& p, const Firebird::string& sqlText,
CreateAlterFunctionNode* aCreateNode)
: FunctionNode(p, sqlText),
createNode(aCreateNode),
dropNode(p, sqlText, createNode->name)
{
dropNode.silent = true;
}
protected:
virtual CreateAlterFunctionNode* getCreateAlterNode()
{
return createNode;
}
public:
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
protected:
virtual DdlNode* internalDsqlPass();
private:
CreateAlterFunctionNode* createNode;
DropFunctionNode dropNode;
};
class CreateAlterProcedureNode;

View File

@ -92,6 +92,8 @@ protected:
DdlTriggerWhen when, int action, const Firebird::MetaName& objectName);
void putType(const TypeClause& type, bool useSubType);
void resetContextStack();
Firebird::MetaName storeGlobalField(thread_db* tdbb, jrd_tra* transaction,
const TypeClause& parameter);
protected:
virtual DdlNode* internalDsqlPass()

View File

@ -954,7 +954,7 @@ SuspendNode* SuspendNode::internalDsqlPass()
{
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_TRIGGER) // triggers only
if (!(dsqlScratch->flags & DsqlCompilerScratch::FLAG_PROCEDURE))
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
// Token unknown
@ -1027,4 +1027,56 @@ jrd_nod* SuspendNode::execute(thread_db* /*tdbb*/, jrd_req* request)
}
//--------------------
ReturnNode* ReturnNode::internalDsqlPass()
{
DsqlCompiledStatement* const statement = dsqlScratch->getStatement();
if (!(dsqlScratch->flags & DsqlCompilerScratch::FLAG_FUNCTION))
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
// Token unknown
Arg::Gds(isc_token_err) <<
Arg::Gds(isc_random) << Arg::Str("RETURN"));
}
if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_IN_AUTO_TRANS_BLOCK) // autonomous transaction
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
Arg::Gds(isc_dsql_unsupported_in_auto_trans) << Arg::Str("RETURN"));
}
ReturnNode* node = FB_NEW(getPool()) ReturnNode(getPool());
node->dsqlScratch = dsqlScratch;
node->blockNode = statement->blockNode;
node->value = PASS1_node(dsqlScratch, value);
return node;
}
void ReturnNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
{
text = "ReturnNode";
}
void ReturnNode::genBlr()
{
DsqlCompiledStatement* const statement = dsqlScratch->getStatement();
statement->append_uchar(blr_assignment);
GEN_expr(dsqlScratch, value);
statement->append_uchar(blr_variable);
statement->append_ushort(0);
blockNode->genReturn();
statement->append_uchar(blr_leave);
statement->append_uchar(0);
}
} // namespace Jrd

View File

@ -256,6 +256,27 @@ public:
};
class ReturnNode : public DsqlOnlyStmtNode
{
public:
explicit ReturnNode(MemoryPool& pool, dsql_nod* val = NULL)
: DsqlOnlyStmtNode(pool), value(val)
{
}
protected:
virtual ReturnNode* internalDsqlPass();
public:
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
virtual void genBlr();
public:
BlockNode* blockNode;
dsql_nod* value;
};
} // namespace
#endif // DSQL_STMT_NODES_H

View File

@ -377,35 +377,6 @@ void DDL_generate(DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
bool DDL_ids(const DsqlCompilerScratch* scratch)
{
return !scratch->getStatement()->ddlNode;
/*
const dsql_nod* ddl_node = request->getStatement()->ddlNode;
if (!ddl_node) {
return true;
}
switch (ddl_node->nod_type)
{
case nod_def_constraint:
case nod_def_computed:
case nod_def_view:
case nod_redef_view:
case nod_mod_view:
case nod_replace_view:
case nod_def_trigger:
case nod_redef_trigger:
case nod_mod_trigger:
case nod_replace_trigger:
case nod_def_procedure:
case nod_redef_procedure:
case nod_mod_procedure:
case nod_replace_procedure:
return false;
default:
return true;
}
*/
}
@ -4514,6 +4485,10 @@ static void put_user_grant(DsqlCompilerScratch* dsqlScratch, const dsql_nod* use
statement->append_cstring(isc_dyn_grant_proc, name->str_data);
break;
case nod_func_obj:
statement->append_cstring(isc_dyn_grant_func, name->str_data);
break;
case nod_trig_obj:
statement->append_cstring(isc_dyn_grant_trig, name->str_data);
break;
@ -4585,6 +4560,8 @@ static void modify_privilege(DsqlCompilerScratch* dsqlScratch,
const dsql_str* name = (dsql_str*) table->nod_arg[0];
if (table->nod_type == nod_procedure_name)
statement->append_cstring(isc_dyn_prc_name, name->str_data);
else if (table->nod_type == nod_function_name)
statement->append_cstring(isc_dyn_fun_name, name->str_data);
else if (table->nod_type == nod_package_name)
statement->append_cstring(isc_dyn_pkg_name, name->str_data);
else
@ -5346,7 +5323,10 @@ void DDL_put_local_variable( DsqlCompilerScratch* dsqlScratch, dsql_var* variabl
statement->append_ushort(variable->var_variable_number);
}
statement->put_debug_variable(variable->var_variable_number, variable->var_name);
if (variable->var_name[0])
{
statement->put_debug_variable(variable->var_variable_number, variable->var_name);
}
++dsqlScratch->hiddenVarsNumber;
}

View File

@ -325,8 +325,6 @@ class dsql_var : public pool_alloc_rpt<SCHAR, dsql_type_var>
{
public:
dsql_fld* var_field; // Field on which variable is based
//USHORT var_flags; // Reserved
//dsql_var_type var_type; // Too cumbersome to compile the right data type.
int var_type; // Input, output or local var.
USHORT var_msg_number; // Message number containing variable
USHORT var_msg_item; // Item number in message
@ -563,6 +561,7 @@ public:
static const unsigned FLAG_BLOCK = 0x20;
static const unsigned FLAG_RECURSIVE_CTE = 0x40;
static const unsigned FLAG_UPDATE_OR_INSERT = 0x80;
static const unsigned FLAG_FUNCTION = 0x100;
public:
explicit DsqlCompilerScratch(MemoryPool& p, dsql_dbb* aDbb, jrd_tra* aTransaction,
@ -760,15 +759,6 @@ public:
dsql_msg* blb_segment_msg; // Segment message
};
//! Transaction block
/* UNUSED
class dsql_tra : public pool_alloc<dsql_type_tra>
{
public:
dsql_tra* tra_next; // Next open transaction
};
*/
//! Implicit (NATURAL and USING) joins
class ImplicitJoin : public pool_alloc<dsql_type_imp_join>
{

View File

@ -165,6 +165,7 @@ static const TOK tokens[] =
{DESC, "DESC", 1, false}, // Alias of DESCENDING
{DESC, "DESCENDING", 1, false},
{KW_DESCRIPTOR, "DESCRIPTOR", 2, true},
{DETERMINISTIC, "DETERMINISTIC", 2, false},
{KW_DIFFERENCE, "DIFFERENCE", 2, true},
{DISCONNECT, "DISCONNECT", 2, false},
{DISTINCT, "DISTINCT", 1, false},
@ -325,6 +326,7 @@ static const TOK tokens[] =
{RESTART, "RESTART", 2, true},
{RESTRICT, "RESTRICT", 1, true},
{RETAIN, "RETAIN", 1, false},
{RETURN, "RETURN", 1, false},
{RETURNING, "RETURNING", 2, true},
{RETURNING_VALUES, "RETURNING_VALUES", 1, false},
{RETURNS, "RETURNS", 1, false},

View File

@ -337,7 +337,9 @@ enum nod_t
nod_package_obj,
nod_window,
nod_mod_field_null_flag,
nod_continue
nod_continue,
nod_func_obj,
nod_function_name
};
/* enumerations of the arguments to a node, offsets

View File

@ -569,7 +569,8 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%token <legacyNode> ACOSH
%token <legacyNode> ASINH
%token <legacyNode> ATANH
%token <legacyNode> RETURN
%token <legacyNode> DETERMINISTIC
// precedence declarations for expression evaluation
@ -663,7 +664,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyNode> decimal_keyword declare declare_clause
%type <legacyNode> decode_pairs def_computed default_par_opt default_value delete delete_positioned
%type <legacyNode> delete_rule delete_searched delimiter_opt derived_column_list derived_table
%type <legacyNode> distinct_clause distinct_predicate domain_clause domain_constraint
%type <legacyNode> deterministic_opt distinct_clause distinct_predicate domain_clause domain_constraint
%type <legacyNode> domain_constraint_clause domain_constraint_def domain_constraint_list
%type <legacyNode> domain_default domain_default_opt domain_or_non_array_type
%type <legacyNode> domain_or_non_array_type_name domain_type drop drop_behaviour
@ -675,7 +676,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyNode> exec_function exec_into exec_procedure exec_sql exec_stmt_inputs
%type <legacyNode> exec_stmt_option exec_stmt_options exec_stmt_options_list exists_predicate
%type <legacyNode> ext_datasrc ext_privs ext_pwd ext_role ext_tran ext_user extra_indices_opt
%type <legacyNode> extract_expression
%type <legacyNode> extract_expression execute_privilege
%type <legacyStr> end_trigger entry_op external_file
%type <legacyNode> fetch_cursor fetch_opt fetch_scroll_opt file1 file_clause file_desc file_desc1
@ -731,7 +732,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyNode> plan_expression plan_item plan_item_list plan_type
%type <legacyNode> post_event prec_scale predicate primary_constraint privilege
%type <legacyNode> privilege_list privileges proc_block proc_inputs proc_outputs_opt
%type <legacyNode> proc_privileges proc_statement proc_statements
%type <legacyNode> proc_statement proc_statements
%type <legacyStr> passwd_clause passwd_opt
%type <int32Val> pos_short_integer precision_opt
@ -751,7 +752,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyNode> sec_shadow_files segment_clause_io segment_length_io select select_expr
%type <legacyNode> select_expr_body select_item select_items select_list set set_generator
%type <legacyNode> set_savepoint set_statistics set_transaction shadow_clause
%type <legacyNode> similar_predicate simple_case
%type <legacyNode> similar_predicate simple_case simple_UDF_name
%type <legacyNode> simple_column_name simple_package_name simple_proc_name simple_proc_statement simple_table_name
%type <legacyNode> simple_type simple_when_clause singleton_select singular_predicate skip_clause
%type <legacyNode> snap_shot some starting_predicate statement stmt_start_column
@ -860,11 +861,17 @@ statement : alter
grant : GRANT privileges ON table_noise simple_table_name
TO non_role_grantee_list grant_option granted_by
{ $$ = make_node (nod_grant, (int) e_grant_count, $2, $5, make_list($7), $8, $9); }
| GRANT proc_privileges ON PROCEDURE simple_proc_name
{ $$ = make_node (nod_grant, (int) e_grant_count,
$2, $5, make_list($7), $8, $9); }
| GRANT execute_privilege ON PROCEDURE simple_proc_name
TO non_role_grantee_list grant_option granted_by
{ $$ = make_node (nod_grant, (int) e_grant_count, $2, $5, make_list($7), $8, $9); }
| GRANT proc_privileges ON PACKAGE simple_package_name
{ $$ = make_node (nod_grant, (int) e_grant_count,
$2, $5, make_list($7), $8, $9); }
| GRANT execute_privilege ON FUNCTION simple_UDF_name
TO non_role_grantee_list grant_option granted_by
{ $$ = make_node (nod_grant, (int) e_grant_count,
$2, $5, make_list($7), $8, $9); }
| GRANT execute_privilege ON PACKAGE simple_package_name
TO non_role_grantee_list grant_option granted_by
{ $$ = make_node (nod_grant, (int) e_grant_count, $2, $5, make_list($7), $8, $9); }
| GRANT role_name_list TO role_grantee_list role_admin_option granted_by
@ -890,7 +897,7 @@ privilege_list : privilege
{ $$ = make_node (nod_list, (int) 2, $1, $3); }
;
proc_privileges : EXECUTE
execute_privilege : EXECUTE
{ $$ = make_list (make_node (nod_execute, (int) 0, NULL)); }
;
@ -942,16 +949,27 @@ simple_proc_name
{ $$ = make_node(nod_procedure_name, (int) 1, $1); }
;
simple_UDF_name
: symbol_UDF_name
{ $$ = make_node(nod_function_name, (int) 1, $1); }
;
// REVOKE statement
revoke : REVOKE rev_grant_option privileges ON table_noise simple_table_name
FROM non_role_grantee_list granted_by
{ $$ = make_node (nod_revoke, (int) e_grant_count, $3, $6, make_list($8), $2, $9); }
| REVOKE rev_grant_option proc_privileges ON PROCEDURE simple_proc_name
{ $$ = make_node (nod_revoke, (int) e_grant_count,
$3, $6, make_list($8), $2, $9); }
| REVOKE rev_grant_option execute_privilege ON PROCEDURE simple_proc_name
FROM non_role_grantee_list granted_by
{ $$ = make_node (nod_revoke, (int) e_grant_count, $3, $6, make_list($8), $2, $9); }
| REVOKE rev_grant_option proc_privileges ON PACKAGE simple_package_name
{ $$ = make_node (nod_revoke, (int) e_grant_count,
$3, $6, make_list($8), $2, $9); }
| REVOKE rev_grant_option execute_privilege ON FUNCTION simple_UDF_name
FROM non_role_grantee_list granted_by
{ $$ = make_node (nod_revoke, (int) e_grant_count,
$3, $6, make_list($8), $2, $9); }
| REVOKE rev_grant_option execute_privilege ON PACKAGE simple_package_name
FROM non_role_grantee_list granted_by
{ $$ = make_node (nod_revoke, (int) e_grant_count, $3, $6, make_list($8), $2, $9); }
| REVOKE rev_admin_option role_name_list FROM role_grantee_list granted_by
@ -990,6 +1008,8 @@ grantee_list : grantee
grantee
: PROCEDURE symbol_procedure_name
{ $$ = make_node (nod_proc_obj, (int) 1, $2); }
| FUNCTION symbol_UDF_name
{ $$ = make_node (nod_func_obj, (int) 1, $2); }
| PACKAGE symbol_package_name
{ $$ = make_node (nod_package_obj, (int) 1, $2); }
| TRIGGER symbol_trigger_name
@ -1189,6 +1209,8 @@ recreate : RECREATE recreate_clause
recreate_clause
: PROCEDURE procedure_clause
{ $$ = makeClassNode(FB_NEW(getPool()) RecreateProcedureNode(getPool(), compilingText, $2)); }
| FUNCTION function_clause
{ $$ = makeClassNode(FB_NEW(getPool()) RecreateFunctionNode(getPool(), compilingText, $2)); }
| TABLE rtable_clause
{ $$ = $2; }
| GLOBAL TEMPORARY TABLE gtt_recreate_clause
@ -1909,7 +1931,14 @@ default_par_opt : DEFAULT begin_trigger default_value end_default
// FUNCTION
function_clause
: function_clause_start external_clause external_body_clause_opt
: function_clause_start AS begin_string local_declaration_list full_proc_block end_trigger
{
$$ = $1;
$$->source = toString($6);
$$->localDeclList = $4;
$$->body = $5;
}
| function_clause_start external_clause external_body_clause_opt
{
$$ = $1;
$$->external = $2;
@ -1923,13 +1952,23 @@ function_clause_start
{ $$ = FB_NEW(getPool()) CreateAlterFunctionNode(getPool(), compilingText, toName($1)); }
input_parameters(&$2->parameters)
RETURNS { $<legacyField>$ = lex.g_field = make_field(NULL); }
domain_or_non_array_type collate_clause
domain_or_non_array_type collate_clause deterministic_opt
{
$$ = $2;
$$->returnType = TypeClause($<legacyField>5, toName($7));
$$->invariant = ($8 != NULL);
}
;
deterministic_opt
: DETERMINISTIC
{ $$ = make_node (nod_flag, 0, NULL); }
| NOT DETERMINISTIC
{ $$ = NULL; }
|
{ $$ = NULL; }
;
external_clause
: EXTERNAL NAME sql_string ENGINE valid_symbol_name
{
@ -2198,6 +2237,8 @@ simple_proc_statement : assignment
{ $$ = makeClassNode(FB_NEW(getPool()) SuspendNode(getPool())); }
| EXIT
{ $$ = makeClassNode(FB_NEW(getPool()) ExitNode(getPool())); }
| RETURN value
{ $$ = makeClassNode(FB_NEW(getPool()) ReturnNode(getPool(), $2)); }
;
complex_proc_statement
@ -3052,6 +3093,8 @@ keyword_or_column : valid_symbol_name
| SIMILAR // added in FB 2.5
| OVER // added in FB 3.0
| SCROLL
| RETURN
| DETERMINISTIC
;
col_opt : ALTER

View File

@ -11534,6 +11534,9 @@ void DSQL_pretty(const dsql_nod* node, int column)
case nod_proc_obj:
verb = "proc_obj";
break;
case nod_func_obj:
verb = "func_obj";
break;
case nod_trig_obj:
verb = "trig_obj";
break;