mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 18:43:02 +01:00
Improvement CORE-5380 - Allow subroutines to call others subroutines and themself recursively.
This commit is contained in:
parent
f350cccf85
commit
4be766b8c8
@ -58,6 +58,10 @@
|
||||
Reference(s): [doc/sql.extensions/README.identity_columns](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.identity_columns.txt)
|
||||
Contributor(s): Adriano dos Santos Fernandes
|
||||
|
||||
* [CORE-5380](http://tracker.firebirdsql.org/browse/CORE-5380): Allow subroutines to call others subroutines and themself recursively
|
||||
Reference(s): [doc/sql.extensions/README.subroutines.txt](https://github.com/FirebirdSQL/firebird/raw/master/doc/sql.extensions/README.subroutines.txt)
|
||||
Contributor(s): Adriano dos Santos Fernandes
|
||||
|
||||
* [CORE-5119](http://tracker.firebirdsql.org/browse/CORE-5119): Support autocommit mode in SET TRANSACTION statement
|
||||
Contributor(s): Dmitry Yemanov
|
||||
|
||||
|
@ -7,7 +7,7 @@ Author:
|
||||
|
||||
Description:
|
||||
Support for PSQL subroutines (functions and procedures) inside functions, procedures, triggers
|
||||
and EXECUTE BLOCK. Subroutines are declared in the main routine and may be used from there.
|
||||
and EXECUTE BLOCK. Subroutines are declared in the main routine and may be used from there or others subroutines.
|
||||
|
||||
Syntax:
|
||||
<declaration item> ::=
|
||||
@ -15,7 +15,21 @@ Syntax:
|
||||
|
|
||||
DECLARE [VARIABLE] CURSOR <cursor name> FOR (<query>);
|
||||
|
|
||||
DECLARE FUNCTION <function name> RETURNS <data type>
|
||||
<subroutine declaration>
|
||||
|
|
||||
<subroutine implementation>
|
||||
|
||||
<subroutine declaration> ::=
|
||||
DECLARE FUNCTION <function name> [ (<input parameters>) ]
|
||||
RETURNS <data type>
|
||||
[ [ NOT ] DETERMINISTIC ] ;
|
||||
|
|
||||
DECLARE PROCEDURE <procedure name> [ (<input parameters>) ] [ RETURNS (<output parameters>) ] ;
|
||||
|
||||
<subroutine implementation> ::=
|
||||
DECLARE FUNCTION <function name> [ (<input parameters>) ]
|
||||
RETURNS <data type>
|
||||
[ [ NOT ] DETERMINISTIC ]
|
||||
AS
|
||||
...
|
||||
BEGIN
|
||||
@ -32,8 +46,11 @@ Syntax:
|
||||
Limitations:
|
||||
1) Subroutines may not be nested in another subroutine. They are only supported in the main
|
||||
routine.
|
||||
2) Currently, a subroutine may not directly access or use variables, cursors or another
|
||||
subroutines of the main statements. This may be allowed in the future.
|
||||
2) Currently, a subroutine may not directly access or use variables or cursors of the
|
||||
main statements. This may be allowed in the future.
|
||||
|
||||
Notes:
|
||||
1) Starting in FB 4, subroutines may be recursive or call others subroutines.
|
||||
|
||||
Examples:
|
||||
set term !;
|
||||
@ -89,3 +106,57 @@ Examples:
|
||||
end!
|
||||
|
||||
select func1(5, 6) from rdb$database!
|
||||
|
||||
|
||||
-- 3) Recursive sub-function in EXECUTE BLOCK.
|
||||
|
||||
execute block returns (i integer, o integer)
|
||||
as
|
||||
-- Recursive function without forward declaration.
|
||||
declare function fibonacci(n integer) returns integer
|
||||
as
|
||||
begin
|
||||
if (n = 0 or n = 1) then
|
||||
return n;
|
||||
else
|
||||
return fibonacci(n - 1) + fibonacci(n - 2);
|
||||
end
|
||||
begin
|
||||
i = 0;
|
||||
|
||||
while (i < 10)
|
||||
do
|
||||
begin
|
||||
o = fibonacci(i);
|
||||
suspend;
|
||||
i = i + 1;
|
||||
end
|
||||
end!
|
||||
|
||||
|
||||
-- 4) Example with forward declaration and parameter with default values.
|
||||
|
||||
execute block returns (o integer)
|
||||
as
|
||||
-- Forward declaration of P1.
|
||||
declare procedure p1(i integer = 1) returns (o integer);
|
||||
|
||||
-- Forward declaration of P2.
|
||||
declare procedure p2(i integer) returns (o integer);
|
||||
|
||||
-- Implementation of P1 should not re-declare parameter default value.
|
||||
declare procedure p1(i integer) returns (o integer)
|
||||
as
|
||||
begin
|
||||
execute procedure p2(i) returning_values o;
|
||||
end
|
||||
|
||||
declare procedure p2(i integer) returns (o integer)
|
||||
as
|
||||
begin
|
||||
o = i;
|
||||
end
|
||||
begin
|
||||
execute procedure p1 returning_values o;
|
||||
suspend;
|
||||
end!
|
||||
|
@ -1698,6 +1698,22 @@ C --
|
||||
PARAMETER (GDS__decfloat_overflow = 335545142)
|
||||
INTEGER*4 GDS__decfloat_underflow
|
||||
PARAMETER (GDS__decfloat_underflow = 335545143)
|
||||
INTEGER*4 GDS__subfunc_notdef
|
||||
PARAMETER (GDS__subfunc_notdef = 335545144)
|
||||
INTEGER*4 GDS__subproc_notdef
|
||||
PARAMETER (GDS__subproc_notdef = 335545145)
|
||||
INTEGER*4 GDS__subfunc_signat
|
||||
PARAMETER (GDS__subfunc_signat = 335545146)
|
||||
INTEGER*4 GDS__subproc_signat
|
||||
PARAMETER (GDS__subproc_signat = 335545147)
|
||||
INTEGER*4 GDS__subfunc_defvaldecl
|
||||
PARAMETER (GDS__subfunc_defvaldecl = 335545148)
|
||||
INTEGER*4 GDS__subproc_defvaldecl
|
||||
PARAMETER (GDS__subproc_defvaldecl = 335545149)
|
||||
INTEGER*4 GDS__subfunc_not_impl
|
||||
PARAMETER (GDS__subfunc_not_impl = 335545150)
|
||||
INTEGER*4 GDS__subproc_not_impl
|
||||
PARAMETER (GDS__subproc_not_impl = 335545151)
|
||||
INTEGER*4 GDS__gfix_db_name
|
||||
PARAMETER (GDS__gfix_db_name = 335740929)
|
||||
INTEGER*4 GDS__gfix_invalid_sw
|
||||
|
@ -1693,6 +1693,22 @@ const
|
||||
gds_decfloat_overflow = 335545142;
|
||||
isc_decfloat_underflow = 335545143;
|
||||
gds_decfloat_underflow = 335545143;
|
||||
isc_subfunc_notdef = 335545144;
|
||||
gds_subfunc_notdef = 335545144;
|
||||
isc_subproc_notdef = 335545145;
|
||||
gds_subproc_notdef = 335545145;
|
||||
isc_subfunc_signat = 335545146;
|
||||
gds_subfunc_signat = 335545146;
|
||||
isc_subproc_signat = 335545147;
|
||||
gds_subproc_signat = 335545147;
|
||||
isc_subfunc_defvaldecl = 335545148;
|
||||
gds_subfunc_defvaldecl = 335545148;
|
||||
isc_subproc_defvaldecl = 335545149;
|
||||
gds_subproc_defvaldecl = 335545149;
|
||||
isc_subfunc_not_impl = 335545150;
|
||||
gds_subfunc_not_impl = 335545150;
|
||||
isc_subproc_not_impl = 335545151;
|
||||
gds_subproc_not_impl = 335545151;
|
||||
isc_gfix_db_name = 335740929;
|
||||
gds_gfix_db_name = 335740929;
|
||||
isc_gfix_invalid_sw = 335740930;
|
||||
|
@ -320,6 +320,37 @@ void DsqlCompilerScratch::putLocalVariables(CompoundStmtNode* parameters, USHORT
|
||||
else
|
||||
fb_assert(false);
|
||||
}
|
||||
|
||||
if (!(flags & DsqlCompilerScratch::FLAG_SUB_ROUTINE))
|
||||
{
|
||||
// Check not implemented sub-functions.
|
||||
|
||||
GenericMap<Left<MetaName, DeclareSubFuncNode*> >::ConstAccessor funcAccessor(&subFunctions);
|
||||
|
||||
for (bool found = funcAccessor.getFirst(); found; found = funcAccessor.getNext())
|
||||
{
|
||||
if (!funcAccessor.current()->second->dsqlBlock)
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_subfunc_not_impl) <<
|
||||
funcAccessor.current()->first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check not implemented sub-procedures.
|
||||
|
||||
GenericMap<Left<MetaName, DeclareSubProcNode*> >::ConstAccessor procAccessor(&subProcedures);
|
||||
|
||||
for (bool found = procAccessor.getFirst(); found; found = procAccessor.getNext())
|
||||
{
|
||||
if (!procAccessor.current()->second->dsqlBlock)
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_subproc_not_impl) <<
|
||||
procAccessor.current()->first.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write out local variable field data type.
|
||||
@ -586,6 +617,50 @@ void DsqlCompilerScratch::checkUnusedCTEs() const
|
||||
}
|
||||
}
|
||||
|
||||
DeclareSubFuncNode* DsqlCompilerScratch::getSubFunction(const Firebird::MetaName& name)
|
||||
{
|
||||
DeclareSubFuncNode* subFunc = NULL;
|
||||
subFunctions.get(name, subFunc);
|
||||
|
||||
if (!subFunc && mainScratch)
|
||||
subFunc = mainScratch->getSubFunction(name);
|
||||
|
||||
return subFunc;
|
||||
}
|
||||
|
||||
void DsqlCompilerScratch::putSubFunction(DeclareSubFuncNode* subFunc, bool replace)
|
||||
{
|
||||
if (!replace && subFunctions.exist(subFunc->name))
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_dsql_duplicate_spec) << subFunc->name);
|
||||
}
|
||||
|
||||
subFunctions.put(subFunc->name, subFunc);
|
||||
}
|
||||
|
||||
DeclareSubProcNode* DsqlCompilerScratch::getSubProcedure(const Firebird::MetaName& name)
|
||||
{
|
||||
DeclareSubProcNode* subProc = NULL;
|
||||
subProcedures.get(name, subProc);
|
||||
|
||||
if (!subProc && mainScratch)
|
||||
subProc = mainScratch->getSubProcedure(name);
|
||||
|
||||
return subProc;
|
||||
}
|
||||
|
||||
void DsqlCompilerScratch::putSubProcedure(DeclareSubProcNode* subProc, bool replace)
|
||||
{
|
||||
if (!replace && subProcedures.exist(subProc->name))
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_dsql_duplicate_spec) << subProc->name);
|
||||
}
|
||||
|
||||
subProcedures.put(subProc->name, subProc);
|
||||
}
|
||||
|
||||
// Process derived table which can be recursive CTE.
|
||||
// If it is non-recursive return input node unchanged.
|
||||
// If it is recursive return new derived table which is an union of union of anchor (non-recursive)
|
||||
|
@ -70,7 +70,7 @@ public:
|
||||
|
||||
public:
|
||||
DsqlCompilerScratch(MemoryPool& p, dsql_dbb* aDbb, jrd_tra* aTransaction,
|
||||
DsqlCompiledStatement* aStatement)
|
||||
DsqlCompiledStatement* aStatement, DsqlCompilerScratch* aMainScratch = NULL)
|
||||
: BlrDebugWriter(p),
|
||||
dbb(aDbb),
|
||||
transaction(aTransaction),
|
||||
@ -79,7 +79,6 @@ public:
|
||||
nestingLevel(0),
|
||||
ports(p),
|
||||
relation(NULL),
|
||||
procedure(NULL),
|
||||
mainContext(p),
|
||||
context(&mainContext),
|
||||
unionContext(p),
|
||||
@ -115,6 +114,7 @@ public:
|
||||
ctes(p),
|
||||
cteAliases(p),
|
||||
psql(false),
|
||||
mainScratch(aMainScratch),
|
||||
subFunctions(p),
|
||||
subProcedures(p)
|
||||
{
|
||||
@ -247,43 +247,11 @@ public:
|
||||
bool isPsql() const { return psql; }
|
||||
void setPsql(bool value) { psql = value; }
|
||||
|
||||
dsql_udf* getSubFunction(const Firebird::MetaName& name)
|
||||
{
|
||||
dsql_udf* subFunc = NULL;
|
||||
subFunctions.get(name, subFunc);
|
||||
return subFunc;
|
||||
}
|
||||
DeclareSubFuncNode* getSubFunction(const Firebird::MetaName& name);
|
||||
void putSubFunction(DeclareSubFuncNode* subFunc, bool replace = false);
|
||||
|
||||
void putSubFunction(dsql_udf* subFunc)
|
||||
{
|
||||
if (subFunctions.exist(subFunc->udf_name.identifier))
|
||||
{
|
||||
using namespace Firebird;
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_dsql_duplicate_spec) << subFunc->udf_name.identifier);
|
||||
}
|
||||
|
||||
subFunctions.put(subFunc->udf_name.identifier, subFunc);
|
||||
}
|
||||
|
||||
dsql_prc* getSubProcedure(const Firebird::MetaName& name)
|
||||
{
|
||||
dsql_prc* subProc = NULL;
|
||||
subProcedures.get(name, subProc);
|
||||
return subProc;
|
||||
}
|
||||
|
||||
void putSubProcedure(dsql_prc* subProc)
|
||||
{
|
||||
if (subProcedures.exist(subProc->prc_name.identifier))
|
||||
{
|
||||
using namespace Firebird;
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_dsql_duplicate_spec) << subProc->prc_name.identifier);
|
||||
}
|
||||
|
||||
subProcedures.put(subProc->prc_name.identifier, subProc);
|
||||
}
|
||||
DeclareSubProcNode* getSubProcedure(const Firebird::MetaName& name);
|
||||
void putSubProcedure(DeclareSubProcNode* subProc, bool replace = false);
|
||||
|
||||
private:
|
||||
SelectExprNode* pass1RecursiveCte(SelectExprNode* input);
|
||||
@ -300,7 +268,6 @@ public:
|
||||
unsigned nestingLevel; // begin...end nesting level
|
||||
Firebird::Array<dsql_msg*> ports; // Port messages
|
||||
dsql_rel* relation; // relation created by this request (for DDL)
|
||||
dsql_prc* procedure; // procedure created by this request (for DDL)
|
||||
DsqlContextStack mainContext;
|
||||
DsqlContextStack* context;
|
||||
DsqlContextStack unionContext; // Save contexts for views of unions
|
||||
@ -340,8 +307,9 @@ private:
|
||||
Firebird::HalfStaticArray<SelectExprNode*, 4> ctes; // common table expressions
|
||||
Firebird::HalfStaticArray<const Firebird::string*, 4> cteAliases; // CTE aliases in recursive members
|
||||
bool psql;
|
||||
Firebird::GenericMap<Firebird::Left<Firebird::MetaName, dsql_udf*> > subFunctions;
|
||||
Firebird::GenericMap<Firebird::Left<Firebird::MetaName, dsql_prc*> > subProcedures;
|
||||
DsqlCompilerScratch* mainScratch;
|
||||
Firebird::GenericMap<Firebird::Left<Firebird::MetaName, DeclareSubFuncNode*> > subFunctions;
|
||||
Firebird::GenericMap<Firebird::Left<Firebird::MetaName, DeclareSubProcNode*> > subProcedures;
|
||||
};
|
||||
|
||||
class PsqlChanger
|
||||
|
@ -11589,9 +11589,13 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
|
||||
if (blrOp == blr_subfunc)
|
||||
{
|
||||
DeclareSubFuncNode* declareNode;
|
||||
if (csb->subFunctions.get(name.identifier, declareNode))
|
||||
|
||||
for (auto curCsb = csb; curCsb && !node->function; curCsb = curCsb->mainCsb)
|
||||
{
|
||||
if (curCsb->subFunctions.get(name.identifier, declareNode))
|
||||
node->function = declareNode->routine;
|
||||
}
|
||||
}
|
||||
|
||||
Function* function = node->function;
|
||||
|
||||
@ -12023,7 +12027,10 @@ ValueExprNode* UdfCallNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
doDsqlPass(dsqlScratch, args));
|
||||
|
||||
if (name.package.isEmpty())
|
||||
node->dsqlFunction = dsqlScratch->getSubFunction(name.identifier);
|
||||
{
|
||||
DeclareSubFuncNode* subFunction = dsqlScratch->getSubFunction(name.identifier);
|
||||
node->dsqlFunction = subFunction ? subFunction->dsqlFunction : NULL;
|
||||
}
|
||||
|
||||
if (!node->dsqlFunction)
|
||||
node->dsqlFunction = METD_get_function(dsqlScratch->getTransaction(), dsqlScratch, name);
|
||||
|
@ -51,164 +51,6 @@ DATABASE DB = STATIC "ODS.RDB";
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ParameterInfo
|
||||
{
|
||||
explicit ParameterInfo(MemoryPool& p)
|
||||
: type(0),
|
||||
number(0),
|
||||
name(p),
|
||||
fieldSource(p),
|
||||
fieldName(p),
|
||||
relationName(p),
|
||||
mechanism(0)
|
||||
{
|
||||
defaultSource.clear();
|
||||
defaultValue.clear();
|
||||
}
|
||||
|
||||
ParameterInfo(MemoryPool& p, const ParameterInfo& o)
|
||||
: type(o.type),
|
||||
number(o.number),
|
||||
name(p, o.name),
|
||||
fieldSource(p, o.fieldSource),
|
||||
fieldName(p, o.fieldName),
|
||||
relationName(p, o.relationName),
|
||||
collationId(o.collationId),
|
||||
nullFlag(o.nullFlag),
|
||||
mechanism(o.mechanism),
|
||||
fieldLength(o.fieldLength),
|
||||
fieldScale(o.fieldScale),
|
||||
fieldType(o.fieldType),
|
||||
fieldSubType(o.fieldSubType),
|
||||
fieldSegmentLength(o.fieldSegmentLength),
|
||||
fieldNullFlag(o.fieldNullFlag),
|
||||
fieldCharLength(o.fieldCharLength),
|
||||
fieldCollationId(o.fieldCollationId),
|
||||
fieldCharSetId(o.fieldCharSetId),
|
||||
fieldPrecision(o.fieldPrecision),
|
||||
defaultSource(o.defaultSource),
|
||||
defaultValue(o.defaultValue)
|
||||
{
|
||||
}
|
||||
|
||||
SSHORT type;
|
||||
SSHORT number;
|
||||
MetaName name;
|
||||
MetaName fieldSource;
|
||||
MetaName fieldName;
|
||||
MetaName relationName;
|
||||
Nullable<SSHORT> collationId;
|
||||
Nullable<SSHORT> nullFlag;
|
||||
SSHORT mechanism;
|
||||
Nullable<SSHORT> fieldLength;
|
||||
Nullable<SSHORT> fieldScale;
|
||||
Nullable<SSHORT> fieldType;
|
||||
Nullable<SSHORT> fieldSubType;
|
||||
Nullable<SSHORT> fieldSegmentLength;
|
||||
Nullable<SSHORT> fieldNullFlag;
|
||||
Nullable<SSHORT> fieldCharLength;
|
||||
Nullable<SSHORT> fieldCollationId;
|
||||
Nullable<SSHORT> fieldCharSetId;
|
||||
Nullable<SSHORT> fieldPrecision;
|
||||
|
||||
// Not compared
|
||||
bid defaultSource;
|
||||
bid defaultValue;
|
||||
|
||||
bool operator >(const ParameterInfo& o) const
|
||||
{
|
||||
return type > o.type || (type == o.type && number > o.number);
|
||||
}
|
||||
|
||||
bool operator ==(const ParameterInfo& o) const
|
||||
{
|
||||
return type == o.type && number == o.number && name == o.name &&
|
||||
(fieldSource == o.fieldSource ||
|
||||
(fb_utils::implicit_domain(fieldSource.c_str()) &&
|
||||
fb_utils::implicit_domain(o.fieldSource.c_str()))) &&
|
||||
fieldName == o.fieldName && relationName == o.relationName &&
|
||||
collationId == o.collationId && nullFlag == o.nullFlag &&
|
||||
mechanism == o.mechanism && fieldLength == o.fieldLength &&
|
||||
fieldScale == o.fieldScale && fieldType == o.fieldType &&
|
||||
fieldSubType == o.fieldSubType && fieldSegmentLength == o.fieldSegmentLength &&
|
||||
fieldNullFlag == o.fieldNullFlag && fieldCharLength == o.fieldCharLength &&
|
||||
fieldCollationId == o.fieldCollationId && fieldCharSetId == o.fieldCharSetId &&
|
||||
fieldPrecision == o.fieldPrecision;
|
||||
}
|
||||
|
||||
bool operator !=(const ParameterInfo& o) const
|
||||
{
|
||||
return !(*this == o);
|
||||
}
|
||||
};
|
||||
|
||||
struct Signature
|
||||
{
|
||||
Signature(MemoryPool& p, const MetaName& aName)
|
||||
: name(p, aName),
|
||||
parameters(p),
|
||||
defined(false)
|
||||
{
|
||||
}
|
||||
|
||||
explicit Signature(const MetaName& aName)
|
||||
: name(aName),
|
||||
parameters(*getDefaultMemoryPool()),
|
||||
defined(false)
|
||||
{
|
||||
}
|
||||
|
||||
explicit Signature(MemoryPool& p)
|
||||
: name(p),
|
||||
parameters(p),
|
||||
defined(false)
|
||||
{
|
||||
}
|
||||
|
||||
Signature(MemoryPool& p, const Signature& o)
|
||||
: name(p, o.name),
|
||||
parameters(p),
|
||||
defined(o.defined)
|
||||
{
|
||||
for (SortedObjectsArray<ParameterInfo>::const_iterator i = o.parameters.begin();
|
||||
i != o.parameters.end(); ++i)
|
||||
{
|
||||
parameters.add(*i);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator >(const Signature& o) const
|
||||
{
|
||||
return name > o.name;
|
||||
}
|
||||
|
||||
bool operator ==(const Signature& o) const
|
||||
{
|
||||
if (name != o.name || parameters.getCount() != o.parameters.getCount())
|
||||
return false;
|
||||
|
||||
for (SortedObjectsArray<ParameterInfo>::const_iterator i = parameters.begin(),
|
||||
j = o.parameters.begin();
|
||||
i != parameters.end(); ++i, ++j)
|
||||
{
|
||||
if (*i != *j)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator !=(const Signature& o) const
|
||||
{
|
||||
return !(*this == o);
|
||||
}
|
||||
|
||||
MetaName name;
|
||||
SortedObjectsArray<ParameterInfo> parameters;
|
||||
bool defined;
|
||||
};
|
||||
|
||||
|
||||
// Return function and procedure names (in the user charset) and optionally its details for a
|
||||
// given package.
|
||||
void collectPackagedItems(thread_db* tdbb, jrd_tra* transaction, const MetaName& metaName,
|
||||
@ -234,7 +76,7 @@ namespace
|
||||
ARG.RDB$FUNCTION_NAME EQ FUN.RDB$FUNCTION_NAME AND
|
||||
FLD.RDB$FIELD_NAME EQ ARG.RDB$FIELD_SOURCE
|
||||
{
|
||||
ParameterInfo parameter(*getDefaultMemoryPool());
|
||||
SignatureParameter parameter(*getDefaultMemoryPool());
|
||||
|
||||
parameter.number = ARG.RDB$ARGUMENT_POSITION;
|
||||
parameter.name = ARG.RDB$ARGUMENT_NAME;
|
||||
@ -271,11 +113,6 @@ namespace
|
||||
if (!FLD.RDB$FIELD_PRECISION.NULL)
|
||||
parameter.fieldPrecision = FLD.RDB$FIELD_PRECISION;
|
||||
|
||||
if (!ARG.RDB$DEFAULT_SOURCE.NULL)
|
||||
parameter.defaultSource = ARG.RDB$DEFAULT_SOURCE;
|
||||
if (!ARG.RDB$DEFAULT_VALUE.NULL)
|
||||
parameter.defaultValue = ARG.RDB$DEFAULT_VALUE;
|
||||
|
||||
function.parameters.add(parameter);
|
||||
}
|
||||
END_FOR
|
||||
@ -304,7 +141,7 @@ namespace
|
||||
PRM.RDB$PROCEDURE_NAME EQ PRC.RDB$PROCEDURE_NAME AND
|
||||
FLD.RDB$FIELD_NAME EQ PRM.RDB$FIELD_SOURCE
|
||||
{
|
||||
ParameterInfo parameter(*getDefaultMemoryPool());
|
||||
SignatureParameter parameter(*getDefaultMemoryPool());
|
||||
parameter.type = PRM.RDB$PARAMETER_TYPE;
|
||||
parameter.number = PRM.RDB$PARAMETER_NUMBER;
|
||||
parameter.name = PRM.RDB$PARAMETER_NAME;
|
||||
@ -341,11 +178,6 @@ namespace
|
||||
if (!FLD.RDB$FIELD_PRECISION.NULL)
|
||||
parameter.fieldPrecision = FLD.RDB$FIELD_PRECISION;
|
||||
|
||||
if (!PRM.RDB$DEFAULT_SOURCE.NULL)
|
||||
parameter.defaultSource = PRM.RDB$DEFAULT_SOURCE;
|
||||
if (!PRM.RDB$DEFAULT_VALUE.NULL)
|
||||
parameter.defaultValue = PRM.RDB$DEFAULT_VALUE;
|
||||
|
||||
procedure.parameters.add(parameter);
|
||||
}
|
||||
END_FOR
|
||||
|
@ -1402,7 +1402,8 @@ DmlNode* DeclareSubFuncNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerSc
|
||||
|
||||
{ // scope
|
||||
CompilerScratch* const subCsb = node->subCsb =
|
||||
FB_NEW_POOL(csb->csb_pool) CompilerScratch(csb->csb_pool);
|
||||
FB_NEW_POOL(csb->csb_pool) CompilerScratch(csb->csb_pool, csb);
|
||||
|
||||
subCsb->csb_g_flags |= csb_subroutine | (csb->csb_g_flags & csb_get_dependencies);
|
||||
subCsb->csb_blr_reader = csb->csb_blr_reader;
|
||||
|
||||
@ -1520,6 +1521,97 @@ DeclareSubFuncNode* DeclareSubFuncNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
|
||||
if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_SUB_ROUTINE)
|
||||
ERR_post(Arg::Gds(isc_wish_list) << Arg::Gds(isc_random) << "nested sub function");
|
||||
|
||||
DeclareSubFuncNode* prevDecl = dsqlScratch->getSubFunction(name);
|
||||
bool implemetingForward = prevDecl && !prevDecl->dsqlBlock && dsqlBlock;
|
||||
|
||||
dsqlFunction = implemetingForward ? prevDecl->dsqlFunction : FB_NEW_POOL(pool) dsql_udf(pool);
|
||||
|
||||
dsqlFunction->udf_flags = UDF_subfunc;
|
||||
dsqlFunction->udf_name.identifier = name;
|
||||
|
||||
fb_assert(dsqlReturns.getCount() == 1);
|
||||
const TypeClause* returnType = dsqlReturns[0]->type;
|
||||
|
||||
dsqlFunction->udf_dtype = returnType->dtype;
|
||||
dsqlFunction->udf_scale = returnType->scale;
|
||||
dsqlFunction->udf_sub_type = returnType->subType;
|
||||
dsqlFunction->udf_length = returnType->length;
|
||||
dsqlFunction->udf_character_set_id = returnType->charSetId;
|
||||
|
||||
if (dsqlDeterministic)
|
||||
dsqlSignature.flags |= Signature::FLAG_DETERMINISTIC;
|
||||
|
||||
SignatureParameter sigRet(pool);
|
||||
sigRet.type = 1;
|
||||
sigRet.number = -1;
|
||||
sigRet.fromType(returnType);
|
||||
dsqlSignature.parameters.add(sigRet);
|
||||
|
||||
Array<NestConst<ParameterClause> >& paramArray = dsqlParameters;
|
||||
bool defaultFound = false;
|
||||
|
||||
for (NestConst<ParameterClause>* i = paramArray.begin(); i != paramArray.end(); ++i)
|
||||
{
|
||||
ParameterClause* param = *i;
|
||||
const unsigned paramIndex = i - paramArray.begin();
|
||||
|
||||
SignatureParameter sigParam(pool);
|
||||
sigParam.type = 0;
|
||||
sigParam.number = (SSHORT) dsqlSignature.parameters.getCount();
|
||||
sigParam.name = param->name;
|
||||
sigParam.fromType(param->type);
|
||||
dsqlSignature.parameters.add(sigParam);
|
||||
|
||||
if (!implemetingForward)
|
||||
{
|
||||
// ASF: dsqlFunction->udf_arguments is only checked for its count for now.
|
||||
dsqlFunction->udf_arguments.add(dsc());
|
||||
}
|
||||
|
||||
if (param->defaultClause)
|
||||
{
|
||||
if (prevDecl)
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_subfunc_defvaldecl) <<
|
||||
name.c_str());
|
||||
}
|
||||
|
||||
defaultFound = true;
|
||||
|
||||
if (!implemetingForward && dsqlFunction->udf_def_count == 0)
|
||||
dsqlFunction->udf_def_count = paramArray.end() - i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (defaultFound)
|
||||
{
|
||||
// Parameter without default value after parameters with default.
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
||||
Arg::Gds(isc_bad_default_value) <<
|
||||
Arg::Gds(isc_invalid_clause) << Arg::Str("defaults must be last"));
|
||||
}
|
||||
|
||||
if (prevDecl && paramIndex < prevDecl->dsqlParameters.getCount())
|
||||
param->defaultClause = prevDecl->dsqlParameters[paramIndex]->defaultClause;
|
||||
}
|
||||
}
|
||||
|
||||
if (!implemetingForward)
|
||||
dsqlScratch->putSubFunction(this);
|
||||
else if (dsqlSignature != prevDecl->dsqlSignature)
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_subfunc_signat) <<
|
||||
name.c_str());
|
||||
}
|
||||
|
||||
if (!dsqlBlock) // forward decl
|
||||
return this;
|
||||
|
||||
if (prevDecl)
|
||||
dsqlScratch->putSubFunction(this, true);
|
||||
|
||||
DsqlCompiledStatement* statement = FB_NEW_POOL(pool) DsqlCompiledStatement(pool);
|
||||
|
||||
if (dsqlScratch->clientDialect > SQL_DIALECT_V5)
|
||||
@ -1535,58 +1627,23 @@ DeclareSubFuncNode* DeclareSubFuncNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
|
||||
statement->setType(DsqlCompiledStatement::TYPE_SELECT);
|
||||
|
||||
blockScratch = FB_NEW_POOL(pool) DsqlCompilerScratch(pool,
|
||||
dsqlScratch->getAttachment(), dsqlScratch->getTransaction(), statement);
|
||||
dsqlScratch->getAttachment(), dsqlScratch->getTransaction(), statement, dsqlScratch);
|
||||
blockScratch->clientDialect = dsqlScratch->clientDialect;
|
||||
blockScratch->flags |= DsqlCompilerScratch::FLAG_FUNCTION | DsqlCompilerScratch::FLAG_SUB_ROUTINE;
|
||||
blockScratch->flags |= dsqlScratch->flags & DsqlCompilerScratch::FLAG_DDL;
|
||||
blockScratch->flags |=
|
||||
DsqlCompilerScratch::FLAG_FUNCTION |
|
||||
DsqlCompilerScratch::FLAG_SUB_ROUTINE |
|
||||
(dsqlScratch->flags & DsqlCompilerScratch::FLAG_DDL);
|
||||
|
||||
dsqlBlock = dsqlBlock->dsqlPass(blockScratch);
|
||||
|
||||
dsqlFunction = FB_NEW_POOL(pool) dsql_udf(pool);
|
||||
dsqlFunction->udf_flags = UDF_subfunc;
|
||||
dsqlFunction->udf_name.identifier = name;
|
||||
|
||||
fb_assert(dsqlBlock->returns.getCount() == 1);
|
||||
const TypeClause* returnType = dsqlBlock->returns[0]->type;
|
||||
dsqlFunction->udf_dtype = returnType->dtype;
|
||||
dsqlFunction->udf_scale = returnType->scale;
|
||||
dsqlFunction->udf_sub_type = returnType->subType;
|
||||
dsqlFunction->udf_length = returnType->length;
|
||||
dsqlFunction->udf_character_set_id = returnType->charSetId;
|
||||
|
||||
const Array<NestConst<ParameterClause> >& paramArray = dsqlBlock->parameters;
|
||||
bool defaultFound = false;
|
||||
|
||||
for (const NestConst<ParameterClause>* i = paramArray.begin(); i != paramArray.end(); ++i)
|
||||
{
|
||||
// ASF: dsqlFunction->udf_arguments is only checked for its count for now.
|
||||
dsqlFunction->udf_arguments.add(dsc());
|
||||
|
||||
const ParameterClause* param = *i;
|
||||
|
||||
if (param->defaultClause)
|
||||
{
|
||||
defaultFound = true;
|
||||
|
||||
if (dsqlFunction->udf_def_count == 0)
|
||||
dsqlFunction->udf_def_count = paramArray.end() - i;
|
||||
}
|
||||
else if (defaultFound)
|
||||
{
|
||||
// Parameter without default value after parameters with default.
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
||||
Arg::Gds(isc_bad_default_value) <<
|
||||
Arg::Gds(isc_invalid_clause) << Arg::Str("defaults must be last"));
|
||||
}
|
||||
}
|
||||
|
||||
dsqlScratch->putSubFunction(dsqlFunction);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void DeclareSubFuncNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
if (!dsqlBlock) // forward decl
|
||||
return;
|
||||
|
||||
GEN_request(blockScratch, dsqlBlock);
|
||||
|
||||
dsqlScratch->appendUChar(blr_subfunc_decl);
|
||||
@ -1677,7 +1734,8 @@ DmlNode* DeclareSubProcNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerSc
|
||||
|
||||
{ // scope
|
||||
CompilerScratch* const subCsb = node->subCsb =
|
||||
FB_NEW_POOL(csb->csb_pool) CompilerScratch(csb->csb_pool);
|
||||
FB_NEW_POOL(csb->csb_pool) CompilerScratch(csb->csb_pool, csb);
|
||||
|
||||
subCsb->csb_g_flags |= csb_subroutine | (csb->csb_g_flags & csb_get_dependencies);
|
||||
subCsb->csb_blr_reader = csb->csb_blr_reader;
|
||||
|
||||
@ -1803,6 +1861,100 @@ DeclareSubProcNode* DeclareSubProcNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
|
||||
if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_SUB_ROUTINE)
|
||||
ERR_post(Arg::Gds(isc_wish_list) << Arg::Gds(isc_random) << "nested sub procedure");
|
||||
|
||||
DeclareSubProcNode* prevDecl = dsqlScratch->getSubProcedure(name);
|
||||
bool implemetingForward = prevDecl && !prevDecl->dsqlBlock && dsqlBlock;
|
||||
|
||||
dsqlProcedure = implemetingForward ? prevDecl->dsqlProcedure : FB_NEW_POOL(pool) dsql_prc(pool);
|
||||
|
||||
dsqlProcedure->prc_flags = PRC_subproc;
|
||||
dsqlProcedure->prc_name.identifier = name;
|
||||
dsqlProcedure->prc_in_count = USHORT(dsqlParameters.getCount());
|
||||
dsqlProcedure->prc_out_count = USHORT(dsqlReturns.getCount());
|
||||
|
||||
if (dsqlParameters.hasData())
|
||||
{
|
||||
Array<NestConst<ParameterClause> >& paramArray = dsqlParameters;
|
||||
bool defaultFound = false;
|
||||
|
||||
dsqlProcedure->prc_inputs = paramArray.front()->type;
|
||||
|
||||
for (NestConst<ParameterClause>* i = paramArray.begin(); i != paramArray.end(); ++i)
|
||||
{
|
||||
ParameterClause* param = *i;
|
||||
const unsigned paramIndex = i - paramArray.begin();
|
||||
|
||||
SignatureParameter sigParam(pool);
|
||||
sigParam.type = 0; // input
|
||||
sigParam.number = (SSHORT) dsqlSignature.parameters.getCount();
|
||||
sigParam.name = param->name;
|
||||
sigParam.fromType(param->type);
|
||||
dsqlSignature.parameters.add(sigParam);
|
||||
|
||||
if (param->defaultClause)
|
||||
{
|
||||
if (prevDecl)
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_subproc_defvaldecl) <<
|
||||
name.c_str());
|
||||
}
|
||||
|
||||
defaultFound = true;
|
||||
|
||||
if (!implemetingForward && dsqlProcedure->prc_def_count == 0)
|
||||
dsqlProcedure->prc_def_count = paramArray.end() - i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (defaultFound)
|
||||
{
|
||||
// Parameter without default value after parameters with default.
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
||||
Arg::Gds(isc_bad_default_value) <<
|
||||
Arg::Gds(isc_invalid_clause) << Arg::Str("defaults must be last"));
|
||||
}
|
||||
|
||||
if (prevDecl && paramIndex < prevDecl->dsqlParameters.getCount())
|
||||
param->defaultClause = prevDecl->dsqlParameters[paramIndex]->defaultClause;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dsqlReturns.hasData())
|
||||
{
|
||||
Array<NestConst<ParameterClause> >& paramArray = dsqlReturns;
|
||||
|
||||
dsqlProcedure->prc_outputs = paramArray.front()->type;
|
||||
|
||||
for (NestConst<ParameterClause>* i = paramArray.begin(); i != paramArray.end(); ++i)
|
||||
{
|
||||
ParameterClause* param = *i;
|
||||
const unsigned paramIndex = i - paramArray.begin();
|
||||
|
||||
SignatureParameter sigParam(pool);
|
||||
sigParam.type = 1; // output
|
||||
sigParam.number = (SSHORT) dsqlSignature.parameters.getCount();
|
||||
sigParam.name = param->name;
|
||||
sigParam.fromType(param->type);
|
||||
dsqlSignature.parameters.add(sigParam);
|
||||
}
|
||||
}
|
||||
|
||||
if (!implemetingForward)
|
||||
dsqlScratch->putSubProcedure(this);
|
||||
else if (dsqlSignature != prevDecl->dsqlSignature)
|
||||
{
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_subproc_signat) <<
|
||||
name.c_str());
|
||||
}
|
||||
|
||||
if (!dsqlBlock) // forward decl
|
||||
return this;
|
||||
|
||||
if (prevDecl)
|
||||
dsqlScratch->putSubProcedure(this, true);
|
||||
|
||||
DsqlCompiledStatement* statement = FB_NEW_POOL(pool) DsqlCompiledStatement(pool);
|
||||
|
||||
if (dsqlScratch->clientDialect > SQL_DIALECT_V5)
|
||||
@ -1818,54 +1970,21 @@ DeclareSubProcNode* DeclareSubProcNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
|
||||
statement->setType(DsqlCompiledStatement::TYPE_SELECT);
|
||||
|
||||
blockScratch = FB_NEW_POOL(pool) DsqlCompilerScratch(pool,
|
||||
dsqlScratch->getAttachment(), dsqlScratch->getTransaction(), statement);
|
||||
dsqlScratch->getAttachment(), dsqlScratch->getTransaction(), statement, dsqlScratch);
|
||||
blockScratch->clientDialect = dsqlScratch->clientDialect;
|
||||
blockScratch->flags |= DsqlCompilerScratch::FLAG_PROCEDURE | DsqlCompilerScratch::FLAG_SUB_ROUTINE;
|
||||
blockScratch->flags |= dsqlScratch->flags & DsqlCompilerScratch::FLAG_DDL;
|
||||
|
||||
dsqlBlock = dsqlBlock->dsqlPass(blockScratch);
|
||||
|
||||
dsqlProcedure = FB_NEW_POOL(pool) dsql_prc(pool);
|
||||
dsqlProcedure->prc_flags = PRC_subproc;
|
||||
dsqlProcedure->prc_name.identifier = name;
|
||||
dsqlProcedure->prc_in_count = USHORT(dsqlBlock->parameters.getCount());
|
||||
dsqlProcedure->prc_out_count = USHORT(dsqlBlock->returns.getCount());
|
||||
|
||||
if (dsqlBlock->parameters.hasData())
|
||||
{
|
||||
Array<NestConst<ParameterClause> >& paramArray = dsqlBlock->parameters;
|
||||
|
||||
dsqlProcedure->prc_inputs = paramArray.front()->type;
|
||||
|
||||
for (const NestConst<ParameterClause>* i = paramArray.begin(); i != paramArray.end(); ++i)
|
||||
{
|
||||
const ParameterClause* param = *i;
|
||||
|
||||
if (param->defaultClause)
|
||||
{
|
||||
if (dsqlProcedure->prc_def_count == 0)
|
||||
dsqlProcedure->prc_def_count = paramArray.end() - i;
|
||||
}
|
||||
else if (dsqlProcedure->prc_def_count != 0)
|
||||
{
|
||||
// Parameter without default value after parameters with default.
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
||||
Arg::Gds(isc_bad_default_value) <<
|
||||
Arg::Gds(isc_invalid_clause) << Arg::Str("defaults must be last"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dsqlBlock->returns.hasData())
|
||||
dsqlProcedure->prc_outputs = dsqlBlock->returns.front()->type;
|
||||
|
||||
dsqlScratch->putSubProcedure(dsqlProcedure);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void DeclareSubProcNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
if (!dsqlBlock) // forward decl
|
||||
return;
|
||||
|
||||
GEN_request(blockScratch, dsqlBlock);
|
||||
|
||||
dsqlScratch->appendUChar(blr_subproc_decl);
|
||||
@ -2636,9 +2755,13 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
|
||||
if (blrOp == blr_exec_subproc)
|
||||
{
|
||||
DeclareSubProcNode* declareNode;
|
||||
if (csb->subProcedures.get(name.identifier, declareNode))
|
||||
|
||||
for (auto curCsb = csb; curCsb && !procedure; curCsb = curCsb->mainCsb)
|
||||
{
|
||||
if (curCsb->subProcedures.get(name.identifier, declareNode))
|
||||
procedure = declareNode->routine;
|
||||
}
|
||||
}
|
||||
else
|
||||
procedure = MET_lookup_procedure(tdbb, name, false);
|
||||
}
|
||||
@ -2669,7 +2792,10 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
dsql_prc* procedure = NULL;
|
||||
|
||||
if (dsqlName.package.isEmpty())
|
||||
procedure = dsqlScratch->getSubProcedure(dsqlName.identifier);
|
||||
{
|
||||
DeclareSubProcNode* subProcedure = dsqlScratch->getSubProcedure(dsqlName.identifier);
|
||||
procedure = subProcedure ? subProcedure->dsqlProcedure : NULL;
|
||||
}
|
||||
|
||||
if (!procedure)
|
||||
procedure = METD_get_procedure(dsqlScratch->getTransaction(), dsqlScratch, dsqlName);
|
||||
@ -2683,10 +2809,7 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
}
|
||||
|
||||
if (!dsqlScratch->isPsql())
|
||||
{
|
||||
dsqlScratch->procedure = procedure;
|
||||
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_EXEC_PROCEDURE);
|
||||
}
|
||||
|
||||
ExecProcedureNode* node = FB_NEW_POOL(getPool()) ExecProcedureNode(getPool(), dsqlName);
|
||||
node->dsqlProcedure = procedure;
|
||||
@ -2740,7 +2863,7 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
Arg::Gds(isc_random) << Arg::Str("RETURNING_VALUES"));
|
||||
}
|
||||
|
||||
node->outputSources = explodeOutputs(dsqlScratch, dsqlScratch->procedure);
|
||||
node->outputSources = explodeOutputs(dsqlScratch, procedure);
|
||||
}
|
||||
|
||||
if (node->outputSources)
|
||||
|
@ -420,6 +420,9 @@ public:
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_DECLARE_SUBFUNC>(pool),
|
||||
name(pool, aName),
|
||||
dsqlDeterministic(false),
|
||||
dsqlParameters(pool),
|
||||
dsqlReturns(pool),
|
||||
dsqlSignature(pool, aName),
|
||||
dsqlBlock(NULL),
|
||||
blockScratch(NULL),
|
||||
dsqlFunction(NULL),
|
||||
@ -451,6 +454,9 @@ private:
|
||||
public:
|
||||
Firebird::MetaName name;
|
||||
bool dsqlDeterministic;
|
||||
Firebird::Array<NestConst<ParameterClause> > dsqlParameters;
|
||||
Firebird::Array<NestConst<ParameterClause> > dsqlReturns;
|
||||
Signature dsqlSignature;
|
||||
NestConst<ExecBlockNode> dsqlBlock;
|
||||
DsqlCompilerScratch* blockScratch;
|
||||
dsql_udf* dsqlFunction;
|
||||
@ -467,6 +473,9 @@ public:
|
||||
explicit DeclareSubProcNode(MemoryPool& pool, const Firebird::MetaName& aName)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_DECLARE_SUBPROC>(pool),
|
||||
name(pool, aName),
|
||||
dsqlParameters(pool),
|
||||
dsqlReturns(pool),
|
||||
dsqlSignature(pool, aName),
|
||||
dsqlBlock(NULL),
|
||||
blockScratch(NULL),
|
||||
dsqlProcedure(NULL),
|
||||
@ -497,6 +506,9 @@ private:
|
||||
|
||||
public:
|
||||
Firebird::MetaName name;
|
||||
Firebird::Array<NestConst<ParameterClause> > dsqlParameters;
|
||||
Firebird::Array<NestConst<ParameterClause> > dsqlReturns;
|
||||
Signature dsqlSignature;
|
||||
NestConst<ExecBlockNode> dsqlBlock;
|
||||
DsqlCompilerScratch* blockScratch;
|
||||
dsql_prc* dsqlProcedure;
|
||||
|
190
src/dsql/dsql.h
190
src/dsql/dsql.h
@ -1000,6 +1000,196 @@ private:
|
||||
int scale;
|
||||
};
|
||||
|
||||
struct SignatureParameter
|
||||
{
|
||||
explicit SignatureParameter(MemoryPool& p)
|
||||
: type(0),
|
||||
number(0),
|
||||
name(p),
|
||||
fieldSource(p),
|
||||
fieldName(p),
|
||||
relationName(p),
|
||||
charSetName(p),
|
||||
collationName(p),
|
||||
subTypeName(p),
|
||||
mechanism(0)
|
||||
{
|
||||
}
|
||||
|
||||
SignatureParameter(MemoryPool& p, const SignatureParameter& o)
|
||||
: type(o.type),
|
||||
number(o.number),
|
||||
name(p, o.name),
|
||||
fieldSource(p, o.fieldSource),
|
||||
fieldName(p, o.fieldName),
|
||||
relationName(p, o.relationName),
|
||||
charSetName(p, o.charSetName),
|
||||
collationName(p, o.collationName),
|
||||
subTypeName(p, o.subTypeName),
|
||||
collationId(o.collationId),
|
||||
nullFlag(o.nullFlag),
|
||||
mechanism(o.mechanism),
|
||||
fieldLength(o.fieldLength),
|
||||
fieldScale(o.fieldScale),
|
||||
fieldType(o.fieldType),
|
||||
fieldSubType(o.fieldSubType),
|
||||
fieldSegmentLength(o.fieldSegmentLength),
|
||||
fieldNullFlag(o.fieldNullFlag),
|
||||
fieldCharLength(o.fieldCharLength),
|
||||
fieldCollationId(o.fieldCollationId),
|
||||
fieldCharSetId(o.fieldCharSetId),
|
||||
fieldPrecision(o.fieldPrecision)
|
||||
{
|
||||
}
|
||||
|
||||
void fromType(const TypeClause* type)
|
||||
{
|
||||
fieldType = type->dtype;
|
||||
fieldScale = type->scale;
|
||||
subTypeName = type->subTypeName;
|
||||
fieldSubType = type->subType;
|
||||
fieldLength = type->length;
|
||||
fieldCharLength = type->charLength;
|
||||
charSetName = type->charSet;
|
||||
fieldCharSetId = type->charSetId;
|
||||
collationName = type->collate;
|
||||
fieldCollationId = type->collationId;
|
||||
fieldSource = type->fieldSource;
|
||||
fieldName = type->typeOfName;
|
||||
relationName = type->typeOfTable;
|
||||
fieldSegmentLength = type->segLength;
|
||||
fieldPrecision = type->precision;
|
||||
nullFlag = (SSHORT) type->notNull;
|
||||
mechanism = (SSHORT) type->fullDomain;
|
||||
}
|
||||
|
||||
SSHORT type;
|
||||
SSHORT number;
|
||||
Firebird::MetaName name;
|
||||
Firebird::MetaName fieldSource;
|
||||
Firebird::MetaName fieldName;
|
||||
Firebird::MetaName relationName;
|
||||
Firebird::MetaName charSetName;
|
||||
Firebird::MetaName collationName;
|
||||
Firebird::MetaName subTypeName;
|
||||
Nullable<SSHORT> collationId;
|
||||
Nullable<SSHORT> nullFlag;
|
||||
SSHORT mechanism;
|
||||
Nullable<SSHORT> fieldLength;
|
||||
Nullable<SSHORT> fieldScale;
|
||||
Nullable<SSHORT> fieldType;
|
||||
Nullable<SSHORT> fieldSubType;
|
||||
Nullable<SSHORT> fieldSegmentLength;
|
||||
Nullable<SSHORT> fieldNullFlag;
|
||||
Nullable<SSHORT> fieldCharLength;
|
||||
Nullable<SSHORT> fieldCollationId;
|
||||
Nullable<SSHORT> fieldCharSetId;
|
||||
Nullable<SSHORT> fieldPrecision;
|
||||
|
||||
bool operator >(const SignatureParameter& o) const
|
||||
{
|
||||
return type > o.type || (type == o.type && number > o.number);
|
||||
}
|
||||
|
||||
bool operator ==(const SignatureParameter& o) const
|
||||
{
|
||||
return type == o.type && number == o.number && name == o.name &&
|
||||
(fieldSource == o.fieldSource ||
|
||||
(fb_utils::implicit_domain(fieldSource.c_str()) &&
|
||||
fb_utils::implicit_domain(o.fieldSource.c_str()))) &&
|
||||
fieldName == o.fieldName && relationName == o.relationName &&
|
||||
collationId == o.collationId && nullFlag == o.nullFlag &&
|
||||
mechanism == o.mechanism && fieldLength == o.fieldLength &&
|
||||
fieldScale == o.fieldScale && fieldType == o.fieldType &&
|
||||
fieldSubType == o.fieldSubType && fieldSegmentLength == o.fieldSegmentLength &&
|
||||
fieldNullFlag == o.fieldNullFlag && fieldCharLength == o.fieldCharLength &&
|
||||
charSetName == o.charSetName && collationName == o.collationName && subTypeName == o.subTypeName &&
|
||||
fieldCollationId == o.fieldCollationId && fieldCharSetId == o.fieldCharSetId &&
|
||||
fieldPrecision == o.fieldPrecision;
|
||||
}
|
||||
|
||||
bool operator !=(const SignatureParameter& o) const
|
||||
{
|
||||
return !(*this == o);
|
||||
}
|
||||
};
|
||||
|
||||
struct Signature
|
||||
{
|
||||
const static unsigned FLAG_DETERMINISTIC = 0x01;
|
||||
|
||||
Signature(MemoryPool& p, const Firebird::MetaName& aName)
|
||||
: name(p, aName),
|
||||
parameters(p),
|
||||
flags(0),
|
||||
defined(false)
|
||||
{
|
||||
}
|
||||
|
||||
explicit Signature(const Firebird::MetaName& aName)
|
||||
: name(aName),
|
||||
parameters(*getDefaultMemoryPool()),
|
||||
flags(0),
|
||||
defined(false)
|
||||
{
|
||||
}
|
||||
|
||||
explicit Signature(MemoryPool& p)
|
||||
: name(p),
|
||||
parameters(p),
|
||||
flags(0),
|
||||
defined(false)
|
||||
{
|
||||
}
|
||||
|
||||
Signature(MemoryPool& p, const Signature& o)
|
||||
: name(p, o.name),
|
||||
parameters(p),
|
||||
flags(0),
|
||||
defined(o.defined)
|
||||
{
|
||||
for (Firebird::SortedObjectsArray<SignatureParameter>::const_iterator i = o.parameters.begin();
|
||||
i != o.parameters.end();
|
||||
++i)
|
||||
{
|
||||
parameters.add(*i);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator >(const Signature& o) const
|
||||
{
|
||||
return name > o.name;
|
||||
}
|
||||
|
||||
bool operator ==(const Signature& o) const
|
||||
{
|
||||
if (name != o.name || flags != o.flags || parameters.getCount() != o.parameters.getCount())
|
||||
return false;
|
||||
|
||||
for (Firebird::SortedObjectsArray<SignatureParameter>::const_iterator i = parameters.begin(),
|
||||
j = o.parameters.begin();
|
||||
i != parameters.end();
|
||||
++i, ++j)
|
||||
{
|
||||
if (*i != *j)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator !=(const Signature& o) const
|
||||
{
|
||||
return !(*this == o);
|
||||
}
|
||||
|
||||
Firebird::MetaName name;
|
||||
Firebird::SortedObjectsArray<SignatureParameter> parameters;
|
||||
unsigned flags;
|
||||
bool defined;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
/*! \var unsigned DSQL_debug
|
||||
|
@ -1 +1 @@
|
||||
46 shift/reduce conflicts, 17 reduce/reduce conflicts.
|
||||
54 shift/reduce conflicts, 17 reduce/reduce conflicts.
|
||||
|
134
src/dsql/parse.y
134
src/dsql/parse.y
@ -2539,7 +2539,7 @@ procedure_clause
|
||||
|
||||
%type <createAlterProcedureNode> psql_procedure_clause
|
||||
psql_procedure_clause
|
||||
: procedure_clause_start sql_security_clause AS local_declaration_list full_proc_block
|
||||
: procedure_clause_start sql_security_clause AS local_declarations_opt full_proc_block
|
||||
{
|
||||
$$ = $1;
|
||||
$$->ssDefiner = $2;
|
||||
@ -2670,7 +2670,7 @@ function_clause
|
||||
|
||||
%type <createAlterFunctionNode> psql_function_clause
|
||||
psql_function_clause
|
||||
: function_clause_start sql_security_clause AS local_declaration_list full_proc_block
|
||||
: function_clause_start sql_security_clause AS local_declarations_opt full_proc_block
|
||||
{
|
||||
$$ = $1;
|
||||
$$->ssDefiner = $2;
|
||||
@ -2869,73 +2869,131 @@ package_body_item
|
||||
;
|
||||
|
||||
|
||||
%type <compoundStmtNode> local_declaration_list
|
||||
local_declaration_list
|
||||
: /* nothing */ { $$ = NULL; }
|
||||
| local_declarations
|
||||
%type <compoundStmtNode> local_declarations_opt
|
||||
local_declarations_opt
|
||||
: local_forward_declarations_opt local_nonforward_declarations_opt
|
||||
{
|
||||
CompoundStmtNode* forward = $1;
|
||||
CompoundStmtNode* nonForward = $2;
|
||||
|
||||
if (!forward)
|
||||
$$ = nonForward;
|
||||
else
|
||||
{
|
||||
if (nonForward)
|
||||
forward->statements.add(nonForward->statements.begin(), nonForward->statements.getCount());
|
||||
|
||||
$$ = forward;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
%type <compoundStmtNode> local_declarations
|
||||
local_declarations
|
||||
: local_declaration
|
||||
%type <compoundStmtNode> local_forward_declarations_opt
|
||||
local_forward_declarations_opt
|
||||
: /* nothing */ { $$ = NULL; }
|
||||
| local_forward_declarations
|
||||
;
|
||||
|
||||
%type <compoundStmtNode> local_forward_declarations
|
||||
local_forward_declarations
|
||||
: local_forward_declaration
|
||||
{
|
||||
$$ = newNode<CompoundStmtNode>();
|
||||
$$->statements.add($1);
|
||||
}
|
||||
| local_declarations local_declaration
|
||||
| local_forward_declarations local_forward_declaration
|
||||
{
|
||||
$1->statements.add($2);
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
%type <stmtNode> local_declaration
|
||||
local_declaration
|
||||
%type <stmtNode> local_forward_declaration
|
||||
local_forward_declaration
|
||||
: local_declaration_subproc_start ';' { $$ = $1; }
|
||||
| local_declaration_subfunc_start ';' { $$ = $1; }
|
||||
;
|
||||
|
||||
%type <compoundStmtNode> local_nonforward_declarations_opt
|
||||
local_nonforward_declarations_opt
|
||||
: /* nothing */ { $$ = NULL; }
|
||||
| local_nonforward_declarations
|
||||
;
|
||||
|
||||
%type <compoundStmtNode> local_nonforward_declarations
|
||||
local_nonforward_declarations
|
||||
: local_nonforward_declaration
|
||||
{
|
||||
$$ = newNode<CompoundStmtNode>();
|
||||
$$->statements.add($1);
|
||||
}
|
||||
| local_nonforward_declarations local_nonforward_declaration
|
||||
{
|
||||
$1->statements.add($2);
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
%type <stmtNode> local_nonforward_declaration
|
||||
local_nonforward_declaration
|
||||
: DECLARE var_decl_opt local_declaration_item ';'
|
||||
{
|
||||
$$ = $3;
|
||||
$$->line = YYPOSNARG(1).firstLine;
|
||||
$$->column = YYPOSNARG(1).firstColumn;
|
||||
}
|
||||
| DECLARE PROCEDURE symbol_procedure_name
|
||||
{ $<execBlockNode>$ = newNode<ExecBlockNode>(); }
|
||||
input_parameters(NOTRIAL(&$<execBlockNode>4->parameters))
|
||||
output_parameters(NOTRIAL(&$<execBlockNode>4->returns)) AS
|
||||
local_declaration_list
|
||||
full_proc_block
|
||||
| local_declaration_subproc_start AS local_declarations_opt full_proc_block
|
||||
{
|
||||
DeclareSubProcNode* node = newNode<DeclareSubProcNode>(*$3);
|
||||
node->dsqlBlock = $<execBlockNode>4;
|
||||
node->dsqlBlock->localDeclList = $8;
|
||||
node->dsqlBlock->body = $9;
|
||||
DeclareSubProcNode* node = $1;
|
||||
node->dsqlBlock = newNode<ExecBlockNode>();
|
||||
node->dsqlBlock->parameters = node->dsqlParameters;
|
||||
node->dsqlBlock->returns = node->dsqlReturns;
|
||||
node->dsqlBlock->localDeclList = $3;
|
||||
node->dsqlBlock->body = $4;
|
||||
|
||||
for (FB_SIZE_T i = 0; i < node->dsqlBlock->parameters.getCount(); ++i)
|
||||
node->dsqlBlock->parameters[i]->parameterExpr = make_parameter();
|
||||
|
||||
$$ = node;
|
||||
}
|
||||
| DECLARE FUNCTION symbol_UDF_name
|
||||
{ $<execBlockNode>$ = newNode<ExecBlockNode>(); }
|
||||
input_parameters(NOTRIAL(&$<execBlockNode>4->parameters))
|
||||
RETURNS domain_or_non_array_type collate_clause deterministic_opt AS
|
||||
local_declaration_list
|
||||
full_proc_block
|
||||
| local_declaration_subfunc_start AS local_declarations_opt full_proc_block
|
||||
{
|
||||
DeclareSubFuncNode* node = newNode<DeclareSubFuncNode>(*$3);
|
||||
node->dsqlDeterministic = $9;
|
||||
node->dsqlBlock = $<execBlockNode>4;
|
||||
node->dsqlBlock->localDeclList = $11;
|
||||
node->dsqlBlock->body = $12;
|
||||
DeclareSubFuncNode* node = $1;
|
||||
node->dsqlBlock = newNode<ExecBlockNode>();
|
||||
node->dsqlBlock->parameters = node->dsqlParameters;
|
||||
node->dsqlBlock->returns = node->dsqlReturns;
|
||||
node->dsqlBlock->localDeclList = $3;
|
||||
node->dsqlBlock->body = $4;
|
||||
|
||||
for (FB_SIZE_T i = 0; i < node->dsqlBlock->parameters.getCount(); ++i)
|
||||
node->dsqlBlock->parameters[i]->parameterExpr = make_parameter();
|
||||
|
||||
node->dsqlBlock->returns.add(newNode<ParameterClause>($<legacyField>7, optName($8)));
|
||||
|
||||
$$ = node;
|
||||
}
|
||||
;
|
||||
|
||||
%type <declareSubProcNode> local_declaration_subproc_start
|
||||
local_declaration_subproc_start
|
||||
: DECLARE PROCEDURE symbol_procedure_name
|
||||
{ $$ = newNode<DeclareSubProcNode>(NOTRIAL(*$3)); }
|
||||
input_parameters(NOTRIAL(&$4->dsqlParameters))
|
||||
output_parameters(NOTRIAL(&$4->dsqlReturns))
|
||||
{ $$ = $4; }
|
||||
;
|
||||
|
||||
%type <declareSubFuncNode> local_declaration_subfunc_start
|
||||
local_declaration_subfunc_start
|
||||
: DECLARE FUNCTION symbol_UDF_name
|
||||
{ $$ = newNode<DeclareSubFuncNode>(NOTRIAL(*$3)); }
|
||||
input_parameters(NOTRIAL(&$4->dsqlParameters))
|
||||
RETURNS domain_or_non_array_type collate_clause deterministic_opt
|
||||
{
|
||||
$$ = $4;
|
||||
$$->dsqlReturns.add(newNode<ParameterClause>($<legacyField>7, optName($8)));
|
||||
$$->dsqlDeterministic = $9;
|
||||
}
|
||||
;
|
||||
|
||||
%type <stmtNode> local_declaration_item
|
||||
local_declaration_item
|
||||
: var_declaration_item
|
||||
@ -3526,7 +3584,7 @@ exec_block
|
||||
{ $<execBlockNode>$ = newNode<ExecBlockNode>(); }
|
||||
block_input_params(NOTRIAL(&$3->parameters))
|
||||
output_parameters(NOTRIAL(&$3->returns)) AS
|
||||
local_declaration_list
|
||||
local_declarations_opt
|
||||
full_proc_block
|
||||
{
|
||||
ExecBlockNode* node = $3;
|
||||
@ -3597,7 +3655,7 @@ check_opt
|
||||
|
||||
%type <createAlterTriggerNode> trigger_clause
|
||||
trigger_clause
|
||||
: create_trigger_start trg_sql_security_clause AS local_declaration_list full_proc_block
|
||||
: create_trigger_start trg_sql_security_clause AS local_declarations_opt full_proc_block
|
||||
{
|
||||
$$ = $1;
|
||||
$$->ssDefiner = $2;
|
||||
@ -4244,7 +4302,7 @@ crypt_key_clause($alterDatabaseNode)
|
||||
%type <createAlterTriggerNode> alter_trigger_clause
|
||||
alter_trigger_clause
|
||||
: symbol_trigger_name trigger_active trigger_type_opt trigger_position trg_sql_security_clause
|
||||
AS local_declaration_list full_proc_block
|
||||
AS local_declarations_opt full_proc_block
|
||||
{
|
||||
$$ = newNode<CreateAlterTriggerNode>(*$1);
|
||||
$$->alter = true;
|
||||
|
@ -367,7 +367,10 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, RecordSourceNode*
|
||||
else if (procNode && (procNode->dsqlName.package.hasData() || procNode->sourceList))
|
||||
{
|
||||
if (procNode->dsqlName.package.isEmpty())
|
||||
procedure = dsqlScratch->getSubProcedure(procNode->dsqlName.identifier);
|
||||
{
|
||||
DeclareSubProcNode* subProcedure = dsqlScratch->getSubProcedure(procNode->dsqlName.identifier);
|
||||
procedure = subProcedure ? subProcedure->dsqlProcedure : NULL;
|
||||
}
|
||||
|
||||
if (!procedure)
|
||||
{
|
||||
@ -390,7 +393,10 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, RecordSourceNode*
|
||||
else
|
||||
{
|
||||
if (procNode && procNode->dsqlName.package.isEmpty())
|
||||
procedure = dsqlScratch->getSubProcedure(procNode->dsqlName.identifier);
|
||||
{
|
||||
DeclareSubProcNode* subProcedure = dsqlScratch->getSubProcedure(procNode->dsqlName.identifier);
|
||||
procedure = subProcedure ? subProcedure->dsqlProcedure : NULL;
|
||||
}
|
||||
|
||||
if (!procedure)
|
||||
relation = METD_get_relation(dsqlScratch->getTransaction(), dsqlScratch, relation_name);
|
||||
|
@ -845,6 +845,14 @@ static const struct {
|
||||
{"decfloat_invalid_operation", 335545141},
|
||||
{"decfloat_overflow", 335545142},
|
||||
{"decfloat_underflow", 335545143},
|
||||
{"subfunc_notdef", 335545144},
|
||||
{"subproc_notdef", 335545145},
|
||||
{"subfunc_signat", 335545146},
|
||||
{"subproc_signat", 335545147},
|
||||
{"subfunc_defvaldecl", 335545148},
|
||||
{"subproc_defvaldecl", 335545149},
|
||||
{"subfunc_not_impl", 335545150},
|
||||
{"subproc_not_impl", 335545151},
|
||||
{"gfix_db_name", 335740929},
|
||||
{"gfix_invalid_sw", 335740930},
|
||||
{"gfix_incmp_sw", 335740932},
|
||||
|
@ -879,6 +879,14 @@ const ISC_STATUS isc_decfloat_inexact_result = 335545140L;
|
||||
const ISC_STATUS isc_decfloat_invalid_operation = 335545141L;
|
||||
const ISC_STATUS isc_decfloat_overflow = 335545142L;
|
||||
const ISC_STATUS isc_decfloat_underflow = 335545143L;
|
||||
const ISC_STATUS isc_subfunc_notdef = 335545144L;
|
||||
const ISC_STATUS isc_subproc_notdef = 335545145L;
|
||||
const ISC_STATUS isc_subfunc_signat = 335545146L;
|
||||
const ISC_STATUS isc_subproc_signat = 335545147L;
|
||||
const ISC_STATUS isc_subfunc_defvaldecl = 335545148L;
|
||||
const ISC_STATUS isc_subproc_defvaldecl = 335545149L;
|
||||
const ISC_STATUS isc_subfunc_not_impl = 335545150L;
|
||||
const ISC_STATUS isc_subproc_not_impl = 335545151L;
|
||||
const ISC_STATUS isc_gfix_db_name = 335740929L;
|
||||
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
|
||||
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
|
||||
@ -1353,7 +1361,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
|
||||
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
|
||||
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
|
||||
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
|
||||
const ISC_STATUS isc_err_max = 1297;
|
||||
const ISC_STATUS isc_err_max = 1305;
|
||||
|
||||
#else /* c definitions */
|
||||
|
||||
@ -2202,6 +2210,14 @@ const ISC_STATUS isc_err_max = 1297;
|
||||
#define isc_decfloat_invalid_operation 335545141L
|
||||
#define isc_decfloat_overflow 335545142L
|
||||
#define isc_decfloat_underflow 335545143L
|
||||
#define isc_subfunc_notdef 335545144L
|
||||
#define isc_subproc_notdef 335545145L
|
||||
#define isc_subfunc_signat 335545146L
|
||||
#define isc_subproc_signat 335545147L
|
||||
#define isc_subfunc_defvaldecl 335545148L
|
||||
#define isc_subproc_defvaldecl 335545149L
|
||||
#define isc_subfunc_not_impl 335545150L
|
||||
#define isc_subproc_not_impl 335545151L
|
||||
#define isc_gfix_db_name 335740929L
|
||||
#define isc_gfix_invalid_sw 335740930L
|
||||
#define isc_gfix_incmp_sw 335740932L
|
||||
@ -2676,7 +2692,7 @@ const ISC_STATUS isc_err_max = 1297;
|
||||
#define isc_trace_switch_param_miss 337182758L
|
||||
#define isc_trace_param_act_notcompat 337182759L
|
||||
#define isc_trace_mandatory_switch_miss 337182760L
|
||||
#define isc_err_max 1297
|
||||
#define isc_err_max 1305
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -848,6 +848,14 @@ Data source : @4"}, /* eds_statement */
|
||||
{335545141, "Decimal float invalid operation. An indeterminant error occurred during an operation."}, /* decfloat_invalid_operation */
|
||||
{335545142, "Decimal float overflow. The exponent of a result is greater than the magnitude allowed."}, /* decfloat_overflow */
|
||||
{335545143, "Decimal float underflow. The exponent of a result is less than the magnitude allowed."}, /* decfloat_underflow */
|
||||
{335545144, "Sub-function @1 has not been defined"}, /* subfunc_notdef */
|
||||
{335545145, "Sub-procedure @1 has not been defined"}, /* subproc_notdef */
|
||||
{335545146, "Sub-function @1 has a signature mismatch with its forward declaration"}, /* subfunc_signat */
|
||||
{335545147, "Sub-procedure @1 has a signature mismatch with its forward declaration"}, /* subproc_signat */
|
||||
{335545148, "Default values for parameters are not allowed in definition of the previously declared sub-function @1"}, /* subfunc_defvaldecl */
|
||||
{335545149, "Default values for parameters are not allowed in definition of the previously declared sub-procedure @1"}, /* subproc_defvaldecl */
|
||||
{335545150, "Sub-function @1 was declared but not implemented"}, /* subfunc_not_impl */
|
||||
{335545151, "Sub-procedure @1 was declared but not implemented"}, /* subproc_not_impl */
|
||||
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
|
||||
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
|
||||
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */
|
||||
@ -976,7 +984,7 @@ Data source : @4"}, /* eds_statement */
|
||||
{336068872, "Procedure @1 has not been defined on the package body @2"}, /* dyn_procnotdef_package */
|
||||
{336068873, "Function @1 has a signature mismatch on package body @2"}, /* dyn_funcsignat_package */
|
||||
{336068874, "Procedure @1 has a signature mismatch on package body @2"}, /* dyn_procsignat_package */
|
||||
{336068875, "Default values for parameters are allowed only in declaration of packaged procedure @1.@2"}, /* dyn_defvaldecl_package_proc */
|
||||
{336068875, "Default values for parameters are not allowed in the definition of a previously declared packaged procedure @1.@2"}, /* dyn_defvaldecl_package_proc */
|
||||
{336068877, "Package body @1 already exists"}, /* dyn_package_body_exists */
|
||||
{336068878, "Invalid DDL statement for function @1"}, /* dyn_invalid_ddl_func */
|
||||
{336068879, "Cannot alter new style function @1 with ALTER EXTERNAL FUNCTION. Use ALTER FUNCTION instead."}, /* dyn_newfc_oldsyntax */
|
||||
@ -990,7 +998,7 @@ Data source : @4"}, /* eds_statement */
|
||||
{336068895, "System @1 @2 cannot be modified"}, /* dyn_cant_modify_sysobj */
|
||||
{336068896, "INCREMENT BY 0 is an illegal option for sequence @1"}, /* dyn_cant_use_zero_increment */
|
||||
{336068897, "Can't use @1 in FOREIGN KEY constraint"}, /* dyn_cant_use_in_foreignkey */
|
||||
{336068898, "Default values for parameters are allowed only in declaration of packaged function @1.@2"}, /* dyn_defvaldecl_package_func */
|
||||
{336068898, "Default values for parameters are not allowed in the definition of a previously declared packaged function @1.@2"}, /* dyn_defvaldecl_package_func */
|
||||
{336068904, "INCREMENT BY 0 is an illegal option for identity column @1 of table @2"}, /* dyn_cant_use_zero_inc_ident */
|
||||
{336330753, "found unknown switch"}, /* gbak_unknown_switch */
|
||||
{336330754, "page size parameter missing"}, /* gbak_page_size_missing */
|
||||
|
@ -844,6 +844,14 @@ static const struct {
|
||||
{335545141, -901}, /* 821 decfloat_invalid_operation */
|
||||
{335545142, -901}, /* 822 decfloat_overflow */
|
||||
{335545143, -901}, /* 823 decfloat_underflow */
|
||||
{335545144, -901}, /* 824 subfunc_notdef */
|
||||
{335545145, -901}, /* 825 subproc_notdef */
|
||||
{335545146, -901}, /* 826 subfunc_signat */
|
||||
{335545147, -901}, /* 827 subproc_signat */
|
||||
{335545148, -901}, /* 828 subfunc_defvaldecl */
|
||||
{335545149, -901}, /* 829 subproc_defvaldecl */
|
||||
{335545150, -901}, /* 830 subfunc_not_impl */
|
||||
{335545151, -901}, /* 831 subproc_not_impl */
|
||||
{335740929, -901}, /* 1 gfix_db_name */
|
||||
{335740930, -901}, /* 2 gfix_invalid_sw */
|
||||
{335740932, -901}, /* 4 gfix_incmp_sw */
|
||||
|
@ -844,6 +844,14 @@ static const struct {
|
||||
{335545141, "22000"}, // 821 decfloat_invalid_operation
|
||||
{335545142, "22003"}, // 822 decfloat_overflow
|
||||
{335545143, "22003"}, // 823 decfloat_underflow
|
||||
{335545144, "42000"}, // 824 subfunc_notdef
|
||||
{335545145, "42000"}, // 825 subproc_notdef
|
||||
{335545146, "42000"}, // 826 subfunc_signat
|
||||
{335545147, "42000"}, // 827 subproc_signat
|
||||
{335545148, "42000"}, // 828 subfunc_defvaldecl
|
||||
{335545149, "42000"}, // 829 subproc_defvaldecl
|
||||
{335545150, "42000"}, // 830 subfunc_not_impl
|
||||
{335545151, "42000"}, // 831 subproc_not_impl
|
||||
{335740929, "00000"}, // 1 gfix_db_name
|
||||
{335740930, "00000"}, // 2 gfix_invalid_sw
|
||||
{335740932, "00000"}, // 4 gfix_incmp_sw
|
||||
|
@ -910,9 +910,13 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
|
||||
|
||||
if (blrOp == blr_subproc)
|
||||
{
|
||||
DeclareSubProcNode* node;
|
||||
if (csb->subProcedures.get(name.identifier, node))
|
||||
procedure = node->routine;
|
||||
DeclareSubProcNode* declareNode;
|
||||
|
||||
for (auto curCsb = csb; curCsb && !procedure; curCsb = curCsb->mainCsb)
|
||||
{
|
||||
if (curCsb->subProcedures.get(name.identifier, declareNode))
|
||||
procedure = declareNode->routine;
|
||||
}
|
||||
}
|
||||
else
|
||||
procedure = MET_lookup_procedure(tdbb, name, false);
|
||||
|
@ -427,7 +427,7 @@ public:
|
||||
SLONG subNumber;
|
||||
};
|
||||
|
||||
explicit CompilerScratch(MemoryPool& p)
|
||||
explicit CompilerScratch(MemoryPool& p, CompilerScratch* aMainCsb = NULL)
|
||||
: /*csb_node(0),
|
||||
csb_variables(0),
|
||||
csb_dependencies(0),
|
||||
@ -439,6 +439,7 @@ public:
|
||||
#ifdef CMP_DEBUG
|
||||
csb_dump(p),
|
||||
#endif
|
||||
mainCsb(aMainCsb),
|
||||
csb_external(p),
|
||||
csb_access(p),
|
||||
csb_resources(p),
|
||||
@ -486,6 +487,7 @@ public:
|
||||
Firebird::string csb_dump;
|
||||
#endif
|
||||
|
||||
CompilerScratch* mainCsb;
|
||||
Firebird::BlrReader csb_blr_reader;
|
||||
DmlNode* csb_node;
|
||||
ExternalAccessList csb_external; // Access to outside procedures/triggers to be checked
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */
|
||||
set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?);
|
||||
--
|
||||
('2017-05-23 16:08:00', 'JRD', 0, 824)
|
||||
('2017-07-10 12:27:00', 'JRD', 0, 832)
|
||||
('2015-03-17 18:33:00', 'QLI', 1, 533)
|
||||
('2015-01-07 18:01:51', 'GFIX', 3, 134)
|
||||
('1996-11-07 13:39:40', 'GPRE', 4, 1)
|
||||
|
@ -931,6 +931,14 @@ Data source : @4', NULL, NULL)
|
||||
('decfloat_invalid_operation', 'DecimalContext::checkForExceptions', 'DecFloat.cpp', NULL, 0, 821, NULL, 'Decimal float invalid operation. An indeterminant error occurred during an operation.', NULL, NULL);
|
||||
('decfloat_overflow', 'DecimalContext::checkForExceptions', 'DecFloat.cpp', NULL, 0, 822, NULL, 'Decimal float overflow. The exponent of a result is greater than the magnitude allowed.', NULL, NULL);
|
||||
('decfloat_underflow', 'DecimalContext::checkForExceptions', 'DecFloat.cpp', NULL, 0, 823, NULL, 'Decimal float underflow. The exponent of a result is less than the magnitude allowed.', NULL, NULL);
|
||||
('subfunc_notdef', NULL, 'StmtNodes.cpp', NULL, 0, 824, NULL, 'Sub-function @1 has not been defined', NULL, NULL);
|
||||
('subproc_notdef', NULL, 'StmtNodes.cpp', NULL, 0, 825, NULL, 'Sub-procedure @1 has not been defined', NULL, NULL);
|
||||
('subfunc_signat', NULL, 'StmtNodes.cpp', NULL, 0, 826, NULL, 'Sub-function @1 has a signature mismatch with its forward declaration', NULL, NULL);
|
||||
('subproc_signat', NULL, 'StmtNodes.cpp', NULL, 0, 827, NULL, 'Sub-procedure @1 has a signature mismatch with its forward declaration', NULL, NULL);
|
||||
('subfunc_defvaldecl', NULL, 'StmtNodes.cpp', NULL, 0, 828, NULL, 'Default values for parameters are not allowed in definition of the previously declared sub-function @1', NULL, NULL);
|
||||
('subproc_defvaldecl', NULL, 'StmtNodes.cpp', NULL, 0, 829, NULL, 'Default values for parameters are not allowed in definition of the previously declared sub-procedure @1', NULL, NULL);
|
||||
('subfunc_not_impl', NULL, 'StmtNodes.cpp', NULL, 0, 830, NULL, 'Sub-function @1 was declared but not implemented', NULL, NULL);
|
||||
('subproc_not_impl', NULL, 'StmtNodes.cpp', NULL, 0, 831, NULL, 'Sub-procedure @1 was declared but not implemented', NULL, NULL);
|
||||
-- QLI
|
||||
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
|
||||
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);
|
||||
@ -1981,7 +1989,7 @@ COMMIT WORK;
|
||||
('dyn_procnotdef_package', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 264, NULL, 'Procedure @1 has not been defined on the package body @2', NULL, NULL);
|
||||
('dyn_funcsignat_package', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 265, NULL, 'Function @1 has a signature mismatch on package body @2', NULL, NULL);
|
||||
('dyn_procsignat_package', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 266, NULL, 'Procedure @1 has a signature mismatch on package body @2', NULL, NULL);
|
||||
('dyn_defvaldecl_package_proc', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 267, NULL, 'Default values for parameters are allowed only in declaration of packaged procedure @1.@2', NULL, NULL);
|
||||
('dyn_defvaldecl_package_proc', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 267, NULL, 'Default values for parameters are not allowed in the definition of a previously declared packaged procedure @1.@2', NULL, NULL);
|
||||
('dyn_dup_function', 'DYN_define_function', 'dyn_def.epp', NULL, 8, 268, NULL, 'Function @1 already exists', NULL, NULL);
|
||||
('dyn_package_body_exists', NULL, 'DdlNodes.epp/PackageNodes.epp', NULL, 8, 269, NULL, 'Package body @1 already exists', NULL, NULL);
|
||||
('dyn_invalid_ddl_func', 'CreateAlterFunctionNode::compile', 'DdlNodes.epp', NULL, 8, 270, NULL, 'Invalid DDL statement for function @1', NULL, NULL);
|
||||
@ -2004,7 +2012,7 @@ COMMIT WORK;
|
||||
('dyn_cant_modify_sysobj', NULL, 'DdlNodes.epp', NULL, 8, 287, NULL, 'System @1 @2 cannot be modified', NULL, 'Ex: System generator rdb$... cannot be modified');
|
||||
('dyn_cant_use_zero_increment', NULL, 'DdlNodes.epp', NULL, 8, 288, NULL, 'INCREMENT BY 0 is an illegal option for sequence @1', NULL, NULL);
|
||||
('dyn_cant_use_in_foreignkey', NULL, 'DdlNodes.epp', NULL, 8, 289, NULL, 'Can''t use @1 in FOREIGN KEY constraint', NULL, NULL);
|
||||
('dyn_defvaldecl_package_func', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 290, NULL, 'Default values for parameters are allowed only in declaration of packaged function @1.@2', NULL, NULL);
|
||||
('dyn_defvaldecl_package_func', 'CreatePackageBodyNode::execute', 'PackageNodes.epp', NULL, 8, 290, NULL, 'Default values for parameters are not allowed in the definition of a previously declared packaged function @1.@2', NULL, NULL);
|
||||
('dyn_create_user_no_password', 'CreateAlterUserNode', 'DdlNodes.epp', NULL, 8, 291, NULL, 'Password must be specified when creating user', NULL, NULL);
|
||||
('dyn_cyclic_role', 'GrantRevokeNode::grantRevoke', 'DdlNodes.epp', NULL, 8, 292, NULL, 'role @1 can not be granted to role @2', NULL, NULL);
|
||||
(NULL, 'CreateAlterRoleNode::execute', 'DdlNodes.epp', NULL, 8, 293, NULL, 'DROP SYSTEM PRIVILEGES should not be used in CREATE ROLE operator', NULL, NULL);
|
||||
|
@ -830,6 +830,14 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA
|
||||
(-901, '22', '000', 0, 821, 'decfloat_invalid_operation', NULL, NULL)
|
||||
(-901, '22', '003', 0, 822, 'decfloat_overflow', NULL, NULL)
|
||||
(-901, '22', '003', 0, 823, 'decfloat_underflow', NULL, NULL)
|
||||
(-901, '42', '000', 0, 824, 'subfunc_notdef', NULL, NULL)
|
||||
(-901, '42', '000', 0, 825, 'subproc_notdef', NULL, NULL)
|
||||
(-901, '42', '000', 0, 826, 'subfunc_signat', NULL, NULL)
|
||||
(-901, '42', '000', 0, 827, 'subproc_signat', NULL, NULL)
|
||||
(-901, '42', '000', 0, 828, 'subfunc_defvaldecl', NULL, NULL)
|
||||
(-901, '42', '000', 0, 829, 'subproc_defvaldecl', NULL, NULL)
|
||||
(-901, '42', '000', 0, 830, 'subfunc_not_impl', NULL, NULL)
|
||||
(-901, '42', '000', 0, 831, 'subproc_not_impl', NULL, NULL)
|
||||
-- GFIX
|
||||
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
|
||||
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user