mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 23:23:02 +01:00
1) Created classes PreparedStatement and ResultSet
2) Changed EXECUTE STATEMENT to use these classes 3) Fixed CORE-1784 - Error with EXECUTE PROCEDURE inside EXECUTE STATEMENT
This commit is contained in:
parent
49e833de50
commit
c7ec88bee4
@ -36,8 +36,8 @@ JRD_ServerFiles= blob_filter.cpp dpm.epp dyn.epp dyn_def.epp \
|
||||
idx.cpp inf.cpp intl.cpp intl_builtin.cpp IntlManager.cpp IntlUtil.cpp \
|
||||
jrd.cpp Database.cpp lck.cpp \
|
||||
mov.cpp nav.cpp opt.cpp Optimizer.cpp pag.cpp par.cpp \
|
||||
ods.cpp plugin_manager.cpp pwd.cpp RandomGenerator.cpp Relation.cpp rlck.cpp \
|
||||
rpb_chain.cpp rse.cpp \
|
||||
ods.cpp plugin_manager.cpp pwd.cpp PreparedStatement.cpp RandomGenerator.cpp \
|
||||
Relation.cpp ResultSet.cpp rlck.cpp rpb_chain.cpp rse.cpp \
|
||||
sdw.cpp shut.cpp sort.cpp sqz.cpp \
|
||||
svc.cpp SysFunction.cpp TempSpace.cpp tpc.cpp tra.cpp validation.cpp vio.cpp \
|
||||
nodebug.cpp nbak.cpp sha.cpp $(Physical_IO_Module) TextType.cpp \
|
||||
|
@ -420,6 +420,10 @@ SOURCE=..\..\..\src\jrd\plugin_manager.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\PreparedStatement.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\pwd.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -436,6 +440,10 @@ SOURCE=..\..\..\src\jrd\Relation.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\ResultSet.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\rlck.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -1164,6 +1172,10 @@ SOURCE=..\..\..\src\jrd\pragma.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\PreparedStatement.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\prv_m_bypass.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -1200,6 +1212,10 @@ SOURCE=..\..\..\src\jrd\relations.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\ResultSet.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\req.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -411,6 +411,10 @@ SOURCE=..\..\..\src\jrd\plugin_manager.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\PreparedStatement.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\pwd.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -427,6 +431,10 @@ SOURCE=..\..\..\src\jrd\Relation.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\ResultSet.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\rlck.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -1133,6 +1141,10 @@ SOURCE=..\..\..\src\jrd\pragma.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\PreparedStatement.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\prv_m_bypass.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -1169,6 +1181,10 @@ SOURCE=..\..\..\src\jrd\relations.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\ResultSet.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\req.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -407,6 +407,10 @@ SOURCE=..\..\..\src\jrd\plugin_manager.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\PreparedStatement.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\pwd.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -423,6 +427,10 @@ SOURCE=..\..\..\src\jrd\Relation.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\ResultSet.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\rlck.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -1137,6 +1145,10 @@ SOURCE=..\..\..\src\jrd\pragma.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\PreparedStatement.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\prv_m_bypass.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@ -1177,6 +1189,10 @@ SOURCE=..\..\..\src\jrd\relations.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\ResultSet.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\req.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -327,6 +327,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\plugin_manager.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\PreparedStatement.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\pwd.cpp">
|
||||
</File>
|
||||
@ -339,6 +342,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\Relation.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ResultSet.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\rlck.cpp">
|
||||
</File>
|
||||
@ -874,6 +880,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\pragma.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\PreparedStatement.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\prv_m_bypass.h">
|
||||
</File>
|
||||
@ -892,6 +901,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\RandomGenerator.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ResultSet.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\rdb.h">
|
||||
</File>
|
||||
|
@ -327,6 +327,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\plugin_manager.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\PreparedStatement.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\pwd.cpp">
|
||||
</File>
|
||||
@ -339,6 +342,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\Relation.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ResultSet.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\rlck.cpp">
|
||||
</File>
|
||||
@ -874,6 +880,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\pragma.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\PreparedStatement.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\prv_m_bypass.h">
|
||||
</File>
|
||||
@ -892,6 +901,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\RandomGenerator.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ResultSet.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\rdb.h">
|
||||
</File>
|
||||
|
@ -331,6 +331,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\plugin_manager.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\PreparedStatement.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\pwd.cpp">
|
||||
</File>
|
||||
@ -343,6 +346,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\Relation.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ResultSet.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\rlck.cpp">
|
||||
</File>
|
||||
@ -875,6 +881,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\pragma.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\PreparedStatement.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\prv_m_bypass.h">
|
||||
</File>
|
||||
@ -893,6 +902,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\RandomGenerator.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ResultSet.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\rdb.h">
|
||||
</File>
|
||||
|
@ -538,6 +538,10 @@
|
||||
RelativePath="..\..\..\src\jrd\plugin_manager.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\PreparedStatement.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\pwd.cpp"
|
||||
>
|
||||
@ -554,6 +558,10 @@
|
||||
RelativePath="..\..\..\src\jrd\Relation.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ResultSet.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\rlck.cpp"
|
||||
>
|
||||
@ -1270,6 +1278,10 @@
|
||||
RelativePath="..\..\..\src\jrd\pragma.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\PreparedStatement.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\prv_m_bypass.h"
|
||||
>
|
||||
@ -1294,6 +1306,10 @@
|
||||
RelativePath="..\..\..\src\jrd\RandomGenerator.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ResultSet.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\rdb.h"
|
||||
>
|
||||
|
@ -538,6 +538,10 @@
|
||||
RelativePath="..\..\..\src\jrd\plugin_manager.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\PreparedStatement.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\pwd.cpp"
|
||||
>
|
||||
@ -554,6 +558,10 @@
|
||||
RelativePath="..\..\..\src\jrd\Relation.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ResultSet.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\rlck.cpp"
|
||||
>
|
||||
@ -1270,6 +1278,10 @@
|
||||
RelativePath="..\..\..\src\jrd\pragma.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\PreparedStatement.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\prv_m_bypass.h"
|
||||
>
|
||||
@ -1294,6 +1306,10 @@
|
||||
RelativePath="..\..\..\src\jrd\RandomGenerator.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ResultSet.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\rdb.h"
|
||||
>
|
||||
|
@ -542,6 +542,10 @@
|
||||
RelativePath="..\..\..\src\jrd\plugin_manager.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\PreparedStatement.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\pwd.cpp"
|
||||
>
|
||||
@ -558,6 +562,10 @@
|
||||
RelativePath="..\..\..\src\jrd\Relation.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ResultSet.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\rlck.cpp"
|
||||
>
|
||||
@ -1270,6 +1278,10 @@
|
||||
RelativePath="..\..\..\src\jrd\pragma.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\PreparedStatement.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\prv_m_bypass.h"
|
||||
>
|
||||
@ -1294,6 +1306,10 @@
|
||||
RelativePath="..\..\..\src\jrd\RandomGenerator.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\ResultSet.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\rdb.h"
|
||||
>
|
||||
|
@ -80,8 +80,7 @@ static void execute_blob(thread_db*, dsql_req*, USHORT, const UCHAR*, USHORT, c
|
||||
static void execute_immediate(thread_db*, Attachment*, jrd_tra**,
|
||||
USHORT, const TEXT*, USHORT,
|
||||
USHORT, const UCHAR*, USHORT, USHORT, const UCHAR*,
|
||||
USHORT, UCHAR*, USHORT, USHORT, UCHAR*,
|
||||
long);
|
||||
USHORT, UCHAR*, USHORT, USHORT, UCHAR*);
|
||||
static void execute_request(thread_db*, dsql_req*, jrd_tra**, USHORT, const UCHAR*,
|
||||
USHORT, const UCHAR*, USHORT, UCHAR*, USHORT, UCHAR*, bool);
|
||||
static SSHORT filter_sub_type(dsql_req*, const dsql_nod*);
|
||||
@ -325,42 +324,7 @@ void DSQL_execute_immediate(thread_db* tdbb,
|
||||
out_blr_length,
|
||||
out_blr,
|
||||
out_msg_type, out_msg_length,
|
||||
out_msg,
|
||||
~0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
DSQL_callback_execute_immediate
|
||||
|
||||
@brief Execute sql_operator in context of jrd_transaction_handle
|
||||
|
||||
|
||||
@param tdbb
|
||||
@param sql_operator
|
||||
@param dialect
|
||||
|
||||
**/
|
||||
void DSQL_callback_execute_immediate(thread_db* tdbb,
|
||||
const Firebird::string& sql_operator)
|
||||
{
|
||||
// Other requests appear to be incorrect in this context
|
||||
long requests = (1 << REQ_INSERT) | (1 << REQ_DELETE) | (1 << REQ_UPDATE)
|
||||
| (1 << REQ_DDL) | (1 << REQ_SET_GENERATOR) | (1 << REQ_EXEC_PROCEDURE)
|
||||
| (1 << REQ_EXEC_BLOCK);
|
||||
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
|
||||
const Database* const dbb = attachment->att_database;
|
||||
const int dialect = dbb->dbb_flags & DBB_DB_SQL_dialect_3 ? SQL_DIALECT_V6 : SQL_DIALECT_V5;
|
||||
|
||||
jrd_tra* transaction = tdbb->getTransaction();
|
||||
|
||||
execute_immediate(tdbb, attachment, &transaction,
|
||||
sql_operator.length(), sql_operator.c_str(), dialect,
|
||||
0, NULL, 0, 0, NULL, 0, NULL, 0, 0, NULL, requests);
|
||||
|
||||
fb_assert(transaction == tdbb->getTransaction());
|
||||
out_msg);
|
||||
}
|
||||
|
||||
|
||||
@ -1130,8 +1094,7 @@ static void execute_immediate(thread_db* tdbb,
|
||||
USHORT in_blr_length, const UCHAR* in_blr,
|
||||
USHORT in_msg_type, USHORT in_msg_length, const UCHAR* in_msg,
|
||||
USHORT out_blr_length, UCHAR* out_blr,
|
||||
USHORT out_msg_type, USHORT out_msg_length, UCHAR* out_msg,
|
||||
long possible_requests)
|
||||
USHORT out_msg_type, USHORT out_msg_length, UCHAR* out_msg)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
@ -1187,17 +1150,6 @@ static void execute_immediate(thread_db* tdbb,
|
||||
|
||||
request = prepare(tdbb, request, length, string, dialect, parser_version);
|
||||
|
||||
if (!((1 << request->req_type) & possible_requests))
|
||||
{
|
||||
const int max_diag_len = 50;
|
||||
char err_str[max_diag_len + 1];
|
||||
strncpy(err_str, string, max_diag_len);
|
||||
err_str[max_diag_len] = 0;
|
||||
ERRD_post(isc_sqlerr, isc_arg_number, (SLONG) -902,
|
||||
isc_arg_gds, isc_exec_sql_invalid_req,
|
||||
isc_arg_string, err_str, isc_arg_end);
|
||||
}
|
||||
|
||||
execute_request(tdbb, request, tra_handle, in_blr_length, in_blr,
|
||||
in_msg_length, in_msg, out_blr_length, out_blr,
|
||||
out_msg_length, out_msg, false);
|
||||
|
@ -19,6 +19,7 @@
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
* Adriano dos Santos Fernandes
|
||||
*/
|
||||
|
||||
#ifndef DSQL_DSQL_PROTO_H
|
||||
@ -82,7 +83,4 @@ void DSQL_sql_info(Jrd::thread_db*,
|
||||
USHORT, const UCHAR*,
|
||||
USHORT, UCHAR*);
|
||||
|
||||
void DSQL_callback_execute_immediate(Jrd::thread_db* tdbb,
|
||||
const Firebird::string& sql_operator);
|
||||
|
||||
#endif // DSQL_DSQL_PROTO_H
|
||||
|
235
src/jrd/PreparedStatement.cpp
Normal file
235
src/jrd/PreparedStatement.cpp
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* 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 Adriano dos Santos Fernandes
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2008 Adriano dos Santos Fernandes <adrianosf@uol.com.br>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#include "../jrd/PreparedStatement.h"
|
||||
#include "../jrd/ResultSet.h"
|
||||
#include "../jrd/align.h"
|
||||
#include "../jrd/jrd.h"
|
||||
#include "../jrd/dsc.h"
|
||||
#include "../dsql/dsql.h"
|
||||
#include "../dsql/sqlda_pub.h"
|
||||
#include "../dsql/dsql_proto.h"
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
|
||||
PreparedStatement::PreparedStatement(thread_db* tdbb, Firebird::MemoryPool& pool,
|
||||
Attachment* attachment, jrd_tra* transaction, const Firebird::string& text)
|
||||
: values(pool),
|
||||
blr(pool),
|
||||
message(pool),
|
||||
resultSet(NULL)
|
||||
{
|
||||
request = DSQL_allocate_statement(tdbb, attachment);
|
||||
|
||||
const Database* const dbb = tdbb->getDatabase();
|
||||
const int dialect = dbb->dbb_flags & DBB_DB_SQL_dialect_3 ? SQL_DIALECT_V6 : SQL_DIALECT_V5;
|
||||
|
||||
DSQL_prepare(tdbb, transaction, &request, text.length(), text.c_str(), dialect,
|
||||
0, NULL, 0, NULL);
|
||||
|
||||
int paramCount = 0;
|
||||
size_t msgLength = 0;
|
||||
|
||||
if (request->req_receive)
|
||||
{
|
||||
for (dsql_par* par = request->req_receive->msg_parameters; par; par = par->par_next)
|
||||
{
|
||||
if (!par->par_index)
|
||||
continue;
|
||||
|
||||
msgLength = FB_ALIGN(msgLength, type_alignments[par->par_desc.dsc_dtype]);
|
||||
msgLength += par->par_desc.dsc_length;
|
||||
msgLength = FB_ALIGN(msgLength, type_alignments[dtype_short]);
|
||||
msgLength += sizeof(SSHORT);
|
||||
|
||||
++paramCount;
|
||||
}
|
||||
|
||||
paramCount *= 2;
|
||||
|
||||
blr.add(blr_version5);
|
||||
blr.add(blr_begin);
|
||||
blr.add(blr_message);
|
||||
blr.add(0);
|
||||
blr.add(paramCount);
|
||||
blr.add(paramCount >> 8);
|
||||
|
||||
values.resize(paramCount);
|
||||
message.resize(msgLength);
|
||||
|
||||
msgLength = 0;
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (int j = 1; j <= paramCount / 2; ++j)
|
||||
{
|
||||
for (dsql_par* par = request->req_receive->msg_parameters; par; par = par->par_next)
|
||||
{
|
||||
if (par->par_index != j)
|
||||
continue;
|
||||
|
||||
if (type_alignments[par->par_desc.dsc_dtype])
|
||||
msgLength = FB_ALIGN(msgLength, type_alignments[par->par_desc.dsc_dtype]);
|
||||
values[i] = par->par_desc;
|
||||
values[i].dsc_address = message.begin() + msgLength;
|
||||
msgLength += par->par_desc.dsc_length;
|
||||
|
||||
generateBlr(&values[i]);
|
||||
|
||||
++i;
|
||||
|
||||
// Calculate the NULL indicator offset
|
||||
if (type_alignments[dtype_short])
|
||||
msgLength = FB_ALIGN(msgLength, type_alignments[dtype_short]);
|
||||
values[i].makeShort(0);
|
||||
values[i].dsc_address = message.begin() + msgLength;
|
||||
msgLength += sizeof(SSHORT);
|
||||
|
||||
// Generate BLR for the NULL indicator
|
||||
blr.add(blr_short);
|
||||
blr.add(0);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
blr.add(blr_end);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PreparedStatement::~PreparedStatement()
|
||||
{
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
DSQL_free_statement(tdbb, request, DSQL_drop);
|
||||
|
||||
if (resultSet)
|
||||
resultSet->stmt = NULL;
|
||||
}
|
||||
|
||||
|
||||
void PreparedStatement::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
DSQL_execute(tdbb, &transaction, request, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
ResultSet* PreparedStatement::executeQuery(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
fb_assert(resultSet == NULL && request->req_receive);
|
||||
return new ResultSet(tdbb, this, transaction);
|
||||
}
|
||||
|
||||
|
||||
int PreparedStatement::getResultCount()
|
||||
{
|
||||
return values.getCount() / 2;
|
||||
}
|
||||
|
||||
|
||||
void PreparedStatement::generateBlr(const dsc* desc)
|
||||
{
|
||||
USHORT length = 0;
|
||||
|
||||
switch (desc->dsc_dtype)
|
||||
{
|
||||
case dtype_text:
|
||||
blr.add(blr_text2);
|
||||
blr.add(desc->dsc_ttype());
|
||||
blr.add(desc->dsc_ttype() >> 8);
|
||||
length = desc->dsc_length;
|
||||
blr.add(length);
|
||||
blr.add(length >> 8);
|
||||
break;
|
||||
|
||||
case dtype_varying:
|
||||
blr.add(blr_varying2);
|
||||
blr.add(desc->dsc_ttype());
|
||||
blr.add(desc->dsc_ttype() >> 8);
|
||||
fb_assert(desc->dsc_length >= sizeof(USHORT));
|
||||
length = desc->dsc_length - sizeof(USHORT);
|
||||
blr.add(length);
|
||||
blr.add(length >> 8);
|
||||
break;
|
||||
|
||||
case dtype_short:
|
||||
blr.add(blr_short);
|
||||
blr.add(desc->dsc_scale);
|
||||
break;
|
||||
|
||||
case dtype_long:
|
||||
blr.add(blr_long);
|
||||
blr.add(desc->dsc_scale);
|
||||
break;
|
||||
|
||||
case dtype_quad:
|
||||
blr.add(blr_quad);
|
||||
blr.add(desc->dsc_scale);
|
||||
break;
|
||||
|
||||
case dtype_int64:
|
||||
blr.add(blr_int64);
|
||||
blr.add(desc->dsc_scale);
|
||||
break;
|
||||
|
||||
case dtype_real:
|
||||
blr.add(blr_float);
|
||||
break;
|
||||
|
||||
case dtype_double:
|
||||
blr.add(blr_double);
|
||||
break;
|
||||
|
||||
case dtype_sql_date:
|
||||
blr.add(blr_sql_date);
|
||||
break;
|
||||
|
||||
case dtype_sql_time:
|
||||
blr.add(blr_sql_time);
|
||||
break;
|
||||
|
||||
case dtype_timestamp:
|
||||
blr.add(blr_timestamp);
|
||||
break;
|
||||
|
||||
case dtype_array:
|
||||
blr.add(blr_quad);
|
||||
blr.add(0);
|
||||
break;
|
||||
|
||||
case dtype_blob:
|
||||
blr.add(blr_blob2);
|
||||
blr.add(desc->dsc_sub_type);
|
||||
blr.add(desc->dsc_sub_type >> 8);
|
||||
blr.add(desc->getTextType());
|
||||
blr.add(desc->getTextType() >> 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
fb_assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
74
src/jrd/PreparedStatement.h
Normal file
74
src/jrd/PreparedStatement.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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 Adriano dos Santos Fernandes
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2008 Adriano dos Santos Fernandes <adrianosf@uol.com.br>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef JRD_PREPARED_STATEMENT_H
|
||||
#define JRD_PREPARED_STATEMENT_H
|
||||
|
||||
#include "../common/classes/fb_string.h"
|
||||
#include "../common/classes/array.h"
|
||||
|
||||
struct dsc;
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
class thread_db;
|
||||
class jrd_tra;
|
||||
class Attachment;
|
||||
class dsql_req;
|
||||
class ResultSet;
|
||||
|
||||
|
||||
class PreparedStatement
|
||||
{
|
||||
friend class ResultSet;
|
||||
|
||||
public:
|
||||
PreparedStatement(thread_db* tdbb, Firebird::MemoryPool& pool, Attachment* attachment,
|
||||
jrd_tra* transaction, const Firebird::string& text);
|
||||
~PreparedStatement();
|
||||
|
||||
public:
|
||||
void execute(thread_db* tdbb, jrd_tra* transaction);
|
||||
ResultSet* executeQuery(thread_db* tdbb, jrd_tra* transaction);
|
||||
|
||||
int getResultCount();
|
||||
|
||||
dsql_req* getRequest()
|
||||
{
|
||||
return request;
|
||||
}
|
||||
|
||||
private:
|
||||
void generateBlr(const dsc* desc);
|
||||
|
||||
private:
|
||||
dsql_req* request;
|
||||
Firebird::Array<dsc> values;
|
||||
Firebird::UCharBuffer blr;
|
||||
Firebird::UCharBuffer message;
|
||||
ResultSet* resultSet;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // JRD_PREPARED_STATEMENT_H
|
94
src/jrd/ResultSet.cpp
Normal file
94
src/jrd/ResultSet.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 Adriano dos Santos Fernandes
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2008 Adriano dos Santos Fernandes <adrianosf@uol.com.br>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#include "../jrd/ResultSet.h"
|
||||
#include "../jrd/PreparedStatement.h"
|
||||
#include "../jrd/align.h"
|
||||
#include "../jrd/jrd.h"
|
||||
#include "../jrd/dsc.h"
|
||||
#include "../dsql/dsql.h"
|
||||
#include "../dsql/sqlda_pub.h"
|
||||
#include "../dsql/dsql_proto.h"
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
|
||||
ResultSet::ResultSet(thread_db* tdbb, PreparedStatement* aStmt, jrd_tra* aTransaction)
|
||||
: stmt(aStmt),
|
||||
transaction(aTransaction),
|
||||
firstFetch(false)
|
||||
{
|
||||
DSQL_execute(tdbb, &transaction, stmt->request, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, NULL);
|
||||
|
||||
stmt->resultSet = this;
|
||||
}
|
||||
|
||||
|
||||
ResultSet::~ResultSet()
|
||||
{
|
||||
if (!stmt)
|
||||
return;
|
||||
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
stmt->resultSet = NULL;
|
||||
|
||||
if (stmt->request->req_type != REQ_EXEC_PROCEDURE)
|
||||
DSQL_free_statement(tdbb, stmt->request, DSQL_close);
|
||||
}
|
||||
|
||||
|
||||
bool ResultSet::fetch(thread_db* tdbb)
|
||||
{
|
||||
if (stmt->request->req_type == REQ_EXEC_PROCEDURE && firstFetch)
|
||||
return false;
|
||||
|
||||
memset(stmt->message.begin(), 0, stmt->message.getCount());
|
||||
|
||||
ISC_STATUS status = DSQL_fetch(tdbb, stmt->request, stmt->blr.getCount(), stmt->blr.begin(),
|
||||
0, stmt->message.getCount(), stmt->message.begin());
|
||||
|
||||
if (status == 100)
|
||||
return false;
|
||||
|
||||
firstFetch = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ResultSet::isNull(int param)
|
||||
{
|
||||
dsc* desc = &stmt->values[(param - 1) * 2 + 1];
|
||||
fb_assert(desc->dsc_dtype == dtype_short);
|
||||
|
||||
return *(SSHORT*) desc->dsc_address != 0;
|
||||
}
|
||||
|
||||
|
||||
dsc ResultSet::getDesc(int param)
|
||||
{
|
||||
return stmt->values[(param - 1) * 2];
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
58
src/jrd/ResultSet.h
Normal file
58
src/jrd/ResultSet.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 Adriano dos Santos Fernandes
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2008 Adriano dos Santos Fernandes <adrianosf@uol.com.br>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef JRD_RESULT_SET_H
|
||||
#define JRD_RESULT_SET_H
|
||||
|
||||
struct dsc;
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
class thread_db;
|
||||
class jrd_tra;
|
||||
class Attachment;
|
||||
class PreparedStatement;
|
||||
|
||||
|
||||
class ResultSet
|
||||
{
|
||||
friend class PreparedStatement;
|
||||
|
||||
public:
|
||||
ResultSet(thread_db* tdbb, PreparedStatement* aStmt, jrd_tra* aTransaction);
|
||||
~ResultSet();
|
||||
|
||||
public:
|
||||
bool fetch(thread_db* tdbb);
|
||||
bool isNull(int param);
|
||||
dsc getDesc(int param);
|
||||
|
||||
private:
|
||||
PreparedStatement* stmt;
|
||||
jrd_tra* transaction;
|
||||
bool firstFetch;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // JRD_RESULT_SET_H
|
@ -1159,7 +1159,7 @@ void EXE_unwind(thread_db* tdbb, jrd_req* request)
|
||||
jrd_nod* node = request->req_exec_sta[i];
|
||||
ExecuteStatement* impure =
|
||||
(ExecuteStatement*) ((char*) request + node->nod_impure);
|
||||
impure->Close(tdbb);
|
||||
impure->close(tdbb);
|
||||
}
|
||||
}
|
||||
catch (const Firebird::Exception&)
|
||||
@ -1477,30 +1477,7 @@ static void exec_sql(thread_db* tdbb, jrd_req* request, DSC* dsc)
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
jrd_tra* const transaction = tdbb->getTransaction();
|
||||
|
||||
if (transaction->tra_callback_count >= MAX_CALLBACKS)
|
||||
{
|
||||
ERR_post(isc_exec_sql_max_call_exceeded, 0);
|
||||
}
|
||||
|
||||
Firebird::string sqlStatementText;
|
||||
ExecuteStatement::getString(tdbb, sqlStatementText, dsc, request);
|
||||
|
||||
transaction->tra_callback_count++;
|
||||
|
||||
try
|
||||
{
|
||||
DSQL_callback_execute_immediate(tdbb, sqlStatementText);
|
||||
}
|
||||
catch (const Firebird::Exception&)
|
||||
{
|
||||
transaction->tra_callback_count--;
|
||||
throw;
|
||||
}
|
||||
|
||||
transaction->tra_callback_count--;
|
||||
ExecuteStatement::execute(tdbb, request, dsc);
|
||||
}
|
||||
|
||||
|
||||
@ -2533,15 +2510,15 @@ static jrd_nod* looper(thread_db* tdbb, jrd_req* request, jrd_nod* in_node)
|
||||
|
||||
case nod_exec_into:
|
||||
{
|
||||
ExecuteStatement* impure =
|
||||
(ExecuteStatement*)
|
||||
((SCHAR *) request + node->nod_impure);
|
||||
ExecuteStatement* impure = (ExecuteStatement*)
|
||||
((SCHAR *) request + node->nod_impure);
|
||||
|
||||
switch (request->req_operation) {
|
||||
case jrd_req::req_evaluate:
|
||||
impure->Open(tdbb, node->nod_arg[0], node->nod_count - 2, !node->nod_arg[1]);
|
||||
impure->open(tdbb, node->nod_arg[0], node->nod_count - 2, !node->nod_arg[1]);
|
||||
case jrd_req::req_return:
|
||||
case jrd_req::req_sync:
|
||||
if (impure->Fetch(tdbb, &node->nod_arg[2])) {
|
||||
if (impure->fetch(tdbb, &node->nod_arg[2])) {
|
||||
request->req_operation = jrd_req::req_evaluate;
|
||||
node = node->nod_arg[1];
|
||||
break;
|
||||
@ -2549,7 +2526,7 @@ static jrd_nod* looper(thread_db* tdbb, jrd_req* request, jrd_nod* in_node)
|
||||
request->req_operation = jrd_req::req_return;
|
||||
default:
|
||||
// if have active opened request - close it
|
||||
impure->Close(tdbb);
|
||||
impure->close(tdbb);
|
||||
node = node->nod_parent;
|
||||
}
|
||||
}
|
||||
|
@ -36,22 +36,69 @@
|
||||
#include "../jrd/mov_proto.h"
|
||||
#include "../jrd/evl_proto.h"
|
||||
#include "../jrd/exe_proto.h"
|
||||
#include "../jrd/align.h"
|
||||
#include "../jrd/execute_statement.h"
|
||||
#include "../dsql/dsql_proto.h"
|
||||
#include "../dsql/dsql.h"
|
||||
#include "../common/classes/auto.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
using namespace Jrd;
|
||||
using Firebird::AutoPtr;
|
||||
|
||||
namespace {
|
||||
|
||||
const UCHAR sql_output_info[] = {isc_info_sql_select, isc_info_sql_num_variables};
|
||||
void ExecuteStatement::execute(Jrd::thread_db* tdbb, jrd_req* request, DSC* dsc)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
} // anonymous namespace
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
jrd_tra* const transaction = tdbb->getTransaction();
|
||||
|
||||
void ExecuteStatement::Open(thread_db* tdbb, jrd_nod* sql, SSHORT nVars, bool singleton)
|
||||
if (transaction->tra_callback_count >= MAX_CALLBACKS)
|
||||
{
|
||||
ERR_post(isc_exec_sql_max_call_exceeded, 0);
|
||||
}
|
||||
|
||||
Firebird::string sqlStatementText;
|
||||
getString(tdbb, sqlStatementText, dsc, request);
|
||||
|
||||
transaction->tra_callback_count++;
|
||||
|
||||
try
|
||||
{
|
||||
AutoPtr<PreparedStatement> stmt = attachment->prepareStatement(
|
||||
tdbb, *tdbb->getDefaultPool(), transaction, sqlStatementText);
|
||||
|
||||
// Other requests appear to be incorrect in this context
|
||||
const long requests =
|
||||
(1 << REQ_INSERT) | (1 << REQ_DELETE) | (1 << REQ_UPDATE) |
|
||||
(1 << REQ_DDL) | (1 << REQ_SET_GENERATOR) | (1 << REQ_EXEC_PROCEDURE) |
|
||||
(1 << REQ_EXEC_BLOCK);
|
||||
|
||||
if (!((1 << stmt->getRequest()->req_type) & requests))
|
||||
{
|
||||
ERR_post(
|
||||
isc_sqlerr, isc_arg_number, (SLONG) -902,
|
||||
isc_arg_gds, isc_exec_sql_invalid_req,
|
||||
isc_arg_string, ERR_string(sqlStatementText),
|
||||
0);
|
||||
}
|
||||
|
||||
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, jrd_nod* sql, SSHORT nVars, bool singleton)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
@ -63,10 +110,6 @@ void ExecuteStatement::Open(thread_db* tdbb, jrd_nod* sql, SSHORT nVars, bool si
|
||||
ERR_post(isc_exec_sql_max_call_exceeded, 0);
|
||||
}
|
||||
|
||||
blr = NULL;
|
||||
message = NULL;
|
||||
values = NULL;
|
||||
|
||||
varCount = nVars;
|
||||
singleMode = singleton;
|
||||
|
||||
@ -79,51 +122,28 @@ void ExecuteStatement::Open(thread_db* tdbb, jrd_nod* sql, SSHORT nVars, bool si
|
||||
|
||||
try
|
||||
{
|
||||
statement = DSQL_allocate_statement(tdbb, attachment);
|
||||
stmt = attachment->prepareStatement(tdbb, *tdbb->getDefaultPool(), transaction, sqlText);
|
||||
|
||||
const Database* const dbb = tdbb->getDatabase();
|
||||
const int dialect = dbb->dbb_flags & DBB_DB_SQL_dialect_3 ? SQL_DIALECT_V6 : SQL_DIALECT_V5;
|
||||
|
||||
UCHAR info_buffer[BUFFER_TINY];
|
||||
|
||||
DSQL_prepare(tdbb, transaction, &statement,
|
||||
sqlText.length(), sqlText.c_str(), dialect,
|
||||
sizeof(sql_output_info), sql_output_info,
|
||||
sizeof(info_buffer), info_buffer);
|
||||
|
||||
const UCHAR* info(info_buffer);
|
||||
UCHAR tag = *info++;
|
||||
fb_assert(tag == isc_info_sql_select);
|
||||
tag = *info++;
|
||||
fb_assert(tag == isc_info_sql_num_variables);
|
||||
const int length = gds__vax_integer(info, sizeof(SSHORT));
|
||||
info += sizeof(SSHORT);
|
||||
const int number = gds__vax_integer(info, length);
|
||||
info += length;
|
||||
tag = *info++;
|
||||
fb_assert(tag == isc_info_end);
|
||||
|
||||
if (!number)
|
||||
if (stmt->getResultCount() == 0)
|
||||
{
|
||||
DSQL_free_statement(tdbb, statement, DSQL_drop);
|
||||
statement = NULL;
|
||||
delete stmt;
|
||||
stmt = NULL;
|
||||
|
||||
ERR_post(isc_exec_sql_invalid_req,
|
||||
isc_arg_string, ERR_cstring(startOfSqlOperator),
|
||||
0);
|
||||
ERR_post(
|
||||
isc_exec_sql_invalid_req,
|
||||
isc_arg_string, ERR_cstring(startOfSqlOperator),
|
||||
0);
|
||||
}
|
||||
|
||||
if (number != varCount)
|
||||
if (stmt->getResultCount() != varCount)
|
||||
{
|
||||
DSQL_free_statement(tdbb, statement, DSQL_drop);
|
||||
statement = NULL;
|
||||
delete stmt;
|
||||
stmt = NULL;
|
||||
|
||||
ERR_post(isc_wronumarg, 0);
|
||||
}
|
||||
|
||||
DSQL_execute(tdbb, &transaction, statement,
|
||||
0, NULL, 0, 0, NULL,
|
||||
0, NULL, 0, 0, NULL);
|
||||
resultSet = stmt->executeQuery(tdbb, transaction);
|
||||
|
||||
fb_assert(transaction == tdbb->getTransaction());
|
||||
}
|
||||
@ -136,103 +156,33 @@ void ExecuteStatement::Open(thread_db* tdbb, jrd_nod* sql, SSHORT nVars, bool si
|
||||
transaction->tra_callback_count--;
|
||||
}
|
||||
|
||||
bool ExecuteStatement::Fetch(thread_db* tdbb, jrd_nod** jrdVar)
|
||||
|
||||
bool ExecuteStatement::fetch(thread_db* tdbb, jrd_nod** jrdVar)
|
||||
{
|
||||
fb_assert(statement);
|
||||
|
||||
size_t blr_length = 0;
|
||||
|
||||
if (!message && !blr && !values)
|
||||
if (!resultSet->fetch(tdbb))
|
||||
{
|
||||
const size_t param_count = varCount * 2;
|
||||
|
||||
MemoryPool& pool = *tdbb->getDefaultPool();
|
||||
|
||||
values = FB_NEW(pool) Firebird::Array<dsc>(pool);
|
||||
values->grow(param_count);
|
||||
|
||||
blr = FB_NEW(pool) Firebird::UCharBuffer(pool);
|
||||
blr->add(blr_version5);
|
||||
blr->add(blr_begin);
|
||||
blr->add(blr_message);
|
||||
blr->add(0);
|
||||
blr->add(param_count);
|
||||
blr->add(param_count >> 8);
|
||||
|
||||
size_t msg_length = 0;
|
||||
|
||||
for (int i = 0; i < varCount; i++)
|
||||
{
|
||||
jrd_nod* const target = jrdVar[i];
|
||||
fb_assert(target);
|
||||
|
||||
dsc* const desc = EVL_assign_to(tdbb, target);
|
||||
(*values)[i * 2] = *desc;
|
||||
|
||||
(*values)[i * 2 + 1].dsc_dtype = dtype_short;
|
||||
(*values)[i * 2 + 1].dsc_length = sizeof(SSHORT);
|
||||
|
||||
// Generate BLR for the value
|
||||
generateBlr(desc);
|
||||
// Generate BLR for the NULL indicator
|
||||
blr->add(blr_short);
|
||||
blr->add(desc->dsc_scale);
|
||||
|
||||
// Calculate the value offset
|
||||
msg_length = FB_ALIGN(msg_length, type_alignments[desc->dsc_dtype]);
|
||||
(*values)[i * 2].dsc_address = (UCHAR*)(IPTR) msg_length;
|
||||
msg_length += desc->dsc_length;
|
||||
|
||||
// Calculate the NULL indicator offset
|
||||
msg_length = FB_ALIGN(msg_length, type_alignments[dtype_short]);
|
||||
(*values)[i * 2 + 1].dsc_address = (UCHAR*)(IPTR) msg_length;
|
||||
msg_length += sizeof(SSHORT);
|
||||
}
|
||||
|
||||
blr->add(blr_end);
|
||||
blr_length = blr->getCount();
|
||||
|
||||
message = FB_NEW(pool) Firebird::UCharBuffer(pool);
|
||||
message->grow(msg_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(message->begin(), 0, message->getCount());
|
||||
}
|
||||
|
||||
ISC_STATUS status = DSQL_fetch(tdbb, statement,
|
||||
blr->getCount(), blr->begin(),
|
||||
0, message->getCount(), message->begin());
|
||||
|
||||
if (status == 100)
|
||||
{
|
||||
DSQL_free_statement(tdbb, statement, DSQL_drop);
|
||||
statement = NULL;
|
||||
|
||||
delete resultSet;
|
||||
resultSet = NULL;
|
||||
delete stmt;
|
||||
stmt = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < varCount; i++)
|
||||
{
|
||||
dsc desc = (*values)[i * 2];
|
||||
desc.dsc_address = message->begin() + (IPTR) desc.dsc_address;
|
||||
dsc null_desc = (*values)[i * 2 + 1];
|
||||
null_desc.dsc_address = message->begin() + (IPTR) null_desc.dsc_address;
|
||||
const bool null_flag = ((*(SSHORT*) null_desc.dsc_address) == 0) ? false : true;
|
||||
EXE_assignment(tdbb, jrdVar[i], &desc, null_flag, NULL, NULL);
|
||||
dsc desc = resultSet->getDesc(i + 1);
|
||||
bool nullFlag = resultSet->isNull(i + 1);
|
||||
EXE_assignment(tdbb, jrdVar[i], &desc, nullFlag, NULL, NULL);
|
||||
}
|
||||
|
||||
if (singleMode)
|
||||
{
|
||||
status = DSQL_fetch(tdbb, statement,
|
||||
blr->getCount(), blr->begin(),
|
||||
0, message->getCount(), message->begin());
|
||||
|
||||
if (status == 100)
|
||||
if (!resultSet->fetch(tdbb))
|
||||
{
|
||||
DSQL_free_statement(tdbb, statement, DSQL_drop);
|
||||
statement = NULL;
|
||||
|
||||
delete resultSet;
|
||||
resultSet = NULL;
|
||||
delete stmt;
|
||||
stmt = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -242,22 +192,14 @@ bool ExecuteStatement::Fetch(thread_db* tdbb, jrd_nod** jrdVar)
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExecuteStatement::Close(thread_db* tdbb)
|
||||
{
|
||||
if (statement)
|
||||
{
|
||||
DSQL_free_statement(tdbb, statement, DSQL_drop);
|
||||
statement = NULL;
|
||||
}
|
||||
|
||||
delete blr;
|
||||
blr = NULL;
|
||||
delete message;
|
||||
message = NULL;
|
||||
delete values;
|
||||
values = NULL;
|
||||
void ExecuteStatement::close(thread_db* tdbb)
|
||||
{
|
||||
delete resultSet;
|
||||
delete stmt;
|
||||
}
|
||||
|
||||
|
||||
void ExecuteStatement::getString(thread_db* tdbb,
|
||||
Firebird::string& sql,
|
||||
const dsc* desc,
|
||||
@ -277,88 +219,3 @@ void ExecuteStatement::getString(thread_db* tdbb,
|
||||
|
||||
sql.assign((const char*) ptr, len);
|
||||
}
|
||||
|
||||
void ExecuteStatement::generateBlr(const dsc* desc)
|
||||
{
|
||||
fb_assert(blr);
|
||||
|
||||
USHORT length = 0;
|
||||
|
||||
switch (desc->dsc_dtype)
|
||||
{
|
||||
case dtype_text:
|
||||
blr->add(blr_text2);
|
||||
blr->add(desc->dsc_ttype());
|
||||
blr->add(desc->dsc_ttype() >> 8);
|
||||
length = desc->dsc_length;
|
||||
blr->add(length);
|
||||
blr->add(length >> 8);
|
||||
break;
|
||||
|
||||
case dtype_varying:
|
||||
blr->add(blr_varying2);
|
||||
blr->add(desc->dsc_ttype());
|
||||
blr->add(desc->dsc_ttype() >> 8);
|
||||
fb_assert(desc->dsc_length >= sizeof(USHORT));
|
||||
length = desc->dsc_length - sizeof(USHORT);
|
||||
blr->add(length);
|
||||
blr->add(length >> 8);
|
||||
break;
|
||||
|
||||
case dtype_short:
|
||||
blr->add(blr_short);
|
||||
blr->add(desc->dsc_scale);
|
||||
break;
|
||||
|
||||
case dtype_long:
|
||||
blr->add(blr_long);
|
||||
blr->add(desc->dsc_scale);
|
||||
break;
|
||||
|
||||
case dtype_quad:
|
||||
blr->add(blr_quad);
|
||||
blr->add(desc->dsc_scale);
|
||||
break;
|
||||
|
||||
case dtype_int64:
|
||||
blr->add(blr_int64);
|
||||
blr->add(desc->dsc_scale);
|
||||
break;
|
||||
|
||||
case dtype_real:
|
||||
blr->add(blr_float);
|
||||
break;
|
||||
|
||||
case dtype_double:
|
||||
blr->add(blr_double);
|
||||
break;
|
||||
|
||||
case dtype_sql_date:
|
||||
blr->add(blr_sql_date);
|
||||
break;
|
||||
|
||||
case dtype_sql_time:
|
||||
blr->add(blr_sql_time);
|
||||
break;
|
||||
|
||||
case dtype_timestamp:
|
||||
blr->add(blr_timestamp);
|
||||
break;
|
||||
|
||||
case dtype_array:
|
||||
blr->add(blr_quad);
|
||||
blr->add(0);
|
||||
break;
|
||||
|
||||
case dtype_blob:
|
||||
blr->add(blr_blob2);
|
||||
blr->add(desc->dsc_sub_type);
|
||||
blr->add(desc->dsc_sub_type >> 8);
|
||||
blr->add(desc->getTextType());
|
||||
blr->add(desc->getTextType() >> 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
fb_assert(false);
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
* Adriano dos Santos Fernandes
|
||||
*/
|
||||
|
||||
#ifndef JRD_EXECUTE_STATEMENT_H
|
||||
@ -29,35 +30,35 @@
|
||||
|
||||
#include "../jrd/jrd_blks.h"
|
||||
#include "../include/fb_blk.h"
|
||||
#include "../jrd/PreparedStatement.h"
|
||||
#include "../jrd/ResultSet.h"
|
||||
#include "../jrd/exe.h"
|
||||
#include "../jrd/ibase.h"
|
||||
#include "../dsql/dsql.h"
|
||||
|
||||
const int MAX_CALLBACKS = 50;
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
class ExecuteStatement {
|
||||
|
||||
class ExecuteStatement
|
||||
{
|
||||
public:
|
||||
static void execute(Jrd::thread_db* tdbb, Jrd::jrd_req* request, DSC* dsc);
|
||||
void open(Jrd::thread_db* tdbb, Jrd::jrd_nod* sql, SSHORT nVars, bool SingleTon);
|
||||
bool fetch(Jrd::thread_db* tdbb, Jrd::jrd_nod** FirstVar);
|
||||
void close(Jrd::thread_db* tdbb);
|
||||
|
||||
static void getString(Jrd::thread_db*, Firebird::string&, const dsc* d, const Jrd::jrd_req* r);
|
||||
|
||||
private:
|
||||
dsql_req* statement;
|
||||
Firebird::UCharBuffer* blr;
|
||||
Firebird::UCharBuffer* message;
|
||||
Firebird::Array<dsc>* values;
|
||||
PreparedStatement* stmt;
|
||||
ResultSet* resultSet;
|
||||
int varCount;
|
||||
bool singleMode;
|
||||
TEXT startOfSqlOperator[32];
|
||||
|
||||
void generateBlr(const dsc* desc);
|
||||
|
||||
public:
|
||||
void Open(Jrd::thread_db* tdbb, Jrd::jrd_nod* sql, SSHORT nVars, bool SingleTon);
|
||||
bool Fetch(Jrd::thread_db* tdbb, Jrd::jrd_nod** FirstVar);
|
||||
void Close(Jrd::thread_db* tdbb);
|
||||
|
||||
static void getString(Jrd::thread_db*, Firebird::string&, const dsc* d, const Jrd::jrd_req* r);
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // JRD_EXECUTE_STATEMENT_H
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
*
|
||||
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
|
||||
* Claudio Valderrama C.
|
||||
* Adriano dos Santos Fernandes
|
||||
*
|
||||
*/
|
||||
|
||||
@ -77,6 +78,7 @@
|
||||
#include "../jrd/iberr.h"
|
||||
#include "../intl/charsets.h"
|
||||
#include "../jrd/sort.h"
|
||||
#include "../jrd/PreparedStatement.h"
|
||||
|
||||
#include "../jrd/blb_proto.h"
|
||||
#include "../jrd/cch_proto.h"
|
||||
@ -5614,6 +5616,13 @@ static vdnResult verify_database_name(const Firebird::PathName& name, ISC_STATUS
|
||||
}
|
||||
|
||||
|
||||
PreparedStatement* Attachment::prepareStatement(thread_db* tdbb, Firebird::MemoryPool& pool,
|
||||
jrd_tra* transaction, const Firebird::string& text)
|
||||
{
|
||||
return new PreparedStatement(tdbb, pool, this, transaction, text);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
getUserInfo
|
||||
|
@ -24,6 +24,7 @@
|
||||
*
|
||||
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
|
||||
* Claudio Valderrama C.
|
||||
* Adriano dos Santos Fernandes
|
||||
*
|
||||
*/
|
||||
|
||||
@ -152,6 +153,7 @@ class TextType;
|
||||
class Parameter;
|
||||
class jrd_fld;
|
||||
class dsql_dbb;
|
||||
class PreparedStatement;
|
||||
|
||||
// The database block, the topmost block in the metadata
|
||||
// cache for a database
|
||||
@ -316,6 +318,9 @@ public:
|
||||
dsql_dbb* att_dsql_instance;
|
||||
|
||||
bool locksmith() const;
|
||||
|
||||
PreparedStatement* prepareStatement(thread_db* tdbb, Firebird::MemoryPool& pool,
|
||||
jrd_tra* transaction, const Firebird::string& text);
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user