8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-28 02:43:03 +01:00
firebird-mirror/src/jrd/execute_statement.cpp

219 lines
5.0 KiB
C++
Raw Normal View History

2004-03-11 05:31:04 +01:00
/*
* 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
2004-03-11 05:31:04 +01:00
*/
#include "firebird.h"
#include "gen/iberror.h"
#include "../jrd/common.h"
#include "../jrd/jrd.h"
#include "../jrd/tra.h"
#include "../jrd/dsc.h"
#include "../jrd/err_proto.h"
#include "../jrd/mov_proto.h"
#include "../jrd/evl_proto.h"
#include "../jrd/exe_proto.h"
2004-03-11 05:31:04 +01:00
#include "../jrd/execute_statement.h"
#include "../dsql/dsql.h"
#include "../common/classes/auto.h"
2004-03-11 05:31:04 +01:00
2008-02-28 14:48:16 +01:00
#include <string.h>
#include <math.h>
2008-02-28 14:48:16 +01:00
using namespace Jrd;
using namespace Firebird;
using Firebird::AutoPtr;
2004-03-11 05:31:04 +01:00
2008-03-15 11:25:30 +01:00
void ExecuteStatement::execute(Jrd::thread_db* tdbb, jrd_req* request, DSC* desc)
2004-03-11 05:31:04 +01:00
{
SET_TDBB(tdbb);
Attachment* attachment = tdbb->getAttachment();
jrd_tra* const transaction = tdbb->getTransaction();
2008-02-28 14:48:16 +01:00
if (transaction->tra_callback_count >= MAX_CALLBACKS)
{
ERR_post(Arg::Gds(isc_exec_sql_max_call_exceeded));
2008-02-28 14:48:16 +01:00
}
2004-03-11 05:31:04 +01:00
Firebird::string sqlStatementText;
2008-03-15 11:25:30 +01:00
getString(tdbb, sqlStatementText, desc, request);
2004-03-11 05:31:04 +01:00
2008-02-28 14:48:16 +01:00
transaction->tra_callback_count++;
2004-03-11 05:31:04 +01:00
try
{
2008-03-14 09:23:26 +01:00
AutoPtr<PreparedStatement> stmt(attachment->prepareStatement(
tdbb, *tdbb->getDefaultPool(), transaction, sqlStatementText));
2004-03-11 05:31:04 +01:00
2008-12-05 02:20:14 +01:00
// 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);
2004-03-11 05:31:04 +01:00
if (!((1 << stmt->getRequest()->req_type) & requests))
{
ERR_post(Arg::Gds(isc_sqlerr) << Arg::Num(-902) <<
Arg::Gds(isc_exec_sql_invalid_req) << Arg::Str(sqlStatementText));
}
2008-02-28 14:48:16 +01:00
stmt->execute(tdbb, transaction);
2008-02-28 14:48:16 +01:00
fb_assert(transaction == tdbb->getTransaction());
}
2008-02-28 14:48:16 +01:00
catch (const Firebird::Exception&)
{
2008-02-28 14:48:16 +01:00
transaction->tra_callback_count--;
throw;
2004-03-11 05:31:04 +01:00
}
2008-02-28 14:48:16 +01:00
transaction->tra_callback_count--;
2004-03-11 05:31:04 +01:00
}
void ExecuteStatement::open(thread_db* tdbb, jrd_nod* sql, SSHORT nVars, bool singleton)
2004-03-11 05:31:04 +01:00
{
SET_TDBB(tdbb);
2004-03-11 05:31:04 +01:00
Attachment* const attachment = tdbb->getAttachment();
jrd_tra* transaction = tdbb->getTransaction();
if (transaction->tra_callback_count >= MAX_CALLBACKS)
2008-02-28 14:48:16 +01:00
{
ERR_post(Arg::Gds(isc_exec_sql_max_call_exceeded));
}
varCount = nVars;
singleMode = singleton;
Firebird::string sqlText;
getString(tdbb, sqlText, EVL_expr(tdbb, sql), tdbb->getRequest());
memcpy(startOfSqlOperator, sqlText.c_str(), sizeof(startOfSqlOperator) - 1);
startOfSqlOperator[sizeof(startOfSqlOperator) - 1] = 0;
2004-03-11 05:31:04 +01:00
transaction->tra_callback_count++;
2008-02-28 14:48:16 +01:00
try
{
stmt = attachment->prepareStatement(tdbb, *tdbb->getDefaultPool(), transaction, sqlText);
if (stmt->getResultCount() == 0)
{
delete stmt;
stmt = NULL;
ERR_post(Arg::Gds(isc_exec_sql_invalid_req) << Arg::Str(startOfSqlOperator));
}
2008-02-28 14:48:16 +01:00
if (stmt->getResultCount() != varCount)
2004-03-11 05:31:04 +01:00
{
delete stmt;
stmt = NULL;
ERR_post(Arg::Gds(isc_wronumarg));
2004-03-11 05:31:04 +01:00
}
resultSet = stmt->executeQuery(tdbb, transaction);
2008-02-28 14:48:16 +01:00
fb_assert(transaction == tdbb->getTransaction());
2008-02-28 14:48:16 +01:00
}
catch (const Firebird::Exception&)
2008-02-28 14:48:16 +01:00
{
transaction->tra_callback_count--;
throw;
2008-02-28 14:48:16 +01:00
}
transaction->tra_callback_count--;
}
2008-02-28 14:48:16 +01:00
bool ExecuteStatement::fetch(thread_db* tdbb, jrd_nod** jrdVar)
{
if (!resultSet->fetch(tdbb))
{
delete resultSet;
resultSet = NULL;
delete stmt;
stmt = NULL;
2008-02-28 14:48:16 +01:00
return false;
}
2008-02-28 14:48:16 +01:00
for (int i = 0; i < varCount; i++)
{
2008-03-13 20:50:13 +01:00
dsc& desc = resultSet->getDesc(i + 1);
bool nullFlag = resultSet->isNull(i + 1);
EXE_assignment(tdbb, jrdVar[i], &desc, nullFlag, NULL, NULL);
}
2004-03-11 05:31:04 +01:00
2008-02-28 14:48:16 +01:00
if (singleMode)
{
if (!resultSet->fetch(tdbb))
2004-03-11 05:31:04 +01:00
{
delete resultSet;
resultSet = NULL;
delete stmt;
stmt = NULL;
2004-03-11 05:31:04 +01:00
return false;
}
ERR_post(Arg::Gds(isc_sing_select_err));
2004-03-11 05:31:04 +01:00
}
2008-02-28 14:48:16 +01:00
2007-10-06 12:22:32 +02:00
return true;
2004-03-11 05:31:04 +01:00
}
void ExecuteStatement::close(thread_db* tdbb)
{
delete resultSet;
2008-03-15 11:25:30 +01:00
resultSet = NULL;
delete stmt;
2008-03-15 11:25:30 +01:00
stmt = NULL;
2004-03-11 05:31:04 +01:00
}
2008-02-28 14:48:16 +01:00
void ExecuteStatement::getString(thread_db* tdbb,
Firebird::string& sql,
const dsc* desc,
const jrd_req* request)
2004-03-11 05:31:04 +01:00
{
2008-02-28 14:48:16 +01:00
MoveBuffer buffer;
2004-03-11 05:31:04 +01:00
2008-02-28 14:48:16 +01:00
UCHAR* ptr = NULL;
2007-10-06 21:08:50 +02:00
2008-02-28 14:48:16 +01:00
const SSHORT len = (desc && !(request->req_flags & req_null)) ?
MOV_make_string2(tdbb, desc, desc->getTextType(), &ptr, buffer) : 0; // !!! How call Msgs ?
2008-02-28 14:48:16 +01:00
if (!ptr)
{
ERR_post(Arg::Gds(isc_exec_sql_invalid_arg));
2007-10-06 12:22:32 +02:00
}
2007-10-06 21:08:50 +02:00
2008-03-02 09:45:41 +01:00
sql.assign((const char*) ptr, len);
2004-03-11 05:31:04 +01:00
}