mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 02:03:04 +01:00
Refactored the support for blr_handler, blr_loop, blr_exec_sql, blr_exec_into, blr_exec_stmt,
blr_start_savepoint, blr_end_savepoint, blr_store, blr_store2, blr_erase, blr_modify, blr_modify2, blr_exec_proc, blr_exec_proc2, blr_exec_pid, blr_dcl_cursor, blr_cursor_stmt, blr_set_generator, blr_receive, blr_stall, blr_select, blr_block, blr_error_handler, blr_label, blr_leave, blr_continue and the source info node.
This commit is contained in:
parent
3f6412d359
commit
8af7ec0211
@ -76,7 +76,6 @@
|
||||
<ClCompile Include="..\..\..\src\jrd\event.cpp" />
|
||||
<ClCompile Include="..\..\..\src\jrd\evl.cpp" />
|
||||
<ClCompile Include="..\..\..\src\jrd\exe.cpp" />
|
||||
<ClCompile Include="..\..\..\src\jrd\execute_statement.cpp" />
|
||||
<ClCompile Include="..\..\..\src\jrd\ext.cpp" />
|
||||
<ClCompile Include="..\..\..\src\jrd\extds\ExtDS.cpp" />
|
||||
<ClCompile Include="..\..\..\src\jrd\extds\InternalDS.cpp" />
|
||||
@ -237,7 +236,6 @@
|
||||
<ClInclude Include="..\..\..\src\jrd\evl_proto.h" />
|
||||
<ClInclude Include="..\..\..\src\jrd\evl_string.h" />
|
||||
<ClInclude Include="..\..\..\src\jrd\exe.h" />
|
||||
<ClInclude Include="..\..\..\src\jrd\execute_statement.h" />
|
||||
<ClInclude Include="..\..\..\src\jrd\exe_proto.h" />
|
||||
<ClInclude Include="..\..\..\src\jrd\ext.h" />
|
||||
<ClInclude Include="..\..\..\src\jrd\extds\ExtDS.h" />
|
||||
@ -562,4 +560,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -258,9 +258,6 @@
|
||||
<ClCompile Include="..\..\..\src\jrd\exe.cpp">
|
||||
<Filter>JRD files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\jrd\execute_statement.cpp">
|
||||
<Filter>JRD files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\jrd\ext.cpp">
|
||||
<Filter>JRD files</Filter>
|
||||
</ClCompile>
|
||||
@ -740,9 +737,6 @@
|
||||
<ClInclude Include="..\..\..\src\jrd\exe_proto.h">
|
||||
<Filter>Header files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\jrd\execute_statement.h">
|
||||
<Filter>Header files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\jrd\ext.h">
|
||||
<Filter>Header files</Filter>
|
||||
</ClInclude>
|
||||
@ -1096,4 +1090,4 @@
|
||||
<Filter>Resource files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -107,8 +107,6 @@
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\exe.cpp">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\execute_statement.cpp">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\ext.cpp">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\extds\ExtDS.cpp">
|
||||
@ -371,8 +369,6 @@
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\exe_proto.h">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\execute_statement.h">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\ext.h">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\ext_proto.h">
|
||||
@ -649,4 +645,4 @@
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
</VisualStudioProject>
|
||||
|
@ -107,8 +107,6 @@
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\exe.cpp">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\execute_statement.cpp">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\ext.cpp">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\extds\ExtDS.cpp">
|
||||
@ -371,8 +369,6 @@
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\exe_proto.h">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\execute_statement.h">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\ext.h">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\ext_proto.h">
|
||||
@ -647,4 +643,4 @@
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
</VisualStudioProject>
|
||||
|
@ -107,8 +107,6 @@
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\exe.cpp">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\execute_statement.cpp">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\ext.cpp">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\extds\ExtDS.cpp">
|
||||
@ -371,8 +369,6 @@
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\exe_proto.h">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\execute_statement.h">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\ext.h">
|
||||
</File>
|
||||
<File RelativePath="..\..\..\src\jrd\ext_proto.h">
|
||||
@ -647,4 +643,4 @@
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
</VisualStudioProject>
|
||||
|
@ -399,10 +399,6 @@
|
||||
RelativePath="..\..\..\src\jrd\exe.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\execute_statement.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ext.cpp"
|
||||
>
|
||||
@ -1107,10 +1103,6 @@
|
||||
RelativePath="..\..\..\src\jrd\exe_proto.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\execute_statement.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\dsql\ExprNodes.h"
|
||||
>
|
||||
|
@ -399,10 +399,6 @@
|
||||
RelativePath="..\..\..\src\jrd\exe.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\execute_statement.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ext.cpp"
|
||||
>
|
||||
@ -1107,10 +1103,6 @@
|
||||
RelativePath="..\..\..\src\jrd\exe_proto.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\execute_statement.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\dsql\ExprNodes.h"
|
||||
>
|
||||
|
@ -8058,7 +8058,7 @@ dsql_nod* CreateAlterViewNode::replaceFieldNames(dsql_nod* input, dsql_nod* sear
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (; search < end; ++search, replaceFields ? ++replace : NULL)
|
||||
for (; search < end; ++search, replace += (replaceFields ? 1 : 0))
|
||||
{
|
||||
const dsql_str* replaceName = NULL;
|
||||
if (replaceFields)
|
||||
|
136
src/dsql/Nodes.h
136
src/dsql/Nodes.h
@ -24,6 +24,7 @@
|
||||
#define DSQL_NODES_H
|
||||
|
||||
#include "../common/common.h"
|
||||
#include "../jrd/jrd.h"
|
||||
#include "../dsql/DsqlCompilerScratch.h"
|
||||
#include "../dsql/node.h"
|
||||
#include "../dsql/Visitors.h"
|
||||
@ -799,13 +800,129 @@ private:
|
||||
class StmtNode : public DmlNode
|
||||
{
|
||||
public:
|
||||
explicit StmtNode(MemoryPool& pool)
|
||||
enum Type
|
||||
{
|
||||
TYPE_BLOCK,
|
||||
TYPE_CONTINUE_LEAVE,
|
||||
TYPE_CURSOR_STMT,
|
||||
TYPE_DECLARE_CURSOR,
|
||||
TYPE_ERASE,
|
||||
TYPE_ERROR_HANDLER,
|
||||
TYPE_EXCEPTION,
|
||||
TYPE_EXEC_BLOCK,
|
||||
TYPE_EXEC_PROCEDURE,
|
||||
TYPE_EXEC_STATEMENT,
|
||||
TYPE_EXIT,
|
||||
TYPE_IF,
|
||||
TYPE_IN_AUTO_TRANS,
|
||||
TYPE_FOR,
|
||||
TYPE_HANDLER,
|
||||
TYPE_LABEL,
|
||||
TYPE_LOOP,
|
||||
TYPE_MERGE,
|
||||
TYPE_MODIFY,
|
||||
TYPE_POST_EVENT,
|
||||
TYPE_RECEIVE,
|
||||
TYPE_RETURN,
|
||||
TYPE_SAVEPOINT,
|
||||
TYPE_SAVEPOINT_ENCLOSE,
|
||||
TYPE_SELECT,
|
||||
TYPE_SET_GENERATOR,
|
||||
TYPE_SOURCE_INFO,
|
||||
TYPE_STALL,
|
||||
TYPE_STORE,
|
||||
TYPE_SUSPEND,
|
||||
TYPE_USER_SAVEPOINT
|
||||
};
|
||||
|
||||
enum WhichTrigger
|
||||
{
|
||||
ALL_TRIGS = 0,
|
||||
PRE_TRIG = 1,
|
||||
POST_TRIG = 2
|
||||
};
|
||||
|
||||
struct ExeState
|
||||
{
|
||||
ExeState(thread_db* tdbb)
|
||||
: oldPool(tdbb->getDefaultPool()),
|
||||
oldRequest(tdbb->getRequest()),
|
||||
errorPending(false),
|
||||
catchDisabled(false),
|
||||
whichEraseTrig(ALL_TRIGS),
|
||||
whichStoTrig(ALL_TRIGS),
|
||||
whichModTrig(ALL_TRIGS),
|
||||
topNode(NULL),
|
||||
prevNode(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
MemoryPool* oldPool; // Save the old pool to restore on exit.
|
||||
jrd_req* oldRequest; // Save the old request to restore on exit.
|
||||
bool errorPending; // Is there an error pending to be handled?
|
||||
bool catchDisabled; // Catch errors so we can unwind cleanly.
|
||||
WhichTrigger whichEraseTrig;
|
||||
WhichTrigger whichStoTrig;
|
||||
WhichTrigger whichModTrig;
|
||||
const jrd_nod* topNode;
|
||||
const jrd_nod* prevNode;
|
||||
};
|
||||
|
||||
public:
|
||||
explicit StmtNode(Type aType, MemoryPool& pool)
|
||||
: DmlNode(pool),
|
||||
type(aType),
|
||||
node(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T> T* as()
|
||||
{
|
||||
return type == T::TYPE ? static_cast<T*>(this) : NULL;
|
||||
}
|
||||
|
||||
template <typename T> const T* as() const
|
||||
{
|
||||
return type == T::TYPE ? static_cast<const T*>(this) : NULL;
|
||||
}
|
||||
|
||||
template <typename T> bool is() const
|
||||
{
|
||||
return type == T::TYPE;
|
||||
}
|
||||
|
||||
template <typename T, typename LegacyType> static T* as(LegacyType* node)
|
||||
{
|
||||
StmtNode* obj = T::fromLegacy(node);
|
||||
return obj ? obj->as<T>() : NULL;
|
||||
}
|
||||
|
||||
template <typename T, typename LegacyType> static const T* as(const LegacyType* node)
|
||||
{
|
||||
const StmtNode* obj = T::fromLegacy(node);
|
||||
return obj ? obj->as<T>() : NULL;
|
||||
}
|
||||
|
||||
template <typename T, typename LegacyType> static bool is(const LegacyType* node)
|
||||
{
|
||||
const StmtNode* obj = T::fromLegacy(node);
|
||||
return obj ? obj->is<T>() : false;
|
||||
}
|
||||
|
||||
static const StmtNode* fromLegacy(const StmtNode* node)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
static StmtNode* fromLegacy(StmtNode* node)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
static StmtNode* fromLegacy(const dsql_nod* node);
|
||||
static const StmtNode* fromLegacy(const jrd_nod* node);
|
||||
static StmtNode* fromLegacy(jrd_nod* node);
|
||||
|
||||
jrd_nod* getNode()
|
||||
{
|
||||
return node;
|
||||
@ -820,7 +937,10 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request) const = 0;
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const = 0;
|
||||
|
||||
public:
|
||||
const Type type;
|
||||
|
||||
protected:
|
||||
NestConst<jrd_nod> node;
|
||||
@ -832,8 +952,8 @@ protected:
|
||||
class DsqlOnlyStmtNode : public StmtNode
|
||||
{
|
||||
public:
|
||||
explicit DsqlOnlyStmtNode(MemoryPool& pool)
|
||||
: StmtNode(pool)
|
||||
explicit DsqlOnlyStmtNode(Type aType, MemoryPool& pool)
|
||||
: StmtNode(aType, pool)
|
||||
{
|
||||
}
|
||||
|
||||
@ -850,7 +970,7 @@ public:
|
||||
return this;
|
||||
}
|
||||
|
||||
const jrd_nod* execute(thread_db* /*tdbb*/, jrd_req* /*request*/) const
|
||||
const jrd_nod* execute(thread_db* /*tdbb*/, jrd_req* /*request*/, ExeState* /*exeState*/) const
|
||||
{
|
||||
fb_assert(false);
|
||||
return NULL;
|
||||
@ -859,11 +979,11 @@ public:
|
||||
|
||||
|
||||
// This class (via the make method) does the job that pass1_savepoint does for the legacy nodes.
|
||||
class SavepointEncloseNode : public DsqlOnlyStmtNode
|
||||
class SavepointEncloseNode : public TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_SAVEPOINT_ENCLOSE>
|
||||
{
|
||||
public:
|
||||
explicit SavepointEncloseNode(MemoryPool& pool, StmtNode* aStmt)
|
||||
: DsqlOnlyStmtNode(pool),
|
||||
: TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_SAVEPOINT_ENCLOSE>(pool),
|
||||
stmt(aStmt)
|
||||
{
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -24,21 +24,302 @@
|
||||
#define DSQL_STMT_NODES_H
|
||||
|
||||
#include "../common/common.h"
|
||||
#include "../common/classes/MetaName.h"
|
||||
#include "../jrd/blr.h"
|
||||
#include "../jrd/extds/ExtDS.h"
|
||||
#include "../dsql/Nodes.h"
|
||||
#include "../dsql/DdlNodes.h"
|
||||
#include "../common/classes/MetaName.h"
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
class PsqlException;
|
||||
class RelationSourceNode;
|
||||
|
||||
|
||||
class IfNode : public StmtNode
|
||||
class BlockNode : public TypedNode<StmtNode, StmtNode::TYPE_BLOCK>
|
||||
{
|
||||
public:
|
||||
explicit BlockNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_BLOCK>(pool),
|
||||
action(NULL),
|
||||
handlers(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual BlockNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual BlockNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual BlockNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
private:
|
||||
static bool testAndFixupError(thread_db* tdbb, jrd_req* request, const PsqlException* conditions);
|
||||
|
||||
public:
|
||||
NestConst<jrd_nod> action;
|
||||
NestConst<jrd_nod> handlers;
|
||||
};
|
||||
|
||||
|
||||
class ContinueLeaveNode : public TypedNode<StmtNode, StmtNode::TYPE_CONTINUE_LEAVE>
|
||||
{
|
||||
public:
|
||||
explicit ContinueLeaveNode(MemoryPool& pool, UCHAR aBlrOp)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_CONTINUE_LEAVE>(pool),
|
||||
blrOp(aBlrOp),
|
||||
labelNumber(0)
|
||||
{
|
||||
fb_assert(blrOp == blr_continue_loop || blrOp == blr_leave);
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ContinueLeaveNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
|
||||
virtual ContinueLeaveNode* pass1(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual ContinueLeaveNode* pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
UCHAR blrOp;
|
||||
USHORT labelNumber;
|
||||
};
|
||||
|
||||
|
||||
class CursorStmtNode : public TypedNode<StmtNode, StmtNode::TYPE_CURSOR_STMT>
|
||||
{
|
||||
public:
|
||||
explicit CursorStmtNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_CURSOR_STMT>(pool),
|
||||
cursorOp(0),
|
||||
cursorNumber(0),
|
||||
scrollOp(0),
|
||||
scrollExpr(NULL),
|
||||
intoStmt(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual CursorStmtNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual CursorStmtNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual CursorStmtNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
UCHAR cursorOp;
|
||||
USHORT cursorNumber;
|
||||
UCHAR scrollOp;
|
||||
NestConst<ValueExprNode> scrollExpr;
|
||||
NestConst<jrd_nod> intoStmt;
|
||||
};
|
||||
|
||||
|
||||
class DeclareCursorNode : public TypedNode<StmtNode, StmtNode::TYPE_DECLARE_CURSOR>
|
||||
{
|
||||
public:
|
||||
explicit DeclareCursorNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_DECLARE_CURSOR>(pool),
|
||||
rse(NULL),
|
||||
refs(NULL),
|
||||
cursorNumber(0),
|
||||
cursor(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual DeclareCursorNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual DeclareCursorNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual DeclareCursorNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
|
||||
virtual void pass2Cursor(RseNode*& rsePtr, Cursor**& cursorPtr)
|
||||
{
|
||||
rsePtr = rse;
|
||||
cursorPtr = cursor.getAddress();
|
||||
}
|
||||
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
NestConst<RseNode> rse;
|
||||
NestConst<ValueListNode> refs;
|
||||
USHORT cursorNumber;
|
||||
NestConst<Cursor> cursor;
|
||||
};
|
||||
|
||||
|
||||
class EraseNode : public TypedNode<StmtNode, StmtNode::TYPE_ERASE>
|
||||
{
|
||||
public:
|
||||
explicit EraseNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_ERASE>(pool),
|
||||
statement(NULL),
|
||||
subStatement(NULL),
|
||||
stream(0)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual EraseNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual EraseNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual EraseNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
private:
|
||||
static void pass1Erase(thread_db* tdbb, CompilerScratch* csb, EraseNode* node);
|
||||
const jrd_nod* erase(thread_db* tdbb, jrd_req* request, WhichTrigger whichTrig) const;
|
||||
|
||||
public:
|
||||
NestConst<jrd_nod> statement;
|
||||
NestConst<jrd_nod> subStatement;
|
||||
USHORT stream;
|
||||
};
|
||||
|
||||
|
||||
class ErrorHandlerNode : public TypedNode<StmtNode, StmtNode::TYPE_ERROR_HANDLER>
|
||||
{
|
||||
public:
|
||||
explicit ErrorHandlerNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_ERROR_HANDLER>(pool),
|
||||
action(NULL),
|
||||
conditions(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ErrorHandlerNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual ErrorHandlerNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual ErrorHandlerNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
NestConst<jrd_nod> action;
|
||||
NestConst<PsqlException> conditions;
|
||||
};
|
||||
|
||||
|
||||
class ExecProcedureNode : public TypedNode<StmtNode, StmtNode::TYPE_EXEC_PROCEDURE>
|
||||
{
|
||||
public:
|
||||
explicit ExecProcedureNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_EXEC_PROCEDURE>(pool),
|
||||
inputSources(NULL),
|
||||
inputTargets(NULL),
|
||||
inputMessage(NULL),
|
||||
outputSources(NULL),
|
||||
outputTargets(NULL),
|
||||
outputMessage(NULL),
|
||||
procedure(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ExecProcedureNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual ExecProcedureNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual ExecProcedureNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
private:
|
||||
void executeProcedure(thread_db* tdbb, jrd_req* request) const;
|
||||
|
||||
public:
|
||||
NestConst<ValueListNode> inputSources;
|
||||
NestConst<ValueListNode> inputTargets;
|
||||
NestConst<jrd_nod> inputMessage;
|
||||
NestConst<ValueListNode> outputSources;
|
||||
NestConst<ValueListNode> outputTargets;
|
||||
NestConst<jrd_nod> outputMessage;
|
||||
NestConst<jrd_prc> procedure;
|
||||
};
|
||||
|
||||
|
||||
class ExecStatementNode : public TypedNode<StmtNode, StmtNode::TYPE_EXEC_STATEMENT>
|
||||
{
|
||||
public:
|
||||
explicit ExecStatementNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_EXEC_STATEMENT>(pool),
|
||||
sql(NULL),
|
||||
dataSource(NULL),
|
||||
userName(NULL),
|
||||
password(NULL),
|
||||
role(NULL),
|
||||
innerStmt(NULL),
|
||||
inputs(NULL),
|
||||
outputs(NULL),
|
||||
useCallerPrivs(false),
|
||||
traScope(EDS::traCommon),
|
||||
inputNames(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ExecStatementNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual ExecStatementNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual ExecStatementNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
private:
|
||||
void getString(thread_db* tdbb, jrd_req* request, const ValueExprNode* node,
|
||||
Firebird::string& str) const;
|
||||
|
||||
public:
|
||||
NestConst<ValueExprNode> sql;
|
||||
NestConst<ValueExprNode> dataSource;
|
||||
NestConst<ValueExprNode> userName;
|
||||
NestConst<ValueExprNode> password;
|
||||
NestConst<ValueExprNode> role;
|
||||
NestConst<jrd_nod> innerStmt;
|
||||
NestConst<ValueListNode> inputs;
|
||||
NestConst<ValueListNode> outputs;
|
||||
bool useCallerPrivs;
|
||||
EDS::TraScope traScope;
|
||||
EDS::ParamNames* inputNames;
|
||||
};
|
||||
|
||||
|
||||
class IfNode : public TypedNode<StmtNode, StmtNode::TYPE_IF>
|
||||
{
|
||||
public:
|
||||
explicit IfNode(MemoryPool& pool)
|
||||
: StmtNode(pool),
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_IF>(pool),
|
||||
dsqlCondition(NULL),
|
||||
dsqlTrueAction(NULL),
|
||||
dsqlFalseAction(NULL),
|
||||
@ -56,7 +337,7 @@ public:
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual IfNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual IfNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
dsql_nod* dsqlCondition;
|
||||
@ -68,11 +349,11 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class InAutonomousTransactionNode : public StmtNode
|
||||
class InAutonomousTransactionNode : public TypedNode<StmtNode, StmtNode::TYPE_IN_AUTO_TRANS>
|
||||
{
|
||||
public:
|
||||
explicit InAutonomousTransactionNode(MemoryPool& pool)
|
||||
: StmtNode(pool),
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_IN_AUTO_TRANS>(pool),
|
||||
dsqlAction(NULL),
|
||||
action(NULL),
|
||||
savNumberOffset(0)
|
||||
@ -87,7 +368,7 @@ public:
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual InAutonomousTransactionNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual InAutonomousTransactionNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
dsql_nod* dsqlAction;
|
||||
@ -96,11 +377,11 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class ExecBlockNode : public DsqlOnlyStmtNode
|
||||
class ExecBlockNode : public TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_EXEC_BLOCK>
|
||||
{
|
||||
public:
|
||||
explicit ExecBlockNode(MemoryPool& pool)
|
||||
: DsqlOnlyStmtNode(pool),
|
||||
: TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_EXEC_BLOCK>(pool),
|
||||
parameters(pool),
|
||||
returns(pool),
|
||||
localDeclList(NULL),
|
||||
@ -123,12 +404,12 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class ExceptionNode : public StmtNode
|
||||
class ExceptionNode : public TypedNode<StmtNode, StmtNode::TYPE_EXCEPTION>
|
||||
{
|
||||
public:
|
||||
explicit ExceptionNode(MemoryPool& pool, const Firebird::MetaName& aName = "",
|
||||
dsql_nod* aDsqlMessageExpr = NULL, dsql_nod* aDsqlParameters = NULL)
|
||||
: StmtNode(pool),
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_EXCEPTION>(pool),
|
||||
name(pool, aName),
|
||||
dsqlMessageExpr(aDsqlMessageExpr),
|
||||
dsqlParameters(aDsqlParameters),
|
||||
@ -146,7 +427,7 @@ public:
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual ExceptionNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual ExceptionNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
private:
|
||||
void setError(thread_db* tdbb) const;
|
||||
@ -161,11 +442,11 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class ExitNode : public DsqlOnlyStmtNode
|
||||
class ExitNode : public TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_EXIT>
|
||||
{
|
||||
public:
|
||||
explicit ExitNode(MemoryPool& pool)
|
||||
: DsqlOnlyStmtNode(pool)
|
||||
: TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_EXIT>(pool)
|
||||
{
|
||||
}
|
||||
|
||||
@ -175,11 +456,11 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class ForNode : public StmtNode
|
||||
class ForNode : public TypedNode<StmtNode, StmtNode::TYPE_FOR>
|
||||
{
|
||||
public:
|
||||
explicit ForNode(MemoryPool& pool)
|
||||
: StmtNode(pool),
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_FOR>(pool),
|
||||
dsqlSelect(NULL),
|
||||
dsqlInto(NULL),
|
||||
dsqlCursor(NULL),
|
||||
@ -208,7 +489,7 @@ public:
|
||||
cursorPtr = cursor.getAddress();
|
||||
}
|
||||
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
dsql_nod* dsqlSelect;
|
||||
@ -224,11 +505,125 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class PostEventNode : public StmtNode
|
||||
class HandlerNode : public TypedNode<StmtNode, StmtNode::TYPE_HANDLER>
|
||||
{
|
||||
public:
|
||||
explicit HandlerNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_HANDLER>(pool),
|
||||
statement(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual HandlerNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual HandlerNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual HandlerNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
NestConst<jrd_nod> statement;
|
||||
};
|
||||
|
||||
|
||||
class LabelNode : public TypedNode<StmtNode, StmtNode::TYPE_LABEL>
|
||||
{
|
||||
public:
|
||||
explicit LabelNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_LABEL>(pool),
|
||||
statement(NULL),
|
||||
labelNumber(0)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual LabelNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual LabelNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual LabelNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
NestConst<jrd_nod> statement;
|
||||
USHORT labelNumber;
|
||||
};
|
||||
|
||||
|
||||
class LoopNode : public TypedNode<StmtNode, StmtNode::TYPE_LOOP>
|
||||
{
|
||||
public:
|
||||
explicit LoopNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_LOOP>(pool),
|
||||
statement(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual LoopNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual LoopNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual LoopNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
NestConst<jrd_nod> statement;
|
||||
};
|
||||
|
||||
|
||||
class ModifyNode : public TypedNode<StmtNode, StmtNode::TYPE_MODIFY>
|
||||
{
|
||||
public:
|
||||
explicit ModifyNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_MODIFY>(pool),
|
||||
statement(NULL),
|
||||
statement2(NULL),
|
||||
subMod(NULL),
|
||||
validate(NULL),
|
||||
mapView(NULL),
|
||||
orgStream(0),
|
||||
newStream(0)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ModifyNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual ModifyNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual ModifyNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
private:
|
||||
static void pass1Modify(thread_db* tdbb, CompilerScratch* csb, ModifyNode* node);
|
||||
const jrd_nod* modify(thread_db* tdbb, jrd_req* request, WhichTrigger whichTrig) const;
|
||||
|
||||
public:
|
||||
NestConst<jrd_nod> statement;
|
||||
NestConst<jrd_nod> statement2;
|
||||
NestConst<jrd_nod> subMod;
|
||||
NestConst<jrd_nod> validate;
|
||||
NestConst<jrd_nod> mapView;
|
||||
USHORT orgStream;
|
||||
USHORT newStream;
|
||||
};
|
||||
|
||||
|
||||
class PostEventNode : public TypedNode<StmtNode, StmtNode::TYPE_POST_EVENT>
|
||||
{
|
||||
public:
|
||||
explicit PostEventNode(MemoryPool& pool)
|
||||
: StmtNode(pool),
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_POST_EVENT>(pool),
|
||||
dsqlEvent(NULL),
|
||||
dsqlArgument(NULL),
|
||||
event(NULL),
|
||||
@ -244,7 +639,7 @@ public:
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual PostEventNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual PostEventNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
dsql_nod* dsqlEvent;
|
||||
@ -254,7 +649,70 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class SavepointNode : public StmtNode
|
||||
class ReceiveNode : public TypedNode<StmtNode, StmtNode::TYPE_RECEIVE>
|
||||
{
|
||||
public:
|
||||
explicit ReceiveNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_RECEIVE>(pool),
|
||||
statement(NULL),
|
||||
message(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ReceiveNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual ReceiveNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual ReceiveNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
NestConst<jrd_nod> statement;
|
||||
NestConst<jrd_nod> message;
|
||||
};
|
||||
|
||||
|
||||
class StoreNode : public TypedNode<StmtNode, StmtNode::TYPE_STORE>
|
||||
{
|
||||
public:
|
||||
explicit StoreNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_STORE>(pool),
|
||||
statement(NULL),
|
||||
statement2(NULL),
|
||||
subStore(NULL),
|
||||
validate(NULL),
|
||||
relationSource(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual StoreNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual StoreNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual StoreNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
private:
|
||||
static bool pass1Store(thread_db* tdbb, CompilerScratch* csb, StoreNode* node);
|
||||
void makeDefaults(thread_db* tdbb, CompilerScratch* csb);
|
||||
const jrd_nod* store(thread_db* tdbb, jrd_req* request, WhichTrigger whichTrig) const;
|
||||
|
||||
public:
|
||||
NestConst<jrd_nod> statement;
|
||||
NestConst<jrd_nod> statement2;
|
||||
NestConst<jrd_nod> subStore;
|
||||
NestConst<jrd_nod> validate;
|
||||
NestConst<RelationSourceNode> relationSource;
|
||||
};
|
||||
|
||||
|
||||
class UserSavepointNode : public TypedNode<StmtNode, StmtNode::TYPE_USER_SAVEPOINT>
|
||||
{
|
||||
public:
|
||||
enum Command
|
||||
@ -267,8 +725,8 @@ public:
|
||||
};
|
||||
|
||||
public:
|
||||
explicit SavepointNode(MemoryPool& pool)
|
||||
: StmtNode(pool),
|
||||
explicit UserSavepointNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_USER_SAVEPOINT>(pool),
|
||||
command(CMD_NOTHING),
|
||||
name(pool)
|
||||
{
|
||||
@ -278,11 +736,11 @@ public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual SavepointNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual UserSavepointNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual SavepointNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual SavepointNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual UserSavepointNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual UserSavepointNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
Command command;
|
||||
@ -290,11 +748,107 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class SuspendNode : public StmtNode
|
||||
class SelectNode : public TypedNode<StmtNode, StmtNode::TYPE_SELECT>
|
||||
{
|
||||
public:
|
||||
explicit SelectNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_SELECT>(pool),
|
||||
statements(pool)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual SelectNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual SelectNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual SelectNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
Firebird::Array<NestConst<jrd_nod> > statements;
|
||||
};
|
||||
|
||||
|
||||
class SetGeneratorNode : public TypedNode<StmtNode, StmtNode::TYPE_SET_GENERATOR>
|
||||
{
|
||||
public:
|
||||
explicit SetGeneratorNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_SET_GENERATOR>(pool),
|
||||
value(NULL),
|
||||
genId(0)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual SetGeneratorNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual SetGeneratorNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual SetGeneratorNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
NestConst<ValueExprNode> value;
|
||||
USHORT genId;
|
||||
};
|
||||
|
||||
|
||||
class SourceInfoNode : public TypedNode<StmtNode, StmtNode::TYPE_SOURCE_INFO>
|
||||
{
|
||||
public:
|
||||
explicit SourceInfoNode(MemoryPool& pool, jrd_nod* aStatement, USHORT aLine, USHORT aColumn)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_SOURCE_INFO>(pool),
|
||||
statement(aStatement),
|
||||
line(aLine),
|
||||
column(aColumn)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual SourceInfoNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual SourceInfoNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual SourceInfoNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
NestConst<jrd_nod> statement;
|
||||
USHORT line;
|
||||
USHORT column;
|
||||
};
|
||||
|
||||
|
||||
class StallNode : public TypedNode<StmtNode, StmtNode::TYPE_STALL>
|
||||
{
|
||||
public:
|
||||
explicit StallNode(MemoryPool& pool)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_STALL>(pool)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual StallNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual StallNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual StallNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
};
|
||||
|
||||
|
||||
class SuspendNode : public TypedNode<StmtNode, StmtNode::TYPE_SUSPEND>
|
||||
{
|
||||
public:
|
||||
explicit SuspendNode(MemoryPool& pool)
|
||||
: StmtNode(pool),
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_SUSPEND>(pool),
|
||||
message(NULL),
|
||||
statement(NULL)
|
||||
{
|
||||
@ -308,7 +862,7 @@ public:
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual SuspendNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual SuspendNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
NestConst<jrd_nod> message;
|
||||
@ -316,11 +870,12 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class ReturnNode : public DsqlOnlyStmtNode
|
||||
class ReturnNode : public TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_RETURN>
|
||||
{
|
||||
public:
|
||||
explicit ReturnNode(MemoryPool& pool, dsql_nod* val = NULL)
|
||||
: DsqlOnlyStmtNode(pool), value(val)
|
||||
: TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_RETURN>(pool),
|
||||
value(val)
|
||||
{
|
||||
}
|
||||
|
||||
@ -333,6 +888,40 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class SavePointNode : public TypedNode<StmtNode, StmtNode::TYPE_SAVEPOINT>
|
||||
{
|
||||
public:
|
||||
explicit SavePointNode(MemoryPool& pool, UCHAR aBlrOp)
|
||||
: TypedNode<StmtNode, StmtNode::TYPE_SAVEPOINT>(pool),
|
||||
blrOp(aBlrOp)
|
||||
{
|
||||
fb_assert(blrOp == blr_start_savepoint || blrOp == blr_end_savepoint);
|
||||
}
|
||||
|
||||
public:
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual SavePointNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
|
||||
virtual SavePointNode* pass1(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual SavePointNode* pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual const jrd_nod* execute(thread_db* tdbb, jrd_req* request, ExeState* exeState) const;
|
||||
|
||||
public:
|
||||
UCHAR blrOp;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // DSQL_STMT_NODES_H
|
||||
|
@ -356,6 +356,23 @@ public:
|
||||
jrd_nod* message;
|
||||
};
|
||||
|
||||
// Node copier that remaps the field id 0 of stream 0 to a given field id.
|
||||
class RemapFieldNodeCopier : public NodeCopier
|
||||
{
|
||||
public:
|
||||
RemapFieldNodeCopier(CompilerScratch* aCsb, UCHAR* aRemap, USHORT aFldId)
|
||||
: NodeCopier(aCsb, aRemap),
|
||||
fldId(aFldId)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual USHORT getFieldId(FieldNode* field);
|
||||
|
||||
private:
|
||||
USHORT fldId;
|
||||
};
|
||||
|
||||
|
||||
template <typename T, typename T2>
|
||||
inline bool DsqlNodeVisitor<T, T2>::visitChildren(T node)
|
||||
|
@ -3956,8 +3956,8 @@ savepoint : set_savepoint
|
||||
set_savepoint
|
||||
: SAVEPOINT symbol_savepoint_name
|
||||
{
|
||||
SavepointNode* node = newNode<SavepointNode>();
|
||||
node->command = SavepointNode::CMD_SET;
|
||||
UserSavepointNode* node = newNode<UserSavepointNode>();
|
||||
node->command = UserSavepointNode::CMD_SET;
|
||||
node->name = toName($2);
|
||||
$$ = makeClassNode(node);
|
||||
}
|
||||
@ -3966,8 +3966,8 @@ set_savepoint
|
||||
release_savepoint
|
||||
: RELEASE SAVEPOINT symbol_savepoint_name release_only_opt
|
||||
{
|
||||
SavepointNode* node = newNode<SavepointNode>();
|
||||
node->command = ($4 ? SavepointNode::CMD_RELEASE_ONLY : SavepointNode::CMD_RELEASE);
|
||||
UserSavepointNode* node = newNode<UserSavepointNode>();
|
||||
node->command = ($4 ? UserSavepointNode::CMD_RELEASE_ONLY : UserSavepointNode::CMD_RELEASE);
|
||||
node->name = toName($3);
|
||||
$$ = makeClassNode(node);
|
||||
}
|
||||
@ -3983,8 +3983,8 @@ release_only_opt
|
||||
undo_savepoint
|
||||
: ROLLBACK optional_work TO optional_savepoint symbol_savepoint_name
|
||||
{
|
||||
SavepointNode* node = newNode<SavepointNode>();
|
||||
node->command = SavepointNode::CMD_ROLLBACK;
|
||||
UserSavepointNode* node = newNode<UserSavepointNode>();
|
||||
node->command = UserSavepointNode::CMD_ROLLBACK;
|
||||
node->name = toName($5);
|
||||
$$ = makeClassNode(node);
|
||||
}
|
||||
|
@ -5082,11 +5082,11 @@ static dsql_nod* pass1_make_derived_field(DsqlCompilerScratch* dsqlScratch, thre
|
||||
static dsql_nod* pass1_merge(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
|
||||
{
|
||||
// Puts a blr_send before blr_for in DSQL statements.
|
||||
class MergeSendNode : public DsqlOnlyStmtNode
|
||||
class MergeSendNode : public TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_MERGE>
|
||||
{
|
||||
public:
|
||||
explicit MergeSendNode(MemoryPool& pool, dsql_nod* aStmt)
|
||||
: DsqlOnlyStmtNode(pool),
|
||||
: TypedNode<DsqlOnlyStmtNode, StmtNode::TYPE_MERGE>(pool),
|
||||
stmt(aStmt)
|
||||
{
|
||||
}
|
||||
|
@ -50,7 +50,6 @@ JrdStatement::JrdStatement(thread_db* tdbb, MemoryPool* p, CompilerScratch* csb)
|
||||
resources(*p),
|
||||
triggerName(*p),
|
||||
fors(*p),
|
||||
execStmts(*p),
|
||||
invariants(*p),
|
||||
blr(*p),
|
||||
mapFieldInfo(*p),
|
||||
@ -132,10 +131,6 @@ JrdStatement::JrdStatement(thread_db* tdbb, MemoryPool* p, CompilerScratch* csb)
|
||||
// make a vector of all used RSEs
|
||||
fors = csb->csb_fors;
|
||||
|
||||
// make a vector of all used ExecuteStatements into
|
||||
for (Array<jrd_nod*>::iterator i = csb->csb_exec_sta.begin(); i != csb->csb_exec_sta.end(); ++i)
|
||||
execStmts.add(*i);
|
||||
|
||||
// make a vector of all invariant-type nodes, so that we will
|
||||
// be able to easily reinitialize them when we restart the request
|
||||
invariants.join(csb->csb_invariants);
|
||||
@ -215,8 +210,6 @@ JrdStatement* JrdStatement::makeStatement(thread_db* tdbb, CompilerScratch* csb,
|
||||
fieldInfo.validationExpr = CMP_pass1(tdbb, csb, fieldInfo.validationExpr);
|
||||
}
|
||||
|
||||
csb->csb_exec_sta.clear();
|
||||
|
||||
csb->csb_node = CMP_pass2(tdbb, csb, csb->csb_node, 0);
|
||||
|
||||
// Compile (pass2) domains DEFAULT and constraints
|
||||
|
@ -76,7 +76,6 @@ public:
|
||||
Firebird::MetaName triggerName; // name of request (trigger), if any
|
||||
const jrd_nod* topNode; // top of execution tree
|
||||
Firebird::Array<const RecordSource*> fors; // record sources
|
||||
Firebird::Array<const jrd_nod*> execStmts; // exec_into nodes
|
||||
Firebird::Array<ULONG*> invariants; // pointer to nodes invariant offsets
|
||||
Firebird::RefStrPtr sqlText; // SQL text (encoded in the metadata charset)
|
||||
Firebird::Array<UCHAR> blr; // BLR for non-SQL query
|
||||
|
726
src/jrd/cmp.cpp
726
src/jrd/cmp.cpp
@ -76,7 +76,6 @@
|
||||
#include "../jrd/met_proto.h"
|
||||
#include "../jrd/mov_proto.h"
|
||||
#include "../common/dsc_proto.h"
|
||||
#include "../jrd/execute_statement.h"
|
||||
#include "../jrd/Optimizer.h"
|
||||
|
||||
#include "../jrd/DataTypeUtil.h"
|
||||
@ -129,47 +128,23 @@ namespace
|
||||
return fldId;
|
||||
}
|
||||
};
|
||||
|
||||
// Node copier that remaps the field id 0 of stream 0 to a given field id.
|
||||
class RemapFieldNodeCopier : public NodeCopier
|
||||
{
|
||||
public:
|
||||
RemapFieldNodeCopier(CompilerScratch* aCsb, UCHAR* aRemap, USHORT aFldId)
|
||||
: NodeCopier(aCsb, aRemap),
|
||||
fldId(aFldId)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual USHORT getFieldId(FieldNode* field)
|
||||
{
|
||||
if (field->byId && field->fieldId == 0 && field->fieldStream == 0)
|
||||
return fldId;
|
||||
|
||||
return NodeCopier::getFieldId(field);
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT fldId;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static jrd_nod* make_defaults(thread_db*, CompilerScratch*, USHORT, jrd_nod*);
|
||||
static jrd_nod* make_validation(thread_db*, CompilerScratch*, USHORT);
|
||||
static void pass1_erase(thread_db*, CompilerScratch*, jrd_nod*);
|
||||
static jrd_nod* pass1_expand_view(thread_db*, CompilerScratch*, USHORT, USHORT, bool);
|
||||
static void pass1_modify(thread_db*, CompilerScratch*, jrd_nod*);
|
||||
static bool pass1_store(thread_db*, CompilerScratch*, jrd_nod*);
|
||||
static RelationSourceNode* pass1_update(thread_db*, CompilerScratch*, jrd_rel*, const trig_vec*, USHORT, USHORT,
|
||||
SecurityClass::flags_t, jrd_rel*, USHORT);
|
||||
static void post_trigger_access(CompilerScratch*, jrd_rel*, ExternalAccess::exa_act, jrd_rel*);
|
||||
|
||||
#ifdef CMP_DEBUG
|
||||
#include <stdarg.h>
|
||||
IMPLEMENT_TRACE_ROUTINE(cmp_trace, "CMP")
|
||||
#endif
|
||||
|
||||
|
||||
USHORT RemapFieldNodeCopier::getFieldId(FieldNode* field)
|
||||
{
|
||||
if (field->byId && field->fieldId == 0 && field->fieldStream == 0)
|
||||
return fldId;
|
||||
|
||||
return NodeCopier::getFieldId(field);
|
||||
}
|
||||
|
||||
|
||||
// Clone a node.
|
||||
ValueExprNode* CMP_clone_node(thread_db* tdbb, CompilerScratch* csb, ValueExprNode* node)
|
||||
{
|
||||
@ -814,14 +789,6 @@ jrd_nod* NodeCopier::copy(thread_db* tdbb, jrd_nod* input)
|
||||
args = e_asgn_length;
|
||||
break;
|
||||
|
||||
case nod_erase:
|
||||
args = e_erase_length;
|
||||
break;
|
||||
|
||||
case nod_modify:
|
||||
args = e_mod_length;
|
||||
break;
|
||||
|
||||
case nod_init_variable:
|
||||
if (csb->csb_remap_variable != 0)
|
||||
{
|
||||
@ -872,26 +839,6 @@ jrd_nod* NodeCopier::copy(thread_db* tdbb, jrd_nod* input)
|
||||
}
|
||||
return input;
|
||||
|
||||
case nod_dcl_cursor:
|
||||
node = PAR_make_node(tdbb, e_dcl_cur_length);
|
||||
node->nod_count = input->nod_count;
|
||||
node->nod_type = input->nod_type;
|
||||
node->nod_arg[e_dcl_cur_rse] = copy(tdbb, input->nod_arg[e_dcl_cur_rse]);
|
||||
node->nod_arg[e_dcl_cur_refs] = copy(tdbb, input->nod_arg[e_dcl_cur_refs]);
|
||||
node->nod_arg[e_dcl_cur_number] = input->nod_arg[e_dcl_cur_number];
|
||||
break;
|
||||
|
||||
case nod_cursor_stmt:
|
||||
node = PAR_make_node(tdbb, e_cursor_stmt_length);
|
||||
node->nod_count = input->nod_count;
|
||||
node->nod_type = input->nod_type;
|
||||
node->nod_arg[e_cursor_stmt_op] = input->nod_arg[e_cursor_stmt_op];
|
||||
node->nod_arg[e_cursor_stmt_number] = input->nod_arg[e_cursor_stmt_number];
|
||||
node->nod_arg[e_cursor_stmt_scroll_op] = input->nod_arg[e_cursor_stmt_scroll_op];
|
||||
node->nod_arg[e_cursor_stmt_scroll_val] = copy(tdbb, input->nod_arg[e_cursor_stmt_scroll_val]);
|
||||
node->nod_arg[e_cursor_stmt_into] = copy(tdbb, input->nod_arg[e_cursor_stmt_into]);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -949,130 +896,7 @@ void CMP_expand_view_nodes(thread_db* tdbb, CompilerScratch* csb, USHORT stream,
|
||||
}
|
||||
|
||||
|
||||
static jrd_nod* make_defaults(thread_db* tdbb, CompilerScratch* csb, USHORT stream, jrd_nod* statement)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* m a k e _ d e f a u l t s
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Build an default value assignments.
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
DEV_BLKCHK(csb, type_csb);
|
||||
DEV_BLKCHK(statement, type_nod);
|
||||
|
||||
jrd_rel* relation = csb->csb_rpt[stream].csb_relation;
|
||||
|
||||
vec<jrd_fld*>* vector = relation->rel_fields;
|
||||
if (!vector)
|
||||
return statement;
|
||||
|
||||
UCHAR local_map[JrdStatement::MAP_LENGTH];
|
||||
UCHAR* map = csb->csb_rpt[stream].csb_map;
|
||||
if (!map)
|
||||
{
|
||||
map = local_map;
|
||||
fb_assert(stream <= MAX_STREAMS); // CVC: MAX_UCHAR relevant, too?
|
||||
map[0] = (UCHAR) stream;
|
||||
map[1] = 1;
|
||||
map[2] = 2;
|
||||
}
|
||||
|
||||
NodeStack stack;
|
||||
|
||||
USHORT field_id = 0;
|
||||
vec<jrd_fld*>::iterator ptr1 = vector->begin();
|
||||
for (const vec<jrd_fld*>::const_iterator end = vector->end(); ptr1 < end; ++ptr1, ++field_id)
|
||||
{
|
||||
ValueExprNode* value;
|
||||
|
||||
if (!*ptr1 || !((*ptr1)->fld_generator_name.hasData() || (value = (*ptr1)->fld_default_value)))
|
||||
continue;
|
||||
|
||||
fb_assert(statement->nod_type == nod_list);
|
||||
if (statement->nod_type == nod_list)
|
||||
{
|
||||
bool inList = false;
|
||||
|
||||
for (unsigned i = 0; i < statement->nod_count; ++i)
|
||||
{
|
||||
const jrd_nod* assign = statement->nod_arg[i];
|
||||
|
||||
fb_assert(assign->nod_type == nod_assignment);
|
||||
if (assign->nod_type == nod_assignment)
|
||||
{
|
||||
const jrd_nod* to = assign->nod_arg[e_asgn_to];
|
||||
|
||||
const FieldNode* fieldNode = ExprNode::as<FieldNode>(to);
|
||||
fb_assert(fieldNode);
|
||||
|
||||
if (fieldNode && fieldNode->fieldStream == stream && fieldNode->fieldId == field_id)
|
||||
{
|
||||
inList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inList)
|
||||
continue;
|
||||
|
||||
jrd_nod* node = PAR_make_node(tdbb, e_asgn_length);
|
||||
node->nod_type = nod_assignment;
|
||||
node->nod_arg[e_asgn_to] = PAR_gen_field(tdbb, stream, field_id);
|
||||
stack.push(node);
|
||||
|
||||
if ((*ptr1)->fld_generator_name.hasData())
|
||||
{
|
||||
// Make a gen_id(<generator name>, 1) expression.
|
||||
|
||||
LiteralNode* literal = FB_NEW(csb->csb_pool) LiteralNode(csb->csb_pool);
|
||||
SLONG* increment = FB_NEW(csb->csb_pool) SLONG(1);
|
||||
literal->litDesc.makeLong(0, increment);
|
||||
|
||||
GenIdNode* genNode = FB_NEW(csb->csb_pool) GenIdNode(csb->csb_pool,
|
||||
(csb->csb_g_flags & csb_blr_version4), (*ptr1)->fld_generator_name);
|
||||
genNode->id = MET_lookup_generator(tdbb, (*ptr1)->fld_generator_name.c_str());
|
||||
genNode->arg = literal;
|
||||
|
||||
jrd_nod* genNod = PAR_make_node(tdbb, 1);
|
||||
genNod->nod_type = nod_class_exprnode_jrd;
|
||||
genNod->nod_count = 0;
|
||||
genNod->nod_arg[0] = reinterpret_cast<jrd_nod*>(genNode);
|
||||
node->nod_arg[e_asgn_from] = genNod;
|
||||
}
|
||||
else //if (value)
|
||||
{
|
||||
// Clone the field default value.
|
||||
|
||||
jrd_nod* nod = PAR_make_node(tdbb, 1);
|
||||
nod->nod_type = nod_class_exprnode_jrd;
|
||||
nod->nod_count = 0;
|
||||
nod->nod_arg[0] = reinterpret_cast<jrd_nod*>(
|
||||
RemapFieldNodeCopier(csb, map, field_id).copy(tdbb, value));
|
||||
|
||||
node->nod_arg[e_asgn_from] = nod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stack.isEmpty())
|
||||
return statement;
|
||||
|
||||
// We have some default - add the original statement and make a list out of the whole mess.
|
||||
|
||||
stack.push(statement);
|
||||
|
||||
return PAR_make_list(tdbb, stack);
|
||||
}
|
||||
|
||||
|
||||
static jrd_nod* make_validation(thread_db* tdbb, CompilerScratch* csb, USHORT stream)
|
||||
jrd_nod* CMP_make_validation(thread_db* tdbb, CompilerScratch* csb, USHORT stream)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1313,49 +1137,10 @@ jrd_nod* CMP_pass1(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
|
||||
}
|
||||
break;
|
||||
|
||||
case nod_modify:
|
||||
pass1_modify(tdbb, csb, node);
|
||||
break;
|
||||
|
||||
case nod_erase:
|
||||
pass1_erase(tdbb, csb, node);
|
||||
break;
|
||||
|
||||
case nod_exec_proc:
|
||||
procedure = (jrd_prc*) node->nod_arg[e_esp_procedure];
|
||||
// Post access to procedure
|
||||
CMP_post_procedure_access(tdbb, csb, procedure);
|
||||
CMP_post_resource(&csb->csb_resources, procedure,
|
||||
Resource::rsc_procedure, procedure->getId());
|
||||
break;
|
||||
|
||||
case nod_store:
|
||||
if (pass1_store(tdbb, csb, node))
|
||||
{
|
||||
fb_assert(node->nod_arg[e_sto_relation]->nod_type == nod_class_recsrcnode_jrd);
|
||||
RelationSourceNode* recSource = reinterpret_cast<RelationSourceNode*>(
|
||||
node->nod_arg[e_sto_relation]->nod_arg[0]);
|
||||
fb_assert(recSource->type == RelationSourceNode::TYPE);
|
||||
|
||||
stream = recSource->getStream();
|
||||
node->nod_arg[e_sto_statement] =
|
||||
make_defaults(tdbb, csb, stream, node->nod_arg[e_sto_statement]);
|
||||
}
|
||||
break;
|
||||
|
||||
case nod_cursor_stmt:
|
||||
node->nod_arg[e_cursor_stmt_scroll_val] = CMP_pass1(tdbb, csb, node->nod_arg[e_cursor_stmt_scroll_val]);
|
||||
node->nod_arg[e_cursor_stmt_into] = CMP_pass1(tdbb, csb, node->nod_arg[e_cursor_stmt_into]);
|
||||
break;
|
||||
|
||||
case nod_class_recsrcnode_jrd:
|
||||
reinterpret_cast<RecordSourceNode*>(node->nod_arg[0])->pass1(tdbb, csb);
|
||||
break;
|
||||
|
||||
case nod_src_info:
|
||||
node->nod_arg[e_src_info_node] = CMP_pass1(tdbb, csb, node->nod_arg[e_src_info_node]);
|
||||
return node;
|
||||
|
||||
case nod_class_exprnode_jrd:
|
||||
{
|
||||
ExprNode* exprNode = reinterpret_cast<ExprNode*>(node->nod_arg[0]);
|
||||
@ -1424,121 +1209,7 @@ jrd_nod* CMP_pass1(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
|
||||
}
|
||||
|
||||
|
||||
static void pass1_erase(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p a s s 1 _ e r a s e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Checkout an erase statement. If it references a view, and
|
||||
* is kosher, fix it up.
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
DEV_BLKCHK(csb, type_csb);
|
||||
DEV_BLKCHK(node, type_nod);
|
||||
|
||||
// if updateable views with triggers are involved, there
|
||||
// maybe a recursive call to be ignored
|
||||
|
||||
if (node->nod_arg[e_erase_sub_erase])
|
||||
return;
|
||||
|
||||
// to support nested views, loop until we hit a table or
|
||||
// a view with user-defined triggers (which means no update)
|
||||
|
||||
jrd_rel* parent = NULL;
|
||||
jrd_rel* view = NULL;
|
||||
USHORT parent_stream = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
USHORT new_stream = (USHORT)(IPTR) node->nod_arg[e_erase_stream];
|
||||
const USHORT stream = new_stream;
|
||||
|
||||
CompilerScratch::csb_repeat* tail = &csb->csb_rpt[stream];
|
||||
tail->csb_flags |= csb_erase;
|
||||
|
||||
jrd_rel* relation = csb->csb_rpt[stream].csb_relation;
|
||||
view = (relation->rel_view_rse) ? relation : view;
|
||||
if (!parent) {
|
||||
parent = tail->csb_view;
|
||||
}
|
||||
|
||||
post_trigger_access(csb, relation, ExternalAccess::exa_delete, view);
|
||||
|
||||
// Check out delete. If this is a delete thru a view, verify the
|
||||
// view by checking for read access on the base table. If field-level select
|
||||
// privileges are implemented, this needs to be enhanced.
|
||||
|
||||
SecurityClass::flags_t priv = SCL_sql_delete;
|
||||
if (parent) {
|
||||
priv |= SCL_read;
|
||||
}
|
||||
|
||||
const trig_vec* trigger = relation->rel_pre_erase ?
|
||||
relation->rel_pre_erase : relation->rel_post_erase;
|
||||
|
||||
// if we have a view with triggers, let's expand it
|
||||
|
||||
if (relation->rel_view_rse && trigger)
|
||||
{
|
||||
new_stream = csb->nextStream();
|
||||
node->nod_arg[e_erase_stream] = (jrd_nod*) (IPTR) new_stream;
|
||||
CMP_csb_element(csb, new_stream)->csb_relation = relation;
|
||||
|
||||
node->nod_arg[e_erase_statement] = pass1_expand_view(tdbb, csb, stream, new_stream, false);
|
||||
node->nod_count = MAX(node->nod_count, (USHORT) e_erase_statement + 1);
|
||||
}
|
||||
|
||||
// get the source relation, either a table or yet another view
|
||||
|
||||
RelationSourceNode* source = pass1_update(tdbb, csb, relation, trigger, stream,
|
||||
new_stream, priv, parent, parent_stream);
|
||||
|
||||
if (!source)
|
||||
return; // no source means we're done
|
||||
|
||||
parent = relation;
|
||||
parent_stream = stream;
|
||||
|
||||
// remap the source stream
|
||||
|
||||
UCHAR* map = csb->csb_rpt[stream].csb_map;
|
||||
|
||||
if (trigger)
|
||||
{
|
||||
// set up the new target stream
|
||||
|
||||
jrd_nod* view_node = NodeCopier::copy(tdbb, csb, node, map);
|
||||
view_node->nod_arg[e_erase_statement] = NULL;
|
||||
view_node->nod_arg[e_erase_sub_erase] = NULL;
|
||||
|
||||
node->nod_arg[e_erase_sub_erase] = view_node;
|
||||
node->nod_count = MAX(node->nod_count, (USHORT) e_erase_sub_erase + 1);
|
||||
|
||||
// substitute the original delete node with the newly created one
|
||||
node = view_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this relation is not actually being updated as this operation
|
||||
// goes deeper (we have a naturally updatable view)
|
||||
csb->csb_rpt[new_stream].csb_flags &= ~csb_view_update;
|
||||
}
|
||||
|
||||
// let's reset the target stream
|
||||
new_stream = source->getStream();
|
||||
node->nod_arg[e_erase_stream] = (jrd_nod*)(IPTR) map[new_stream];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static jrd_nod* pass1_expand_view(thread_db* tdbb,
|
||||
jrd_nod* CMP_pass1_expand_view(thread_db* tdbb,
|
||||
CompilerScratch* csb,
|
||||
USHORT org_stream,
|
||||
USHORT new_stream,
|
||||
@ -1602,286 +1273,7 @@ static jrd_nod* pass1_expand_view(thread_db* tdbb,
|
||||
}
|
||||
|
||||
|
||||
static void pass1_modify(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p a s s 1 _ m o d i f y
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Process a source for a modify statement. This can
|
||||
* get a little tricky if the relation is a view.
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
DEV_BLKCHK(csb, type_csb);
|
||||
DEV_BLKCHK(node, type_nod);
|
||||
|
||||
// if updateable views with triggers are involved, there
|
||||
// maybe a recursive call to be ignored
|
||||
|
||||
if (node->nod_arg[e_mod_sub_mod])
|
||||
return;
|
||||
|
||||
jrd_rel* parent = NULL;
|
||||
jrd_rel* view = NULL;
|
||||
USHORT parent_stream = 0;
|
||||
|
||||
// to support nested views, loop until we hit a table or
|
||||
// a view with user-defined triggers (which means no update)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
USHORT stream = (USHORT)(IPTR) node->nod_arg[e_mod_org_stream];
|
||||
USHORT new_stream = (USHORT)(IPTR) node->nod_arg[e_mod_new_stream];
|
||||
|
||||
CompilerScratch::csb_repeat* tail = &csb->csb_rpt[new_stream];
|
||||
tail->csb_flags |= csb_modify;
|
||||
|
||||
jrd_rel* relation = csb->csb_rpt[stream].csb_relation;
|
||||
view = (relation->rel_view_rse) ? relation : view;
|
||||
if (!parent) {
|
||||
parent = tail->csb_view;
|
||||
}
|
||||
|
||||
post_trigger_access(csb, relation, ExternalAccess::exa_update, view);
|
||||
|
||||
// Check out update. If this is an update thru a view, verify the
|
||||
// view by checking for read access on the base table. If field-level select
|
||||
// privileges are implemented, this needs to be enhanced.
|
||||
|
||||
SecurityClass::flags_t priv = SCL_sql_update;
|
||||
if (parent) {
|
||||
priv |= SCL_read;
|
||||
}
|
||||
|
||||
const trig_vec* trigger = (relation->rel_pre_modify) ?
|
||||
relation->rel_pre_modify : relation->rel_post_modify;
|
||||
|
||||
// if we have a view with triggers, let's expand it
|
||||
|
||||
if (relation->rel_view_rse && trigger)
|
||||
{
|
||||
node->nod_arg[e_mod_map_view] = pass1_expand_view(tdbb, csb, stream, new_stream, false);
|
||||
node->nod_count = MAX(node->nod_count, (USHORT) e_mod_map_view + 1);
|
||||
}
|
||||
|
||||
// get the source relation, either a table or yet another view
|
||||
|
||||
RelationSourceNode* source = pass1_update(tdbb, csb, relation, trigger, stream,
|
||||
new_stream, priv, parent, parent_stream);
|
||||
|
||||
if (!source)
|
||||
{
|
||||
// no source means we're done
|
||||
|
||||
if (!relation->rel_view_rse)
|
||||
{
|
||||
// apply validation constraints
|
||||
|
||||
if ( (node->nod_arg[e_mod_validate] = make_validation(tdbb, csb, new_stream)) )
|
||||
node->nod_count = MAX(node->nod_count, (USHORT) e_mod_validate + 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
parent = relation;
|
||||
parent_stream = stream;
|
||||
|
||||
// remap the source stream
|
||||
|
||||
UCHAR* map = csb->csb_rpt[stream].csb_map;
|
||||
|
||||
stream = source->getStream();
|
||||
stream = map[stream];
|
||||
|
||||
// copy the view source
|
||||
|
||||
map = CMP_alloc_map(tdbb, csb, (SSHORT)(IPTR) node->nod_arg[e_mod_new_stream]);
|
||||
NodeCopier copier(csb, map);
|
||||
source = source->copy(tdbb, copier);
|
||||
|
||||
if (trigger)
|
||||
{
|
||||
// set up the new target stream
|
||||
|
||||
const USHORT view_stream = new_stream;
|
||||
new_stream = source->getStream();
|
||||
fb_assert(new_stream <= MAX_STREAMS);
|
||||
map[view_stream] = new_stream;
|
||||
|
||||
jrd_nod* view_node = ViewNodeCopier(csb, map).copy(tdbb, node);
|
||||
view_node->nod_arg[e_mod_map_view] = NULL;
|
||||
view_node->nod_arg[e_mod_statement] =
|
||||
pass1_expand_view(tdbb, csb, view_stream, new_stream, true);
|
||||
|
||||
node->nod_arg[e_mod_sub_mod] = view_node;
|
||||
node->nod_count = MAX(node->nod_count, (USHORT) e_mod_sub_mod + 1);
|
||||
|
||||
// substitute the original update node with the newly created one
|
||||
node = view_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this relation is not actually being updated as this operation
|
||||
// goes deeper (we have a naturally updatable view)
|
||||
|
||||
csb->csb_rpt[new_stream].csb_flags &= ~csb_view_update;
|
||||
}
|
||||
|
||||
// let's reset streams to represent the mapped source and target
|
||||
node->nod_arg[e_mod_org_stream] = (jrd_nod*)(IPTR) stream;
|
||||
node->nod_arg[e_mod_new_stream] = (jrd_nod*)(IPTR) source->getStream();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool pass1_store(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p a s s 1 _ s t o r e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Process a source for a store statement. This can get a little tricky if
|
||||
* the relation is a view.
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
DEV_BLKCHK(csb, type_csb);
|
||||
DEV_BLKCHK(node, type_nod);
|
||||
|
||||
// if updateable views with triggers are involved, there
|
||||
// may be a recursive call to be ignored
|
||||
|
||||
if (node->nod_arg[e_sto_sub_store])
|
||||
return false;
|
||||
|
||||
jrd_rel* parent = NULL;
|
||||
jrd_rel* view = NULL;
|
||||
USHORT parent_stream = 0;
|
||||
|
||||
// to support nested views, loop until we hit a table or
|
||||
// a view with user-defined triggers (which means no update)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
fb_assert(node->nod_arg[e_sto_relation]->nod_type == nod_class_recsrcnode_jrd);
|
||||
RelationSourceNode* relSource = reinterpret_cast<RelationSourceNode*>(
|
||||
node->nod_arg[e_sto_relation]->nod_arg[0]);
|
||||
fb_assert(relSource->type == RelationSourceNode::TYPE);
|
||||
|
||||
const USHORT stream = relSource->getStream();
|
||||
|
||||
CompilerScratch::csb_repeat* tail = &csb->csb_rpt[stream];
|
||||
tail->csb_flags |= csb_store;
|
||||
|
||||
jrd_rel* relation = csb->csb_rpt[stream].csb_relation;
|
||||
view = (relation->rel_view_rse) ? relation : view;
|
||||
if (!parent) {
|
||||
parent = tail->csb_view;
|
||||
}
|
||||
|
||||
post_trigger_access(csb, relation, ExternalAccess::exa_insert, view);
|
||||
|
||||
const trig_vec* trigger = (relation->rel_pre_store) ?
|
||||
relation->rel_pre_store : relation->rel_post_store;
|
||||
|
||||
// Check out insert. If this is an insert thru a view, verify the
|
||||
// view by checking for read access on the base table. If field-level select
|
||||
// privileges are implemented, this needs to be enhanced.
|
||||
|
||||
SecurityClass::flags_t priv = SCL_sql_insert;
|
||||
if (parent) {
|
||||
priv |= SCL_read;
|
||||
}
|
||||
|
||||
// get the source relation, either a table or yet another view
|
||||
|
||||
relSource = pass1_update(tdbb, csb, relation, trigger, stream, stream, priv,
|
||||
parent, parent_stream);
|
||||
|
||||
if (!relSource)
|
||||
{
|
||||
CMP_post_resource(&csb->csb_resources, relation, Resource::rsc_relation, relation->rel_id);
|
||||
|
||||
if (!relation->rel_view_rse)
|
||||
{
|
||||
// apply validation constraints
|
||||
if ( (node->nod_arg[e_sto_validate] = make_validation(tdbb, csb, stream)) )
|
||||
node->nod_count = MAX(node->nod_count, (USHORT) e_sto_validate + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
parent = relation;
|
||||
parent_stream = stream;
|
||||
|
||||
UCHAR* map = CMP_alloc_map(tdbb, csb, stream);
|
||||
NodeCopier copier(csb, map);
|
||||
|
||||
if (trigger)
|
||||
{
|
||||
CMP_post_resource(&csb->csb_resources, relation, Resource::rsc_relation, relation->rel_id);
|
||||
|
||||
// set up the new target stream
|
||||
|
||||
jrd_nod* view_node = NodeCopier::copy(tdbb, csb, node, map);
|
||||
view_node->nod_arg[e_sto_sub_store] = NULL;
|
||||
|
||||
relSource = relSource->copy(tdbb, copier);
|
||||
|
||||
view_node->nod_arg[e_sto_relation] = PAR_make_node(tdbb, 1);
|
||||
view_node->nod_arg[e_sto_relation]->nod_type = nod_class_recsrcnode_jrd;
|
||||
view_node->nod_arg[e_sto_relation]->nod_count = 0;
|
||||
view_node->nod_arg[e_sto_relation]->nod_arg[0] = reinterpret_cast<jrd_nod*>(relSource);
|
||||
|
||||
const USHORT new_stream = relSource->getStream();
|
||||
view_node->nod_arg[e_sto_statement] =
|
||||
pass1_expand_view(tdbb, csb, stream, new_stream, true);
|
||||
|
||||
// dimitr: I don't think the below code is required, but time will show
|
||||
// view_node->nod_arg[e_sto_statement] =
|
||||
// NodeCopier::copy(tdbb, csb, view_node->nod_arg[e_sto_statement], NULL);
|
||||
|
||||
// bug 8150: use of blr_store2 against a view with a trigger was causing
|
||||
// the second statement to be executed, which is not desirable
|
||||
|
||||
view_node->nod_arg[e_sto_statement2] = NULL;
|
||||
|
||||
node->nod_arg[e_sto_sub_store] = view_node;
|
||||
node->nod_count = MAX(node->nod_count, (USHORT) e_sto_sub_store + 1);
|
||||
|
||||
// substitute the original update node with the newly created one
|
||||
node = view_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this relation is not actually being updated as this operation
|
||||
// goes deeper (we have a naturally updatable view)
|
||||
|
||||
csb->csb_rpt[stream].csb_flags &= ~csb_view_update;
|
||||
|
||||
relSource = relSource->copy(tdbb, copier);
|
||||
|
||||
node->nod_arg[e_sto_relation] = PAR_make_node(tdbb, 1);
|
||||
node->nod_arg[e_sto_relation]->nod_type = nod_class_recsrcnode_jrd;
|
||||
node->nod_arg[e_sto_relation]->nod_count = 0;
|
||||
node->nod_arg[e_sto_relation]->nod_arg[0] = reinterpret_cast<jrd_nod*>(relSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static RelationSourceNode* pass1_update(thread_db* tdbb, CompilerScratch* csb, jrd_rel* relation,
|
||||
RelationSourceNode* CMP_pass1_update(thread_db* tdbb, CompilerScratch* csb, jrd_rel* relation,
|
||||
const trig_vec* trigger, USHORT stream, USHORT update_stream, SecurityClass::flags_t priv,
|
||||
jrd_rel* view, USHORT view_stream)
|
||||
{
|
||||
@ -2020,22 +1412,6 @@ jrd_nod* CMP_pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node, j
|
||||
reinterpret_cast<StmtNode*>(node->nod_arg[0])->pass2Cursor(rse_node, cursor_ptr);
|
||||
break;
|
||||
|
||||
case nod_dcl_cursor:
|
||||
fb_assert(node->nod_arg[e_dcl_cur_rse]->nod_type == nod_class_recsrcnode_jrd);
|
||||
rse_node = reinterpret_cast<RseNode*>(node->nod_arg[e_dcl_cur_rse]->nod_arg[0]);
|
||||
fb_assert(rse_node->type == RseNode::TYPE);
|
||||
cursor_ptr = (Cursor**) &node->nod_arg[e_dcl_cur_cursor];
|
||||
break;
|
||||
|
||||
case nod_cursor_stmt:
|
||||
CMP_pass2(tdbb, csb, node->nod_arg[e_cursor_stmt_scroll_val], node);
|
||||
CMP_pass2(tdbb, csb, node->nod_arg[e_cursor_stmt_into], node);
|
||||
break;
|
||||
|
||||
case nod_src_info:
|
||||
node->nod_arg[e_src_info_node] = CMP_pass2(tdbb, csb, node->nod_arg[e_src_info_node], node);
|
||||
return node;
|
||||
|
||||
case nod_init_variable:
|
||||
node->nod_arg[e_init_var_info] = reinterpret_cast<jrd_nod*>(CMP_pass2_validation(tdbb,
|
||||
csb, Item(Item::TYPE_VARIABLE, (IPTR) node->nod_arg[e_init_var_id])));
|
||||
@ -2050,26 +1426,6 @@ jrd_nod* CMP_pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node, j
|
||||
|
||||
// handle sub-expressions here
|
||||
|
||||
// AB: Mark the streams involved with INSERT/UPDATE statements active.
|
||||
// So that the optimizer can use indices for eventually used sub-selects.
|
||||
if (node->nod_type == nod_modify)
|
||||
{
|
||||
stream = (USHORT)(IPTR) node->nod_arg[e_mod_org_stream];
|
||||
csb->csb_rpt[stream].csb_flags |= csb_active;
|
||||
stream = (USHORT)(IPTR) node->nod_arg[e_mod_new_stream];
|
||||
csb->csb_rpt[stream].csb_flags |= csb_active;
|
||||
}
|
||||
else if (node->nod_type == nod_store)
|
||||
{
|
||||
fb_assert(node->nod_arg[e_sto_relation]->nod_type == nod_class_recsrcnode_jrd);
|
||||
RelationSourceNode* recSource = reinterpret_cast<RelationSourceNode*>(
|
||||
node->nod_arg[e_sto_relation]->nod_arg[0]);
|
||||
fb_assert(recSource->type == RelationSourceNode::TYPE);
|
||||
|
||||
stream = recSource->getStream();
|
||||
csb->csb_rpt[stream].csb_flags |= csb_active;
|
||||
}
|
||||
|
||||
jrd_nod** ptr = node->nod_arg;
|
||||
// This "end" is used later.
|
||||
const jrd_nod* const* const end = ptr + node->nod_count;
|
||||
@ -2077,25 +1433,6 @@ jrd_nod* CMP_pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node, j
|
||||
for (; ptr < end; ptr++)
|
||||
CMP_pass2(tdbb, csb, *ptr, node);
|
||||
|
||||
// AB: Remove the previous flags
|
||||
if (node->nod_type == nod_modify)
|
||||
{
|
||||
stream = (USHORT)(IPTR) node->nod_arg[e_mod_org_stream];
|
||||
csb->csb_rpt[stream].csb_flags &= ~csb_active;
|
||||
stream = (USHORT)(IPTR) node->nod_arg[e_mod_new_stream];
|
||||
csb->csb_rpt[stream].csb_flags &= ~csb_active;
|
||||
}
|
||||
else if (node->nod_type == nod_store)
|
||||
{
|
||||
fb_assert(node->nod_arg[e_sto_relation]->nod_type == nod_class_recsrcnode_jrd);
|
||||
RelationSourceNode* recSource = reinterpret_cast<RelationSourceNode*>(
|
||||
node->nod_arg[e_sto_relation]->nod_arg[0]);
|
||||
fb_assert(recSource->type == RelationSourceNode::TYPE);
|
||||
|
||||
stream = recSource->getStream();
|
||||
csb->csb_rpt[stream].csb_flags &= ~csb_active;
|
||||
}
|
||||
|
||||
// Handle any residual work
|
||||
|
||||
switch (node->nod_type)
|
||||
@ -2108,10 +1445,6 @@ jrd_nod* CMP_pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node, j
|
||||
CMP_pass2(tdbb, csb, node->nod_arg[e_asgn_missing2], node);
|
||||
break;
|
||||
|
||||
case nod_block:
|
||||
node->nod_impure = CMP_impure(csb, sizeof(SLONG));
|
||||
break;
|
||||
|
||||
case nod_dcl_variable:
|
||||
{
|
||||
const dsc* desc = (DSC*) (node->nod_arg + e_dcl_desc);
|
||||
@ -2129,22 +1462,6 @@ jrd_nod* CMP_pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node, j
|
||||
}
|
||||
break;
|
||||
|
||||
case nod_modify:
|
||||
{
|
||||
stream = (USHORT)(IPTR) node->nod_arg[e_mod_org_stream];
|
||||
csb->csb_rpt[stream].csb_flags |= csb_update;
|
||||
const Format* format = CMP_format(tdbb, csb, stream);
|
||||
Format::fmt_desc_const_iterator desc = format->fmt_desc.begin();
|
||||
for (ULONG id = 0; id < format->fmt_count; ++id, ++desc)
|
||||
{
|
||||
if (desc->dsc_dtype) {
|
||||
SBM_SET(tdbb->getDefaultPool(), &csb->csb_rpt[stream].csb_fields, id);
|
||||
}
|
||||
}
|
||||
node->nod_impure = CMP_impure(csb, sizeof(impure_state));
|
||||
}
|
||||
break;
|
||||
|
||||
case nod_list:
|
||||
// We are using the same "node" always. The "end" was set in the middle
|
||||
// of the two huge switch() statements (this is the second).
|
||||
@ -2160,26 +1477,9 @@ jrd_nod* CMP_pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node, j
|
||||
}
|
||||
}
|
||||
}
|
||||
// FALL INTO
|
||||
|
||||
case nod_store:
|
||||
node->nod_impure = CMP_impure(csb, sizeof(impure_state));
|
||||
break;
|
||||
|
||||
case nod_erase:
|
||||
stream = (USHORT)(IPTR) node->nod_arg[e_erase_stream];
|
||||
csb->csb_rpt[stream].csb_flags |= csb_update;
|
||||
break;
|
||||
|
||||
case nod_exec_into:
|
||||
node->nod_impure = CMP_impure(csb, sizeof(ExecuteStatement));
|
||||
csb->csb_exec_sta.push(node);
|
||||
break;
|
||||
|
||||
case nod_exec_stmt:
|
||||
node->nod_impure = CMP_impure(csb, sizeof(void**));
|
||||
break;
|
||||
|
||||
case nod_class_exprnode_jrd:
|
||||
{
|
||||
ExprNode* exprNode = CMP_pass2(tdbb, csb, reinterpret_cast<ExprNode*>(node->nod_arg[0]));
|
||||
@ -2316,7 +1616,7 @@ RecordSource* CMP_post_rse(thread_db* tdbb, CompilerScratch* csb, RseNode* rse)
|
||||
}
|
||||
|
||||
|
||||
static void post_trigger_access(CompilerScratch* csb,
|
||||
void CMP_post_trigger_access(CompilerScratch* csb,
|
||||
jrd_rel* owner_relation,
|
||||
ExternalAccess::exa_act operation, jrd_rel* view)
|
||||
{
|
||||
|
@ -28,6 +28,11 @@
|
||||
// req.h includes exe.h => Jrd::CompilerScratch and Jrd::CompilerScratch::csb_repeat.
|
||||
#include "../jrd/scl.h"
|
||||
|
||||
namespace Jrd
|
||||
{
|
||||
class RelationSourceNode;
|
||||
}
|
||||
|
||||
UCHAR* CMP_alloc_map(Jrd::thread_db*, Jrd::CompilerScratch*, USHORT);
|
||||
Jrd::ValueExprNode* CMP_clone_node_opt(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::ValueExprNode*);
|
||||
Jrd::BoolExprNode* CMP_clone_node_opt(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::BoolExprNode*);
|
||||
@ -44,12 +49,17 @@ void CMP_get_desc(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::jrd_nod*, dsc*);
|
||||
Jrd::IndexLock* CMP_get_index_lock(Jrd::thread_db*, Jrd::jrd_rel*, USHORT);
|
||||
ULONG CMP_impure(Jrd::CompilerScratch*, ULONG);
|
||||
Jrd::jrd_req* CMP_make_request(Jrd::thread_db*, Jrd::CompilerScratch*, bool);
|
||||
Jrd::jrd_nod* CMP_make_validation(Jrd::thread_db*, Jrd::CompilerScratch*, USHORT);
|
||||
void CMP_mark_variant(Jrd::CompilerScratch*, USHORT stream);
|
||||
|
||||
Jrd::ValueExprNode* CMP_pass1(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, Jrd::ValueExprNode* node);
|
||||
Jrd::BoolExprNode* CMP_pass1(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, Jrd::BoolExprNode* node);
|
||||
Jrd::jrd_nod* CMP_pass1(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, Jrd::jrd_nod* node);
|
||||
|
||||
Jrd::jrd_nod* CMP_pass1_expand_view(Jrd::thread_db*, Jrd::CompilerScratch*, USHORT, USHORT, bool);
|
||||
Jrd::RelationSourceNode* CMP_pass1_update(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::jrd_rel*,
|
||||
const Jrd::trig_vec*, USHORT, USHORT, Jrd::SecurityClass::flags_t, Jrd::jrd_rel*, USHORT);
|
||||
|
||||
Jrd::ExprNode* CMP_pass2(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, Jrd::ExprNode* node);
|
||||
Jrd::ValueExprNode* CMP_pass2(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, Jrd::ValueExprNode* node);
|
||||
Jrd::BoolExprNode* CMP_pass2(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, Jrd::BoolExprNode* node);
|
||||
@ -65,6 +75,9 @@ void CMP_post_access(Jrd::thread_db*, Jrd::CompilerScratch*, const Firebird::Met
|
||||
void CMP_post_procedure_access(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::jrd_prc*);
|
||||
void CMP_post_resource(Jrd::ResourceList*, void*, Jrd::Resource::rsc_s, USHORT);
|
||||
Jrd::RecordSource* CMP_post_rse(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::RseNode*);
|
||||
|
||||
void CMP_post_trigger_access(Jrd::CompilerScratch*, Jrd::jrd_rel*, Jrd::ExternalAccess::exa_act, Jrd::jrd_rel*);
|
||||
|
||||
void CMP_release(Jrd::thread_db*, Jrd::jrd_req*);
|
||||
void CMP_shutdown_database(Jrd::thread_db*);
|
||||
|
||||
|
1815
src/jrd/exe.cpp
1815
src/jrd/exe.cpp
File diff suppressed because it is too large
Load Diff
@ -189,65 +189,17 @@ const int e_msg_format = 1;
|
||||
const int e_msg_impure_flags = 2;
|
||||
const int e_msg_length = 3;
|
||||
|
||||
const int e_sto_statement = 0;
|
||||
const int e_sto_statement2 = 1;
|
||||
const int e_sto_sub_store = 2;
|
||||
const int e_sto_validate = 3;
|
||||
const int e_sto_relation = 4;
|
||||
const int e_sto_length = 5;
|
||||
|
||||
const int e_erase_statement = 0;
|
||||
const int e_erase_sub_erase = 1;
|
||||
const int e_erase_stream = 2;
|
||||
const int e_erase_rsb = 3;
|
||||
const int e_erase_length = 4;
|
||||
|
||||
const int e_mod_statement = 0;
|
||||
const int e_mod_statement2 = 1;
|
||||
const int e_mod_sub_mod = 2;
|
||||
const int e_mod_validate = 3;
|
||||
const int e_mod_map_view = 4;
|
||||
const int e_mod_org_stream = 5;
|
||||
const int e_mod_new_stream = 6;
|
||||
const int e_mod_rsb = 7;
|
||||
const int e_mod_length = 8;
|
||||
|
||||
const int e_send_statement = 0;
|
||||
const int e_send_message = 1;
|
||||
const int e_send_length = 2;
|
||||
|
||||
const int e_asgn_from = 0;
|
||||
const int e_asgn_to = 1;
|
||||
const int e_asgn_missing = 2; // Value for comparison for missing
|
||||
const int e_asgn_missing2 = 3; // Value for substitute for missing
|
||||
const int e_asgn_length = 4;
|
||||
|
||||
const int e_lbl_statement = 0;
|
||||
const int e_lbl_label = 1;
|
||||
const int e_lbl_length = 2;
|
||||
|
||||
const int e_val_stmt = 0;
|
||||
const int e_val_boolean = 1;
|
||||
const int e_val_value = 2;
|
||||
const int e_val_length = 3;
|
||||
|
||||
// Execute stored procedure
|
||||
|
||||
const int e_esp_input_sources = 0;
|
||||
const int e_esp_input_targets = 1;
|
||||
const int e_esp_in_msg = 2;
|
||||
const int e_esp_output_sources = 3;
|
||||
const int e_esp_output_targets = 4;
|
||||
const int e_esp_out_msg = 5;
|
||||
const int e_esp_procedure = 6;
|
||||
const int e_esp_length = 7;
|
||||
|
||||
// Generate id
|
||||
|
||||
const int e_gen_value = 0;
|
||||
const int e_gen_id = 1; // Generator id (replaces e_gen_relation)
|
||||
const int e_gen_length = 2;
|
||||
|
||||
// Protection mask
|
||||
|
||||
const int e_pro_class = 0;
|
||||
@ -260,55 +212,12 @@ const int e_dcl_id = 0;
|
||||
const int e_dcl_desc = 1;
|
||||
const int e_dcl_length = (1 + sizeof (DSC) / sizeof(::Jrd::jrd_nod*)); // Room for descriptor
|
||||
|
||||
const int e_blk_action = 0;
|
||||
const int e_blk_handlers = 1;
|
||||
const int e_blk_length = 2;
|
||||
|
||||
const int e_err_action = 0;
|
||||
const int e_err_conditions = 1;
|
||||
const int e_err_length = 2;
|
||||
|
||||
const int e_dcl_cur_rse = 0;
|
||||
const int e_dcl_cur_refs = 1;
|
||||
const int e_dcl_cur_number = 2;
|
||||
const int e_dcl_cur_cursor = 3;
|
||||
const int e_dcl_cur_length = 4;
|
||||
|
||||
const int e_cursor_stmt_op = 0;
|
||||
const int e_cursor_stmt_number = 1;
|
||||
const int e_cursor_stmt_scroll_op = 2;
|
||||
const int e_cursor_stmt_scroll_val = 3;
|
||||
const int e_cursor_stmt_into = 4;
|
||||
const int e_cursor_stmt_length = 5;
|
||||
|
||||
// nod_src_info
|
||||
const int e_src_info_line = 0;
|
||||
const int e_src_info_col = 1;
|
||||
const int e_src_info_node = 2;
|
||||
const int e_src_info_length = 3;
|
||||
|
||||
// nod_init_variable
|
||||
const int e_init_var_id = 0;
|
||||
const int e_init_var_variable = 1;
|
||||
const int e_init_var_info = 2;
|
||||
const int e_init_var_length = 3;
|
||||
|
||||
// nod_exec_stmt
|
||||
const int e_exec_stmt_stmt_sql = 0;
|
||||
const int e_exec_stmt_data_src = 1;
|
||||
const int e_exec_stmt_user = 2;
|
||||
const int e_exec_stmt_password = 3;
|
||||
const int e_exec_stmt_role = 4;
|
||||
const int e_exec_stmt_proc_block = 5;
|
||||
const int e_exec_stmt_fixed_count = 6;
|
||||
|
||||
const int e_exec_stmt_extra_inputs = 0;
|
||||
const int e_exec_stmt_extra_input_names = 1;
|
||||
const int e_exec_stmt_extra_outputs = 2;
|
||||
const int e_exec_stmt_extra_tran = 3;
|
||||
const int e_exec_stmt_extra_privs = 4;
|
||||
const int e_exec_stmt_extra_count = 5;
|
||||
|
||||
// index (in nod_list) for external procedure blr
|
||||
const int e_extproc_input_message = 0;
|
||||
const int e_extproc_output_message = 1;
|
||||
@ -601,7 +510,6 @@ class CompilerScratch : public pool_alloc<type_csb>
|
||||
csb_resources(p),
|
||||
csb_dependencies(p),
|
||||
csb_fors(p),
|
||||
csb_exec_sta(p),
|
||||
csb_invariants(p),
|
||||
csb_current_nodes(p),
|
||||
csb_pool(p),
|
||||
@ -676,7 +584,6 @@ public:
|
||||
ResourceList csb_resources; // Resources (relations and indexes)
|
||||
Firebird::Array<Dependency> csb_dependencies; // objects that this statement depends upon
|
||||
Firebird::Array<const RecordSource*> csb_fors; // record sources
|
||||
Firebird::Array<jrd_nod*> csb_exec_sta; // Array of exec_into nodes
|
||||
Firebird::Array<ULONG*> csb_invariants; // stack of pointer to nodes invariant offsets
|
||||
Firebird::Array<RseOrExprNode> csb_current_nodes; // RseNode's and other invariant
|
||||
// candidates within whose scope we are
|
||||
|
@ -36,16 +36,26 @@ void EXE_assignment(Jrd::thread_db*, const Jrd::jrd_nod*);
|
||||
void EXE_assignment(Jrd::thread_db*, const Jrd::ValueExprNode*, const Jrd::ValueExprNode*);
|
||||
void EXE_assignment(Jrd::thread_db* tdbb, const Jrd::ValueExprNode* to, dsc* from_desc, bool from_null,
|
||||
const Jrd::jrd_nod* missing_node, const Jrd::jrd_nod* missing2_node);
|
||||
|
||||
void EXE_cleanup_rpb(Jrd::thread_db*, Jrd::record_param*);
|
||||
void EXE_execute_db_triggers(Jrd::thread_db*, Jrd::jrd_tra*, enum Jrd::jrd_req::req_ta);
|
||||
void EXE_execute_ddl_triggers(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction,
|
||||
bool preTriggers, int action);
|
||||
const Jrd::jrd_nod* EXE_looper(Jrd::thread_db* tdbb, Jrd::jrd_req* request,
|
||||
const Jrd::jrd_nod* in_node, bool stmtExpr = false);
|
||||
|
||||
void EXE_execute_triggers(Jrd::thread_db*, Jrd::trig_vec**, Jrd::record_param*, Jrd::record_param*,
|
||||
Jrd::jrd_req::req_ta, Jrd::StmtNode::WhichTrigger);
|
||||
|
||||
void EXE_PreModifyEraseTriggers(Jrd::thread_db*, Jrd::trig_vec**, Jrd::StmtNode::WhichTrigger,
|
||||
Jrd::record_param*, Jrd::record_param*, Jrd::jrd_req::req_ta);
|
||||
|
||||
void EXE_receive(Jrd::thread_db*, Jrd::jrd_req*, USHORT, ULONG, UCHAR*, bool = false);
|
||||
void EXE_release(Jrd::thread_db*, Jrd::jrd_req*);
|
||||
void EXE_send(Jrd::thread_db*, Jrd::jrd_req*, USHORT, ULONG, const UCHAR*);
|
||||
void EXE_start(Jrd::thread_db*, Jrd::jrd_req*, Jrd::jrd_tra*);
|
||||
void EXE_unwind(Jrd::thread_db*, Jrd::jrd_req*);
|
||||
void EXE_validate(Jrd::thread_db*, const Jrd::jrd_nod*);
|
||||
void EXE_verb_cleanup(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction);
|
||||
|
||||
namespace Jrd
|
||||
|
@ -1,252 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Access Method
|
||||
* MODULE: execute_statement.cpp
|
||||
* DESCRIPTION: Dynamic SQL statements execution
|
||||
*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Alexander Peshkoff
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2003 Alexander Peshkoff <peshkoff@mail.ru>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
* Adriano dos Santos Fernandes
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
#include "gen/iberror.h"
|
||||
|
||||
#include "../common/common.h"
|
||||
#include "../jrd/jrd.h"
|
||||
#include "../jrd/tra.h"
|
||||
#include "../common/dsc.h"
|
||||
#include "../jrd/intl.h"
|
||||
#include "../jrd/err_proto.h"
|
||||
#include "../jrd/mov_proto.h"
|
||||
#include "../jrd/evl_proto.h"
|
||||
#include "../jrd/exe_proto.h"
|
||||
#include "../jrd/intl_proto.h"
|
||||
#include "../jrd/execute_statement.h"
|
||||
#include "../dsql/dsql.h"
|
||||
#include "../common/classes/auto.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
using namespace Jrd;
|
||||
using namespace Firebird;
|
||||
using Firebird::AutoPtr;
|
||||
|
||||
|
||||
void ExecuteStatement::execute(Jrd::thread_db* tdbb, jrd_req* request, DSC* desc)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
jrd_tra* const transaction = tdbb->getTransaction();
|
||||
|
||||
if (transaction->tra_callback_count >= MAX_CALLBACKS)
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_exec_sql_max_call_exceeded));
|
||||
}
|
||||
|
||||
Firebird::string sqlStatementText;
|
||||
getString(tdbb, sqlStatementText, desc, request);
|
||||
|
||||
transaction->tra_callback_count++;
|
||||
|
||||
try
|
||||
{
|
||||
AutoPtr<PreparedStatement> stmt(attachment->prepareUserStatement(
|
||||
tdbb, transaction, sqlStatementText));
|
||||
|
||||
// Other requests appear to be incorrect in this context
|
||||
const long requests =
|
||||
(1 << DsqlCompiledStatement::TYPE_INSERT) |
|
||||
(1 << DsqlCompiledStatement::TYPE_DELETE) |
|
||||
(1 << DsqlCompiledStatement::TYPE_UPDATE) |
|
||||
(1 << DsqlCompiledStatement::TYPE_DDL) |
|
||||
(1 << DsqlCompiledStatement::TYPE_SET_GENERATOR) |
|
||||
(1 << DsqlCompiledStatement::TYPE_EXEC_PROCEDURE) |
|
||||
(1 << DsqlCompiledStatement::TYPE_EXEC_BLOCK);
|
||||
|
||||
if (!((1 << stmt->getRequest()->getStatement()->getType()) & requests))
|
||||
{
|
||||
UCharBuffer dst;
|
||||
|
||||
if (attachment->att_charset == CS_METADATA || attachment->att_charset == CS_NONE)
|
||||
dst.push((const UCHAR*) sqlStatementText.c_str(), sqlStatementText.length());
|
||||
else
|
||||
{
|
||||
CsConvert conversor(INTL_charset_lookup(tdbb, attachment->att_charset)->getStruct(),
|
||||
INTL_charset_lookup(tdbb, CS_METADATA)->getStruct());
|
||||
conversor.convert(sqlStatementText.length(),
|
||||
(const UCHAR*) sqlStatementText.c_str(), dst);
|
||||
}
|
||||
|
||||
ERR_post(Arg::Gds(isc_sqlerr) << Arg::Num(-902) <<
|
||||
Arg::Gds(isc_exec_sql_invalid_req) <<
|
||||
Arg::Str(string((const char*) dst.begin(), dst.getCount())));
|
||||
}
|
||||
|
||||
stmt->execute(tdbb, transaction);
|
||||
|
||||
fb_assert(transaction == tdbb->getTransaction());
|
||||
}
|
||||
catch (const Firebird::Exception&)
|
||||
{
|
||||
transaction->tra_callback_count--;
|
||||
throw;
|
||||
}
|
||||
|
||||
transaction->tra_callback_count--;
|
||||
}
|
||||
|
||||
|
||||
void ExecuteStatement::open(thread_db* tdbb, const jrd_nod* sql, SSHORT nVars, bool singleton)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
jrd_tra* transaction = tdbb->getTransaction();
|
||||
|
||||
if (transaction->tra_callback_count >= MAX_CALLBACKS)
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_exec_sql_max_call_exceeded));
|
||||
}
|
||||
|
||||
varCount = nVars;
|
||||
singleMode = singleton;
|
||||
|
||||
jrd_req* request = tdbb->getRequest();
|
||||
Firebird::string sqlText;
|
||||
|
||||
getString(tdbb, sqlText, EVL_expr(tdbb, request, sql->asValue()), request);
|
||||
memcpy(startOfSqlOperator, sqlText.c_str(), sizeof(startOfSqlOperator) - 1);
|
||||
startOfSqlOperator[sizeof(startOfSqlOperator) - 1] = 0;
|
||||
|
||||
transaction->tra_callback_count++;
|
||||
|
||||
try
|
||||
{
|
||||
stmt = attachment->prepareUserStatement(tdbb, transaction, sqlText);
|
||||
|
||||
if (stmt->getResultCount() == 0)
|
||||
{
|
||||
delete stmt;
|
||||
stmt = NULL;
|
||||
|
||||
UCharBuffer dst;
|
||||
|
||||
if (attachment->att_charset == CS_METADATA || attachment->att_charset == CS_NONE)
|
||||
dst.push((const UCHAR*) startOfSqlOperator, strlen(startOfSqlOperator));
|
||||
else
|
||||
{
|
||||
CsConvert conversor(INTL_charset_lookup(tdbb, attachment->att_charset)->getStruct(),
|
||||
INTL_charset_lookup(tdbb, CS_METADATA)->getStruct());
|
||||
conversor.convert(strlen(startOfSqlOperator),
|
||||
(const UCHAR*) startOfSqlOperator, dst);
|
||||
}
|
||||
|
||||
ERR_post(Arg::Gds(isc_exec_sql_invalid_req) <<
|
||||
Arg::Str(string((const char*) dst.begin(), dst.getCount())));
|
||||
}
|
||||
|
||||
if (stmt->getResultCount() != varCount)
|
||||
{
|
||||
delete stmt;
|
||||
stmt = NULL;
|
||||
|
||||
ERR_post(Arg::Gds(isc_wronumarg));
|
||||
}
|
||||
|
||||
resultSet = stmt->executeQuery(tdbb, transaction);
|
||||
|
||||
fb_assert(transaction == tdbb->getTransaction());
|
||||
}
|
||||
catch (const Firebird::Exception&)
|
||||
{
|
||||
transaction->tra_callback_count--;
|
||||
throw;
|
||||
}
|
||||
|
||||
transaction->tra_callback_count--;
|
||||
}
|
||||
|
||||
|
||||
bool ExecuteStatement::fetch(thread_db* tdbb, const jrd_nod* const* jrdVar)
|
||||
{
|
||||
if (!resultSet->fetch(tdbb))
|
||||
{
|
||||
delete resultSet;
|
||||
resultSet = NULL;
|
||||
delete stmt;
|
||||
stmt = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < varCount; i++)
|
||||
{
|
||||
dsc& desc = resultSet->getDesc(i + 1);
|
||||
bool nullFlag = resultSet->isNull(i + 1);
|
||||
EXE_assignment(tdbb, jrdVar[i]->asValue(), &desc, nullFlag, NULL, NULL);
|
||||
}
|
||||
|
||||
if (singleMode)
|
||||
{
|
||||
if (!resultSet->fetch(tdbb))
|
||||
{
|
||||
delete resultSet;
|
||||
resultSet = NULL;
|
||||
delete stmt;
|
||||
stmt = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
ERR_post(Arg::Gds(isc_sing_select_err));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ExecuteStatement::close(thread_db* /*tdbb*/)
|
||||
{
|
||||
delete resultSet;
|
||||
resultSet = NULL;
|
||||
delete stmt;
|
||||
stmt = NULL;
|
||||
}
|
||||
|
||||
|
||||
void ExecuteStatement::getString(thread_db* tdbb,
|
||||
Firebird::string& sql,
|
||||
const dsc* desc,
|
||||
const jrd_req* request)
|
||||
{
|
||||
MoveBuffer buffer;
|
||||
|
||||
UCHAR* ptr = NULL;
|
||||
|
||||
const SSHORT len = (desc && !(request->req_flags & req_null)) ?
|
||||
MOV_make_string2(tdbb, desc, desc->getTextType(), &ptr, buffer) : 0; // !!! How call Msgs ?
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_exec_sql_invalid_arg));
|
||||
}
|
||||
|
||||
sql.assign((const char*) ptr, len);
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Access Method
|
||||
* MODULE: execute_statement.h
|
||||
* DESCRIPTION: Dynamic SQL statements execution
|
||||
*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Alexander Peshkoff
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2003 Alexander Peshkoff <peshkoff@mail.ru>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
* Adriano dos Santos Fernandes
|
||||
*/
|
||||
|
||||
#ifndef JRD_EXECUTE_STATEMENT_H
|
||||
#define JRD_EXECUTE_STATEMENT_H
|
||||
|
||||
#include "../include/fb_blk.h"
|
||||
#include "../jrd/PreparedStatement.h"
|
||||
#include "../jrd/ResultSet.h"
|
||||
#include "../jrd/exe.h"
|
||||
#include "../jrd/ibase.h"
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
|
||||
class ExecuteStatement
|
||||
{
|
||||
public:
|
||||
static void execute(Jrd::thread_db* tdbb, Jrd::jrd_req* request, DSC* desc);
|
||||
void open(Jrd::thread_db* tdbb, const Jrd::jrd_nod* sql, SSHORT nVars, bool singleton);
|
||||
bool fetch(Jrd::thread_db* tdbb, const Jrd::jrd_nod* const* jrdVar);
|
||||
void close(Jrd::thread_db* tdbb);
|
||||
|
||||
static void getString(Jrd::thread_db* tdbb, Firebird::string& sql, const dsc* desc,
|
||||
const Jrd::jrd_req* request);
|
||||
|
||||
private:
|
||||
PreparedStatement* stmt;
|
||||
ResultSet* resultSet;
|
||||
int varCount;
|
||||
bool singleMode;
|
||||
TEXT startOfSqlOperator[32];
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // JRD_EXECUTE_STATEMENT_H
|
@ -29,6 +29,7 @@
|
||||
#include "iberror.h"
|
||||
|
||||
#include "../../dsql/chars.h"
|
||||
#include "../../dsql/ExprNodes.h"
|
||||
#include "../common/dsc.h"
|
||||
#include "../exe.h"
|
||||
#include "ExtDS.h"
|
||||
@ -838,22 +839,22 @@ void Statement::prepare(thread_db* tdbb, Transaction* tran, const string& sql, b
|
||||
m_preparedByReq = m_callerPrivileges ? tdbb->getRequest() : NULL;
|
||||
}
|
||||
|
||||
void Statement::execute(thread_db* tdbb, Transaction* tran, int in_count,
|
||||
const string* const* in_names, const jrd_nod* const* in_params, int out_count,
|
||||
const jrd_nod* const* out_params)
|
||||
void Statement::execute(thread_db* tdbb, Transaction* tran,
|
||||
const string* const* in_names, const ValueListNode* in_params,
|
||||
const ValueListNode* out_params)
|
||||
{
|
||||
fb_assert(isAllocated() && !m_stmt_selectable);
|
||||
fb_assert(!m_error);
|
||||
fb_assert(!m_active);
|
||||
|
||||
m_transaction = tran;
|
||||
setInParams(tdbb, in_count, in_names, in_params);
|
||||
setInParams(tdbb, in_names, in_params);
|
||||
doExecute(tdbb);
|
||||
getOutParams(tdbb, out_count, out_params);
|
||||
getOutParams(tdbb, out_params);
|
||||
}
|
||||
|
||||
void Statement::open(thread_db* tdbb, Transaction* tran, int in_count,
|
||||
const string* const* in_names, const jrd_nod* const* in_params, bool singleton)
|
||||
void Statement::open(thread_db* tdbb, Transaction* tran,
|
||||
const string* const* in_names, const ValueListNode* in_params, bool singleton)
|
||||
{
|
||||
fb_assert(isAllocated() && m_stmt_selectable);
|
||||
fb_assert(!m_error);
|
||||
@ -862,12 +863,12 @@ void Statement::open(thread_db* tdbb, Transaction* tran, int in_count,
|
||||
m_singleton = singleton;
|
||||
m_transaction = tran;
|
||||
|
||||
setInParams(tdbb, in_count, in_names, in_params);
|
||||
setInParams(tdbb, in_names, in_params);
|
||||
doOpen(tdbb);
|
||||
m_active = true;
|
||||
}
|
||||
|
||||
bool Statement::fetch(thread_db* tdbb, int out_count, const jrd_nod* const* out_params)
|
||||
bool Statement::fetch(thread_db* tdbb, const ValueListNode* out_params)
|
||||
{
|
||||
fb_assert(isAllocated() && m_stmt_selectable);
|
||||
fb_assert(!m_error);
|
||||
@ -876,7 +877,7 @@ bool Statement::fetch(thread_db* tdbb, int out_count, const jrd_nod* const* out_
|
||||
if (!doFetch(tdbb))
|
||||
return false;
|
||||
|
||||
getOutParams(tdbb, out_count, out_params);
|
||||
getOutParams(tdbb, out_params);
|
||||
|
||||
if (m_singleton)
|
||||
{
|
||||
@ -1221,10 +1222,12 @@ void Statement::preprocess(const string& sql, string& ret)
|
||||
return;
|
||||
}
|
||||
|
||||
void Statement::setInParams(thread_db* tdbb, int count, const string* const* names,
|
||||
const jrd_nod* const* params)
|
||||
void Statement::setInParams(thread_db* tdbb, const string* const* names,
|
||||
const ValueListNode* params)
|
||||
{
|
||||
m_error = (names && ((int) m_sqlParamNames.getCount() != count || !count)) ||
|
||||
size_t count = params ? params->args.getCount() : 0;
|
||||
|
||||
m_error = (names && ((int) m_sqlParamNames.getCount() != count || count == 0)) ||
|
||||
(!names && m_sqlParamNames.getCount());
|
||||
|
||||
if (m_error)
|
||||
@ -1236,8 +1239,9 @@ void Statement::setInParams(thread_db* tdbb, int count, const string* const* nam
|
||||
if (m_sqlParamNames.getCount())
|
||||
{
|
||||
const int sqlCount = m_sqlParamsMap.getCount();
|
||||
Array<const jrd_nod*> sqlParamsArray(getPool(), 16);
|
||||
const jrd_nod** sqlParams = sqlParamsArray.getBuffer(sqlCount);
|
||||
// Here NestConst plays against its objective. It temporary unconstifies the values.
|
||||
Array<NestConst<ValueExprNode> > sqlParamsArray(getPool(), 16);
|
||||
NestConst<ValueExprNode>* sqlParams = sqlParamsArray.getBuffer(sqlCount);
|
||||
|
||||
for (int sqlNum = 0; sqlNum < sqlCount; sqlNum++)
|
||||
{
|
||||
@ -1256,19 +1260,17 @@ void Statement::setInParams(thread_db* tdbb, int count, const string* const* nam
|
||||
status_exception::raise(Arg::Gds(isc_eds_input_prm_not_set) << Arg::Str(*sqlName));
|
||||
}
|
||||
|
||||
sqlParams[sqlNum] = params[num];
|
||||
sqlParams[sqlNum] = params->args[num];
|
||||
}
|
||||
|
||||
doSetInParams(tdbb, sqlCount, m_sqlParamsMap.begin(), sqlParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
doSetInParams(tdbb, count, names, params);
|
||||
}
|
||||
doSetInParams(tdbb, count, names, (params ? params->args.begin() : NULL));
|
||||
}
|
||||
|
||||
void Statement::doSetInParams(thread_db* tdbb, int count, const string* const* /*names*/,
|
||||
const jrd_nod* const* params)
|
||||
const NestConst<ValueExprNode>* params)
|
||||
{
|
||||
if (count != getInputs())
|
||||
{
|
||||
@ -1280,12 +1282,12 @@ void Statement::doSetInParams(thread_db* tdbb, int count, const string* const* /
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
const jrd_nod* const* jrdVar = params;
|
||||
GenericMap<Pair<NonPooled<const jrd_nod*, dsc*> > > paramDescs(getPool());
|
||||
const NestConst<ValueExprNode>* jrdVar = params;
|
||||
GenericMap<Pair<NonPooled<const ValueExprNode*, dsc*> > > paramDescs(getPool());
|
||||
|
||||
jrd_req* request = tdbb->getRequest();
|
||||
|
||||
for (int i = 0; i < count; i++, jrdVar++)
|
||||
for (size_t i = 0; i < count; ++i, ++jrdVar)
|
||||
{
|
||||
dsc* src = NULL;
|
||||
dsc& dst = m_inDescs[i * 2];
|
||||
@ -1293,7 +1295,7 @@ void Statement::doSetInParams(thread_db* tdbb, int count, const string* const* /
|
||||
|
||||
if (!paramDescs.get(*jrdVar, src))
|
||||
{
|
||||
src = EVL_expr(tdbb, request, (*jrdVar)->asValue());
|
||||
src = EVL_expr(tdbb, request, *jrdVar);
|
||||
paramDescs.put(*jrdVar, src);
|
||||
|
||||
if (src)
|
||||
@ -1340,8 +1342,10 @@ void Statement::doSetInParams(thread_db* tdbb, int count, const string* const* /
|
||||
|
||||
|
||||
// m_outDescs -> jrd_nod
|
||||
void Statement::getOutParams(thread_db* tdbb, int count, const jrd_nod* const* params)
|
||||
void Statement::getOutParams(thread_db* tdbb, const ValueListNode* params)
|
||||
{
|
||||
size_t count = params ? params->args.getCount() : 0;
|
||||
|
||||
if (count != getOutputs())
|
||||
{
|
||||
m_error = true;
|
||||
@ -1352,11 +1356,12 @@ void Statement::getOutParams(thread_db* tdbb, int count, const jrd_nod* const* p
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
const jrd_nod* const* jrdVar = params;
|
||||
for (int i = 0; i < count; i++, jrdVar++)
|
||||
const NestConst<ValueExprNode>* jrdVar = params->args.begin();
|
||||
|
||||
for (size_t i = 0; i < count; ++i, ++jrdVar)
|
||||
{
|
||||
/*
|
||||
dsc* d = EVL_assign_to(tdbb, (*jrdVar)->asValue());
|
||||
dsc* d = EVL_assign_to(tdbb, *jrdVar);
|
||||
if (d->dsc_dtype >= FB_NELEM(sqlType) || sqlType[d->dsc_dtype] < 0)
|
||||
{
|
||||
m_error = true;
|
||||
@ -1382,7 +1387,7 @@ void Statement::getOutParams(thread_db* tdbb, int count, const jrd_nod* const* p
|
||||
}
|
||||
|
||||
// and assign to the target
|
||||
EXE_assignment(tdbb, (*jrdVar)->asValue(), local, srcNull, NULL, NULL);
|
||||
EXE_assignment(tdbb, *jrdVar, local, srcNull, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ namespace Jrd
|
||||
class jrd_nod;
|
||||
class jrd_tra;
|
||||
class thread_db;
|
||||
class ValueListNode;
|
||||
}
|
||||
|
||||
namespace EDS {
|
||||
@ -315,12 +316,12 @@ public:
|
||||
Transaction* getTransaction() { return m_transaction; }
|
||||
|
||||
void prepare(Jrd::thread_db* tdbb, Transaction* tran, const Firebird::string& sql, bool named);
|
||||
void execute(Jrd::thread_db* tdbb, Transaction* tran, int in_count,
|
||||
const Firebird::string* const* in_names, const Jrd::jrd_nod* const* in_params,
|
||||
int out_count, const Jrd::jrd_nod* const* out_params);
|
||||
void open(Jrd::thread_db* tdbb, Transaction* tran, int in_count,
|
||||
const Firebird::string* const* in_names, const Jrd::jrd_nod* const* in_params, bool singleton);
|
||||
bool fetch(Jrd::thread_db* tdbb, int out_count, const Jrd::jrd_nod* const* out_params);
|
||||
void execute(Jrd::thread_db* tdbb, Transaction* tran,
|
||||
const Firebird::string* const* in_names, const Jrd::ValueListNode* in_params,
|
||||
const Jrd::ValueListNode* out_params);
|
||||
void open(Jrd::thread_db* tdbb, Transaction* tran,
|
||||
const Firebird::string* const* in_names, const Jrd::ValueListNode* in_params, bool singleton);
|
||||
bool fetch(Jrd::thread_db* tdbb, const Jrd::ValueListNode* out_params);
|
||||
void close(Jrd::thread_db* tdbb);
|
||||
void deallocate(Jrd::thread_db* tdbb);
|
||||
|
||||
@ -356,12 +357,12 @@ protected:
|
||||
virtual bool doFetch(Jrd::thread_db* tdbb) = 0;
|
||||
virtual void doClose(Jrd::thread_db* tdbb, bool drop) = 0;
|
||||
|
||||
void setInParams(Jrd::thread_db* tdbb, int count, const Firebird::string* const* names,
|
||||
const Jrd::jrd_nod* const* params);
|
||||
virtual void getOutParams(Jrd::thread_db* tdbb, int count, const Jrd::jrd_nod* const* params);
|
||||
void setInParams(Jrd::thread_db* tdbb, const Firebird::string* const* names,
|
||||
const Jrd::ValueListNode* params);
|
||||
virtual void getOutParams(Jrd::thread_db* tdbb, const Jrd::ValueListNode* params);
|
||||
|
||||
virtual void doSetInParams(Jrd::thread_db* tdbb, int count, const Firebird::string* const* names,
|
||||
const Jrd::jrd_nod* const* params);
|
||||
const NestConst<Jrd::ValueExprNode>* params);
|
||||
|
||||
virtual void putExtBlob(Jrd::thread_db* tdbb, dsc& src, dsc& dst);
|
||||
virtual void getExtBlob(Jrd::thread_db* tdbb, const dsc& src, dsc& dst);
|
||||
|
@ -515,7 +515,8 @@ void IscStatement::doClose(thread_db* tdbb, bool drop)
|
||||
}
|
||||
}
|
||||
|
||||
void IscStatement::doSetInParams(thread_db* tdbb, int count, const string* const* names, jrd_nod** params)
|
||||
void IscStatement::doSetInParams(thread_db* tdbb, int count, const string* const* names,
|
||||
const NestConst<Jrd::ValueExprNode>* params)
|
||||
{
|
||||
Statement::doSetInParams(tdbb, count, names, params);
|
||||
|
||||
|
@ -579,7 +579,7 @@ protected:
|
||||
virtual void doClose(Jrd::thread_db* tdbb, bool drop);
|
||||
|
||||
virtual void doSetInParams(Jrd::thread_db* tdbb, int count, const Firebird::string* const* names,
|
||||
Jrd::jrd_nod** params);
|
||||
const NestConst<Jrd::ValueExprNode>* params);
|
||||
|
||||
IscTransaction* getIscTransaction() { return (IscTransaction*) m_transaction; }
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "../jrd/scl.h"
|
||||
#include "../jrd/lck.h"
|
||||
#include "../jrd/cch.h"
|
||||
#include "../dsql/StmtNodes.h"
|
||||
#include "../jrd/license.h"
|
||||
#include "../jrd/cch_proto.h"
|
||||
#include "../jrd/inf_proto.h"
|
||||
@ -993,7 +994,8 @@ void INF_request_info(const jrd_req* request,
|
||||
else if (request->req_operation == jrd_req::req_receive)
|
||||
{
|
||||
const jrd_nod* node = request->req_next;
|
||||
if (node->nod_type == nod_select)
|
||||
|
||||
if (StmtNode::is<SelectNode>(node))
|
||||
state = isc_info_req_select;
|
||||
else
|
||||
state = isc_info_req_receive;
|
||||
|
@ -28,35 +28,10 @@ NODE(nod_validate, validate, "")
|
||||
|
||||
NODE(nod_assignment, assignment, "")
|
||||
NODE(nod_dcl_variable, declare, "")
|
||||
NODE(nod_erase, erase, "")
|
||||
NODE(nod_handler, handler, "")
|
||||
NODE(nod_label, label, "")
|
||||
NODE(nod_leave, leave, "")
|
||||
NODE(nod_list, list, "")
|
||||
NODE(nod_loop, loop, "")
|
||||
NODE(nod_message, message, "")
|
||||
NODE(nod_modify, modify, "")
|
||||
NODE(nod_receive, receive, "")
|
||||
NODE(nod_select, select, "")
|
||||
NODE(nod_store, store, "")
|
||||
NODE(nod_exec_proc, exec_proc, "")
|
||||
NODE(nod_block, block, "")
|
||||
NODE(nod_error_handler, error_handler, "")
|
||||
NODE(nod_start_savepoint, start_savepoint, "")
|
||||
NODE(nod_end_savepoint, end_savepoint, "")
|
||||
NODE(nod_stall, stall, "SERVER STALL")
|
||||
NODE(nod_exec_sql, exec_sql, "EXECUTE STATEMENT")
|
||||
NODE(nod_exec_into, exec_sql_into, "EXECUTE VARCHAR INTO")
|
||||
NODE(nod_exec_stmt, exec_stmt, "EXECUTE STATEMENT")
|
||||
NODE(nod_dcl_cursor, declare_cursor, "DECLARE CURSOR")
|
||||
NODE(nod_cursor_stmt, cursor_stmt, "CURSOR STATEMENT")
|
||||
NODE(nod_continue_loop, continue_loop, "")
|
||||
NODE(nod_src_info, source_info, "")
|
||||
NODE(nod_init_variable, init_variable, "")
|
||||
|
||||
NODE(nod_set_generator, set_generator, "")
|
||||
NODE(nod_set_generator2, set_generator, "")
|
||||
|
||||
NODE(nod_class_exprnode_jrd, class_exprnode_jrd, "class_exprnode_jrd")
|
||||
NODE(nod_class_stmtnode_jrd, class_stmtnode_jrd, "class_stmtnode_jrd")
|
||||
NODE(nod_class_recsrcnode_jrd, class_recsrcnode_jrd, "class_recsrcnode_jrd")
|
||||
|
535
src/jrd/par.cpp
535
src/jrd/par.cpp
@ -87,13 +87,9 @@ static NodeParseFunc blr_parsers[256] = {NULL}; // TODO: separate statements and
|
||||
static BoolExprNodeParseFunc boolParsers[256] = {NULL};
|
||||
|
||||
|
||||
static PsqlException* par_conditions(thread_db*, CompilerScratch*);
|
||||
static jrd_nod* par_exec_proc(thread_db*, CompilerScratch*, SSHORT);
|
||||
static jrd_nod* par_fetch(thread_db*, CompilerScratch*, jrd_nod*);
|
||||
static jrd_nod* par_message(thread_db*, CompilerScratch*);
|
||||
static jrd_nod* par_modify(thread_db*, CompilerScratch*, SSHORT);
|
||||
static PlanNode* par_plan(thread_db*, CompilerScratch*);
|
||||
static RecordSourceNode* parseRecordSource(thread_db* tdbb, CompilerScratch* csb);
|
||||
|
||||
|
||||
// Parse blr, returning a compiler scratch block with the results.
|
||||
@ -914,81 +910,6 @@ ValueListNode* PAR_args(thread_db* tdbb, CompilerScratch* csb)
|
||||
}
|
||||
|
||||
|
||||
static PsqlException* par_conditions(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p a r _ c o n d i t i o n s
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Parse an error conditions list.
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
// allocate a node to represent the conditions list
|
||||
|
||||
const USHORT n = csb->csb_blr_reader.getWord();
|
||||
PsqlException* exception_list = FB_NEW_RPT(*tdbb->getDefaultPool(), n) PsqlException();
|
||||
exception_list->xcp_count = n;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
const USHORT code_type = csb->csb_blr_reader.getByte();
|
||||
xcp_repeat& item = exception_list->xcp_rpt[i];
|
||||
|
||||
switch (code_type)
|
||||
{
|
||||
case blr_sql_code:
|
||||
item.xcp_type = xcp_sql_code;
|
||||
item.xcp_code = (SSHORT) csb->csb_blr_reader.getWord();
|
||||
break;
|
||||
|
||||
case blr_gds_code:
|
||||
{
|
||||
string name;
|
||||
item.xcp_type = xcp_gds_code;
|
||||
PAR_name(csb, name);
|
||||
name.lower();
|
||||
SLONG code_number = PAR_symbol_to_gdscode(name);
|
||||
if (code_number)
|
||||
item.xcp_code = code_number;
|
||||
else
|
||||
PAR_error(csb, Arg::Gds(isc_codnotdef) << Arg::Str(name));
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_exception:
|
||||
{
|
||||
MetaName name;
|
||||
item.xcp_type = xcp_xcp_code;
|
||||
PAR_name(csb, name);
|
||||
if (!(item.xcp_code = MET_lookup_exception_number(tdbb, name)))
|
||||
PAR_error(csb, Arg::Gds(isc_xcpnotdef) << Arg::Str(name));
|
||||
|
||||
CompilerScratch::Dependency dependency(obj_exception);
|
||||
dependency.number = item.xcp_code;
|
||||
csb->csb_dependencies.push(dependency);
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_default_code:
|
||||
item.xcp_type = xcp_default;
|
||||
item.xcp_code = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
fb_assert(FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return exception_list;
|
||||
}
|
||||
|
||||
|
||||
SSHORT PAR_context(CompilerScratch* csb, SSHORT* context_ptr)
|
||||
{
|
||||
/**************************************
|
||||
@ -1078,90 +999,6 @@ void PAR_dependency(thread_db* tdbb, CompilerScratch* csb, SSHORT stream, SSHORT
|
||||
}
|
||||
|
||||
|
||||
static jrd_nod* par_exec_proc(thread_db* tdbb, CompilerScratch* csb, SSHORT blr_operator)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p a r _ e x e c _ p r o c
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Parse an execute procedure reference.
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
jrd_prc* procedure = NULL;
|
||||
QualifiedName name;
|
||||
|
||||
if (blr_operator == blr_exec_pid)
|
||||
{
|
||||
const USHORT pid = csb->csb_blr_reader.getWord();
|
||||
if (!(procedure = MET_lookup_procedure_id(tdbb, pid, false, false, 0)))
|
||||
name.identifier.printf("id %d", pid);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (blr_operator == blr_exec_proc2)
|
||||
PAR_name(csb, name.package);
|
||||
PAR_name(csb, name.identifier);
|
||||
procedure = MET_lookup_procedure(tdbb, name, false);
|
||||
}
|
||||
|
||||
if (!procedure)
|
||||
{
|
||||
PAR_error(csb, Arg::Gds(isc_prcnotdef) << Arg::Str(name.toString()));
|
||||
}
|
||||
|
||||
jrd_nod* node = PAR_make_node(tdbb, e_esp_length);
|
||||
node->nod_type = nod_exec_proc;
|
||||
node->nod_count = count_table[blr_exec_proc];
|
||||
node->nod_arg[e_esp_procedure] = (jrd_nod*) procedure;
|
||||
|
||||
NestConst<ValueListNode> inputSources, inputTargets, outputSources, outputTargets;
|
||||
|
||||
PAR_procedure_parms(tdbb, csb, procedure, &node->nod_arg[e_esp_in_msg],
|
||||
inputSources.getAddress(), inputTargets.getAddress(), true);
|
||||
PAR_procedure_parms(tdbb, csb, procedure, &node->nod_arg[e_esp_out_msg],
|
||||
outputSources.getAddress(), outputTargets.getAddress(), false);
|
||||
|
||||
jrd_nod* temp;
|
||||
|
||||
if (inputSources)
|
||||
{
|
||||
temp = node->nod_arg[e_esp_input_sources] = PAR_make_node(tdbb, 1);
|
||||
temp->nod_count = 0;
|
||||
temp->nod_type = nod_class_exprnode_jrd;
|
||||
temp->nod_arg[0] = reinterpret_cast<jrd_nod*>(inputSources.getObject());
|
||||
|
||||
temp = node->nod_arg[e_esp_input_targets] = PAR_make_node(tdbb, 1);
|
||||
temp->nod_count = 0;
|
||||
temp->nod_type = nod_class_exprnode_jrd;
|
||||
temp->nod_arg[0] = reinterpret_cast<jrd_nod*>(inputTargets.getObject());
|
||||
}
|
||||
|
||||
if (outputSources)
|
||||
{
|
||||
temp = node->nod_arg[e_esp_output_sources] = PAR_make_node(tdbb, 1);
|
||||
temp->nod_count = 0;
|
||||
temp->nod_type = nod_class_exprnode_jrd;
|
||||
temp->nod_arg[0] = reinterpret_cast<jrd_nod*>(outputSources.getObject());
|
||||
|
||||
temp = node->nod_arg[e_esp_output_targets] = PAR_make_node(tdbb, 1);
|
||||
temp->nod_count = 0;
|
||||
temp->nod_type = nod_class_exprnode_jrd;
|
||||
temp->nod_arg[0] = reinterpret_cast<jrd_nod*>(outputTargets.getObject());
|
||||
}
|
||||
|
||||
CompilerScratch::Dependency dependency(obj_procedure);
|
||||
dependency.procedure = procedure;
|
||||
csb->csb_dependencies.push(dependency);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
static jrd_nod* par_fetch(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
|
||||
{
|
||||
/**************************************
|
||||
@ -1282,62 +1119,6 @@ static jrd_nod* par_message(thread_db* tdbb, CompilerScratch* csb)
|
||||
}
|
||||
|
||||
|
||||
static jrd_nod* par_modify(thread_db* tdbb, CompilerScratch* csb, SSHORT blr_operator)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p a r _ m o d i f y
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Parse a modify statement.
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
// Parse the original and new contexts
|
||||
|
||||
USHORT context = (unsigned int) csb->csb_blr_reader.getByte();
|
||||
if (context >= csb->csb_rpt.getCount() || !(csb->csb_rpt[context].csb_flags & csb_used))
|
||||
{
|
||||
PAR_error(csb, Arg::Gds(isc_ctxnotdef));
|
||||
}
|
||||
const SSHORT org_stream = csb->csb_rpt[context].csb_stream;
|
||||
const SSHORT new_stream = csb->nextStream(false);
|
||||
if (new_stream >= MAX_STREAMS)
|
||||
{
|
||||
PAR_error(csb, Arg::Gds(isc_too_many_contexts));
|
||||
}
|
||||
context = (unsigned int) csb->csb_blr_reader.getByte();
|
||||
|
||||
// Make sure the compiler scratch block is big enough to hold everything
|
||||
|
||||
CompilerScratch::csb_repeat* tail = CMP_csb_element(csb, context);
|
||||
tail->csb_stream = (UCHAR) new_stream;
|
||||
tail->csb_flags |= csb_used;
|
||||
|
||||
tail = CMP_csb_element(csb, new_stream);
|
||||
tail->csb_relation = csb->csb_rpt[org_stream].csb_relation;
|
||||
|
||||
// Make the node and parse the sub-expression
|
||||
|
||||
jrd_nod* node = PAR_make_node(tdbb, e_mod_length);
|
||||
node->nod_count = 1;
|
||||
node->nod_arg[e_mod_org_stream] = (jrd_nod*) (IPTR) org_stream;
|
||||
node->nod_arg[e_mod_new_stream] = (jrd_nod*) (IPTR) new_stream;
|
||||
node->nod_arg[e_mod_statement] = PAR_parse_node(tdbb, csb, STATEMENT);
|
||||
|
||||
if (blr_operator == blr_modify2)
|
||||
{
|
||||
node->nod_count = 2;
|
||||
node->nod_arg[e_mod_statement2] = PAR_parse_node(tdbb, csb, STATEMENT);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
USHORT PAR_name(CompilerScratch* csb, Firebird::MetaName& name)
|
||||
{
|
||||
/**************************************
|
||||
@ -1686,7 +1467,7 @@ void PAR_procedure_parms(thread_db* tdbb, CompilerScratch* csb, jrd_prc* procedu
|
||||
|
||||
|
||||
// Parse a RecordSourceNode.
|
||||
static RecordSourceNode* parseRecordSource(thread_db* tdbb, CompilerScratch* csb)
|
||||
RecordSourceNode* PAR_parseRecordSource(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
@ -1739,7 +1520,7 @@ RseNode* PAR_rse(thread_db* tdbb, CompilerScratch* csb, SSHORT rse_op)
|
||||
RseNode* rse = FB_NEW(*tdbb->getDefaultPool()) RseNode(*tdbb->getDefaultPool());
|
||||
|
||||
while (--count >= 0)
|
||||
rse->rse_relations.add(parseRecordSource(tdbb, csb));
|
||||
rse->rse_relations.add(PAR_parseRecordSource(tdbb, csb));
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -2014,280 +1795,13 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
|
||||
{
|
||||
case blr_assignment:
|
||||
*arg++ = PAR_parse_node(tdbb, csb, sub_type);
|
||||
// Fall into ...
|
||||
|
||||
case blr_handler:
|
||||
case blr_loop:
|
||||
*arg++ = PAR_parse_node(tdbb, csb, sub_type);
|
||||
break;
|
||||
|
||||
case blr_exec_sql:
|
||||
{
|
||||
n = e_exec_stmt_fixed_count;
|
||||
|
||||
node = PAR_make_node(tdbb, n + e_exec_stmt_extra_count);
|
||||
node->nod_count = n;
|
||||
node->nod_type = nod_exec_stmt;
|
||||
set_type = false;
|
||||
|
||||
arg = node->nod_arg;
|
||||
*arg++ = PAR_parse_node(tdbb, csb, VALUE); // e_exec_stmt_stmt_sql
|
||||
*arg++ = NULL; // e_exec_stmt_data_src
|
||||
*arg++ = NULL; // e_exec_stmt_user
|
||||
*arg++ = NULL; // e_exec_stmt_password
|
||||
*arg++ = NULL; // e_exec_stmt_role;
|
||||
*arg++ = NULL; // e_exec_stmt_proc_block;
|
||||
|
||||
*arg++ = NULL; // e_exec_stmt_extra_inputs
|
||||
*arg++ = NULL; // e_exec_stmt_extra_input_names
|
||||
*arg++ = NULL; // e_exec_stmt_extra_outputs
|
||||
*arg++ = NULL; // e_exec_stmt_extra_tran
|
||||
*arg++ = NULL; // e_exec_stmt_extra_privs
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_exec_into:
|
||||
{
|
||||
const USHORT outputs = csb->csb_blr_reader.getWord();
|
||||
n = outputs + e_exec_stmt_fixed_count;
|
||||
|
||||
node = PAR_make_node(tdbb, n + e_exec_stmt_extra_count);
|
||||
node->nod_count = n;
|
||||
node->nod_type = nod_exec_stmt;
|
||||
set_type = false;
|
||||
|
||||
arg = node->nod_arg;
|
||||
*arg++ = PAR_parse_node(tdbb, csb, VALUE); // e_exec_stmt_stmt_sql
|
||||
*arg++ = NULL; // e_exec_stmt_data_src
|
||||
*arg++ = NULL; // e_exec_stmt_user
|
||||
*arg++ = NULL; // e_exec_stmt_password
|
||||
*arg++ = NULL; // e_exec_stmt_role;
|
||||
|
||||
if (csb->csb_blr_reader.getByte()) // singleton flag
|
||||
*arg++ = NULL; // e_exec_stmt_proc_block
|
||||
else
|
||||
*arg++ = PAR_parse_node(tdbb, csb, STATEMENT); // e_exec_stmt_proc_block
|
||||
|
||||
// output parameters
|
||||
for (n = e_exec_stmt_fixed_count; n < node->nod_count; n++) {
|
||||
*arg++ = PAR_parse_node(tdbb, csb, VALUE);
|
||||
}
|
||||
|
||||
*arg++ = NULL; // e_exec_stmt_extra_inputs
|
||||
*arg++ = NULL; // e_exec_stmt_extra_input_names
|
||||
*arg++ = (jrd_nod*)(IPTR) outputs; // e_exec_stmt_extra_outputs
|
||||
*arg++ = NULL; // e_exec_stmt_extra_tran
|
||||
*arg++ = NULL; // e_exec_stmt_extra_privs
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_exec_stmt:
|
||||
{
|
||||
USHORT inputs = 0;
|
||||
USHORT outputs = 0;
|
||||
UCHAR tra_mode = 0;
|
||||
int use_caller_privs = 0;
|
||||
EDS::ParamNames* paramNames = NULL;
|
||||
|
||||
while (true)
|
||||
{
|
||||
const UCHAR code = csb->csb_blr_reader.getByte();
|
||||
switch (code)
|
||||
{
|
||||
case blr_exec_stmt_inputs:
|
||||
inputs = csb->csb_blr_reader.getWord();
|
||||
break;
|
||||
|
||||
case blr_exec_stmt_outputs:
|
||||
outputs = csb->csb_blr_reader.getWord();
|
||||
break;
|
||||
|
||||
case blr_exec_stmt_sql:
|
||||
n = inputs + outputs + e_exec_stmt_fixed_count;
|
||||
|
||||
node = PAR_make_node(tdbb, n + e_exec_stmt_extra_count);
|
||||
node->nod_count = n;
|
||||
node->nod_arg[e_exec_stmt_stmt_sql] = PAR_parse_node(tdbb, csb, VALUE);
|
||||
break;
|
||||
|
||||
case blr_exec_stmt_proc_block:
|
||||
node->nod_arg[e_exec_stmt_proc_block] = PAR_parse_node(tdbb, csb, STATEMENT);
|
||||
break;
|
||||
|
||||
case blr_exec_stmt_data_src:
|
||||
node->nod_arg[e_exec_stmt_data_src] = PAR_parse_node(tdbb, csb, VALUE);
|
||||
break;
|
||||
|
||||
case blr_exec_stmt_user:
|
||||
node->nod_arg[e_exec_stmt_user] = PAR_parse_node(tdbb, csb, VALUE);
|
||||
break;
|
||||
|
||||
case blr_exec_stmt_pwd:
|
||||
node->nod_arg[e_exec_stmt_password] = PAR_parse_node(tdbb, csb, VALUE);
|
||||
break;
|
||||
|
||||
case blr_exec_stmt_role:
|
||||
node->nod_arg[e_exec_stmt_role] = PAR_parse_node(tdbb, csb, VALUE);
|
||||
break;
|
||||
|
||||
case blr_exec_stmt_tran:
|
||||
PAR_syntax_error(csb, "external transaction parameters");
|
||||
break;
|
||||
|
||||
case blr_exec_stmt_tran_clone:
|
||||
tra_mode = csb->csb_blr_reader.getByte();
|
||||
break;
|
||||
|
||||
case blr_exec_stmt_privs:
|
||||
use_caller_privs = 1;
|
||||
break;
|
||||
|
||||
case blr_exec_stmt_in_params:
|
||||
case blr_exec_stmt_in_params2:
|
||||
// input parameters and their names
|
||||
n = e_exec_stmt_fixed_count;
|
||||
arg = node->nod_arg + n;
|
||||
|
||||
for (; n < e_exec_stmt_fixed_count + inputs; n++)
|
||||
{
|
||||
if (code == blr_exec_stmt_in_params2)
|
||||
{
|
||||
Firebird::string name;
|
||||
if (PAR_name(csb, name))
|
||||
{
|
||||
Firebird::MemoryPool& pool = csb->csb_pool;
|
||||
if (!paramNames) {
|
||||
paramNames = FB_NEW (pool) EDS::ParamNames(pool);
|
||||
}
|
||||
Firebird::string* newName = FB_NEW (pool) Firebird::string(pool, name);
|
||||
paramNames->add(newName);
|
||||
}
|
||||
}
|
||||
*arg++ = PAR_parse_node(tdbb, csb, VALUE);
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_exec_stmt_out_params:
|
||||
// output parameters
|
||||
n = e_exec_stmt_fixed_count + inputs;
|
||||
arg = node->nod_arg + n;
|
||||
for (; n < node->nod_count; n++) {
|
||||
*arg++ = PAR_parse_node(tdbb, csb, VALUE);
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_end:
|
||||
break;
|
||||
|
||||
default:
|
||||
PAR_syntax_error(csb, "unknown EXECUTE STATEMENT option");
|
||||
}
|
||||
|
||||
if (code == blr_end)
|
||||
break;
|
||||
}
|
||||
|
||||
arg = node->nod_arg + node->nod_count;
|
||||
*arg++ = (jrd_nod*)(IPTR) inputs; // e_exec_stmt_extra_inputs
|
||||
*arg++ = (jrd_nod*) paramNames; // e_exec_stmt_extra_input_names
|
||||
*arg++ = (jrd_nod*)(IPTR) outputs; // e_exec_stmt_extra_outputs
|
||||
*arg++ = (jrd_nod*)(IPTR) tra_mode; // e_exec_stmt_extra_tran
|
||||
*arg++ = (jrd_nod*)(IPTR) use_caller_privs; // e_exec_stmt_extra_privs
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_start_savepoint:
|
||||
case blr_end_savepoint:
|
||||
break;
|
||||
|
||||
case blr_store:
|
||||
case blr_store2:
|
||||
node->nod_arg[e_sto_relation] = PAR_parse_node(tdbb, csb, RELATION);
|
||||
node->nod_arg[e_sto_statement] = PAR_parse_node(tdbb, csb, sub_type);
|
||||
if (blr_operator == blr_store2)
|
||||
node->nod_arg[e_sto_statement2] = PAR_parse_node(tdbb, csb, sub_type);
|
||||
break;
|
||||
|
||||
case blr_erase:
|
||||
n = csb->csb_blr_reader.getByte();
|
||||
if (n >= csb->csb_rpt.getCount() || !(csb->csb_rpt[n].csb_flags & csb_used))
|
||||
PAR_error(csb, Arg::Gds(isc_ctxnotdef));
|
||||
node->nod_arg[e_erase_stream] = (jrd_nod*) (IPTR) csb->csb_rpt[n].csb_stream;
|
||||
break;
|
||||
|
||||
case blr_modify:
|
||||
case blr_modify2:
|
||||
node = par_modify(tdbb, csb, blr_operator);
|
||||
break;
|
||||
|
||||
case blr_exec_proc:
|
||||
case blr_exec_proc2:
|
||||
case blr_exec_pid:
|
||||
node = par_exec_proc(tdbb, csb, blr_operator);
|
||||
set_type = false;
|
||||
break;
|
||||
|
||||
case blr_dcl_cursor:
|
||||
{
|
||||
node->nod_arg[e_dcl_cur_number] = (jrd_nod*) (IPTR) csb->csb_blr_reader.getWord();
|
||||
node->nod_arg[e_dcl_cur_rse] = PAR_parse_node(tdbb, csb, TYPE_RSE);
|
||||
n = csb->csb_blr_reader.getWord();
|
||||
jrd_nod* temp = PAR_make_node(tdbb, n);
|
||||
temp->nod_type = nod_list;
|
||||
for (jrd_nod** ptr = temp->nod_arg; n; n--) {
|
||||
*ptr++ = PAR_parse_node(tdbb, csb, VALUE);
|
||||
}
|
||||
node->nod_arg[e_dcl_cur_refs] = temp;
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_cursor_stmt:
|
||||
n = csb->csb_blr_reader.getByte();
|
||||
node->nod_arg[e_cursor_stmt_op] = (jrd_nod*) (IPTR) n;
|
||||
node->nod_arg[e_cursor_stmt_number] = (jrd_nod*) (IPTR) csb->csb_blr_reader.getWord();
|
||||
switch (n)
|
||||
{
|
||||
case blr_cursor_open:
|
||||
case blr_cursor_close:
|
||||
break;
|
||||
case blr_cursor_fetch_scroll:
|
||||
node->nod_arg[e_cursor_stmt_scroll_op] = (jrd_nod*)(IPTR) csb->csb_blr_reader.getByte();
|
||||
node->nod_arg[e_cursor_stmt_scroll_val] = PAR_parse_node(tdbb, csb, VALUE);
|
||||
// FALL INTO
|
||||
case blr_cursor_fetch:
|
||||
csb->csb_g_flags |= csb_reuse_context;
|
||||
node->nod_arg[e_cursor_stmt_into] = PAR_parse_node(tdbb, csb, STATEMENT);
|
||||
csb->csb_g_flags &= ~csb_reuse_context;
|
||||
break;
|
||||
default:
|
||||
PAR_syntax_error(csb, "cursor operation clause");
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_set_generator:
|
||||
{
|
||||
Firebird::MetaName name;
|
||||
PAR_name(csb, name);
|
||||
|
||||
const SLONG tmp = MET_lookup_generator(tdbb, name.c_str());
|
||||
if (tmp < 0)
|
||||
PAR_error(csb, Arg::Gds(isc_gennotdef) << Arg::Str(name));
|
||||
|
||||
node->nod_arg[e_gen_id] = (jrd_nod*)(IPTR) tmp;
|
||||
node->nod_arg[e_gen_value] = PAR_parse_node(tdbb, csb, VALUE);
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_fetch:
|
||||
par_fetch(tdbb, csb, node);
|
||||
break;
|
||||
|
||||
case blr_receive:
|
||||
n = csb->csb_blr_reader.getByte();
|
||||
node->nod_arg[e_send_message] = csb->csb_rpt[n].csb_message;
|
||||
node->nod_arg[e_send_statement] = PAR_parse_node(tdbb, csb, sub_type);
|
||||
break;
|
||||
|
||||
case blr_message:
|
||||
node = par_message(tdbb, csb);
|
||||
break;
|
||||
@ -2319,10 +1833,6 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_stall:
|
||||
break;
|
||||
|
||||
case blr_select:
|
||||
case blr_begin:
|
||||
{
|
||||
NodeStack stack;
|
||||
@ -2338,35 +1848,6 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_block:
|
||||
{
|
||||
NodeStack stack;
|
||||
|
||||
node->nod_arg[e_blk_action] = PAR_parse_node(tdbb, csb, sub_type);
|
||||
while (csb->csb_blr_reader.peekByte() != (UCHAR) blr_end)
|
||||
{
|
||||
stack.push(PAR_parse_node(tdbb, csb, sub_type));
|
||||
}
|
||||
csb->csb_blr_reader.getByte(); // skip blr_end
|
||||
node->nod_arg[e_blk_handlers] = PAR_make_list(tdbb, stack);
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_error_handler:
|
||||
node->nod_arg[e_err_conditions] = (jrd_nod*) par_conditions(tdbb, csb);
|
||||
node->nod_arg[e_err_action] = PAR_parse_node(tdbb, csb, sub_type);
|
||||
break;
|
||||
|
||||
case blr_label:
|
||||
node->nod_arg[e_lbl_label] = (jrd_nod*) (IPTR) csb->csb_blr_reader.getByte();
|
||||
node->nod_arg[e_lbl_statement] = PAR_parse_node(tdbb, csb, sub_type);
|
||||
break;
|
||||
|
||||
case blr_leave:
|
||||
case blr_continue_loop:
|
||||
node->nod_arg[0] = (jrd_nod*)(IPTR) csb->csb_blr_reader.getByte();
|
||||
break;
|
||||
|
||||
case blr_init_variable:
|
||||
{
|
||||
n = csb->csb_blr_reader.getWord();
|
||||
@ -2400,7 +1881,7 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
|
||||
case blr_window:
|
||||
case blr_aggregate:
|
||||
csb->csb_blr_reader.seekBackward(1);
|
||||
node->nod_arg[0] = reinterpret_cast<jrd_nod*>(parseRecordSource(tdbb, csb));
|
||||
node->nod_arg[0] = reinterpret_cast<jrd_nod*>(PAR_parseRecordSource(tdbb, csb));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2433,12 +1914,12 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
|
||||
if (csb->csb_dbg_info.blrToSrc.find(blr_offset, pos))
|
||||
{
|
||||
Firebird::MapBlrToSrcItem& i = csb->csb_dbg_info.blrToSrc[pos];
|
||||
jrd_nod* node_src = PAR_make_node(tdbb, e_src_info_length);
|
||||
|
||||
node_src->nod_type = nod_src_info;
|
||||
node_src->nod_arg[e_src_info_line] = (jrd_nod*) (IPTR) i.mbs_src_line;
|
||||
node_src->nod_arg[e_src_info_col] = (jrd_nod*) (IPTR) i.mbs_src_col;
|
||||
node_src->nod_arg[e_src_info_node] = node;
|
||||
jrd_nod* node_src = PAR_make_node(tdbb, 1);
|
||||
node_src->nod_type = nod_class_stmtnode_jrd;
|
||||
node_src->nod_count = 0;
|
||||
node_src->nod_arg[0] = reinterpret_cast<jrd_nod*>(FB_NEW(*tdbb->getDefaultPool())
|
||||
SourceInfoNode(*tdbb->getDefaultPool(), node, i.mbs_src_line, i.mbs_src_col));
|
||||
|
||||
return node_src;
|
||||
}
|
||||
|
@ -72,6 +72,8 @@ USHORT PAR_name(Jrd::CompilerScratch*, Firebird::MetaName&);
|
||||
size_t PAR_name(Jrd::CompilerScratch* csb, Firebird::string& name);
|
||||
Jrd::CompilerScratch* PAR_parse(Jrd::thread_db*, const UCHAR* blr, ULONG blr_length,
|
||||
bool internal_flag, USHORT = 0, const UCHAR* = NULL);
|
||||
|
||||
Jrd::RecordSourceNode* PAR_parseRecordSource(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb);
|
||||
void PAR_procedure_parms(Jrd::thread_db*, Jrd::CompilerScratch*, Jrd::jrd_prc*,
|
||||
Jrd::jrd_nod**, Jrd::ValueListNode**, Jrd::ValueListNode**, bool input_flag);
|
||||
Jrd::RseNode* PAR_rse(Jrd::thread_db*, Jrd::CompilerScratch*, SSHORT);
|
||||
|
@ -53,10 +53,6 @@ enum {
|
||||
{ blr, #internal, 0, #length, #count, \
|
||||
#type, #sub_type }
|
||||
|
||||
#define PAIR2(internal, blr, length, count, type, sub_type) \
|
||||
{ blr, #internal, STRINGIZER(internal##2), #length, #count, \
|
||||
#type, #sub_type }
|
||||
|
||||
static void print(const SCHAR **, int, const SCHAR *);
|
||||
|
||||
struct VERB
|
||||
@ -73,30 +69,30 @@ struct VERB
|
||||
static const VERB verbs[] =
|
||||
{
|
||||
PAIR(nod_assignment, blr_assignment, e_asgn_length, 2, STATEMENT, VALUE),
|
||||
PAIR(nod_erase, blr_erase, e_erase_length, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_erase, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_dcl_variable, blr_dcl_variable, e_dcl_length, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_fetch, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_for, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_handler, blr_handler, 1, 1, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_handler, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_if, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_label, blr_label, e_lbl_length, 1, STATEMENT, STATEMENT),
|
||||
PAIR(nod_leave, blr_leave, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_label, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_leave, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_list, blr_begin, 0, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_loop, blr_loop, 1, 1, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_loop, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_message, blr_message, 0, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_modify, blr_modify, 0, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_modify, blr_modify2, 0, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_modify, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_modify2, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_user_savepoint, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_receive, blr_receive, e_send_length, 1, STATEMENT, STATEMENT),
|
||||
PAIR(nod_select, blr_select, 0, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_receive, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_select, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_send, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_store, blr_store, e_sto_length, e_sto_length - 1, STATEMENT, STATEMENT),
|
||||
PAIR(nod_store, blr_store2, e_sto_length, e_sto_length - 1, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_store, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_store2, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_post, 1, 0, STATEMENT, VALUE),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_post_arg, 1, 0, STATEMENT, VALUE),
|
||||
PAIR(nod_exec_sql, blr_exec_sql, 1, 1, STATEMENT, VALUE),
|
||||
PAIR(nod_exec_into, blr_exec_into, 0, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_exec_stmt, blr_exec_stmt, 0, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_exec_sql, 1, 0, STATEMENT, VALUE),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_exec_into, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_exec_stmt, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_exprnode_jrd, blr_internal_info, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_add, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_agg_count, 1, 0, VALUE, VALUE),
|
||||
@ -166,30 +162,30 @@ static const VERB verbs[] =
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_relation, 1, 0, RELATION, OTHER),
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_rid, 1, 0, RELATION, OTHER),
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_rs_stream, 1, 0, RELATION, OTHER),
|
||||
PAIR(nod_exec_proc, blr_exec_proc, e_esp_length, 6, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_exec_proc, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_procedure, 1, 0, RELATION, OTHER),
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_procedure2, 1, 0, RELATION, OTHER),
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_procedure3, 1, 0, RELATION, OTHER),
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_procedure4, 1, 0, RELATION, OTHER),
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_pid, 1, 0, RELATION, OTHER),
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_pid2, 1, 0, RELATION, OTHER),
|
||||
PAIR(nod_exec_proc, blr_exec_pid, e_esp_length, 6, STATEMENT, OTHER),
|
||||
PAIR(nod_block, blr_block, e_blk_length, e_blk_length, STATEMENT, STATEMENT),
|
||||
PAIR(nod_error_handler, blr_error_handler, e_err_length, 1, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_exec_pid, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_block, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_error_handler, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_abort, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_exprnode_jrd, blr_cast, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_singular, 0, 0, TYPE_RSE, OTHER),
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_scrollable, 0, 0, TYPE_RSE, OTHER),
|
||||
PAIR(nod_start_savepoint, blr_start_savepoint, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_end_savepoint, blr_end_savepoint, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_start_savepoint, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_end_savepoint, 1, 0, STATEMENT, OTHER),
|
||||
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_relation2, 1, 0, RELATION, OTHER),
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_rid2, 1, 0, RELATION, OTHER),
|
||||
PAIR2(nod_set_generator, blr_set_generator, e_gen_length, 1, STATEMENT, VALUE),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_set_generator, 1, 0, STATEMENT, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_ansi_any, 1, 0, TYPE_BOOL, TYPE_RSE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_exists, 1, 0, TYPE_BOOL, TYPE_RSE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_record_version, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_stall, blr_stall, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_stall, 1, 0, STATEMENT, STATEMENT),
|
||||
PAIR(nod_class_exprnode_jrd, blr_ansi_all, 1, 0, TYPE_BOOL, TYPE_RSE),
|
||||
|
||||
/* Improved Date Support */
|
||||
@ -201,8 +197,8 @@ static const VERB verbs[] =
|
||||
PAIR(nod_class_exprnode_jrd, blr_current_timestamp2, 1, 0, VALUE, OTHER),
|
||||
|
||||
PAIR(nod_class_exprnode_jrd, blr_current_role, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_dcl_cursor, blr_dcl_cursor, e_dcl_cur_length, 2, STATEMENT, OTHER),
|
||||
PAIR(nod_cursor_stmt, blr_cursor_stmt, e_cursor_stmt_length, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_dcl_cursor, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_cursor_stmt, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_exprnode_jrd, blr_lowcase, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_strlen, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_trim, 1, 0, VALUE, VALUE),
|
||||
@ -213,7 +209,7 @@ static const VERB verbs[] =
|
||||
PAIR(nod_class_exprnode_jrd, blr_stmt_expr, 1, 0, VALUE, OTHER),
|
||||
PAIR(nod_class_exprnode_jrd, blr_derived_expr, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_recsrcnode_jrd, blr_window, 1, 0, RELATION, OTHER),
|
||||
PAIR(nod_continue_loop, blr_continue_loop, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_stmtnode_jrd, blr_continue_loop, 1, 0, STATEMENT, OTHER),
|
||||
PAIR(nod_class_exprnode_jrd, blr_agg_function, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_substring_similar, 1, 0, VALUE, VALUE),
|
||||
{0, NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
|
Loading…
Reference in New Issue
Block a user