8
0
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:
asfernandes 2010-11-29 02:17:04 +00:00
parent 3f6412d359
commit 8af7ec0211
32 changed files with 4020 additions and 3621 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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"
>

View File

@ -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"
>

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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);
}

View File

@ -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)
{
}

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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*);

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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; }

View File

@ -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;

View File

@ -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")

View File

@ -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;
}

View File

@ -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);

View File

@ -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}