mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 18:03:04 +01:00
Refactor DSQL, continuing the work I started in 2.5:
- Renamed CompiledStatement to DsqlCompilerScratch and removed inheritance to dsql_req. - Introduced DsqlCompilerStatement, moving things from dsql_req - not completelly shareable yet. - Make dsql_req reference a DsqlCompilerStatement. DsqlCompilerScratch may be discarded in the future. - Replaced AlterCharSetNode usage by PreparedStatement for the default collation in database creation. - Changed METD API.
This commit is contained in:
parent
0aac87c0e6
commit
488eb40fe0
@ -59,22 +59,6 @@ DATABASE DB = STATIC "ODS.RDB";
|
||||
//----------------------
|
||||
|
||||
|
||||
// Escape a string accordingly to SQL rules.
|
||||
template <typename T> static string escapeString(const T& s)
|
||||
{
|
||||
string ret;
|
||||
|
||||
for (const char* p = s.begin(); p != s.end(); ++p)
|
||||
{
|
||||
ret += *p;
|
||||
if (*p == '\'')
|
||||
ret += '\'';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void DdlNode::executeDdlTrigger(thread_db* tdbb, jrd_tra* transaction,
|
||||
DdlTriggerWhen when, int action, const Firebird::MetaName& objectName,
|
||||
const Firebird::string& sqlText)
|
||||
@ -107,15 +91,6 @@ void DdlNode::executeDdlTrigger(thread_db* tdbb, jrd_tra* transaction,
|
||||
}
|
||||
|
||||
|
||||
void DdlNode::checkEmptyName(const MetaName& name)
|
||||
{
|
||||
// ASF: Not passing in DYN, it's better to remove this function and make the scanner doesn't
|
||||
// recognize empty double-quoted string as identifiers.
|
||||
if (name.isEmpty())
|
||||
status_exception::raise(Arg::Gds(isc_dyn_zero_len_id));
|
||||
}
|
||||
|
||||
|
||||
void DdlNode::putType(const TypeClause& type, bool useSubType)
|
||||
{
|
||||
#ifdef DEV_BUILD
|
||||
@ -129,8 +104,10 @@ void DdlNode::putType(const TypeClause& type, bool useSubType)
|
||||
}
|
||||
#endif
|
||||
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
if (type.notNull)
|
||||
compiledStatement->append_uchar(blr_not_nullable);
|
||||
statement->append_uchar(blr_not_nullable);
|
||||
|
||||
if (type.typeOfName.hasData())
|
||||
{
|
||||
@ -138,34 +115,34 @@ void DdlNode::putType(const TypeClause& type, bool useSubType)
|
||||
{
|
||||
if (type.collateSpecified)
|
||||
{
|
||||
compiledStatement->append_uchar(blr_column_name2);
|
||||
compiledStatement->append_uchar(type.fullDomain ? blr_domain_full : blr_domain_type_of);
|
||||
compiledStatement->append_meta_string(type.typeOfTable.c_str());
|
||||
compiledStatement->append_meta_string(type.typeOfName.c_str());
|
||||
compiledStatement->append_ushort(type.textType);
|
||||
statement->append_uchar(blr_column_name2);
|
||||
statement->append_uchar(type.fullDomain ? blr_domain_full : blr_domain_type_of);
|
||||
statement->append_meta_string(type.typeOfTable.c_str());
|
||||
statement->append_meta_string(type.typeOfName.c_str());
|
||||
statement->append_ushort(type.textType);
|
||||
}
|
||||
else
|
||||
{
|
||||
compiledStatement->append_uchar(blr_column_name);
|
||||
compiledStatement->append_uchar(type.fullDomain ? blr_domain_full : blr_domain_type_of);
|
||||
compiledStatement->append_meta_string(type.typeOfTable.c_str());
|
||||
compiledStatement->append_meta_string(type.typeOfName.c_str());
|
||||
statement->append_uchar(blr_column_name);
|
||||
statement->append_uchar(type.fullDomain ? blr_domain_full : blr_domain_type_of);
|
||||
statement->append_meta_string(type.typeOfTable.c_str());
|
||||
statement->append_meta_string(type.typeOfName.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type.collateSpecified)
|
||||
{
|
||||
compiledStatement->append_uchar(blr_domain_name2);
|
||||
compiledStatement->append_uchar(type.fullDomain ? blr_domain_full : blr_domain_type_of);
|
||||
compiledStatement->append_meta_string(type.typeOfName.c_str());
|
||||
compiledStatement->append_ushort(type.textType);
|
||||
statement->append_uchar(blr_domain_name2);
|
||||
statement->append_uchar(type.fullDomain ? blr_domain_full : blr_domain_type_of);
|
||||
statement->append_meta_string(type.typeOfName.c_str());
|
||||
statement->append_ushort(type.textType);
|
||||
}
|
||||
else
|
||||
{
|
||||
compiledStatement->append_uchar(blr_domain_name);
|
||||
compiledStatement->append_uchar(type.fullDomain ? blr_domain_full : blr_domain_type_of);
|
||||
compiledStatement->append_meta_string(type.typeOfName.c_str());
|
||||
statement->append_uchar(blr_domain_name);
|
||||
statement->append_uchar(type.fullDomain ? blr_domain_full : blr_domain_type_of);
|
||||
statement->append_meta_string(type.typeOfName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,39 +156,39 @@ void DdlNode::putType(const TypeClause& type, bool useSubType)
|
||||
case dtype_varying:
|
||||
case dtype_blob:
|
||||
if (!useSubType)
|
||||
compiledStatement->append_uchar(blr_dtypes[type.type]);
|
||||
statement->append_uchar(blr_dtypes[type.type]);
|
||||
else if (type.type == dtype_varying)
|
||||
{
|
||||
compiledStatement->append_uchar(blr_varying2);
|
||||
compiledStatement->append_ushort(type.textType);
|
||||
statement->append_uchar(blr_varying2);
|
||||
statement->append_ushort(type.textType);
|
||||
}
|
||||
else if (type.type == dtype_cstring)
|
||||
{
|
||||
compiledStatement->append_uchar(blr_cstring2);
|
||||
compiledStatement->append_ushort(type.textType);
|
||||
statement->append_uchar(blr_cstring2);
|
||||
statement->append_ushort(type.textType);
|
||||
}
|
||||
else if (type.type == dtype_blob)
|
||||
{
|
||||
compiledStatement->append_uchar(blr_blob2);
|
||||
compiledStatement->append_ushort(type.subType);
|
||||
compiledStatement->append_ushort(type.textType);
|
||||
statement->append_uchar(blr_blob2);
|
||||
statement->append_ushort(type.subType);
|
||||
statement->append_ushort(type.textType);
|
||||
}
|
||||
else
|
||||
{
|
||||
compiledStatement->append_uchar(blr_text2);
|
||||
compiledStatement->append_ushort(type.textType);
|
||||
statement->append_uchar(blr_text2);
|
||||
statement->append_ushort(type.textType);
|
||||
}
|
||||
|
||||
if (type.type == dtype_varying)
|
||||
compiledStatement->append_ushort(type.length - sizeof(USHORT));
|
||||
statement->append_ushort(type.length - sizeof(USHORT));
|
||||
else if (type.type != dtype_blob)
|
||||
compiledStatement->append_ushort(type.length);
|
||||
statement->append_ushort(type.length);
|
||||
break;
|
||||
|
||||
default:
|
||||
compiledStatement->append_uchar(blr_dtypes[type.type]);
|
||||
statement->append_uchar(blr_dtypes[type.type]);
|
||||
if (DTYPE_IS_EXACT(type.type) || dtype_quad == type.type)
|
||||
compiledStatement->append_uchar(type.scale);
|
||||
statement->append_uchar(type.scale);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -219,8 +196,8 @@ void DdlNode::putType(const TypeClause& type, bool useSubType)
|
||||
|
||||
void DdlNode::resetContextStack()
|
||||
{
|
||||
compiledStatement->req_context->clear();
|
||||
compiledStatement->req_context_number = 0;
|
||||
dsqlScratch->context->clear();
|
||||
dsqlScratch->contextNumber = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -234,9 +211,9 @@ TypeClause::TypeClause(dsql_fld* aLegacyField, const MetaName& aCollate)
|
||||
}
|
||||
|
||||
|
||||
void TypeClause::resolve(CompiledStatement* compiledStatement)
|
||||
void TypeClause::resolve(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
DDL_resolve_intl_type(compiledStatement, legacyField,
|
||||
DDL_resolve_intl_type(dsqlScratch, legacyField,
|
||||
(collate.isEmpty() ? NULL : MAKE_cstring(collate.c_str())));
|
||||
|
||||
type = legacyField->fld_dtype;
|
||||
@ -302,11 +279,8 @@ void AlterCharSetNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
|
||||
|
||||
void AlterCharSetNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
if (compiledStatement && compiledStatement->req_dbb) // do not run in CREATE DATABASE
|
||||
{
|
||||
METD_drop_charset(compiledStatement, charSet);
|
||||
MET_dsql_cache_release(tdbb, SYM_intlsym_charset, charSet);
|
||||
}
|
||||
METD_drop_charset(transaction, charSet);
|
||||
MET_dsql_cache_release(tdbb, SYM_intlsym_charset, charSet);
|
||||
|
||||
bool charSetFound = false;
|
||||
bool collationFound = false;
|
||||
@ -582,15 +556,19 @@ void CreateAlterFunctionNode::print(string& text, Array<dsql_nod*>& /*nodes*/) c
|
||||
}
|
||||
|
||||
|
||||
DdlNode* CreateAlterFunctionNode::internalDsqlPass()
|
||||
{
|
||||
for (unsigned i = 0; i < parameters.getCount(); ++i)
|
||||
parameters[i].resolve(dsqlScratch);
|
||||
|
||||
returnType.resolve(dsqlScratch);
|
||||
|
||||
return DdlNode::internalDsqlPass();
|
||||
}
|
||||
|
||||
|
||||
void CreateAlterFunctionNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
checkEmptyName(name);
|
||||
|
||||
for (unsigned i = 0; i < parameters.getCount(); ++i)
|
||||
parameters[i].resolve(compiledStatement);
|
||||
|
||||
returnType.resolve(compiledStatement);
|
||||
|
||||
fb_assert(create || alter);
|
||||
|
||||
// run all statements under savepoint control
|
||||
@ -612,7 +590,7 @@ void CreateAlterFunctionNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
|
||||
// Update DSQL cache
|
||||
AutoPtr<dsql_str> str(MAKE_string(name.c_str(), name.length()));
|
||||
METD_drop_function(compiledStatement, str, package);
|
||||
METD_drop_function(transaction, str, package);
|
||||
MET_dsql_cache_release(tdbb, SYM_udf, str->str_data, package);
|
||||
}
|
||||
else
|
||||
@ -986,7 +964,7 @@ void DropFunctionNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
|
||||
// Update DSQL cache
|
||||
AutoPtr<dsql_str> str(MAKE_string(name.c_str(), name.length()));
|
||||
METD_drop_function(compiledStatement, str, package);
|
||||
METD_drop_function(transaction, str, package);
|
||||
MET_dsql_cache_release(tdbb, SYM_udf, str->str_data, package);
|
||||
}
|
||||
|
||||
@ -996,7 +974,7 @@ void DropFunctionNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
|
||||
void ProcedureNode::genReturn()
|
||||
{
|
||||
GEN_return(compiledStatement, getCreateAlterNode()->outputVariables, false);
|
||||
GEN_return(dsqlScratch, getCreateAlterNode()->outputVariables, false);
|
||||
}
|
||||
|
||||
|
||||
@ -1050,10 +1028,11 @@ void CreateAlterProcedureNode::print(string& text, Array<dsql_nod*>& /*nodes*/)
|
||||
}
|
||||
|
||||
|
||||
Node* CreateAlterProcedureNode::internalDsqlPass()
|
||||
DdlNode* CreateAlterProcedureNode::internalDsqlPass()
|
||||
{
|
||||
compiledStatement->blockNode = this;
|
||||
compiledStatement->req_flags |= (REQ_block | REQ_procedure);
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
statement->blockNode = this;
|
||||
statement->flags |= (REQ_block | REQ_procedure);
|
||||
|
||||
const dsql_nod* variables = localDeclList;
|
||||
if (variables)
|
||||
@ -1103,10 +1082,16 @@ Node* CreateAlterProcedureNode::internalDsqlPass()
|
||||
if (parameter.legacyDefault)
|
||||
{
|
||||
parameter.legacyDefault->nod_arg[e_dft_default] =
|
||||
PASS1_node(compiledStatement, parameter.legacyDefault->nod_arg[e_dft_default]);
|
||||
PASS1_node(dsqlScratch, parameter.legacyDefault->nod_arg[e_dft_default]);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < parameters.getCount(); ++i)
|
||||
parameters[i].resolve(dsqlScratch);
|
||||
|
||||
for (unsigned i = 0; i < returns.getCount(); ++i)
|
||||
returns[i].resolve(dsqlScratch);
|
||||
|
||||
return DdlNode::internalDsqlPass();
|
||||
}
|
||||
|
||||
@ -1115,14 +1100,6 @@ void CreateAlterProcedureNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
fb_assert(create || alter);
|
||||
|
||||
checkEmptyName(name);
|
||||
|
||||
for (unsigned i = 0; i < parameters.getCount(); ++i)
|
||||
parameters[i].resolve(compiledStatement);
|
||||
|
||||
for (unsigned i = 0; i < returns.getCount(); ++i)
|
||||
returns[i].resolve(compiledStatement);
|
||||
|
||||
// run all statements under savepoint control
|
||||
AutoSavePoint savePoint(tdbb, transaction);
|
||||
bool altered = false;
|
||||
@ -1163,7 +1140,7 @@ void CreateAlterProcedureNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
// Update DSQL cache
|
||||
AutoPtr<dsql_str> str(MAKE_string(name.c_str(), name.length()));
|
||||
METD_drop_procedure(compiledStatement, str, package);
|
||||
METD_drop_procedure(transaction, str, package);
|
||||
MET_dsql_cache_release(tdbb, SYM_procedure, str->str_data, package);
|
||||
}
|
||||
}
|
||||
@ -1266,6 +1243,8 @@ bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, jrd_tra* transactio
|
||||
AutoCacheRequest requestHandle(tdbb, drq_m_prcs2, DYN_REQUESTS);
|
||||
bool modified = false;
|
||||
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
|
||||
P IN RDB$PROCEDURES
|
||||
WITH P.RDB$PROCEDURE_NAME EQ name.c_str() AND
|
||||
@ -1337,17 +1316,17 @@ bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, jrd_tra* transactio
|
||||
{
|
||||
P.RDB$PROCEDURE_BLR.NULL = FALSE;
|
||||
attachment->storeBinaryBlob(tdbb, transaction, &P.RDB$PROCEDURE_BLR,
|
||||
compiledStatement->req_blr_data.begin(),
|
||||
compiledStatement->req_blr_data.getCount());
|
||||
statement->blrData.begin(),
|
||||
statement->blrData.getCount());
|
||||
|
||||
P.RDB$DEBUG_INFO.NULL = FALSE;
|
||||
attachment->storeBinaryBlob(tdbb, transaction, &P.RDB$DEBUG_INFO,
|
||||
compiledStatement->req_debug_data.begin(),
|
||||
compiledStatement->req_debug_data.getCount());
|
||||
statement->debugData.begin(),
|
||||
statement->debugData.getCount());
|
||||
|
||||
// ODS_11_1
|
||||
P.RDB$PROCEDURE_TYPE.NULL = FALSE;
|
||||
P.RDB$PROCEDURE_TYPE = (USHORT) (compiledStatement->req_flags & REQ_selectable ?
|
||||
P.RDB$PROCEDURE_TYPE = (USHORT) (statement->flags & REQ_selectable ?
|
||||
prc_selectable : prc_executable);
|
||||
}
|
||||
}
|
||||
@ -1386,8 +1365,6 @@ void CreateAlterProcedureNode::storeParameter(thread_db* tdbb, jrd_tra* transact
|
||||
{
|
||||
Attachment* attachment = transaction->getAttachment();
|
||||
|
||||
checkEmptyName(parameter.name);
|
||||
|
||||
//Database* dbb = tdbb->getDatabase();
|
||||
AutoCacheRequest requestHandle(tdbb, drq_s_prms4, DYN_REQUESTS);
|
||||
|
||||
@ -1560,20 +1537,22 @@ void CreateAlterProcedureNode::storeParameter(thread_db* tdbb, jrd_tra* transact
|
||||
string defaultSource = string(defaultString->str_data, defaultString->str_length);
|
||||
attachment->storeMetaDataBlob(tdbb, transaction, &PRM.RDB$DEFAULT_SOURCE, defaultSource);
|
||||
|
||||
compiledStatement->req_blr_data.clear();
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
if (compiledStatement->req_flags & REQ_blr_version4)
|
||||
compiledStatement->append_uchar(blr_version4);
|
||||
statement->blrData.clear();
|
||||
|
||||
if (statement->flags & REQ_blr_version4)
|
||||
statement->append_uchar(blr_version4);
|
||||
else
|
||||
compiledStatement->append_uchar(blr_version5);
|
||||
statement->append_uchar(blr_version5);
|
||||
|
||||
GEN_expr(compiledStatement, parameter.legacyDefault->nod_arg[e_dft_default]);
|
||||
GEN_expr(dsqlScratch, parameter.legacyDefault->nod_arg[e_dft_default]);
|
||||
|
||||
compiledStatement->append_uchar(blr_eoc);
|
||||
statement->append_uchar(blr_eoc);
|
||||
|
||||
attachment->storeBinaryBlob(tdbb, transaction, &PRM.RDB$DEFAULT_VALUE,
|
||||
compiledStatement->req_blr_data.begin(),
|
||||
compiledStatement->req_blr_data.getCount());
|
||||
statement->blrData.begin(),
|
||||
statement->blrData.getCount());
|
||||
}
|
||||
}
|
||||
END_STORE
|
||||
@ -1595,32 +1574,34 @@ void CreateAlterProcedureNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/
|
||||
|
||||
invalid = true;
|
||||
|
||||
compiledStatement->begin_debug();
|
||||
compiledStatement->req_blr_data.clear();
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
if (compiledStatement->req_flags & REQ_blr_version4)
|
||||
compiledStatement->append_uchar(blr_version4);
|
||||
statement->begin_debug();
|
||||
statement->blrData.clear();
|
||||
|
||||
if (statement->flags & REQ_blr_version4)
|
||||
statement->append_uchar(blr_version4);
|
||||
else
|
||||
compiledStatement->append_uchar(blr_version5);
|
||||
statement->append_uchar(blr_version5);
|
||||
|
||||
compiledStatement->append_uchar(blr_begin);
|
||||
statement->append_uchar(blr_begin);
|
||||
|
||||
if (parameters.getCount() != 0)
|
||||
{
|
||||
fb_assert(parameters.getCount() < MAX_USHORT / 2);
|
||||
compiledStatement->append_uchar(blr_message);
|
||||
compiledStatement->append_uchar(0);
|
||||
compiledStatement->append_ushort(2 * parameters.getCount());
|
||||
statement->append_uchar(blr_message);
|
||||
statement->append_uchar(0);
|
||||
statement->append_ushort(2 * parameters.getCount());
|
||||
|
||||
for (unsigned i = 0; i < parameters.getCount(); ++i)
|
||||
{
|
||||
ParameterClause& parameter = parameters[i];
|
||||
compiledStatement->put_debug_argument(fb_dbg_arg_input, i, parameter.name.c_str());
|
||||
statement->put_debug_argument(fb_dbg_arg_input, i, parameter.name.c_str());
|
||||
putType(parameter, true);
|
||||
|
||||
// add slot for null flag (parameter2)
|
||||
compiledStatement->append_uchar(blr_short);
|
||||
compiledStatement->append_uchar(0);
|
||||
statement->append_uchar(blr_short);
|
||||
statement->append_uchar(0);
|
||||
|
||||
variables.add(MAKE_variable(parameter.legacyField,
|
||||
parameter.name.c_str(), VAR_input, 0, (USHORT) (2 * i), 0));
|
||||
@ -1628,21 +1609,21 @@ void CreateAlterProcedureNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/
|
||||
}
|
||||
|
||||
fb_assert(returns.getCount() < MAX_USHORT / 2);
|
||||
compiledStatement->append_uchar(blr_message);
|
||||
compiledStatement->append_uchar(1);
|
||||
compiledStatement->append_ushort(2 * returns.getCount() + 1);
|
||||
statement->append_uchar(blr_message);
|
||||
statement->append_uchar(1);
|
||||
statement->append_ushort(2 * returns.getCount() + 1);
|
||||
|
||||
if (returns.getCount() != 0)
|
||||
{
|
||||
for (unsigned i = 0; i < returns.getCount(); ++i)
|
||||
{
|
||||
ParameterClause& parameter = returns[i];
|
||||
compiledStatement->put_debug_argument(fb_dbg_arg_output, i, parameter.name.c_str());
|
||||
statement->put_debug_argument(fb_dbg_arg_output, i, parameter.name.c_str());
|
||||
putType(parameter, true);
|
||||
|
||||
// add slot for null flag (parameter2)
|
||||
compiledStatement->append_uchar(blr_short);
|
||||
compiledStatement->append_uchar(0);
|
||||
statement->append_uchar(blr_short);
|
||||
statement->append_uchar(0);
|
||||
|
||||
dsql_nod* var = MAKE_variable(parameter.legacyField,
|
||||
parameter.name.c_str(), VAR_output, 1, (USHORT) (2 * i), i);
|
||||
@ -1653,16 +1634,16 @@ void CreateAlterProcedureNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/
|
||||
}
|
||||
|
||||
// add slot for EOS
|
||||
compiledStatement->append_uchar(blr_short);
|
||||
compiledStatement->append_uchar(0);
|
||||
statement->append_uchar(blr_short);
|
||||
statement->append_uchar(0);
|
||||
|
||||
if (parameters.getCount() != 0)
|
||||
{
|
||||
compiledStatement->append_uchar(blr_receive);
|
||||
compiledStatement->append_uchar(0);
|
||||
statement->append_uchar(blr_receive);
|
||||
statement->append_uchar(0);
|
||||
}
|
||||
|
||||
compiledStatement->append_uchar(blr_begin);
|
||||
statement->append_uchar(blr_begin);
|
||||
|
||||
for (unsigned i = 0; i < parameters.getCount(); ++i)
|
||||
{
|
||||
@ -1672,12 +1653,12 @@ void CreateAlterProcedureNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/
|
||||
{
|
||||
// ASF: To validate an input parameter we need only to read its value.
|
||||
// Assigning it to null is an easy way to do this.
|
||||
compiledStatement->append_uchar(blr_assignment);
|
||||
compiledStatement->append_uchar(blr_parameter2);
|
||||
compiledStatement->append_uchar(0); // input
|
||||
compiledStatement->append_ushort(i * 2);
|
||||
compiledStatement->append_ushort(i * 2 + 1);
|
||||
compiledStatement->append_uchar(blr_null);
|
||||
statement->append_uchar(blr_assignment);
|
||||
statement->append_uchar(blr_parameter2);
|
||||
statement->append_uchar(0); // input
|
||||
statement->append_ushort(i * 2);
|
||||
statement->append_ushort(i * 2 + 1);
|
||||
statement->append_uchar(blr_null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1685,33 +1666,33 @@ void CreateAlterProcedureNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/
|
||||
{
|
||||
dsql_nod* parameter = *i;
|
||||
dsql_var* variable = (dsql_var*) parameter->nod_arg[Dsql::e_var_variable];
|
||||
DDL_put_local_variable(compiledStatement, variable, 0, NULL);
|
||||
DDL_put_local_variable(dsqlScratch, variable, 0, NULL);
|
||||
}
|
||||
|
||||
// ASF: This is here to not change the old logic (proc_flag)
|
||||
// of previous calls to PASS1_node and PASS1_statement.
|
||||
compiledStatement->setPsql(true);
|
||||
dsqlScratch->setPsql(true);
|
||||
|
||||
DDL_put_local_variables(compiledStatement, localDeclList, returns.getCount(), variables);
|
||||
DDL_put_local_variables(dsqlScratch, localDeclList, returns.getCount(), variables);
|
||||
|
||||
compiledStatement->append_uchar(blr_stall);
|
||||
statement->append_uchar(blr_stall);
|
||||
// put a label before body of procedure,
|
||||
// so that any EXIT statement can get out
|
||||
compiledStatement->append_uchar(blr_label);
|
||||
compiledStatement->append_uchar(0);
|
||||
compiledStatement->req_loop_level = 0;
|
||||
compiledStatement->req_cursor_number = 0;
|
||||
statement->append_uchar(blr_label);
|
||||
statement->append_uchar(0);
|
||||
dsqlScratch->loopLevel = 0;
|
||||
dsqlScratch->cursorNumber = 0;
|
||||
|
||||
GEN_statement(compiledStatement, PASS1_statement(compiledStatement, body));
|
||||
GEN_statement(dsqlScratch, PASS1_statement(dsqlScratch, body));
|
||||
|
||||
compiledStatement->req_type = REQ_DDL;
|
||||
compiledStatement->append_uchar(blr_end);
|
||||
GEN_return(compiledStatement, outputVariables, true);
|
||||
statement->type = REQ_DDL;
|
||||
statement->append_uchar(blr_end);
|
||||
GEN_return(dsqlScratch, outputVariables, true);
|
||||
|
||||
compiledStatement->append_uchar(blr_end);
|
||||
compiledStatement->append_uchar(blr_eoc);
|
||||
statement->append_uchar(blr_end);
|
||||
statement->append_uchar(blr_eoc);
|
||||
|
||||
compiledStatement->end_debug();
|
||||
statement->end_debug();
|
||||
|
||||
invalid = false;
|
||||
}
|
||||
@ -1782,9 +1763,9 @@ void DropProcedureNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
|
||||
}
|
||||
|
||||
|
||||
Node* DropProcedureNode::internalDsqlPass()
|
||||
DdlNode* DropProcedureNode::internalDsqlPass()
|
||||
{
|
||||
compiledStatement->req_flags |= (REQ_block | REQ_procedure);
|
||||
dsqlScratch->getStatement()->flags |= (REQ_block | REQ_procedure);
|
||||
return DdlNode::internalDsqlPass();
|
||||
}
|
||||
|
||||
@ -1859,7 +1840,7 @@ void DropProcedureNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
|
||||
// Update DSQL cache
|
||||
AutoPtr<dsql_str> str(MAKE_string(name.c_str(), name.length()));
|
||||
METD_drop_procedure(compiledStatement, str, package);
|
||||
METD_drop_procedure(transaction, str, package);
|
||||
MET_dsql_cache_release(tdbb, SYM_procedure, str->str_data, package);
|
||||
}
|
||||
|
||||
@ -1873,10 +1854,10 @@ void RecreateProcedureNode::print(string& text, Array<dsql_nod*>& /*nodes*/) con
|
||||
}
|
||||
|
||||
|
||||
Node* RecreateProcedureNode::internalDsqlPass()
|
||||
DdlNode* RecreateProcedureNode::internalDsqlPass()
|
||||
{
|
||||
dropNode.dsqlPass(compiledStatement);
|
||||
createNode->dsqlPass(compiledStatement);
|
||||
dropNode.dsqlPass(dsqlScratch);
|
||||
createNode->dsqlPass(dsqlScratch);
|
||||
return DdlNode::internalDsqlPass();
|
||||
}
|
||||
|
||||
@ -1927,10 +1908,11 @@ void CreateAlterTriggerNode::print(string& text, Array<dsql_nod*>& /*nodes*/) co
|
||||
}
|
||||
|
||||
|
||||
Node* CreateAlterTriggerNode::internalDsqlPass()
|
||||
DdlNode* CreateAlterTriggerNode::internalDsqlPass()
|
||||
{
|
||||
compiledStatement->blockNode = this;
|
||||
compiledStatement->req_flags |= (REQ_block | REQ_procedure | REQ_trigger);
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
statement->blockNode = this;
|
||||
statement->flags |= (REQ_block | REQ_procedure | REQ_trigger);
|
||||
|
||||
if (type.specified)
|
||||
{
|
||||
@ -1955,8 +1937,6 @@ void CreateAlterTriggerNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
fb_assert(create || alter);
|
||||
|
||||
checkEmptyName(name);
|
||||
|
||||
Attachment* attachment = transaction->getAttachment();
|
||||
|
||||
if (relationName.isEmpty() && !attachment->locksmith())
|
||||
@ -2139,16 +2119,18 @@ bool CreateAlterTriggerNode::executeAlter(thread_db* tdbb, jrd_tra* transaction,
|
||||
}
|
||||
else if (body)
|
||||
{
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
TRG.RDB$TRIGGER_BLR.NULL = FALSE;
|
||||
attachment->storeBinaryBlob(tdbb, transaction, &TRG.RDB$TRIGGER_BLR,
|
||||
compiledStatement->req_blr_data.begin(),
|
||||
compiledStatement->req_blr_data.getCount());
|
||||
statement->blrData.begin(),
|
||||
statement->blrData.getCount());
|
||||
|
||||
// ODS_11_1
|
||||
TRG.RDB$DEBUG_INFO.NULL = FALSE;
|
||||
attachment->storeBinaryBlob(tdbb, transaction, &TRG.RDB$DEBUG_INFO,
|
||||
compiledStatement->req_debug_data.begin(),
|
||||
compiledStatement->req_debug_data.getCount());
|
||||
statement->debugData.begin(),
|
||||
statement->debugData.getCount());
|
||||
}
|
||||
|
||||
if (source.hasData())
|
||||
@ -2184,14 +2166,16 @@ void CreateAlterTriggerNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/)
|
||||
|
||||
if (body)
|
||||
{
|
||||
compiledStatement->begin_debug();
|
||||
compiledStatement->req_blr_data.clear();
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
statement->begin_debug();
|
||||
statement->blrData.clear();
|
||||
|
||||
// Create the "OLD" and "NEW" contexts for the trigger --
|
||||
// the new one could be a dummy place holder to avoid resolving
|
||||
// fields to that context but prevent relations referenced in
|
||||
// the trigger actions from referencing the predefined "1" context.
|
||||
if (compiledStatement->req_context_number)
|
||||
if (dsqlScratch->contextNumber)
|
||||
resetContextStack();
|
||||
|
||||
if (relationName.hasData())
|
||||
@ -2207,38 +2191,38 @@ void CreateAlterTriggerNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/)
|
||||
if (hasOldContext(type.value))
|
||||
{
|
||||
relationNode->nod_arg[e_rln_alias] = (dsql_nod*) MAKE_cstring(OLD_CONTEXT);
|
||||
dsql_ctx* oldContext = PASS1_make_context(compiledStatement, relationNode);
|
||||
dsql_ctx* oldContext = PASS1_make_context(dsqlScratch, relationNode);
|
||||
oldContext->ctx_flags |= CTX_system;
|
||||
}
|
||||
else
|
||||
compiledStatement->req_context_number++;
|
||||
dsqlScratch->contextNumber++;
|
||||
|
||||
if (hasNewContext(type.value))
|
||||
{
|
||||
relationNode->nod_arg[e_rln_alias] = (dsql_nod*) MAKE_cstring(NEW_CONTEXT);
|
||||
dsql_ctx* newContext = PASS1_make_context(compiledStatement, relationNode);
|
||||
dsql_ctx* newContext = PASS1_make_context(dsqlScratch, relationNode);
|
||||
newContext->ctx_flags |= CTX_system;
|
||||
}
|
||||
else
|
||||
compiledStatement->req_context_number++;
|
||||
dsqlScratch->contextNumber++;
|
||||
|
||||
relationNode->nod_arg[e_rln_alias] = temp;
|
||||
}
|
||||
|
||||
// generate the trigger blr
|
||||
|
||||
if (compiledStatement->req_flags & REQ_blr_version4)
|
||||
compiledStatement->append_uchar(blr_version4);
|
||||
if (statement->flags & REQ_blr_version4)
|
||||
statement->append_uchar(blr_version4);
|
||||
else
|
||||
compiledStatement->append_uchar(blr_version5);
|
||||
statement->append_uchar(blr_version5);
|
||||
|
||||
compiledStatement->append_uchar(blr_begin);
|
||||
statement->append_uchar(blr_begin);
|
||||
|
||||
compiledStatement->setPsql(true);
|
||||
dsqlScratch->setPsql(true);
|
||||
|
||||
DDL_put_local_variables(compiledStatement, localDeclList, 0, variables);
|
||||
DDL_put_local_variables(dsqlScratch, localDeclList, 0, variables);
|
||||
|
||||
compiledStatement->req_scope_level++;
|
||||
dsqlScratch->scopeLevel++;
|
||||
// dimitr: I see no reason to deny EXIT command in triggers,
|
||||
// hence I've added zero label at the beginning.
|
||||
// My first suspicion regarding an obvious conflict
|
||||
@ -2246,21 +2230,21 @@ void CreateAlterTriggerNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/)
|
||||
// although the fact that they use the same BLR code
|
||||
// is still a potential danger and must be fixed.
|
||||
// Hopefully, system triggers are never recompiled.
|
||||
compiledStatement->append_uchar(blr_label);
|
||||
compiledStatement->append_uchar(0);
|
||||
compiledStatement->req_loop_level = 0;
|
||||
compiledStatement->req_cursor_number = 0;
|
||||
GEN_statement(compiledStatement, PASS1_statement(compiledStatement, body));
|
||||
compiledStatement->req_scope_level--;
|
||||
compiledStatement->append_uchar(blr_end);
|
||||
compiledStatement->append_uchar(blr_eoc);
|
||||
statement->append_uchar(blr_label);
|
||||
statement->append_uchar(0);
|
||||
dsqlScratch->loopLevel = 0;
|
||||
dsqlScratch->cursorNumber = 0;
|
||||
GEN_statement(dsqlScratch, PASS1_statement(dsqlScratch, body));
|
||||
dsqlScratch->scopeLevel--;
|
||||
statement->append_uchar(blr_end);
|
||||
statement->append_uchar(blr_eoc);
|
||||
|
||||
compiledStatement->end_debug();
|
||||
statement->end_debug();
|
||||
|
||||
// The statement type may have been set incorrectly when parsing
|
||||
// the trigger actions, so reset it to reflect the fact that this
|
||||
// is a data definition statement; also reset the ddl node.
|
||||
compiledStatement->req_type = REQ_DDL;
|
||||
statement->type = REQ_DDL;
|
||||
}
|
||||
|
||||
invalid = false;
|
||||
@ -2279,9 +2263,9 @@ void DropTriggerNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
|
||||
}
|
||||
|
||||
|
||||
Node* DropTriggerNode::internalDsqlPass()
|
||||
DdlNode* DropTriggerNode::internalDsqlPass()
|
||||
{
|
||||
compiledStatement->req_flags |= (REQ_block | REQ_procedure | REQ_trigger);
|
||||
dsqlScratch->getStatement()->flags |= (REQ_block | REQ_procedure | REQ_trigger);
|
||||
return DdlNode::internalDsqlPass();
|
||||
}
|
||||
|
||||
@ -2408,10 +2392,10 @@ void RecreateTriggerNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
|
||||
}
|
||||
|
||||
|
||||
Node* RecreateTriggerNode::internalDsqlPass()
|
||||
DdlNode* RecreateTriggerNode::internalDsqlPass()
|
||||
{
|
||||
dropNode.dsqlPass(compiledStatement);
|
||||
createNode->dsqlPass(compiledStatement);
|
||||
dropNode.dsqlPass(dsqlScratch);
|
||||
createNode->dsqlPass(dsqlScratch);
|
||||
return DdlNode::internalDsqlPass();
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
virtual ~TypeClause() {}
|
||||
|
||||
public:
|
||||
void resolve(CompiledStatement* compiledStatement);
|
||||
void resolve(DsqlCompilerScratch* dsqlScratch);
|
||||
|
||||
public:
|
||||
virtual void print(Firebird::string& text) const;
|
||||
@ -167,6 +167,9 @@ public:
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual DdlNode* internalDsqlPass();
|
||||
|
||||
private:
|
||||
void executeCreate(thread_db* tdbb, jrd_tra* transaction);
|
||||
bool executeAlter(thread_db* tdbb, jrd_tra* transaction);
|
||||
@ -266,7 +269,7 @@ public:
|
||||
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual Node* internalDsqlPass();
|
||||
virtual DdlNode* internalDsqlPass();
|
||||
|
||||
private:
|
||||
void executeCreate(thread_db* tdbb, jrd_tra* transaction);
|
||||
@ -316,7 +319,7 @@ public:
|
||||
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual Node* internalDsqlPass();
|
||||
virtual DdlNode* internalDsqlPass();
|
||||
|
||||
public:
|
||||
Firebird::MetaName name;
|
||||
@ -348,7 +351,7 @@ public:
|
||||
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual Node* internalDsqlPass();
|
||||
virtual DdlNode* internalDsqlPass();
|
||||
|
||||
private:
|
||||
CreateAlterProcedureNode* createNode;
|
||||
@ -412,7 +415,7 @@ public:
|
||||
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual Node* internalDsqlPass();
|
||||
virtual DdlNode* internalDsqlPass();
|
||||
|
||||
private:
|
||||
void executeCreate(thread_db* tdbb, jrd_tra* transaction);
|
||||
@ -469,7 +472,7 @@ public:
|
||||
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual Node* internalDsqlPass();
|
||||
virtual DdlNode* internalDsqlPass();
|
||||
|
||||
public:
|
||||
Firebird::MetaName name;
|
||||
@ -501,7 +504,7 @@ public:
|
||||
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual Node* internalDsqlPass();
|
||||
virtual DdlNode* internalDsqlPass();
|
||||
|
||||
private:
|
||||
CreateAlterTriggerNode* createNode;
|
||||
|
@ -37,7 +37,7 @@ class Node : public Firebird::PermanentStorage
|
||||
public:
|
||||
explicit Node(MemoryPool& pool)
|
||||
: PermanentStorage(pool),
|
||||
compiledStatement(NULL)
|
||||
dsqlScratch(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -46,9 +46,9 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
Node* dsqlPass(CompiledStatement* aCompiledStatement)
|
||||
Node* dsqlPass(DsqlCompilerScratch* aDsqlScratch)
|
||||
{
|
||||
compiledStatement = aCompiledStatement;
|
||||
dsqlScratch = aDsqlScratch;
|
||||
return internalDsqlPass();
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ protected:
|
||||
}
|
||||
|
||||
protected:
|
||||
CompiledStatement* compiledStatement;
|
||||
DsqlCompilerScratch* dsqlScratch;
|
||||
};
|
||||
|
||||
|
||||
@ -87,9 +87,6 @@ public:
|
||||
DdlTriggerWhen when, int action, const Firebird::MetaName& objectName,
|
||||
const Firebird::string& sqlText);
|
||||
|
||||
public:
|
||||
static void checkEmptyName(const Firebird::MetaName& name);
|
||||
|
||||
protected:
|
||||
void executeDdlTrigger(thread_db* tdbb, jrd_tra* transaction,
|
||||
DdlTriggerWhen when, int action, const Firebird::MetaName& objectName);
|
||||
@ -97,9 +94,9 @@ protected:
|
||||
void resetContextStack();
|
||||
|
||||
protected:
|
||||
virtual Node* internalDsqlPass()
|
||||
virtual DdlNode* internalDsqlPass()
|
||||
{
|
||||
compiledStatement->req_type = REQ_DDL;
|
||||
dsqlScratch->getStatement()->type = REQ_DDL;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "../jrd/met_proto.h"
|
||||
#include "../jrd/vio_proto.h"
|
||||
#include "../dsql/make_proto.h"
|
||||
#include "../dsql/metd_proto.h"
|
||||
#include "../dsql/pass1_proto.h"
|
||||
#include "../common/StatusArg.h"
|
||||
|
||||
@ -376,19 +375,19 @@ void CreateAlterPackageNode::print(string& text, Array<dsql_nod*>& /*nodes*/) co
|
||||
}
|
||||
|
||||
|
||||
Node* CreateAlterPackageNode::internalDsqlPass()
|
||||
DdlNode* CreateAlterPackageNode::internalDsqlPass()
|
||||
{
|
||||
source.ltrim("\n\r\t ");
|
||||
|
||||
// items
|
||||
for (unsigned i = 0; i < items->getCount(); ++i)
|
||||
{
|
||||
CompiledStatement* itemStatement = FB_NEW(getPool()) CompiledStatement(getPool());
|
||||
itemStatement->req_dbb = compiledStatement->req_dbb;
|
||||
itemStatement->req_transaction = compiledStatement->req_transaction;
|
||||
itemStatement->req_client_dialect = compiledStatement->req_client_dialect;
|
||||
itemStatement->req_package = name;
|
||||
itemStatement->req_ddl_node = MAKE_node(nod_class_node, 1);
|
||||
DsqlCompiledStatement* itemStatement = FB_NEW(getPool()) DsqlCompiledStatement(getPool());
|
||||
DsqlCompilerScratch* itemScratch = FB_NEW(getPool()) DsqlCompilerScratch(getPool(),
|
||||
dsqlScratch->getAttachment(), dsqlScratch->getTransaction(), itemStatement);
|
||||
itemScratch->clientDialect = dsqlScratch->clientDialect;
|
||||
itemScratch->package = name;
|
||||
itemStatement->ddlNode = MAKE_node(nod_class_node, 1);
|
||||
|
||||
switch ((*items)[i].type)
|
||||
{
|
||||
@ -398,8 +397,8 @@ Node* CreateAlterPackageNode::internalDsqlPass()
|
||||
functionNames.add(fun->name);
|
||||
fun->alter = true;
|
||||
fun->package = name;
|
||||
itemStatement->req_ddl_node->nod_arg[0] = (dsql_nod*) fun;
|
||||
fun->dsqlPass(itemStatement);
|
||||
itemStatement->ddlNode->nod_arg[0] = (dsql_nod*) fun;
|
||||
fun->dsqlPass(itemScratch);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -409,8 +408,8 @@ Node* CreateAlterPackageNode::internalDsqlPass()
|
||||
procedureNames.add(proc->name);
|
||||
proc->alter = true;
|
||||
proc->package = name;
|
||||
itemStatement->req_ddl_node->nod_arg[0] = (dsql_nod*) proc;
|
||||
proc->dsqlPass(itemStatement);
|
||||
itemStatement->ddlNode->nod_arg[0] = (dsql_nod*) proc;
|
||||
proc->dsqlPass(itemScratch);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -541,7 +540,7 @@ bool CreateAlterPackageNode::executeAlter(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
DropFunctionNode dropNode(getPool(), "", i->name);
|
||||
dropNode.package = name;
|
||||
dropNode.dsqlPass(compiledStatement);
|
||||
dropNode.dsqlPass(dsqlScratch);
|
||||
dropNode.execute(tdbb, transaction);
|
||||
}
|
||||
}
|
||||
@ -553,7 +552,7 @@ bool CreateAlterPackageNode::executeAlter(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
DropProcedureNode dropNode(getPool(), "", i->name);
|
||||
dropNode.package = name;
|
||||
dropNode.dsqlPass(compiledStatement);
|
||||
dropNode.dsqlPass(dsqlScratch);
|
||||
dropNode.execute(tdbb, transaction);
|
||||
}
|
||||
}
|
||||
@ -633,7 +632,7 @@ void DropPackageNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
DropFunctionNode dropNode(getPool(), "", i->name);
|
||||
dropNode.package = name;
|
||||
dropNode.dsqlPass(compiledStatement);
|
||||
dropNode.dsqlPass(dsqlScratch);
|
||||
dropNode.execute(tdbb, transaction);
|
||||
}
|
||||
|
||||
@ -642,7 +641,7 @@ void DropPackageNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
DropProcedureNode dropNode(getPool(), "", i->name);
|
||||
dropNode.package = name;
|
||||
dropNode.dsqlPass(compiledStatement);
|
||||
dropNode.dsqlPass(dsqlScratch);
|
||||
dropNode.execute(tdbb, transaction);
|
||||
}
|
||||
|
||||
@ -674,10 +673,10 @@ void RecreatePackageNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
|
||||
}
|
||||
|
||||
|
||||
Node* RecreatePackageNode::internalDsqlPass()
|
||||
DdlNode* RecreatePackageNode::internalDsqlPass()
|
||||
{
|
||||
dropNode.dsqlPass(compiledStatement);
|
||||
createNode->dsqlPass(compiledStatement);
|
||||
dropNode.dsqlPass(dsqlScratch);
|
||||
createNode->dsqlPass(dsqlScratch);
|
||||
return DdlNode::internalDsqlPass();
|
||||
}
|
||||
|
||||
@ -758,7 +757,7 @@ void CreatePackageBodyNode::print(string& text, Array<dsql_nod*>& /*nodes*/) con
|
||||
}
|
||||
|
||||
|
||||
Node* CreatePackageBodyNode::internalDsqlPass()
|
||||
DdlNode* CreatePackageBodyNode::internalDsqlPass()
|
||||
{
|
||||
source.ltrim("\n\r\t ");
|
||||
|
||||
@ -772,12 +771,12 @@ Node* CreatePackageBodyNode::internalDsqlPass()
|
||||
|
||||
for (unsigned j = 0; j < arrays[i]->getCount(); ++j)
|
||||
{
|
||||
CompiledStatement* itemStatement = FB_NEW(getPool()) CompiledStatement(getPool());
|
||||
itemStatement->req_dbb = compiledStatement->req_dbb;
|
||||
itemStatement->req_transaction = compiledStatement->req_transaction;
|
||||
itemStatement->req_client_dialect = compiledStatement->req_client_dialect;
|
||||
itemStatement->req_package = name;
|
||||
itemStatement->req_ddl_node = MAKE_node(nod_class_node, 1);
|
||||
DsqlCompiledStatement* itemStatement = FB_NEW(getPool()) DsqlCompiledStatement(getPool());
|
||||
DsqlCompilerScratch* itemScratch = FB_NEW(getPool()) DsqlCompilerScratch(getPool(),
|
||||
dsqlScratch->getAttachment(), dsqlScratch->getTransaction(), itemStatement);
|
||||
itemScratch->clientDialect = dsqlScratch->clientDialect;
|
||||
itemScratch->package = name;
|
||||
itemStatement->ddlNode = MAKE_node(nod_class_node, 1);
|
||||
|
||||
switch ((*arrays[i])[j].type)
|
||||
{
|
||||
@ -790,8 +789,8 @@ Node* CreatePackageBodyNode::internalDsqlPass()
|
||||
fun->alter = true;
|
||||
else
|
||||
fun->privateScope = true;
|
||||
itemStatement->req_ddl_node->nod_arg[0] = (dsql_nod*) fun;
|
||||
fun->dsqlPass(itemStatement);
|
||||
itemStatement->ddlNode->nod_arg[0] = (dsql_nod*) fun;
|
||||
fun->dsqlPass(itemScratch);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -804,8 +803,8 @@ Node* CreatePackageBodyNode::internalDsqlPass()
|
||||
proc->alter = true;
|
||||
else
|
||||
proc->privateScope = true;
|
||||
itemStatement->req_ddl_node->nod_arg[0] = (dsql_nod*) proc;
|
||||
proc->dsqlPass(itemStatement);
|
||||
itemStatement->ddlNode->nod_arg[0] = (dsql_nod*) proc;
|
||||
proc->dsqlPass(itemScratch);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1024,7 +1023,7 @@ void DropPackageBodyNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
DropFunctionNode dropNode(getPool(), "", FUN.RDB$FUNCTION_NAME);
|
||||
dropNode.package = name;
|
||||
dropNode.dsqlPass(compiledStatement);
|
||||
dropNode.dsqlPass(dsqlScratch);
|
||||
dropNode.execute(tdbb, transaction);
|
||||
}
|
||||
else
|
||||
@ -1048,7 +1047,7 @@ void DropPackageBodyNode::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
DropProcedureNode dropNode(getPool(), "", PRC.RDB$PROCEDURE_NAME);
|
||||
dropNode.package = name;
|
||||
dropNode.dsqlPass(compiledStatement);
|
||||
dropNode.dsqlPass(dsqlScratch);
|
||||
dropNode.execute(tdbb, transaction);
|
||||
}
|
||||
else
|
||||
@ -1079,10 +1078,10 @@ void RecreatePackageBodyNode::print(string& text, Array<dsql_nod*>& /*nodes*/) c
|
||||
}
|
||||
|
||||
|
||||
Node* RecreatePackageBodyNode::internalDsqlPass()
|
||||
DdlNode* RecreatePackageBodyNode::internalDsqlPass()
|
||||
{
|
||||
dropNode.dsqlPass(compiledStatement);
|
||||
createNode->dsqlPass(compiledStatement);
|
||||
dropNode.dsqlPass(dsqlScratch);
|
||||
createNode->dsqlPass(dsqlScratch);
|
||||
return DdlNode::internalDsqlPass();
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ public:
|
||||
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual Node* internalDsqlPass();
|
||||
virtual DdlNode* internalDsqlPass();
|
||||
|
||||
private:
|
||||
void executeCreate(thread_db* tdbb, jrd_tra* transaction);
|
||||
@ -142,7 +142,7 @@ public:
|
||||
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual Node* internalDsqlPass();
|
||||
virtual DdlNode* internalDsqlPass();
|
||||
|
||||
private:
|
||||
CreateAlterPackageNode* createNode;
|
||||
@ -169,7 +169,7 @@ public:
|
||||
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual Node* internalDsqlPass();
|
||||
virtual DdlNode* internalDsqlPass();
|
||||
|
||||
public:
|
||||
Firebird::MetaName name;
|
||||
@ -217,7 +217,7 @@ public:
|
||||
virtual void execute(thread_db* tdbb, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual Node* internalDsqlPass();
|
||||
virtual DdlNode* internalDsqlPass();
|
||||
|
||||
private:
|
||||
CreatePackageBodyNode* createNode;
|
||||
|
@ -93,10 +93,10 @@ DmlNode* IfNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb,
|
||||
IfNode* IfNode::internalDsqlPass()
|
||||
{
|
||||
IfNode* node = FB_NEW(getPool()) IfNode(getPool());
|
||||
node->compiledStatement = compiledStatement;
|
||||
node->dsqlCondition = PASS1_node(compiledStatement, dsqlCondition);
|
||||
node->dsqlTrueAction = PASS1_statement(compiledStatement, dsqlTrueAction);
|
||||
node->dsqlFalseAction = PASS1_statement(compiledStatement, dsqlFalseAction);
|
||||
node->dsqlScratch = dsqlScratch;
|
||||
node->dsqlCondition = PASS1_node(dsqlScratch, dsqlCondition);
|
||||
node->dsqlTrueAction = PASS1_statement(dsqlScratch, dsqlTrueAction);
|
||||
node->dsqlFalseAction = PASS1_statement(dsqlScratch, dsqlFalseAction);
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -114,13 +114,15 @@ void IfNode::print(string& text, Array<dsql_nod*>& nodes) const
|
||||
|
||||
void IfNode::genBlr()
|
||||
{
|
||||
stuff(compiledStatement, blr_if);
|
||||
GEN_expr(compiledStatement, dsqlCondition);
|
||||
GEN_statement(compiledStatement, dsqlTrueAction);
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
stuff(statement, blr_if);
|
||||
GEN_expr(dsqlScratch, dsqlCondition);
|
||||
GEN_statement(dsqlScratch, dsqlTrueAction);
|
||||
if (dsqlFalseAction)
|
||||
GEN_statement(compiledStatement, dsqlFalseAction);
|
||||
GEN_statement(dsqlScratch, dsqlFalseAction);
|
||||
else
|
||||
stuff(compiledStatement, blr_end);
|
||||
stuff(statement, blr_end);
|
||||
}
|
||||
|
||||
|
||||
@ -187,15 +189,17 @@ DmlNode* InAutonomousTransactionNode::parse(thread_db* tdbb, MemoryPool& pool, C
|
||||
|
||||
InAutonomousTransactionNode* InAutonomousTransactionNode::internalDsqlPass()
|
||||
{
|
||||
const bool autoTrans = compiledStatement->req_flags & REQ_in_auto_trans_block;
|
||||
compiledStatement->req_flags |= REQ_in_auto_trans_block;
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
const bool autoTrans = statement->flags & REQ_in_auto_trans_block;
|
||||
statement->flags |= REQ_in_auto_trans_block;
|
||||
|
||||
InAutonomousTransactionNode* node = FB_NEW(getPool()) InAutonomousTransactionNode(getPool());
|
||||
node->compiledStatement = compiledStatement;
|
||||
node->dsqlAction = PASS1_statement(compiledStatement, dsqlAction);
|
||||
node->dsqlScratch = dsqlScratch;
|
||||
node->dsqlAction = PASS1_statement(dsqlScratch, dsqlAction);
|
||||
|
||||
if (!autoTrans)
|
||||
compiledStatement->req_flags &= ~REQ_in_auto_trans_block;
|
||||
statement->flags &= ~REQ_in_auto_trans_block;
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -210,9 +214,11 @@ void InAutonomousTransactionNode::print(string& text, Array<dsql_nod*>& nodes) c
|
||||
|
||||
void InAutonomousTransactionNode::genBlr()
|
||||
{
|
||||
stuff(compiledStatement, blr_auto_trans);
|
||||
stuff(compiledStatement, 0); // to extend syntax in the future
|
||||
GEN_statement(compiledStatement, dsqlAction);
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
stuff(statement, blr_auto_trans);
|
||||
stuff(statement, 0); // to extend syntax in the future
|
||||
GEN_statement(dsqlScratch, dsqlAction);
|
||||
}
|
||||
|
||||
|
||||
@ -376,19 +382,21 @@ jrd_nod* InAutonomousTransactionNode::execute(thread_db* tdbb, jrd_req* request)
|
||||
|
||||
ExecBlockNode* ExecBlockNode::internalDsqlPass()
|
||||
{
|
||||
compiledStatement->blockNode = this;
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
statement->blockNode = this;
|
||||
|
||||
if (returns.hasData())
|
||||
compiledStatement->req_type = REQ_SELECT_BLOCK;
|
||||
statement->type = REQ_SELECT_BLOCK;
|
||||
else
|
||||
compiledStatement->req_type = REQ_EXEC_BLOCK;
|
||||
statement->type = REQ_EXEC_BLOCK;
|
||||
|
||||
compiledStatement->req_flags |= REQ_block;
|
||||
statement->flags |= REQ_block;
|
||||
|
||||
ExecBlockNode* node = FB_NEW(getPool()) ExecBlockNode(getPool());
|
||||
node->compiledStatement = compiledStatement;
|
||||
node->dsqlScratch = dsqlScratch;
|
||||
|
||||
node->legacyParameters = PASS1_node_psql(compiledStatement, legacyParameters, false);
|
||||
node->legacyParameters = PASS1_node_psql(dsqlScratch, legacyParameters, false);
|
||||
node->returns = returns;
|
||||
node->localDeclList = localDeclList;
|
||||
node->body = body;
|
||||
@ -448,10 +456,12 @@ void ExecBlockNode::print(string& text, Array<dsql_nod*>& nodes) const
|
||||
|
||||
void ExecBlockNode::genBlr()
|
||||
{
|
||||
// Update blockNode, because we have a reference to the original unprocessed node.
|
||||
compiledStatement->blockNode = this;
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
compiledStatement->begin_debug();
|
||||
// Update blockNode, because we have a reference to the original unprocessed node.
|
||||
statement->blockNode = this;
|
||||
|
||||
statement->begin_debug();
|
||||
|
||||
USHORT inputs = 0, outputs = 0, locals = 0;
|
||||
|
||||
@ -466,7 +476,7 @@ void ExecBlockNode::genBlr()
|
||||
dsql_fld* field = (dsql_fld*) parameter->nod_arg[Dsql::e_dfl_field];
|
||||
// parameter = (*ptr)->nod_arg[Dsql::e_prm_val_val]; USELESS
|
||||
|
||||
DDL_resolve_intl_type(compiledStatement, field,
|
||||
DDL_resolve_intl_type(dsqlScratch, field,
|
||||
reinterpret_cast<const dsql_str*>(parameter->nod_arg[Dsql::e_dfl_collate]));
|
||||
|
||||
variables.add(MAKE_variable(field, field->fld_name.c_str(),
|
||||
@ -483,7 +493,7 @@ void ExecBlockNode::genBlr()
|
||||
{
|
||||
ParameterClause& parameter = returns[i];
|
||||
|
||||
parameter.resolve(compiledStatement);
|
||||
parameter.resolve(dsqlScratch);
|
||||
|
||||
dsql_nod* var = MAKE_variable(parameter.legacyField,
|
||||
parameter.name.c_str(), VAR_output, 1, (USHORT) (2 * outputs), locals++);
|
||||
@ -494,42 +504,42 @@ void ExecBlockNode::genBlr()
|
||||
++outputs;
|
||||
}
|
||||
|
||||
compiledStatement->append_uchar(blr_begin);
|
||||
statement->append_uchar(blr_begin);
|
||||
|
||||
if (inputs)
|
||||
{
|
||||
revertParametersOrder(compiledStatement->req_send->msg_parameters);
|
||||
GEN_port(compiledStatement, compiledStatement->req_send);
|
||||
revertParametersOrder(statement->sendMsg->msg_parameters);
|
||||
GEN_port(dsqlScratch, statement->sendMsg);
|
||||
}
|
||||
else
|
||||
compiledStatement->req_send = NULL;
|
||||
statement->sendMsg = NULL;
|
||||
|
||||
for (Array<dsql_nod*>::const_iterator i = outputVariables.begin(); i != outputVariables.end(); ++i)
|
||||
{
|
||||
dsql_par* param = MAKE_parameter(compiledStatement->req_receive, true, true,
|
||||
dsql_par* param = MAKE_parameter(statement->receiveMsg, true, true,
|
||||
(i - outputVariables.begin()) + 1, *i);
|
||||
param->par_node = *i;
|
||||
MAKE_desc(compiledStatement, ¶m->par_desc, *i, NULL);
|
||||
MAKE_desc(dsqlScratch, ¶m->par_desc, *i, NULL);
|
||||
param->par_desc.dsc_flags |= DSC_nullable;
|
||||
}
|
||||
|
||||
// Set up parameter to handle EOF
|
||||
dsql_par* param = MAKE_parameter(compiledStatement->req_receive, false, false, 0, NULL);
|
||||
compiledStatement->req_eof = param;
|
||||
dsql_par* param = MAKE_parameter(statement->receiveMsg, false, false, 0, NULL);
|
||||
statement->eof = param;
|
||||
param->par_desc.dsc_dtype = dtype_short;
|
||||
param->par_desc.dsc_scale = 0;
|
||||
param->par_desc.dsc_length = sizeof(SSHORT);
|
||||
|
||||
revertParametersOrder(compiledStatement->req_receive->msg_parameters);
|
||||
GEN_port(compiledStatement, compiledStatement->req_receive);
|
||||
revertParametersOrder(statement->receiveMsg->msg_parameters);
|
||||
GEN_port(dsqlScratch, statement->receiveMsg);
|
||||
|
||||
if (inputs)
|
||||
{
|
||||
compiledStatement->append_uchar(blr_receive);
|
||||
compiledStatement->append_uchar(0);
|
||||
statement->append_uchar(blr_receive);
|
||||
statement->append_uchar(0);
|
||||
}
|
||||
|
||||
compiledStatement->append_uchar(blr_begin);
|
||||
statement->append_uchar(blr_begin);
|
||||
|
||||
for (unsigned i = 0; i < returnsPos; ++i)
|
||||
{
|
||||
@ -542,14 +552,14 @@ void ExecBlockNode::genBlr()
|
||||
// ASF: Validation of execute block input parameters is different than procedure
|
||||
// parameters, because we can't generate messages using the domains due to the
|
||||
// connection charset influence. So to validate, we cast them and assign to null.
|
||||
compiledStatement->append_uchar(blr_assignment);
|
||||
compiledStatement->append_uchar(blr_cast);
|
||||
DDL_put_field_dtype(compiledStatement, field, true);
|
||||
compiledStatement->append_uchar(blr_parameter2);
|
||||
compiledStatement->append_uchar(0);
|
||||
compiledStatement->append_ushort(variable->var_msg_item);
|
||||
compiledStatement->append_ushort(variable->var_msg_item + 1);
|
||||
compiledStatement->append_uchar(blr_null);
|
||||
statement->append_uchar(blr_assignment);
|
||||
statement->append_uchar(blr_cast);
|
||||
DDL_put_field_dtype(dsqlScratch, field, true);
|
||||
statement->append_uchar(blr_parameter2);
|
||||
statement->append_uchar(0);
|
||||
statement->append_ushort(variable->var_msg_item);
|
||||
statement->append_ushort(variable->var_msg_item + 1);
|
||||
statement->append_uchar(blr_null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -557,40 +567,40 @@ void ExecBlockNode::genBlr()
|
||||
{
|
||||
dsql_nod* parameter = *i;
|
||||
dsql_var* variable = (dsql_var*) parameter->nod_arg[Dsql::e_var_variable];
|
||||
DDL_put_local_variable(compiledStatement, variable, 0, NULL);
|
||||
DDL_put_local_variable(dsqlScratch, variable, 0, NULL);
|
||||
}
|
||||
|
||||
compiledStatement->setPsql(true);
|
||||
dsqlScratch->setPsql(true);
|
||||
|
||||
DDL_put_local_variables(compiledStatement, localDeclList, locals, variables);
|
||||
DDL_put_local_variables(dsqlScratch, localDeclList, locals, variables);
|
||||
|
||||
compiledStatement->req_loop_level = 0;
|
||||
dsqlScratch->loopLevel = 0;
|
||||
|
||||
dsql_nod* stmtNode = PASS1_statement(compiledStatement, body);
|
||||
GEN_hidden_variables(compiledStatement, false);
|
||||
dsql_nod* stmtNode = PASS1_statement(dsqlScratch, body);
|
||||
GEN_hidden_variables(dsqlScratch, false);
|
||||
|
||||
compiledStatement->append_uchar(blr_stall);
|
||||
statement->append_uchar(blr_stall);
|
||||
// Put a label before body of procedure, so that
|
||||
// any exit statement can get out
|
||||
compiledStatement->append_uchar(blr_label);
|
||||
compiledStatement->append_uchar(0);
|
||||
GEN_statement(compiledStatement, stmtNode);
|
||||
statement->append_uchar(blr_label);
|
||||
statement->append_uchar(0);
|
||||
GEN_statement(dsqlScratch, stmtNode);
|
||||
if (outputs)
|
||||
compiledStatement->req_type = REQ_SELECT_BLOCK;
|
||||
statement->type = REQ_SELECT_BLOCK;
|
||||
else
|
||||
compiledStatement->req_type = REQ_EXEC_BLOCK;
|
||||
statement->type = REQ_EXEC_BLOCK;
|
||||
|
||||
compiledStatement->append_uchar(blr_end);
|
||||
GEN_return(compiledStatement, outputVariables, true);
|
||||
compiledStatement->append_uchar(blr_end);
|
||||
statement->append_uchar(blr_end);
|
||||
GEN_return(dsqlScratch, outputVariables, true);
|
||||
statement->append_uchar(blr_end);
|
||||
|
||||
compiledStatement->end_debug();
|
||||
statement->end_debug();
|
||||
}
|
||||
|
||||
|
||||
void ExecBlockNode::genReturn()
|
||||
{
|
||||
GEN_return(compiledStatement, outputVariables, false);
|
||||
GEN_return(dsqlScratch, outputVariables, false);
|
||||
}
|
||||
|
||||
|
||||
@ -629,8 +639,9 @@ void ExitNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
|
||||
|
||||
void ExitNode::genBlr()
|
||||
{
|
||||
stuff(compiledStatement, blr_leave);
|
||||
stuff(compiledStatement, 0);
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
stuff(statement, blr_leave);
|
||||
stuff(statement, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -656,10 +667,10 @@ DmlNode* PostEventNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch
|
||||
PostEventNode* PostEventNode::internalDsqlPass()
|
||||
{
|
||||
PostEventNode* node = FB_NEW(getPool()) PostEventNode(getPool());
|
||||
node->compiledStatement = compiledStatement;
|
||||
node->dsqlScratch = dsqlScratch;
|
||||
|
||||
node->dsqlEvent = PASS1_node(compiledStatement, dsqlEvent);
|
||||
node->dsqlArgument = PASS1_node(compiledStatement, dsqlArgument);
|
||||
node->dsqlEvent = PASS1_node(dsqlScratch, dsqlEvent);
|
||||
node->dsqlArgument = PASS1_node(dsqlScratch, dsqlArgument);
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -676,16 +687,18 @@ void PostEventNode::print(string& text, Array<dsql_nod*>& nodes) const
|
||||
|
||||
void PostEventNode::genBlr()
|
||||
{
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
if (dsqlArgument)
|
||||
{
|
||||
stuff(compiledStatement, blr_post_arg);
|
||||
GEN_expr(compiledStatement, dsqlEvent);
|
||||
GEN_expr(compiledStatement, dsqlArgument);
|
||||
stuff(statement, blr_post_arg);
|
||||
GEN_expr(dsqlScratch, dsqlEvent);
|
||||
GEN_expr(dsqlScratch, dsqlArgument);
|
||||
}
|
||||
else
|
||||
{
|
||||
stuff(compiledStatement, blr_post);
|
||||
GEN_expr(compiledStatement, dsqlEvent);
|
||||
stuff(statement, blr_post);
|
||||
GEN_expr(dsqlScratch, dsqlEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -745,8 +758,10 @@ DmlNode* SavepointNode::parse(thread_db* /*tdbb*/, MemoryPool& pool, CompilerScr
|
||||
|
||||
SavepointNode* SavepointNode::internalDsqlPass()
|
||||
{
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
// ASF: It should never enter in this IF, because the grammar does not allow it.
|
||||
if (compiledStatement->req_flags & REQ_block) // blocks, procedures and triggers
|
||||
if (statement->flags & REQ_block) // blocks, procedures and triggers
|
||||
{
|
||||
const char* cmd = NULL;
|
||||
|
||||
@ -777,7 +792,7 @@ SavepointNode* SavepointNode::internalDsqlPass()
|
||||
Arg::Gds(isc_random) << Arg::Str(cmd));
|
||||
}
|
||||
|
||||
compiledStatement->req_type = REQ_SAVEPOINT;
|
||||
statement->type = REQ_SAVEPOINT;
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -791,9 +806,10 @@ void SavepointNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
|
||||
|
||||
void SavepointNode::genBlr()
|
||||
{
|
||||
stuff(compiledStatement, blr_user_savepoint);
|
||||
stuff(compiledStatement, (UCHAR) command);
|
||||
stuff_cstring(compiledStatement, name.c_str());
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
stuff(statement, blr_user_savepoint);
|
||||
stuff(statement, (UCHAR) command);
|
||||
stuff_cstring(statement, name.c_str());
|
||||
}
|
||||
|
||||
|
||||
@ -936,7 +952,9 @@ DmlNode* SuspendNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
|
||||
|
||||
SuspendNode* SuspendNode::internalDsqlPass()
|
||||
{
|
||||
if (compiledStatement->req_flags & REQ_trigger) // triggers only
|
||||
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
|
||||
|
||||
if (statement->flags & REQ_trigger) // triggers only
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
||||
// Token unknown
|
||||
@ -944,15 +962,15 @@ SuspendNode* SuspendNode::internalDsqlPass()
|
||||
Arg::Gds(isc_random) << Arg::Str("SUSPEND"));
|
||||
}
|
||||
|
||||
if (compiledStatement->req_flags & REQ_in_auto_trans_block) // autonomous transaction
|
||||
if (statement->flags & REQ_in_auto_trans_block) // autonomous transaction
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
|
||||
Arg::Gds(isc_dsql_unsupported_in_auto_trans) << Arg::Str("SUSPEND"));
|
||||
}
|
||||
|
||||
compiledStatement->req_flags |= REQ_selectable;
|
||||
statement->flags |= REQ_selectable;
|
||||
|
||||
blockNode = compiledStatement->blockNode;
|
||||
blockNode = statement->blockNode;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ namespace Jrd {
|
||||
class IfNode : public StmtNode
|
||||
{
|
||||
public:
|
||||
explicit IfNode(MemoryPool& pool, CompiledStatement* aCompiledStatement = NULL)
|
||||
explicit IfNode(MemoryPool& pool, DsqlCompilerScratch* aDsqlScratch = NULL)
|
||||
: StmtNode(pool),
|
||||
dsqlCondition(NULL),
|
||||
dsqlTrueAction(NULL),
|
||||
@ -44,7 +44,7 @@ public:
|
||||
trueAction(NULL),
|
||||
falseAction(NULL)
|
||||
{
|
||||
compiledStatement = aCompiledStatement;
|
||||
dsqlScratch = aDsqlScratch;
|
||||
}
|
||||
|
||||
public:
|
||||
|
1116
src/dsql/ddl.cpp
1116
src/dsql/ddl.cpp
File diff suppressed because it is too large
Load Diff
@ -32,7 +32,7 @@
|
||||
|
||||
namespace Jrd {
|
||||
class dsql_req;
|
||||
class CompiledStatement;
|
||||
class DsqlCompilerScratch;
|
||||
class dsql_fld;
|
||||
class dsql_nod;
|
||||
class dsql_str;
|
||||
@ -62,14 +62,14 @@ const USHORT blr_dtypes[] = {
|
||||
};
|
||||
|
||||
void DDL_execute(Jrd::dsql_req*);
|
||||
void DDL_generate(Jrd::CompiledStatement*, Jrd::dsql_nod*);
|
||||
bool DDL_ids(const Jrd::dsql_req*);
|
||||
void DDL_put_field_dtype(Jrd::CompiledStatement*, const Jrd::dsql_fld*, bool);
|
||||
void DDL_resolve_intl_type(Jrd::CompiledStatement*, Jrd::dsql_fld*, const Jrd::dsql_str*);
|
||||
void DDL_resolve_intl_type2(Jrd::CompiledStatement*, Jrd::dsql_fld*, const Jrd::dsql_str*, bool);
|
||||
void DDL_generate(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);
|
||||
bool DDL_ids(const Jrd::DsqlCompilerScratch*);
|
||||
void DDL_put_field_dtype(Jrd::DsqlCompilerScratch*, const Jrd::dsql_fld*, bool);
|
||||
void DDL_resolve_intl_type(Jrd::DsqlCompilerScratch*, Jrd::dsql_fld*, const Jrd::dsql_str*);
|
||||
void DDL_resolve_intl_type2(Jrd::DsqlCompilerScratch*, Jrd::dsql_fld*, const Jrd::dsql_str*, bool);
|
||||
|
||||
void DDL_put_local_variable(Jrd::CompiledStatement*, Jrd::dsql_var*, Jrd::dsql_nod*, const Jrd::dsql_str*);
|
||||
void DDL_put_local_variables(Jrd::CompiledStatement*, const Jrd::dsql_nod*, SSHORT,
|
||||
void DDL_put_local_variable(Jrd::DsqlCompilerScratch*, Jrd::dsql_var*, Jrd::dsql_nod*, const Jrd::dsql_str*);
|
||||
void DDL_put_local_variables(Jrd::DsqlCompilerScratch*, const Jrd::dsql_nod*, SSHORT,
|
||||
Firebird::Array<Jrd::dsql_nod*>& variables);
|
||||
|
||||
#endif // DSQL_DDL_PROTO_H
|
||||
|
@ -96,14 +96,15 @@ static void map_in_out(dsql_req*, bool, const dsql_msg*, USHORT, const UCHAR*,
|
||||
static USHORT parse_blr(dsql_req*, USHORT, const UCHAR*, const USHORT, const Array<dsql_par*>&);
|
||||
static dsql_req* prepare(thread_db*, dsql_dbb*, jrd_tra*, USHORT, const TEXT*, USHORT, USHORT, bool);
|
||||
static UCHAR* put_item(UCHAR, const USHORT, const UCHAR*, UCHAR*, const UCHAR* const, const bool copy = true);
|
||||
static void release_statement(DsqlCompiledStatement* statement);
|
||||
static void release_request(thread_db*, dsql_req*, bool);
|
||||
static void sql_info(thread_db*, dsql_req*, USHORT, const UCHAR*, ULONG, UCHAR*);
|
||||
static UCHAR* var_info(dsql_msg*, const UCHAR*, const UCHAR* const, UCHAR*,
|
||||
const UCHAR* const, USHORT, bool);
|
||||
|
||||
static inline bool reqTypeWithCursor(REQ_TYPE req_type)
|
||||
static inline bool reqTypeWithCursor(REQ_TYPE type)
|
||||
{
|
||||
switch (req_type)
|
||||
switch (type)
|
||||
{
|
||||
case REQ_SELECT:
|
||||
case REQ_SELECT_BLOCK:
|
||||
@ -182,7 +183,8 @@ dsql_req* DSQL_allocate_statement(thread_db* tdbb, Jrd::Attachment* attachment)
|
||||
// allocate the request block
|
||||
|
||||
MemoryPool& pool = *tdbb->getDefaultPool();
|
||||
dsql_req* const request = FB_NEW(pool) dsql_req(pool);
|
||||
DsqlCompiledStatement* statement = FB_NEW(pool) DsqlCompiledStatement(pool);
|
||||
dsql_req* const request = FB_NEW(pool) dsql_req(statement);
|
||||
request->req_dbb = database;
|
||||
|
||||
return request;
|
||||
@ -222,19 +224,19 @@ void DSQL_execute(thread_db* tdbb,
|
||||
|
||||
Jrd::ContextPoolHolder context(tdbb, &request->req_pool);
|
||||
|
||||
if (request->req_flags & REQ_orphan)
|
||||
if (request->getStatement()->flags & REQ_orphan)
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
|
||||
Arg::Gds(isc_bad_req_handle));
|
||||
}
|
||||
|
||||
if ((SSHORT) in_msg_type == -1) {
|
||||
request->req_type = REQ_EMBED_SELECT;
|
||||
request->getStatement()->type = REQ_EMBED_SELECT;
|
||||
}
|
||||
|
||||
// Only allow NULL trans_handle if we're starting a transaction
|
||||
|
||||
if (!*tra_handle && request->req_type != REQ_START_TRANS)
|
||||
if (!*tra_handle && request->getStatement()->type != REQ_START_TRANS)
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
|
||||
Arg::Gds(isc_bad_trans_handle));
|
||||
@ -243,9 +245,9 @@ void DSQL_execute(thread_db* tdbb,
|
||||
// If the request is a SELECT or blob statement then this is an open.
|
||||
// Make sure the cursor is not already open.
|
||||
|
||||
if (reqTypeWithCursor(request->req_type))
|
||||
if (reqTypeWithCursor(request->getStatement()->type))
|
||||
{
|
||||
if (request->req_flags & REQ_cursor_open)
|
||||
if (request->getStatement()->flags & REQ_cursor_open)
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-502) <<
|
||||
Arg::Gds(isc_dsql_cursor_open_err));
|
||||
@ -254,14 +256,14 @@ void DSQL_execute(thread_db* tdbb,
|
||||
|
||||
// A select with a non zero output length is a singleton select
|
||||
bool singleton;
|
||||
if (request->req_type == REQ_SELECT && out_msg_length != 0) {
|
||||
if (request->getStatement()->type == REQ_SELECT && out_msg_length != 0) {
|
||||
singleton = true;
|
||||
}
|
||||
else {
|
||||
singleton = false;
|
||||
}
|
||||
|
||||
if (request->req_type != REQ_EMBED_SELECT)
|
||||
if (request->getStatement()->type != REQ_EMBED_SELECT)
|
||||
{
|
||||
execute_request(tdbb, request, tra_handle,
|
||||
in_blr_length, in_blr, in_msg_length, in_msg,
|
||||
@ -279,9 +281,9 @@ void DSQL_execute(thread_db* tdbb,
|
||||
// a singleton SELECT. In that event, we don't add the cursor
|
||||
// to the list of open cursors (it's not really open).
|
||||
|
||||
if (reqTypeWithCursor(request->req_type) && !singleton)
|
||||
if (reqTypeWithCursor(request->getStatement()->type) && !singleton)
|
||||
{
|
||||
request->req_flags |= REQ_cursor_open;
|
||||
request->getStatement()->flags |= REQ_cursor_open;
|
||||
TRA_link_cursor(request->req_transaction, request);
|
||||
}
|
||||
}
|
||||
@ -355,14 +357,14 @@ ISC_STATUS DSQL_fetch(thread_db* tdbb,
|
||||
Jrd::ContextPoolHolder context(tdbb, &request->req_pool);
|
||||
|
||||
// if the cursor isn't open, we've got a problem
|
||||
if (!(request->req_flags & REQ_cursor_open))
|
||||
if (!(request->getStatement()->flags & REQ_cursor_open))
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-504) <<
|
||||
Arg::Gds(isc_dsql_cursor_err) <<
|
||||
Arg::Gds(isc_dsql_cursor_not_open));
|
||||
}
|
||||
|
||||
dsql_msg* message = (dsql_msg*) request->req_receive;
|
||||
dsql_msg* message = (dsql_msg*) request->getStatement()->receiveMsg;
|
||||
|
||||
// Set up things for tracing this call
|
||||
Jrd::Attachment* att = request->req_dbb->dbb_attachment;
|
||||
@ -375,11 +377,11 @@ ISC_STATUS DSQL_fetch(thread_db* tdbb,
|
||||
parse_blr(request, blr_length, blr, msg_length, message->msg_parameters);
|
||||
}
|
||||
|
||||
if (request->req_type == REQ_GET_SEGMENT)
|
||||
if (request->getStatement()->type == REQ_GET_SEGMENT)
|
||||
{
|
||||
// For get segment, use the user buffer and indicator directly.
|
||||
|
||||
dsql_par* parameter = request->req_blob->blb_segment;
|
||||
dsql_par* parameter = request->getStatement()->blob->blb_segment;
|
||||
dsql_par* null = parameter->par_null;
|
||||
|
||||
dsc userDesc;
|
||||
@ -409,7 +411,7 @@ ISC_STATUS DSQL_fetch(thread_db* tdbb,
|
||||
JRD_receive(tdbb, request->req_request, message->msg_number, message->msg_length,
|
||||
msgBuffer, 0);
|
||||
|
||||
const dsql_par* const eof = request->req_eof;
|
||||
const dsql_par* const eof = request->getStatement()->eof;
|
||||
|
||||
dsc eofDesc = eof->par_desc;
|
||||
eofDesc.dsc_address = msgBuffer + IPTR(eofDesc.dsc_address);
|
||||
@ -459,7 +461,7 @@ void DSQL_free_statement(thread_db* tdbb, dsql_req* request, USHORT option)
|
||||
else if (option & DSQL_close)
|
||||
{
|
||||
// Just close the cursor associated with the request
|
||||
if (!(request->req_flags & REQ_cursor_open))
|
||||
if (!(request->getStatement()->flags & REQ_cursor_open))
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-501) <<
|
||||
Arg::Gds(isc_dsql_cursor_close_err));
|
||||
@ -493,7 +495,7 @@ void DSQL_insert(thread_db* tdbb,
|
||||
|
||||
Jrd::ContextPoolHolder context(tdbb, &request->req_pool);
|
||||
|
||||
if (request->req_flags & REQ_orphan)
|
||||
if (request->getStatement()->flags & REQ_orphan)
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
|
||||
Arg::Gds(isc_bad_req_handle));
|
||||
@ -501,9 +503,9 @@ void DSQL_insert(thread_db* tdbb,
|
||||
|
||||
// if the cursor isn't open, we've got a problem
|
||||
|
||||
if (request->req_type == REQ_PUT_SEGMENT)
|
||||
if (request->getStatement()->type == REQ_PUT_SEGMENT)
|
||||
{
|
||||
if (!(request->req_flags & REQ_cursor_open))
|
||||
if (!(request->getStatement()->flags & REQ_cursor_open))
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-504) <<
|
||||
Arg::Gds(isc_dsql_cursor_err) <<
|
||||
@ -511,7 +513,7 @@ void DSQL_insert(thread_db* tdbb,
|
||||
}
|
||||
}
|
||||
|
||||
dsql_msg* message = (dsql_msg*) request->req_receive;
|
||||
dsql_msg* message = (dsql_msg*) request->getStatement()->receiveMsg;
|
||||
|
||||
// Insure that the blr for the message is parsed, regardless of
|
||||
// whether anything is found by the call to receive.
|
||||
@ -519,11 +521,11 @@ void DSQL_insert(thread_db* tdbb,
|
||||
if (blr_length)
|
||||
parse_blr(request, blr_length, blr, msg_length, message->msg_parameters);
|
||||
|
||||
if (request->req_type == REQ_PUT_SEGMENT)
|
||||
if (request->getStatement()->type == REQ_PUT_SEGMENT)
|
||||
{
|
||||
// For put segment, use the user buffer and indicator directly.
|
||||
|
||||
dsql_par* parameter = request->req_blob->blb_segment;
|
||||
dsql_par* parameter = request->getStatement()->blob->blb_segment;
|
||||
|
||||
dsc userDesc;
|
||||
if (!request->req_user_descs.get(parameter, userDesc))
|
||||
@ -581,7 +583,7 @@ void DSQL_prepare(thread_db* tdbb,
|
||||
|
||||
// check to see if old request has an open cursor
|
||||
|
||||
if (old_request && (old_request->req_flags & REQ_cursor_open))
|
||||
if (old_request && (old_request->getStatement()->flags & REQ_cursor_open))
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-519) <<
|
||||
Arg::Gds(isc_dsql_open_cursor_request));
|
||||
@ -648,13 +650,13 @@ void DSQL_prepare(thread_db* tdbb,
|
||||
|
||||
// Can not prepare a CREATE DATABASE/SCHEMA statement
|
||||
|
||||
if (request->req_type == REQ_CREATE_DB)
|
||||
if (request->getStatement()->type == REQ_CREATE_DB)
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-530) <<
|
||||
Arg::Gds(isc_dsql_crdb_prepare_err));
|
||||
}
|
||||
|
||||
request->req_flags |= REQ_prepared;
|
||||
request->getStatement()->flags |= REQ_prepared;
|
||||
|
||||
// Now that we know that the new request exists, zap the old one.
|
||||
|
||||
@ -814,7 +816,8 @@ static void close_cursor(thread_db* tdbb, dsql_req* request)
|
||||
ThreadStatusGuard status_vector(tdbb);
|
||||
try
|
||||
{
|
||||
if (request->req_type == REQ_GET_SEGMENT || request->req_type == REQ_PUT_SEGMENT)
|
||||
if (request->getStatement()->type == REQ_GET_SEGMENT ||
|
||||
request->getStatement()->type == REQ_PUT_SEGMENT)
|
||||
{
|
||||
BLB_close(tdbb, request->req_blb);
|
||||
request->req_blb = NULL;
|
||||
@ -843,7 +846,7 @@ static void close_cursor(thread_db* tdbb, dsql_req* request)
|
||||
}
|
||||
}
|
||||
|
||||
request->req_flags &= ~REQ_cursor_open;
|
||||
request->getStatement()->flags &= ~REQ_cursor_open;
|
||||
TRA_unlink_cursor(request->req_transaction, request);
|
||||
}
|
||||
|
||||
@ -919,7 +922,7 @@ static void execute_blob(thread_db* tdbb,
|
||||
{
|
||||
UCHAR bpb[24];
|
||||
|
||||
dsql_blb* blob = request->req_blob;
|
||||
dsql_blb* blob = request->getStatement()->blob;
|
||||
map_in_out(request, false, blob->blb_open_in_msg, in_blr_length, in_blr, in_msg_length,
|
||||
NULL, in_msg);
|
||||
|
||||
@ -956,7 +959,7 @@ static void execute_blob(thread_db* tdbb,
|
||||
|
||||
bid* blob_id = (bid*) desc.dsc_address;
|
||||
|
||||
if (request->req_type == REQ_GET_SEGMENT)
|
||||
if (request->getStatement()->type == REQ_GET_SEGMENT)
|
||||
{
|
||||
if (null)
|
||||
{
|
||||
@ -1122,11 +1125,11 @@ static void execute_request(thread_db* tdbb,
|
||||
{
|
||||
request->req_transaction = *tra_handle;
|
||||
|
||||
switch (request->req_type)
|
||||
switch (request->getStatement()->type)
|
||||
{
|
||||
case REQ_START_TRANS:
|
||||
JRD_start_transaction(tdbb, &request->req_transaction, 1, &request->req_dbb->dbb_attachment,
|
||||
request->req_blr_data.getCount(), request->req_blr_data.begin());
|
||||
request->getStatement()->blrData.getCount(), request->getStatement()->blrData.begin());
|
||||
*tra_handle = request->req_transaction;
|
||||
return;
|
||||
|
||||
@ -1191,7 +1194,7 @@ static void execute_request(thread_db* tdbb,
|
||||
|
||||
// If there is no data required, just start the request
|
||||
|
||||
dsql_msg* message = request->req_send;
|
||||
dsql_msg* message = request->getStatement()->sendMsg;
|
||||
if (message)
|
||||
map_in_out(request, false, message, in_blr_length, in_blr, in_msg_length, NULL, in_msg);
|
||||
|
||||
@ -1211,9 +1214,9 @@ static void execute_request(thread_db* tdbb,
|
||||
// REQ_EXEC_BLOCK has no outputs so there are no out_msg
|
||||
// supplied from client side, but REQ_EXEC_BLOCK requires
|
||||
// 2-byte message for EOS synchronization
|
||||
const bool isBlock = (request->req_type == REQ_EXEC_BLOCK);
|
||||
const bool isBlock = (request->getStatement()->type == REQ_EXEC_BLOCK);
|
||||
|
||||
message = request->req_receive;
|
||||
message = request->getStatement()->receiveMsg;
|
||||
if ((out_msg_length && message) || isBlock)
|
||||
{
|
||||
UCHAR temp_buffer[FB_DOUBLE_ALIGN * 2];
|
||||
@ -1290,7 +1293,7 @@ static void execute_request(thread_db* tdbb,
|
||||
}
|
||||
|
||||
UCHAR buffer[20]; // Not used after retrieved
|
||||
if (request->req_type == REQ_UPDATE_CURSOR)
|
||||
if (request->getStatement()->type == REQ_UPDATE_CURSOR)
|
||||
{
|
||||
sql_info(tdbb, request, sizeof(sql_records_info), sql_records_info, sizeof(buffer), buffer);
|
||||
|
||||
@ -1301,7 +1304,7 @@ static void execute_request(thread_db* tdbb,
|
||||
Arg::Gds(isc_update_conflict));
|
||||
}
|
||||
}
|
||||
else if (request->req_type == REQ_DELETE_CURSOR)
|
||||
else if (request->getStatement()->type == REQ_DELETE_CURSOR)
|
||||
{
|
||||
sql_info(tdbb, request, sizeof(sql_records_info), sql_records_info, sizeof(buffer), buffer);
|
||||
|
||||
@ -1313,7 +1316,7 @@ static void execute_request(thread_db* tdbb,
|
||||
}
|
||||
}
|
||||
|
||||
const bool have_cursor = reqTypeWithCursor(request->req_type) && !singleton;
|
||||
const bool have_cursor = reqTypeWithCursor(request->getStatement()->type) && !singleton;
|
||||
trace.finish(have_cursor, res_successful);
|
||||
}
|
||||
|
||||
@ -2188,13 +2191,14 @@ static void map_in_out(dsql_req* request, bool toExternal, const dsql_msg* messa
|
||||
Arg::Gds(isc_dsql_sqlda_err));
|
||||
}
|
||||
|
||||
DsqlCompiledStatement* statement = request->getStatement();
|
||||
dsql_par* parameter;
|
||||
|
||||
dsql_par* dbkey;
|
||||
if (!toExternal && (dbkey = request->req_parent_dbkey) && (parameter = request->req_dbkey))
|
||||
if (!toExternal && (dbkey = statement->parentDbkey) && (parameter = statement->dbkey))
|
||||
{
|
||||
UCHAR* parentMsgBuffer = request->req_parent ?
|
||||
request->req_parent->req_msg_buffers[dbkey->par_message->msg_buffer_number] : NULL;
|
||||
UCHAR* parentMsgBuffer = statement->parentRequest ?
|
||||
statement->parentRequest->req_msg_buffers[dbkey->par_message->msg_buffer_number] : NULL;
|
||||
UCHAR* msgBuffer = request->req_msg_buffers[parameter->par_message->msg_buffer_number];
|
||||
|
||||
fb_assert(parentMsgBuffer);
|
||||
@ -2219,11 +2223,11 @@ static void map_in_out(dsql_req* request, bool toExternal, const dsql_msg* messa
|
||||
}
|
||||
|
||||
dsql_par* rec_version;
|
||||
if (!toExternal && (rec_version = request->req_parent_rec_version) &&
|
||||
(parameter = request->req_rec_version))
|
||||
if (!toExternal && (rec_version = statement->parentRecVersion) &&
|
||||
(parameter = statement->recVersion))
|
||||
{
|
||||
UCHAR* parentMsgBuffer = request->req_parent ?
|
||||
request->req_parent->req_msg_buffers[rec_version->par_message->msg_buffer_number] : NULL;
|
||||
UCHAR* parentMsgBuffer = statement->parentRequest ?
|
||||
statement->parentRequest->req_msg_buffers[rec_version->par_message->msg_buffer_number] : NULL;
|
||||
UCHAR* msgBuffer = request->req_msg_buffers[parameter->par_message->msg_buffer_number];
|
||||
|
||||
fb_assert(parentMsgBuffer);
|
||||
@ -2527,22 +2531,27 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
|
||||
// allocate the statement block, then prepare the statement
|
||||
|
||||
Jrd::ContextPoolHolder context(tdbb, database->createPool());
|
||||
|
||||
MemoryPool& pool = *tdbb->getDefaultPool();
|
||||
CompiledStatement* statement = FB_NEW(pool) CompiledStatement(pool);
|
||||
statement->req_dbb = database;
|
||||
statement->req_transaction = transaction;
|
||||
statement->req_client_dialect = client_dialect;
|
||||
statement->req_traced = true;
|
||||
|
||||
trace.setStatement(statement);
|
||||
DsqlCompiledStatement* statement = FB_NEW(pool) DsqlCompiledStatement(pool);
|
||||
DsqlCompilerScratch* scratch = FB_NEW(pool) DsqlCompilerScratch(pool, database,
|
||||
transaction, statement);
|
||||
scratch->clientDialect = client_dialect;
|
||||
|
||||
dsql_req* request = FB_NEW(statement->getPool()) dsql_req(statement);
|
||||
request->req_dbb = database;
|
||||
request->req_transaction = transaction;
|
||||
|
||||
request->req_traced = true;
|
||||
trace.setStatement(request);
|
||||
|
||||
try {
|
||||
|
||||
// Parse the SQL statement. If it croaks, return
|
||||
|
||||
Parser parser(*tdbb->getDefaultPool(), client_dialect, statement->req_dbb->dbb_db_SQL_dialect,
|
||||
parser_version, string, string_length, tdbb->getAttachment()->att_charset);
|
||||
Parser parser(*tdbb->getDefaultPool(), client_dialect,
|
||||
scratch->getAttachment()->dbb_db_SQL_dialect, parser_version, string, string_length,
|
||||
tdbb->getAttachment()->att_charset);
|
||||
|
||||
dsql_nod* node = parser.parse();
|
||||
Firebird::string transformedText = parser.getTransformedString();
|
||||
@ -2570,7 +2579,7 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
|
||||
}
|
||||
}
|
||||
|
||||
statement->req_sql_text = FB_NEW(pool) RefString(pool, transformedText);
|
||||
statement->sqlText = FB_NEW(pool) RefString(pool, transformedText);
|
||||
|
||||
if (!node)
|
||||
{
|
||||
@ -2584,24 +2593,24 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
|
||||
|
||||
// allocate the send and receive messages
|
||||
|
||||
statement->req_send = FB_NEW(pool) dsql_msg(pool);
|
||||
statement->sendMsg = FB_NEW(pool) dsql_msg(pool);
|
||||
dsql_msg* message = FB_NEW(pool) dsql_msg(pool);
|
||||
statement->req_receive = message;
|
||||
statement->receiveMsg = message;
|
||||
message->msg_number = 1;
|
||||
|
||||
statement->req_type = REQ_SELECT;
|
||||
statement->req_flags &= ~REQ_cursor_open;
|
||||
statement->type = REQ_SELECT;
|
||||
statement->flags &= ~REQ_cursor_open;
|
||||
|
||||
// No work is done during pass1 for set transaction - like
|
||||
// checking for valid table names. This is because that will
|
||||
// require a valid transaction handle.
|
||||
// Error will be caught at execute time.
|
||||
|
||||
node = PASS1_statement(statement, node);
|
||||
node = PASS1_statement(scratch, node);
|
||||
if (!node)
|
||||
return statement;
|
||||
return request;
|
||||
|
||||
switch (statement->req_type)
|
||||
switch (statement->type)
|
||||
{
|
||||
case REQ_COMMIT:
|
||||
case REQ_COMMIT_RETAIN:
|
||||
@ -2610,60 +2619,94 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
|
||||
case REQ_GET_SEGMENT:
|
||||
case REQ_PUT_SEGMENT:
|
||||
case REQ_START_TRANS:
|
||||
statement->req_traced = false;
|
||||
request->req_traced = false;
|
||||
break;
|
||||
default:
|
||||
statement->req_traced = true;
|
||||
request->req_traced = true;
|
||||
}
|
||||
|
||||
// stop here for statements not requiring code generation
|
||||
|
||||
if (statement->req_type == REQ_DDL && parser.isStmtAmbiguous() &&
|
||||
statement->req_dbb->dbb_db_SQL_dialect != client_dialect)
|
||||
if (statement->type == REQ_DDL && parser.isStmtAmbiguous() &&
|
||||
scratch->getAttachment()->dbb_db_SQL_dialect != client_dialect)
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-817) <<
|
||||
Arg::Gds(isc_ddl_not_allowed_by_db_sql_dial) << Arg::Num(statement->req_dbb->dbb_db_SQL_dialect));
|
||||
Arg::Gds(isc_ddl_not_allowed_by_db_sql_dial) <<
|
||||
Arg::Num(scratch->getAttachment()->dbb_db_SQL_dialect));
|
||||
}
|
||||
|
||||
switch (statement->req_type)
|
||||
switch (statement->type)
|
||||
{
|
||||
case REQ_COMMIT:
|
||||
case REQ_COMMIT_RETAIN:
|
||||
case REQ_ROLLBACK:
|
||||
case REQ_ROLLBACK_RETAIN:
|
||||
return statement;
|
||||
|
||||
// Work on blob segment statements
|
||||
case REQ_GET_SEGMENT:
|
||||
case REQ_PUT_SEGMENT:
|
||||
GEN_port(statement, statement->req_blob->blb_open_in_msg);
|
||||
GEN_port(statement, statement->req_blob->blb_open_out_msg);
|
||||
GEN_port(statement, statement->req_blob->blb_segment_msg);
|
||||
return statement;
|
||||
|
||||
// Generate BLR, DDL or TPB for statement
|
||||
// Start transactions takes parameters via a parameter block.
|
||||
// The statement blr string is used for that
|
||||
case REQ_START_TRANS:
|
||||
GEN_start_transaction(statement, node);
|
||||
return statement;
|
||||
// Work on blob segment statements
|
||||
case REQ_GET_SEGMENT:
|
||||
case REQ_PUT_SEGMENT:
|
||||
GEN_port(scratch, statement->blob->blb_open_in_msg);
|
||||
GEN_port(scratch, statement->blob->blb_open_out_msg);
|
||||
GEN_port(scratch, statement->blob->blb_segment_msg);
|
||||
break;
|
||||
}
|
||||
|
||||
if (client_dialect > SQL_DIALECT_V5)
|
||||
statement->req_flags |= REQ_blr_version5;
|
||||
else
|
||||
statement->req_flags |= REQ_blr_version4;
|
||||
switch (statement->type)
|
||||
{
|
||||
case REQ_COMMIT:
|
||||
case REQ_COMMIT_RETAIN:
|
||||
case REQ_ROLLBACK:
|
||||
case REQ_ROLLBACK_RETAIN:
|
||||
return request;
|
||||
|
||||
GEN_request(statement, node);
|
||||
const ULONG length = (ULONG) statement->req_blr_data.getCount();
|
||||
case REQ_START_TRANS:
|
||||
GEN_start_transaction(scratch, node);
|
||||
return request;
|
||||
|
||||
default:
|
||||
if (client_dialect > SQL_DIALECT_V5)
|
||||
statement->flags |= REQ_blr_version5;
|
||||
else
|
||||
statement->flags |= REQ_blr_version4;
|
||||
|
||||
GEN_request(request, scratch, node);
|
||||
// fall into
|
||||
|
||||
case REQ_GET_SEGMENT:
|
||||
case REQ_PUT_SEGMENT:
|
||||
{
|
||||
// Create the messages buffers
|
||||
for (size_t i = 0; i < scratch->ports.getCount(); ++i)
|
||||
{
|
||||
dsql_msg* message = scratch->ports[i];
|
||||
|
||||
// Allocate buffer for message
|
||||
const ULONG newLen = message->msg_length + FB_DOUBLE_ALIGN - 1;
|
||||
|
||||
message->msg_buffer_number = request->req_msg_buffers.getCount();
|
||||
request->req_msg_buffers.grow(message->msg_buffer_number + 1);
|
||||
|
||||
UCHAR*& msgBuffer = request->req_msg_buffers[message->msg_buffer_number];
|
||||
fb_assert(!msgBuffer);
|
||||
|
||||
msgBuffer = FB_NEW(*tdbb->getDefaultPool()) UCHAR[newLen];
|
||||
msgBuffer = (UCHAR*) FB_ALIGN((U_IPTR) msgBuffer, FB_DOUBLE_ALIGN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (statement->type)
|
||||
{
|
||||
case REQ_GET_SEGMENT:
|
||||
case REQ_PUT_SEGMENT:
|
||||
return request;
|
||||
}
|
||||
|
||||
const ULONG length = (ULONG) statement->blrData.getCount();
|
||||
|
||||
// stop here for ddl statements
|
||||
|
||||
if (statement->req_type == REQ_CREATE_DB || statement->req_type == REQ_DDL)
|
||||
if (statement->type == REQ_CREATE_DB || statement->type == REQ_DDL)
|
||||
{
|
||||
// Notify Trace API manager about new DDL request cooked.
|
||||
trace.prepare(res_successful);
|
||||
return statement;
|
||||
return request;
|
||||
}
|
||||
|
||||
// have the access method compile the statement
|
||||
@ -2675,8 +2718,8 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
|
||||
gds__trace_raw("Statement:\n");
|
||||
gds__trace_raw(string, string_length);
|
||||
gds__trace_raw("\nBLR:\n");
|
||||
fb_print_blr(statement->req_blr_data.begin(),
|
||||
(ULONG) statement->req_blr_data.getCount(),
|
||||
fb_print_blr(statement->blrData.begin(),
|
||||
(ULONG) statement->blrData.getCount(),
|
||||
gds__trace_printer, 0, 0);
|
||||
}
|
||||
#endif
|
||||
@ -2693,13 +2736,13 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
|
||||
try
|
||||
{
|
||||
JRD_compile(tdbb,
|
||||
statement->req_dbb->dbb_attachment,
|
||||
&statement->req_request,
|
||||
scratch->getAttachment()->dbb_attachment,
|
||||
&request->req_request,
|
||||
length,
|
||||
statement->req_blr_data.begin(),
|
||||
statement->req_sql_text,
|
||||
statement->req_debug_data.getCount(),
|
||||
statement->req_debug_data.begin(),
|
||||
statement->blrData.begin(),
|
||||
statement->sqlText,
|
||||
statement->debugData.getCount(),
|
||||
statement->debugData.begin(),
|
||||
isInternalRequest);
|
||||
}
|
||||
catch (const Firebird::Exception&)
|
||||
@ -2727,7 +2770,7 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
|
||||
}
|
||||
|
||||
// free blr memory
|
||||
statement->req_blr_data.free();
|
||||
statement->blrData.free();
|
||||
|
||||
if (status)
|
||||
Firebird::status_exception::raise(tdbb->tdbb_status_vector);
|
||||
@ -2735,13 +2778,13 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
|
||||
// Notify Trace API manager about new request cooked.
|
||||
trace.prepare(res_successful);
|
||||
|
||||
return statement;
|
||||
return request;
|
||||
|
||||
}
|
||||
catch (const Firebird::Exception&)
|
||||
{
|
||||
trace.prepare(res_failed);
|
||||
release_request(tdbb, statement, true);
|
||||
release_request(tdbb, request, true);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@ -2789,6 +2832,25 @@ static UCHAR* put_item( UCHAR item,
|
||||
}
|
||||
|
||||
|
||||
// Release a compiled statement.
|
||||
static void release_statement(DsqlCompiledStatement* statement)
|
||||
{
|
||||
if (statement->parentRequest)
|
||||
{
|
||||
dsql_req* parent = statement->parentRequest;
|
||||
|
||||
size_t pos;
|
||||
if (parent->cursors.find(statement, pos))
|
||||
parent->cursors.remove(pos);
|
||||
|
||||
statement->parentRequest = NULL;
|
||||
}
|
||||
|
||||
statement->sqlText = NULL;
|
||||
statement->blrData.free(); // free blr memory
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
release_request
|
||||
@ -2804,36 +2866,27 @@ static void release_request(thread_db* tdbb, dsql_req* request, bool drop)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
// If request is parent, orphan the children and
|
||||
// release a portion of their requests
|
||||
// If request is parent, orphan the children and release a portion of their requests
|
||||
|
||||
for (dsql_req* child = request->req_offspring; child; child = child->req_sibling)
|
||||
for (size_t i = 0; i < request->cursors.getCount(); ++i)
|
||||
{
|
||||
child->req_flags |= REQ_orphan;
|
||||
child->req_parent = NULL;
|
||||
Jrd::ContextPoolHolder context(tdbb, &child->req_pool);
|
||||
release_request(tdbb, child, false);
|
||||
DsqlCompiledStatement* child = request->cursors[i];
|
||||
child->flags |= REQ_orphan;
|
||||
child->parentRequest = NULL;
|
||||
|
||||
Jrd::ContextPoolHolder context(tdbb, &child->getPool());
|
||||
release_statement(child);
|
||||
}
|
||||
|
||||
// For requests that are linked to a parent, unlink it
|
||||
|
||||
if (request->req_parent)
|
||||
{
|
||||
dsql_req* parent = request->req_parent;
|
||||
for (dsql_req** ptr = &parent->req_offspring; *ptr; ptr = &(*ptr)->req_sibling)
|
||||
{
|
||||
if (*ptr == request)
|
||||
{
|
||||
*ptr = request->req_sibling;
|
||||
break;
|
||||
}
|
||||
}
|
||||
request->req_parent = NULL;
|
||||
}
|
||||
DsqlCompiledStatement* statement = request->getStatement();
|
||||
|
||||
release_statement(statement);
|
||||
|
||||
// If the request had an open cursor, close it
|
||||
|
||||
if (request->req_flags & REQ_cursor_open) {
|
||||
if (statement->flags & REQ_cursor_open) {
|
||||
close_cursor(tdbb, request);
|
||||
}
|
||||
|
||||
@ -2867,17 +2920,10 @@ static void release_request(thread_db* tdbb, dsql_req* request, bool drop)
|
||||
}
|
||||
}
|
||||
|
||||
request->req_sql_text = NULL;
|
||||
|
||||
// free blr memory
|
||||
request->req_blr_data.free();
|
||||
|
||||
// Release the entire request if explicitly asked for
|
||||
|
||||
if (drop)
|
||||
{
|
||||
request->req_dbb->deletePool(&request->req_pool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2937,7 +2983,7 @@ static void sql_info(thread_db* tdbb,
|
||||
{
|
||||
case isc_info_sql_select:
|
||||
case isc_info_sql_bind:
|
||||
message = (item == isc_info_sql_select) ? &request->req_receive : &request->req_send;
|
||||
message = (item == isc_info_sql_select) ? &request->getStatement()->receiveMsg : &request->getStatement()->sendMsg;
|
||||
if (info + 1 >= end_info)
|
||||
{
|
||||
*info = isc_info_truncated;
|
||||
@ -2946,7 +2992,7 @@ static void sql_info(thread_db* tdbb,
|
||||
*info++ = item;
|
||||
break;
|
||||
case isc_info_sql_stmt_type:
|
||||
switch (request->req_type)
|
||||
switch (request->getStatement()->type)
|
||||
{
|
||||
case REQ_SELECT:
|
||||
case REQ_EMBED_SELECT:
|
||||
@ -3018,7 +3064,7 @@ static void sql_info(thread_db* tdbb,
|
||||
items += length;
|
||||
break;
|
||||
case isc_info_sql_batch_fetch:
|
||||
if (request->req_flags & REQ_no_batch)
|
||||
if (request->getStatement()->flags & REQ_no_batch)
|
||||
number = 0;
|
||||
else
|
||||
number = 1;
|
||||
@ -3102,7 +3148,7 @@ static void sql_info(thread_db* tdbb,
|
||||
}
|
||||
|
||||
info = var_info(*message, items, end_describe, info, end_info, first_index,
|
||||
message == &request->req_send);
|
||||
message == &request->getStatement()->sendMsg);
|
||||
if (!info) {
|
||||
return;
|
||||
}
|
||||
|
361
src/dsql/dsql.h
361
src/dsql/dsql.h
@ -378,48 +378,141 @@ enum REQ_TYPE
|
||||
};
|
||||
|
||||
|
||||
class dsql_req : public pool_alloc<dsql_type_req>
|
||||
// Compiled statement - shared by multiple requests.
|
||||
class DsqlCompiledStatement : public Firebird::PermanentStorage
|
||||
{
|
||||
public:
|
||||
explicit dsql_req(MemoryPool& p)
|
||||
: req_pool(p),
|
||||
req_blr_data(p),
|
||||
req_msg_buffers(p),
|
||||
req_user_descs(p)
|
||||
DsqlCompiledStatement(MemoryPool& p)
|
||||
: PermanentStorage(p),
|
||||
blrData(p),
|
||||
debugData(p),
|
||||
type(REQ_SELECT),
|
||||
blockNode(NULL),
|
||||
ddlNode(NULL),
|
||||
baseOffset(0),
|
||||
flags(0),
|
||||
blob(NULL),
|
||||
sendMsg(NULL),
|
||||
receiveMsg(NULL),
|
||||
eof(NULL),
|
||||
dbkey(NULL),
|
||||
recVersion(NULL),
|
||||
parentRecVersion(NULL),
|
||||
parentDbkey(NULL),
|
||||
parentRequest(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
MemoryPool& req_pool;
|
||||
public:
|
||||
MemoryPool& getPool()
|
||||
{
|
||||
return PermanentStorage::getPool();
|
||||
}
|
||||
|
||||
dsql_req* req_parent; // Source request, if cursor update
|
||||
dsql_req* req_sibling; // Next sibling request, if cursor update
|
||||
dsql_req* req_offspring; // Cursor update requests
|
||||
public:
|
||||
void append_uchar(UCHAR byte)
|
||||
{
|
||||
blrData.add(byte);
|
||||
}
|
||||
|
||||
void append_ushort(USHORT val)
|
||||
{
|
||||
append_uchar(val);
|
||||
append_uchar(val >> 8);
|
||||
}
|
||||
|
||||
void append_ulong(ULONG val)
|
||||
{
|
||||
append_ushort(val);
|
||||
append_ushort(val >> 16);
|
||||
}
|
||||
|
||||
void append_cstring(UCHAR verb, const char* string);
|
||||
void append_meta_string(const char* string);
|
||||
void append_raw_string(const char* string, USHORT len);
|
||||
void append_raw_string(const UCHAR* string, USHORT len);
|
||||
void append_string(UCHAR verb, const char* string, USHORT len);
|
||||
void append_string(UCHAR verb, const Firebird::MetaName& name);
|
||||
void append_string(UCHAR verb, const Firebird::string& name);
|
||||
void append_number(UCHAR verb, SSHORT number);
|
||||
void begin_blr(UCHAR verb);
|
||||
void end_blr();
|
||||
void append_uchars(UCHAR byte, int count);
|
||||
void append_ushort_with_length(USHORT val);
|
||||
void append_ulong_with_length(ULONG val);
|
||||
void append_file_length(ULONG length);
|
||||
void append_file_start(ULONG start);
|
||||
void generate_unnamed_trigger_beginning(bool on_update_trigger, const char* prim_rel_name,
|
||||
const dsql_nod* prim_columns, const char* for_rel_name, const dsql_nod* for_columns);
|
||||
|
||||
void begin_debug();
|
||||
void end_debug();
|
||||
void put_debug_src_info(USHORT, USHORT);
|
||||
void put_debug_variable(USHORT, const TEXT*);
|
||||
void put_debug_argument(UCHAR, USHORT, const TEXT*);
|
||||
void append_debug_info();
|
||||
|
||||
public:
|
||||
Firebird::RefStrPtr sqlText;
|
||||
Firebird::HalfStaticArray<BLOB_PTR, 1024> blrData;
|
||||
Firebird::HalfStaticArray<BLOB_PTR, 128> debugData;
|
||||
REQ_TYPE type; // Type of request
|
||||
BlockNode* blockNode; // Defining block
|
||||
dsql_nod* ddlNode; // Store metadata request
|
||||
ULONG baseOffset; // place to go back and stuff in blr length
|
||||
ULONG flags; // generic flag
|
||||
dsql_blb* blob; // Blob info for blob requests
|
||||
dsql_msg* sendMsg; // Message to be sent to start request
|
||||
dsql_msg* receiveMsg; // Per record message to be received
|
||||
dsql_par* eof; // End of file parameter
|
||||
dsql_par* dbkey; // Database key for current of
|
||||
dsql_par* recVersion; // Record Version for current of
|
||||
dsql_par* parentRecVersion; // parent record version
|
||||
dsql_par* parentDbkey; // Parent database key for current of
|
||||
dsql_req* parentRequest; // Source request, if cursor update
|
||||
};
|
||||
|
||||
|
||||
class dsql_req : public pool_alloc<dsql_type_req>
|
||||
{
|
||||
public:
|
||||
explicit dsql_req(DsqlCompiledStatement* aStatement)
|
||||
: req_pool(aStatement->getPool()),
|
||||
statement(aStatement),
|
||||
cursors(req_pool),
|
||||
req_msg_buffers(req_pool),
|
||||
req_user_descs(req_pool)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
jrd_tra* getTransaction()
|
||||
{
|
||||
return req_transaction;
|
||||
}
|
||||
|
||||
DsqlCompiledStatement* getStatement()
|
||||
{
|
||||
return statement;
|
||||
}
|
||||
|
||||
const DsqlCompiledStatement* getStatement() const
|
||||
{
|
||||
return statement;
|
||||
}
|
||||
|
||||
public:
|
||||
MemoryPool& req_pool;
|
||||
DsqlCompiledStatement* statement;
|
||||
Firebird::Array<DsqlCompiledStatement*> cursors; // Cursor update statements
|
||||
|
||||
dsql_dbb* req_dbb; // DSQL attachment
|
||||
jrd_tra* req_transaction; // JRD transaction
|
||||
dsql_nod* req_ddl_node; // Store metadata request
|
||||
dsql_blb* req_blob; // Blob info for blob requests
|
||||
jrd_req* req_request; // JRD request
|
||||
dsql_msg* req_send; // Message to be sent to start request
|
||||
dsql_msg* req_receive; // Per record message to be received
|
||||
dsql_par* req_eof; // End of file parameter
|
||||
dsql_par* req_dbkey; // Database key for current of
|
||||
dsql_par* req_rec_version; // Record Version for current of
|
||||
dsql_par* req_parent_rec_version; // parent record version
|
||||
dsql_par* req_parent_dbkey; // Parent database key for current of
|
||||
REQ_TYPE req_type; // Type of request
|
||||
ULONG req_flags; // generic flag
|
||||
|
||||
Firebird::HalfStaticArray<BLOB_PTR, 1024> req_blr_data;
|
||||
Firebird::RefStrPtr req_sql_text;
|
||||
|
||||
// Execution state
|
||||
|
||||
Firebird::Array<UCHAR*> req_msg_buffers;
|
||||
|
||||
dsql_sym* req_cursor; // Cursor symbol, if any
|
||||
blb* req_blb; // JRD blob
|
||||
|
||||
Firebird::GenericMap<Firebird::NonPooled<const dsql_par*, dsc> > req_user_descs; // SQLDA data type
|
||||
|
||||
ULONG req_inserts; // records processed in request
|
||||
@ -435,9 +528,7 @@ public:
|
||||
protected:
|
||||
// Request should never be destroyed using delete.
|
||||
// It dies together with it's pool in release_request().
|
||||
~dsql_req()
|
||||
{
|
||||
}
|
||||
~dsql_req();
|
||||
|
||||
// To avoid posix warning about missing public destructor declare
|
||||
// MemoryPool as friend class. In fact IT releases request memory!
|
||||
@ -445,78 +536,83 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class CompiledStatement : public dsql_req
|
||||
// DSQL Compiler scratch block - may be discarded after compilation in the future.
|
||||
class DsqlCompilerScratch : public Firebird::PermanentStorage
|
||||
{
|
||||
public:
|
||||
explicit CompiledStatement(MemoryPool& p)
|
||||
: dsql_req(p),
|
||||
req_debug_data(p),
|
||||
req_main_context(p),
|
||||
req_context(&req_main_context),
|
||||
req_union_context(p),
|
||||
req_dt_context(p),
|
||||
req_labels(p),
|
||||
req_cursors(p),
|
||||
req_hidden_vars(p),
|
||||
req_package(p),
|
||||
req_curr_ctes(p),
|
||||
req_ctes(p),
|
||||
req_cte_aliases(p)
|
||||
explicit DsqlCompilerScratch(MemoryPool& p, dsql_dbb* aDbb, jrd_tra* aTransaction,
|
||||
DsqlCompiledStatement* aStatement)
|
||||
: PermanentStorage(p),
|
||||
dbb(aDbb),
|
||||
transaction(aTransaction),
|
||||
statement(aStatement),
|
||||
ports(p),
|
||||
relation(NULL),
|
||||
procedure(NULL),
|
||||
mainContext(p),
|
||||
context(&mainContext),
|
||||
unionContext(p),
|
||||
derivedContext(p),
|
||||
outerAggContext(NULL),
|
||||
contextNumber(0),
|
||||
derivedContextNumber(0),
|
||||
scopeLevel(0),
|
||||
loopLevel(0),
|
||||
labels(p),
|
||||
cursorNumber(0),
|
||||
cursors(p),
|
||||
inSelectList(0),
|
||||
inWhereClause(0),
|
||||
inGroupByClause(0),
|
||||
inHavingClause(0),
|
||||
inOrderByClause(0),
|
||||
errorHandlers(0),
|
||||
clientDialect(0),
|
||||
inOuterJoin(0),
|
||||
aliasRelationPrefix(NULL),
|
||||
hiddenVars(p),
|
||||
hiddenVarsNumber(0),
|
||||
package(p),
|
||||
currCtes(p),
|
||||
recursiveCtx(0),
|
||||
recursiveCtxId(0),
|
||||
ctes(p),
|
||||
cteAliases(p),
|
||||
currCteAlias(NULL),
|
||||
psql(false)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
// Request should never be destroyed using delete.
|
||||
// It dies together with its pool in release_request().
|
||||
~CompiledStatement();
|
||||
// DsqlCompilerScratch should never be destroyed using delete.
|
||||
// It dies together with it's pool in release_request().
|
||||
~DsqlCompilerScratch();
|
||||
|
||||
public:
|
||||
// begin - member functions that should be private
|
||||
void append_uchar(UCHAR byte)
|
||||
MemoryPool& getPool()
|
||||
{
|
||||
req_blr_data.add(byte);
|
||||
return PermanentStorage::getPool();
|
||||
}
|
||||
|
||||
void append_ushort(USHORT val)
|
||||
dsql_dbb* getAttachment()
|
||||
{
|
||||
append_uchar(val);
|
||||
append_uchar(val >> 8);
|
||||
return dbb;
|
||||
}
|
||||
|
||||
void append_ulong(ULONG val)
|
||||
jrd_tra* getTransaction()
|
||||
{
|
||||
append_ushort(val);
|
||||
append_ushort(val >> 16);
|
||||
return transaction;
|
||||
}
|
||||
|
||||
void append_cstring(UCHAR verb, const char* string);
|
||||
void append_meta_string(const char* string);
|
||||
void append_raw_string(const char* string, USHORT len);
|
||||
void append_raw_string(const UCHAR* string, USHORT len);
|
||||
void append_string(UCHAR verb, const char* string, USHORT len);
|
||||
void append_string(UCHAR verb, const Firebird::MetaName& name);
|
||||
void append_string(UCHAR verb, const Firebird::string& name);
|
||||
void append_number(UCHAR verb, SSHORT number);
|
||||
void begin_blr(UCHAR verb);
|
||||
void end_blr();
|
||||
void append_uchars(UCHAR byte, int count);
|
||||
void append_ushort_with_length(USHORT val);
|
||||
void append_ulong_with_length(ULONG val);
|
||||
void append_file_length(ULONG length);
|
||||
void append_file_start(ULONG start);
|
||||
void generate_unnamed_trigger_beginning( bool on_update_trigger,
|
||||
const char* prim_rel_name,
|
||||
const dsql_nod* prim_columns,
|
||||
const char* for_rel_name,
|
||||
const dsql_nod* for_columns);
|
||||
DsqlCompiledStatement* getStatement()
|
||||
{
|
||||
return statement;
|
||||
}
|
||||
|
||||
void begin_debug();
|
||||
void end_debug();
|
||||
void put_debug_src_info(USHORT, USHORT);
|
||||
void put_debug_variable(USHORT, const TEXT*);
|
||||
void put_debug_argument(UCHAR, USHORT, const TEXT*);
|
||||
void append_debug_info();
|
||||
// end - member functions that should be private
|
||||
DsqlCompiledStatement* getStatement() const
|
||||
{
|
||||
return statement;
|
||||
}
|
||||
|
||||
void addCTEs(dsql_nod* list);
|
||||
dsql_nod* findCTE(const dsql_str* name);
|
||||
@ -531,15 +627,17 @@ public:
|
||||
// recursive CTE
|
||||
void addCTEAlias(const dsql_str* alias)
|
||||
{
|
||||
req_cte_aliases.add(alias);
|
||||
cteAliases.add(alias);
|
||||
}
|
||||
|
||||
const dsql_str* getNextCTEAlias()
|
||||
{
|
||||
return *(--req_curr_cte_alias);
|
||||
return *(--currCteAlias);
|
||||
}
|
||||
|
||||
void resetCTEAlias()
|
||||
{
|
||||
req_curr_cte_alias = req_cte_aliases.end();
|
||||
currCteAlias = cteAliases.end();
|
||||
}
|
||||
|
||||
bool isPsql() const
|
||||
@ -552,46 +650,47 @@ public:
|
||||
psql = value;
|
||||
}
|
||||
|
||||
dsql_rel* req_relation; // relation created by this request (for DDL)
|
||||
dsql_prc* req_procedure; // procedure created by this request (for DDL)
|
||||
Firebird::HalfStaticArray<BLOB_PTR, 128> req_debug_data;
|
||||
DsqlContextStack req_main_context;
|
||||
DsqlContextStack* req_context;
|
||||
DsqlContextStack req_union_context; // Save contexts for views of unions
|
||||
DsqlContextStack req_dt_context; // Save contexts for views of derived tables
|
||||
class dsql_ctx* req_outer_agg_context; // agg context for outer ref
|
||||
ULONG req_base_offset; // place to go back and stuff in blr length
|
||||
USHORT req_context_number; // Next available context number
|
||||
USHORT req_derived_context_number; // Next available context number for derived tables
|
||||
USHORT req_scope_level; // Scope level for parsing aliases in subqueries
|
||||
//USHORT req_message_number; // Next available message number
|
||||
USHORT req_loop_level; // Loop level
|
||||
DsqlStrStack req_labels; // Loop labels
|
||||
USHORT req_cursor_number; // Cursor number
|
||||
DsqlNodStack req_cursors; // Cursors
|
||||
USHORT req_in_select_list; // now processing "select list"
|
||||
USHORT req_in_where_clause; // processing "where clause"
|
||||
USHORT req_in_group_by_clause; // processing "group by clause"
|
||||
USHORT req_in_having_clause; // processing "having clause"
|
||||
USHORT req_in_order_by_clause; // processing "order by clause"
|
||||
USHORT req_error_handlers; // count of active error handlers
|
||||
USHORT req_client_dialect; // dialect passed into the API call
|
||||
USHORT req_in_outer_join; // processing inside outer-join part
|
||||
dsql_str* req_alias_relation_prefix; // prefix for every relation-alias.
|
||||
DsqlNodStack req_hidden_vars; // hidden variables
|
||||
USHORT req_hidden_vars_number; // next hidden variable number
|
||||
Firebird::MetaName req_package; // package being defined
|
||||
private:
|
||||
dsql_dbb* dbb; // DSQL attachment
|
||||
jrd_tra* transaction; // Transaction
|
||||
DsqlCompiledStatement* statement; // Compiled statement
|
||||
|
||||
DsqlNodStack req_curr_ctes; // current processing CTE's
|
||||
class dsql_ctx* req_recursive_ctx; // context of recursive CTE
|
||||
USHORT req_recursive_ctx_id; // id of recursive union stream context
|
||||
BlockNode* blockNode;
|
||||
public:
|
||||
Firebird::Array<dsql_msg*> ports; // Port messages
|
||||
dsql_rel* relation; // relation created by this request (for DDL)
|
||||
dsql_prc* procedure; // procedure created by this request (for DDL)
|
||||
DsqlContextStack mainContext;
|
||||
DsqlContextStack* context;
|
||||
DsqlContextStack unionContext; // Save contexts for views of unions
|
||||
DsqlContextStack derivedContext; // Save contexts for views of derived tables
|
||||
dsql_ctx* outerAggContext; // agg context for outer ref
|
||||
USHORT contextNumber; // Next available context number
|
||||
USHORT derivedContextNumber; // Next available context number for derived tables
|
||||
USHORT scopeLevel; // Scope level for parsing aliases in subqueries
|
||||
USHORT loopLevel; // Loop level
|
||||
DsqlStrStack labels; // Loop labels
|
||||
USHORT cursorNumber; // Cursor number
|
||||
DsqlNodStack cursors; // Cursors
|
||||
USHORT inSelectList; // now processing "select list"
|
||||
USHORT inWhereClause; // processing "where clause"
|
||||
USHORT inGroupByClause; // processing "group by clause"
|
||||
USHORT inHavingClause; // processing "having clause"
|
||||
USHORT inOrderByClause; // processing "order by clause"
|
||||
USHORT errorHandlers; // count of active error handlers
|
||||
USHORT clientDialect; // dialect passed into the API call
|
||||
USHORT inOuterJoin; // processing inside outer-join part
|
||||
dsql_str* aliasRelationPrefix; // prefix for every relation-alias.
|
||||
DsqlNodStack hiddenVars; // hidden variables
|
||||
USHORT hiddenVarsNumber; // next hidden variable number
|
||||
Firebird::MetaName package; // package being defined
|
||||
DsqlNodStack currCtes; // current processing CTE's
|
||||
class dsql_ctx* recursiveCtx; // context of recursive CTE
|
||||
USHORT recursiveCtxId; // id of recursive union stream context
|
||||
|
||||
private:
|
||||
Firebird::HalfStaticArray<dsql_nod*, 4> req_ctes; // common table expressions
|
||||
Firebird::HalfStaticArray<const dsql_str*, 4> req_cte_aliases; // CTE aliases in recursive members
|
||||
const dsql_str* const* req_curr_cte_alias;
|
||||
|
||||
Firebird::HalfStaticArray<dsql_nod*, 4> ctes; // common table expressions
|
||||
Firebird::HalfStaticArray<const dsql_str*, 4> cteAliases; // CTE aliases in recursive members
|
||||
const dsql_str* const* currCteAlias;
|
||||
bool psql;
|
||||
};
|
||||
|
||||
@ -599,7 +698,7 @@ private:
|
||||
class PsqlChanger
|
||||
{
|
||||
public:
|
||||
PsqlChanger(CompiledStatement* aStatement, bool value)
|
||||
PsqlChanger(DsqlCompilerScratch* aStatement, bool value)
|
||||
: statement(aStatement),
|
||||
oldValue(statement->isPsql())
|
||||
{
|
||||
@ -616,13 +715,13 @@ private:
|
||||
PsqlChanger(const PsqlChanger&);
|
||||
PsqlChanger& operator =(const PsqlChanger&);
|
||||
|
||||
CompiledStatement* statement;
|
||||
DsqlCompilerScratch* statement;
|
||||
const bool oldValue;
|
||||
};
|
||||
|
||||
|
||||
// values used in req_flags
|
||||
enum req_flags_vals {
|
||||
// values used in flags
|
||||
enum flags_vals {
|
||||
REQ_cursor_open = 0x00001,
|
||||
REQ_save_metadata = 0x00002,
|
||||
REQ_prepared = 0x00004, // Set in DSQL_prepare but never checked
|
||||
@ -681,7 +780,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
dsql_req* ctx_request; // Parent request
|
||||
dsql_rel* ctx_relation; // Relation for context
|
||||
dsql_prc* ctx_procedure; // Procedure for context
|
||||
dsql_nod* ctx_proc_inputs; // Procedure input parameters
|
||||
@ -694,7 +792,7 @@ public:
|
||||
USHORT ctx_recursive; // Secondary context id for recursive UNION (nobody referred to this context)
|
||||
USHORT ctx_scope_level; // Subquery level within this request
|
||||
USHORT ctx_flags; // Various flag values
|
||||
USHORT ctx_in_outer_join; // req_in_outer_join when context was created
|
||||
USHORT ctx_in_outer_join; // inOuterJoin when context was created
|
||||
DsqlContextStack ctx_main_derived_contexts; // contexts used for blr_derived_expr
|
||||
DsqlContextStack ctx_childs_derived_table; // Childs derived table context
|
||||
Firebird::GenericMap<Firebird::Pair<Firebird::Left<
|
||||
@ -702,7 +800,6 @@ public:
|
||||
|
||||
dsql_ctx& operator=(dsql_ctx& v)
|
||||
{
|
||||
ctx_request = v.ctx_request;
|
||||
ctx_relation = v.ctx_relation;
|
||||
ctx_procedure = v.ctx_procedure;
|
||||
ctx_proc_inputs = v.ctx_proc_inputs;
|
||||
|
1452
src/dsql/gen.cpp
1452
src/dsql/gen.cpp
File diff suppressed because it is too large
Load Diff
@ -24,23 +24,23 @@
|
||||
#ifndef DSQL_GEN_PROTO_H
|
||||
#define DSQL_GEN_PROTO_H
|
||||
|
||||
void GEN_descriptor(Jrd::CompiledStatement* statement, const dsc* desc, bool texttype);
|
||||
void GEN_expr(Jrd::CompiledStatement*, Jrd::dsql_nod*);
|
||||
void GEN_hidden_variables(Jrd::CompiledStatement* statement, bool inExpression);
|
||||
void GEN_port(Jrd::CompiledStatement*, Jrd::dsql_msg*);
|
||||
void GEN_request(Jrd::CompiledStatement*, Jrd::dsql_nod*);
|
||||
void GEN_return(Jrd::CompiledStatement*, const Firebird::Array<Jrd::dsql_nod*>& variables, bool);
|
||||
void GEN_start_transaction(Jrd::CompiledStatement*, const Jrd::dsql_nod*);
|
||||
void GEN_statement(Jrd::CompiledStatement*, Jrd::dsql_nod*);
|
||||
void GEN_descriptor(Jrd::DsqlCompilerScratch* dsqlScratch, const dsc* desc, bool texttype);
|
||||
void GEN_expr(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);
|
||||
void GEN_hidden_variables(Jrd::DsqlCompilerScratch* dsqlScratch, bool inExpression);
|
||||
void GEN_port(Jrd::DsqlCompilerScratch*, Jrd::dsql_msg*);
|
||||
void GEN_request(Jrd::dsql_req*, Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);
|
||||
void GEN_return(Jrd::DsqlCompilerScratch*, const Firebird::Array<Jrd::dsql_nod*>& variables, bool);
|
||||
void GEN_start_transaction(Jrd::DsqlCompilerScratch*, const Jrd::dsql_nod*);
|
||||
void GEN_statement(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);
|
||||
|
||||
// CVC: I think this can be replaced by statement->append_uchar(byte) in the calling code.
|
||||
inline void stuff(Jrd::CompiledStatement* statement, const UCHAR byte)
|
||||
inline void stuff(Jrd::DsqlCompiledStatement* statement, const UCHAR byte)
|
||||
{
|
||||
statement->req_blr_data.add(byte);
|
||||
statement->blrData.add(byte);
|
||||
}
|
||||
|
||||
// Write out a string with one byte of length.
|
||||
inline void stuff_string(Jrd::CompiledStatement* statement, const char* string, int len)
|
||||
inline void stuff_string(Jrd::DsqlCompiledStatement* statement, const char* string, int len)
|
||||
{
|
||||
fb_assert(len >= 0 && len <= 255);
|
||||
// CVC: Maybe the Release version should truncate "len" to 255?
|
||||
@ -50,7 +50,7 @@ inline void stuff_string(Jrd::CompiledStatement* statement, const char* string,
|
||||
}
|
||||
|
||||
// Write out a string with one byte of length.
|
||||
inline void stuff_cstring(Jrd::CompiledStatement* statement, const char* string)
|
||||
inline void stuff_cstring(Jrd::DsqlCompiledStatement* statement, const char* string)
|
||||
{
|
||||
stuff_string(statement, string, strlen(string));
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ dsql_str* MAKE_cstring(const char* str)
|
||||
@param null_replacement
|
||||
|
||||
**/
|
||||
void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod* null_replacement)
|
||||
void MAKE_desc(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* node, dsql_nod* null_replacement)
|
||||
{
|
||||
dsc desc1, desc2, desc3;
|
||||
USHORT dtype, dtype1, dtype2;
|
||||
@ -433,7 +433,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
case nod_map:
|
||||
map = (dsql_map*) node->nod_arg[e_map_map];
|
||||
context = (dsql_ctx*) node->nod_arg[e_map_context];
|
||||
MAKE_desc(statement, desc, map->map_node, null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, map->map_node, null_replacement);
|
||||
|
||||
// ASF: We should mark nod_agg_count as nullable when it's in an outer join - CORE-2660.
|
||||
if (context->ctx_flags & CTX_outer_join)
|
||||
@ -444,12 +444,12 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
case nod_agg_min:
|
||||
case nod_agg_max:
|
||||
case nod_window:
|
||||
MAKE_desc(statement, desc, node->nod_arg[0], null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[0], null_replacement);
|
||||
desc->dsc_flags = DSC_nullable;
|
||||
return;
|
||||
|
||||
case nod_agg_average:
|
||||
MAKE_desc(statement, desc, node->nod_arg[0], null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[0], null_replacement);
|
||||
desc->dsc_flags = DSC_nullable;
|
||||
if (!DTYPE_IS_NUMERIC(desc->dsc_dtype) && !DTYPE_IS_TEXT(desc->dsc_dtype))
|
||||
{
|
||||
@ -464,7 +464,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_agg_average2:
|
||||
MAKE_desc(statement, desc, node->nod_arg[0], null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[0], null_replacement);
|
||||
desc->dsc_flags = DSC_nullable;
|
||||
dtype = desc->dsc_dtype;
|
||||
if (!DTYPE_IS_NUMERIC(dtype))
|
||||
@ -486,7 +486,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_agg_total:
|
||||
MAKE_desc(statement, desc, node->nod_arg[0], null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[0], null_replacement);
|
||||
if (!DTYPE_IS_NUMERIC(desc->dsc_dtype) && !DTYPE_IS_TEXT(desc->dsc_dtype))
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_expression_eval_err) <<
|
||||
@ -511,7 +511,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_agg_total2:
|
||||
MAKE_desc(statement, desc, node->nod_arg[0], null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[0], null_replacement);
|
||||
dtype = desc->dsc_dtype;
|
||||
if (!DTYPE_IS_NUMERIC(dtype))
|
||||
{
|
||||
@ -533,24 +533,24 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_agg_list:
|
||||
MAKE_desc(statement, desc, node->nod_arg[0], null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[0], null_replacement);
|
||||
desc->makeBlob(desc->getBlobSubType(), desc->getTextType());
|
||||
desc->setNullable(true);
|
||||
return;
|
||||
|
||||
case nod_concatenate:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(statement, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
DSqlDataTypeUtil(statement).makeConcatenate(desc, &desc1, &desc2);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(dsqlScratch, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
DSqlDataTypeUtil(dsqlScratch).makeConcatenate(desc, &desc1, &desc2);
|
||||
return;
|
||||
|
||||
case nod_derived_field:
|
||||
MAKE_desc(statement, desc, node->nod_arg[e_derived_field_value], null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[e_derived_field_value], null_replacement);
|
||||
return;
|
||||
|
||||
case nod_upcase:
|
||||
case nod_lowcase:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[0], null_replacement);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[0], null_replacement);
|
||||
if (desc1.dsc_dtype <= dtype_any_text || desc1.dsc_dtype == dtype_blob)
|
||||
{
|
||||
*desc = desc1;
|
||||
@ -565,16 +565,16 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_substr:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[0], null_replacement);
|
||||
MAKE_desc(statement, &desc2, node->nod_arg[1], null_replacement);
|
||||
MAKE_desc(statement, &desc3, node->nod_arg[2], null_replacement);
|
||||
DSqlDataTypeUtil(statement).makeSubstr(desc, &desc1, &desc2, &desc3);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[0], null_replacement);
|
||||
MAKE_desc(dsqlScratch, &desc2, node->nod_arg[1], null_replacement);
|
||||
MAKE_desc(dsqlScratch, &desc3, node->nod_arg[2], null_replacement);
|
||||
DSqlDataTypeUtil(dsqlScratch).makeSubstr(desc, &desc1, &desc2, &desc3);
|
||||
return;
|
||||
|
||||
case nod_trim:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[e_trim_value], null_replacement);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[e_trim_value], null_replacement);
|
||||
if (node->nod_arg[e_trim_characters])
|
||||
MAKE_desc(statement, &desc2, node->nod_arg[e_trim_characters], null_replacement);
|
||||
MAKE_desc(dsqlScratch, &desc2, node->nod_arg[e_trim_characters], null_replacement);
|
||||
else
|
||||
desc2.dsc_flags = 0;
|
||||
|
||||
@ -604,24 +604,24 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
case nod_cast:
|
||||
field = (dsql_fld*) node->nod_arg[e_cast_target];
|
||||
MAKE_desc_from_field(desc, field);
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[e_cast_source], NULL);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[e_cast_source], NULL);
|
||||
desc->dsc_flags = desc1.dsc_flags & DSC_nullable;
|
||||
return;
|
||||
|
||||
case nod_simple_case:
|
||||
MAKE_desc_from_list(statement, &desc1, node->nod_arg[e_simple_case_results],
|
||||
MAKE_desc_from_list(dsqlScratch, &desc1, node->nod_arg[e_simple_case_results],
|
||||
null_replacement, "CASE");
|
||||
*desc = desc1;
|
||||
return;
|
||||
|
||||
case nod_searched_case:
|
||||
MAKE_desc_from_list(statement, &desc1, node->nod_arg[e_searched_case_results],
|
||||
MAKE_desc_from_list(dsqlScratch, &desc1, node->nod_arg[e_searched_case_results],
|
||||
null_replacement, "CASE");
|
||||
*desc = desc1;
|
||||
return;
|
||||
|
||||
case nod_coalesce:
|
||||
MAKE_desc_from_list(statement, &desc1, node->nod_arg[0],
|
||||
MAKE_desc_from_list(dsqlScratch, &desc1, node->nod_arg[0],
|
||||
null_replacement, "COALESCE");
|
||||
*desc = desc1;
|
||||
return;
|
||||
@ -634,8 +634,8 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
|
||||
case nod_add:
|
||||
case nod_subtract:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(statement, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(dsqlScratch, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
|
||||
if (node->nod_arg[0]->nod_type == nod_null && node->nod_arg[1]->nod_type == nod_null)
|
||||
{
|
||||
@ -793,8 +793,8 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
|
||||
case nod_add2:
|
||||
case nod_subtract2:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(statement, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(dsqlScratch, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
|
||||
if (node->nod_arg[0]->nod_type == nod_null && node->nod_arg[1]->nod_type == nod_null)
|
||||
{
|
||||
@ -973,8 +973,8 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_multiply:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(statement, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(dsqlScratch, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
|
||||
if (node->nod_arg[0]->nod_type == nod_null && node->nod_arg[1]->nod_type == nod_null)
|
||||
{
|
||||
@ -1016,8 +1016,8 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_multiply2:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(statement, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(dsqlScratch, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
|
||||
if (node->nod_arg[0]->nod_type == nod_null && node->nod_arg[1]->nod_type == nod_null)
|
||||
{
|
||||
@ -1078,8 +1078,8 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
*/
|
||||
|
||||
case nod_divide:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(statement, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(dsqlScratch, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
|
||||
if (node->nod_arg[0]->nod_type == nod_null && node->nod_arg[1]->nod_type == nod_null)
|
||||
{
|
||||
@ -1118,8 +1118,8 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_divide2:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(statement, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[0], node->nod_arg[1]);
|
||||
MAKE_desc(dsqlScratch, &desc2, node->nod_arg[1], node->nod_arg[0]);
|
||||
|
||||
if (node->nod_arg[0]->nod_type == nod_null && node->nod_arg[1]->nod_type == nod_null)
|
||||
{
|
||||
@ -1168,7 +1168,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_negate:
|
||||
MAKE_desc(statement, desc, node->nod_arg[0], null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[0], null_replacement);
|
||||
|
||||
if (node->nod_arg[0]->nod_type == nod_null)
|
||||
{
|
||||
@ -1181,7 +1181,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
// (use a specific cast instead)
|
||||
if (DTYPE_IS_TEXT(desc->dsc_dtype))
|
||||
{
|
||||
if (statement->req_client_dialect >= SQL_DIALECT_V6_TRANSITION)
|
||||
if (dsqlScratch->clientDialect >= SQL_DIALECT_V6_TRANSITION)
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_expression_eval_err) <<
|
||||
Arg::Gds(isc_dsql_nostring_neg_dial3));
|
||||
@ -1204,7 +1204,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_alias:
|
||||
MAKE_desc(statement, desc, node->nod_arg[e_alias_value], null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[e_alias_value], null_replacement);
|
||||
return;
|
||||
|
||||
case nod_dbkey:
|
||||
@ -1260,19 +1260,20 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
for (dsql_nod** p = nodeArgs->nod_arg;
|
||||
p < nodeArgs->nod_arg + nodeArgs->nod_count; ++p)
|
||||
{
|
||||
MAKE_desc(statement, &(*p)->nod_desc, *p, NULL);
|
||||
MAKE_desc(dsqlScratch, &(*p)->nod_desc, *p, NULL);
|
||||
args.add(&(*p)->nod_desc);
|
||||
}
|
||||
}
|
||||
|
||||
const dsql_str* name = (dsql_str*) node->nod_arg[e_sysfunc_name];
|
||||
DSqlDataTypeUtil(statement).makeSysFunction(desc, name->str_data, args.getCount(), args.begin());
|
||||
DSqlDataTypeUtil(dsqlScratch).makeSysFunction(desc, name->str_data,
|
||||
args.getCount(), args.begin());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case nod_gen_id:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[e_gen_id_value], NULL);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[e_gen_id_value], NULL);
|
||||
desc->dsc_dtype = dtype_long;
|
||||
desc->dsc_sub_type = 0;
|
||||
desc->dsc_scale = 0;
|
||||
@ -1281,7 +1282,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_gen_id2:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[e_gen_id_value], NULL);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[e_gen_id_value], NULL);
|
||||
desc->dsc_dtype = dtype_int64;
|
||||
desc->dsc_sub_type = 0;
|
||||
desc->dsc_scale = 0;
|
||||
@ -1292,7 +1293,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
|
||||
case nod_limit:
|
||||
case nod_rows:
|
||||
if (statement->req_client_dialect <= SQL_DIALECT_V5)
|
||||
if (dsqlScratch->clientDialect <= SQL_DIALECT_V5)
|
||||
{
|
||||
desc->dsc_dtype = dtype_long;
|
||||
desc->dsc_length = sizeof (SLONG);
|
||||
@ -1327,7 +1328,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
desc->dsc_ttype() = ttype_metadata;
|
||||
desc->dsc_length =
|
||||
(USERNAME_LENGTH / METADATA_BYTES_PER_CHAR) *
|
||||
METD_get_charset_bpc(statement, ttype_metadata) + sizeof(USHORT);
|
||||
METD_get_charset_bpc(dsqlScratch->getTransaction(), ttype_metadata) + sizeof(USHORT);
|
||||
return;
|
||||
|
||||
case nod_internal_info:
|
||||
@ -1362,7 +1363,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_extract:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[e_extract_value], NULL);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[e_extract_value], NULL);
|
||||
|
||||
switch (node->nod_arg[e_extract_part]->getSlong())
|
||||
{
|
||||
@ -1384,7 +1385,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_strlen:
|
||||
MAKE_desc(statement, &desc1, node->nod_arg[e_strlen_value], NULL);
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[e_strlen_value], NULL);
|
||||
desc->dsc_sub_type = 0;
|
||||
desc->dsc_scale = 0;
|
||||
desc->dsc_flags = (desc1.dsc_flags & DSC_nullable);
|
||||
@ -1421,7 +1422,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
|
||||
if (null_replacement)
|
||||
{
|
||||
MAKE_desc(statement, desc, null_replacement, NULL);
|
||||
MAKE_desc(dsqlScratch, desc, null_replacement, NULL);
|
||||
desc->dsc_flags |= (DSC_nullable | DSC_null);
|
||||
}
|
||||
else
|
||||
@ -1429,7 +1430,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_via:
|
||||
MAKE_desc(statement, desc, node->nod_arg[e_via_value_1], null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[e_via_value_1], null_replacement);
|
||||
// Set the descriptor flag as nullable. The
|
||||
// select expression may or may not return
|
||||
// this row based on the WHERE clause. Setting this
|
||||
@ -1440,7 +1441,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
return;
|
||||
|
||||
case nod_hidden_var:
|
||||
MAKE_desc(statement, desc, node->nod_arg[e_hidden_var_expr], null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[e_hidden_var_expr], null_replacement);
|
||||
return;
|
||||
|
||||
case nod_select_expr: // this should come from pass1_any call to set_parameter_type
|
||||
@ -1448,7 +1449,7 @@ void MAKE_desc(CompiledStatement* statement, dsc* desc, dsql_nod* node, dsql_nod
|
||||
fb_assert(node->nod_type == nod_query_spec);
|
||||
node = node->nod_arg[e_qry_list];
|
||||
fb_assert(node->nod_type == nod_list && node->nod_count > 0);
|
||||
MAKE_desc(statement, desc, node->nod_arg[0], null_replacement);
|
||||
MAKE_desc(dsqlScratch, desc, node->nod_arg[0], null_replacement);
|
||||
return;
|
||||
|
||||
default:
|
||||
@ -1511,7 +1512,7 @@ void MAKE_desc_from_field(dsc* desc, const dsql_fld* field)
|
||||
@param expression_name
|
||||
|
||||
**/
|
||||
void MAKE_desc_from_list(CompiledStatement* statement, dsc* desc, dsql_nod* node,
|
||||
void MAKE_desc_from_list(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* node,
|
||||
dsql_nod* null_replacement,
|
||||
const TEXT* expression_name)
|
||||
{
|
||||
@ -1521,17 +1522,17 @@ void MAKE_desc_from_list(CompiledStatement* statement, dsc* desc, dsql_nod* node
|
||||
|
||||
for (dsql_nod** p = node->nod_arg; p < node->nod_arg + node->nod_count; ++p)
|
||||
{
|
||||
MAKE_desc(statement, &(*p)->nod_desc, *p, NULL);
|
||||
MAKE_desc(dsqlScratch, &(*p)->nod_desc, *p, NULL);
|
||||
args.add(&(*p)->nod_desc);
|
||||
}
|
||||
|
||||
DSqlDataTypeUtil(statement).makeFromList(desc, expression_name, args.getCount(), args.begin());
|
||||
DSqlDataTypeUtil(dsqlScratch).makeFromList(desc, expression_name, args.getCount(), args.begin());
|
||||
|
||||
// If we have literal NULLs only, let the result be either
|
||||
// CHAR(1) CHARACTER SET NONE or the context-provided datatype
|
||||
if (desc->isNull() && null_replacement)
|
||||
{
|
||||
MAKE_desc(statement, desc, null_replacement, NULL);
|
||||
MAKE_desc(dsqlScratch, desc, null_replacement, NULL);
|
||||
desc->dsc_flags |= DSC_null | DSC_nullable;
|
||||
return;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ namespace Jrd {
|
||||
class dsql_nod;
|
||||
class dsql_fld;
|
||||
class dsql_req;
|
||||
class CompiledStatement;
|
||||
class DsqlCompilerScratch;
|
||||
|
||||
// Parameters to MAKE_constant
|
||||
enum dsql_constant_type {
|
||||
@ -60,9 +60,9 @@ Jrd::dsql_nod* MAKE_const_slong(SLONG);
|
||||
Jrd::dsql_nod* MAKE_constant(Jrd::dsql_str*, Jrd::dsql_constant_type);
|
||||
Jrd::dsql_nod* MAKE_str_constant(Jrd::dsql_str*, SSHORT);
|
||||
Jrd::dsql_str* MAKE_cstring(const char*);
|
||||
void MAKE_desc(Jrd::CompiledStatement*, dsc*, Jrd::dsql_nod*, Jrd::dsql_nod*);
|
||||
void MAKE_desc(Jrd::DsqlCompilerScratch*, dsc*, Jrd::dsql_nod*, Jrd::dsql_nod*);
|
||||
void MAKE_desc_from_field(dsc*, const Jrd::dsql_fld*);
|
||||
void MAKE_desc_from_list(Jrd::CompiledStatement*, dsc*, Jrd::dsql_nod*, Jrd::dsql_nod*, const TEXT*);
|
||||
void MAKE_desc_from_list(Jrd::DsqlCompilerScratch*, dsc*, Jrd::dsql_nod*, Jrd::dsql_nod*, const TEXT*);
|
||||
Jrd::dsql_nod* MAKE_field(Jrd::dsql_ctx*, Jrd::dsql_fld*, Jrd::dsql_nod*);
|
||||
Jrd::dsql_nod* MAKE_field_name(const char*);
|
||||
Jrd::dsql_nod* MAKE_list(Jrd::DsqlNodStack&);
|
||||
@ -75,4 +75,3 @@ Jrd::dsql_nod* MAKE_variable(Jrd::dsql_fld*, const TEXT*, const Jrd::dsql_var_ty
|
||||
USHORT, USHORT);
|
||||
|
||||
#endif // DSQL_MAKE_PROTO_H
|
||||
|
||||
|
@ -78,9 +78,9 @@ static void free_relation(dsql_rel*);
|
||||
|
||||
namespace
|
||||
{
|
||||
inline void validateTransaction(const dsql_req* request)
|
||||
inline void validateTransaction(const jrd_tra* transaction)
|
||||
{
|
||||
if (!request->req_transaction->checkHandle())
|
||||
if (!transaction->checkHandle())
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_bad_trans_handle));
|
||||
}
|
||||
@ -88,7 +88,7 @@ namespace
|
||||
}
|
||||
|
||||
|
||||
void METD_drop_charset(dsql_req* request, const MetaName& metaName)
|
||||
void METD_drop_charset(jrd_tra* transaction, const MetaName& metaName)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -105,19 +105,20 @@ void METD_drop_charset(dsql_req* request, const MetaName& metaName)
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
dsql_intlsym* charSet;
|
||||
|
||||
if (request->req_dbb->dbb_charsets.get(metaName, charSet))
|
||||
if (dbb->dbb_charsets.get(metaName, charSet))
|
||||
{
|
||||
MET_dsql_cache_use(tdbb, SYM_intlsym_charset, metaName);
|
||||
charSet->intlsym_flags |= INTLSYM_dropped;
|
||||
request->req_dbb->dbb_charsets.remove(metaName);
|
||||
request->req_dbb->dbb_charsets_by_id.remove(charSet->intlsym_charset_id);
|
||||
dbb->dbb_charsets.remove(metaName);
|
||||
dbb->dbb_charsets_by_id.remove(charSet->intlsym_charset_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void METD_drop_collation(dsql_req* request, const dsql_str* name)
|
||||
void METD_drop_collation(jrd_tra* transaction, const dsql_str* name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -136,20 +137,21 @@ void METD_drop_collation(dsql_req* request, const dsql_str* name)
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
|
||||
MetaName metaName(name->str_data, name->str_length);
|
||||
dsql_intlsym* collation;
|
||||
|
||||
if (request->req_dbb->dbb_collations.get(metaName, collation))
|
||||
if (dbb->dbb_collations.get(metaName, collation))
|
||||
{
|
||||
MET_dsql_cache_use(tdbb, SYM_intlsym_collation, metaName);
|
||||
collation->intlsym_flags |= INTLSYM_dropped;
|
||||
request->req_dbb->dbb_collations.remove(metaName);
|
||||
dbb->dbb_collations.remove(metaName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void METD_drop_function(dsql_req* request, const dsql_str* name, const MetaName& packageName)
|
||||
void METD_drop_function(jrd_tra* transaction, const dsql_str* name, const MetaName& packageName)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -168,21 +170,22 @@ void METD_drop_function(dsql_req* request, const dsql_str* name, const MetaName&
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
|
||||
const QualifiedName metaName(MetaName(name->str_data, name->str_length), packageName);
|
||||
dsql_udf* function;
|
||||
|
||||
if (request->req_dbb->dbb_functions.get(metaName, function))
|
||||
if (dbb->dbb_functions.get(metaName, function))
|
||||
{
|
||||
MET_dsql_cache_use(tdbb, SYM_udf, metaName.identifier, metaName.qualifier);
|
||||
function->udf_flags |= UDF_dropped;
|
||||
request->req_dbb->dbb_functions.remove(metaName);
|
||||
dbb->dbb_functions.remove(metaName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void METD_drop_procedure(dsql_req* request, const dsql_str* name, const MetaName& packageName)
|
||||
void METD_drop_procedure(jrd_tra* transaction, const dsql_str* name, const MetaName& packageName)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -201,20 +204,21 @@ void METD_drop_procedure(dsql_req* request, const dsql_str* name, const MetaName
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
|
||||
const QualifiedName metaName(MetaName(name->str_data, name->str_length), packageName);
|
||||
dsql_prc* procedure;
|
||||
|
||||
if (request->req_dbb->dbb_procedures.get(metaName, procedure))
|
||||
if (dbb->dbb_procedures.get(metaName, procedure))
|
||||
{
|
||||
MET_dsql_cache_use(tdbb, SYM_procedure, metaName.identifier, metaName.qualifier);
|
||||
procedure->prc_flags |= PRC_dropped;
|
||||
request->req_dbb->dbb_procedures.remove(metaName);
|
||||
dbb->dbb_procedures.remove(metaName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void METD_drop_relation(dsql_req* request, const dsql_str* name)
|
||||
void METD_drop_relation(jrd_tra* transaction, const dsql_str* name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -233,20 +237,21 @@ void METD_drop_relation(dsql_req* request, const dsql_str* name)
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
|
||||
MetaName metaName(name->str_data, name->str_length);
|
||||
dsql_rel* relation;
|
||||
|
||||
if (request->req_dbb->dbb_relations.get(metaName, relation))
|
||||
if (dbb->dbb_relations.get(metaName, relation))
|
||||
{
|
||||
MET_dsql_cache_use(tdbb, SYM_relation, metaName);
|
||||
relation->rel_flags |= REL_dropped;
|
||||
request->req_dbb->dbb_relations.remove(metaName);
|
||||
dbb->dbb_relations.remove(metaName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dsql_intlsym* METD_get_collation(dsql_req* request, const dsql_str* name, USHORT charset_id)
|
||||
dsql_intlsym* METD_get_collation(jrd_tra* transaction, const dsql_str* name, USHORT charset_id)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -261,7 +266,9 @@ dsql_intlsym* METD_get_collation(dsql_req* request, const dsql_str* name, USHORT
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
dsql_dbb* dbb = request->req_dbb;
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
MetaName metaName(name->str_data, name->str_length);
|
||||
|
||||
// Start by seeing if symbol is already defined
|
||||
@ -277,13 +284,11 @@ dsql_intlsym* METD_get_collation(dsql_req* request, const dsql_str* name, USHORT
|
||||
|
||||
// Now see if it is in the database
|
||||
|
||||
validateTransaction(request);
|
||||
|
||||
symbol = NULL;
|
||||
|
||||
jrd_req* handle = CMP_find_request(tdbb, irq_collation, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE request->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$COLLATIONS
|
||||
CROSS Y IN RDB$CHARACTER_SETS OVER RDB$CHARACTER_SET_ID
|
||||
WITH X.RDB$COLLATION_NAME EQ name->str_data AND
|
||||
@ -317,12 +322,8 @@ dsql_intlsym* METD_get_collation(dsql_req* request, const dsql_str* name, USHORT
|
||||
}
|
||||
|
||||
|
||||
USHORT METD_get_col_default(dsql_req* request,
|
||||
const char* for_rel_name,
|
||||
const char* for_col_name,
|
||||
bool* has_default,
|
||||
UCHAR* buffer,
|
||||
USHORT buff_length)
|
||||
USHORT METD_get_col_default(jrd_tra* transaction, const char* for_rel_name,
|
||||
const char* for_col_name, bool* has_default, UCHAR* buffer, USHORT buff_length)
|
||||
{
|
||||
/*************************************************************
|
||||
*
|
||||
@ -343,10 +344,9 @@ USHORT METD_get_col_default(dsql_req* request,
|
||||
**************************************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
validateTransaction(request);
|
||||
|
||||
dsql_dbb* dbb = request->req_dbb;
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
bid* blob_id;
|
||||
|
||||
USHORT result = 0;
|
||||
@ -356,7 +356,7 @@ USHORT METD_get_col_default(dsql_req* request,
|
||||
|
||||
jrd_req* handle = CMP_find_request(tdbb, irq_col_default, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE request->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
RFL IN RDB$RELATION_FIELDS CROSS
|
||||
FLD IN RDB$FIELDS WITH
|
||||
RFL.RDB$RELATION_NAME EQ for_rel_name AND
|
||||
@ -381,8 +381,7 @@ USHORT METD_get_col_default(dsql_req* request,
|
||||
|
||||
if (*has_default)
|
||||
{
|
||||
blob_handle = BLB_open2(tdbb, request->req_transaction, blob_id,
|
||||
sizeof(blr_bpb), blr_bpb, true);
|
||||
blob_handle = BLB_open2(tdbb, transaction, blob_id, sizeof(blr_bpb), blr_bpb, true);
|
||||
|
||||
// fetch segments. Assuming here that the buffer is big enough.
|
||||
UCHAR* ptr_in_buffer = buffer;
|
||||
@ -424,7 +423,7 @@ USHORT METD_get_col_default(dsql_req* request,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request->req_dbb->dbb_db_SQL_dialect > SQL_DIALECT_V5)
|
||||
if (dbb->dbb_db_SQL_dialect > SQL_DIALECT_V5)
|
||||
buffer[0] = blr_version5;
|
||||
else
|
||||
buffer[0] = blr_version4;
|
||||
@ -441,7 +440,7 @@ USHORT METD_get_col_default(dsql_req* request,
|
||||
}
|
||||
|
||||
|
||||
dsql_intlsym* METD_get_charset(dsql_req* request, USHORT length, const char* name) // UTF-8
|
||||
dsql_intlsym* METD_get_charset(jrd_tra* transaction, USHORT length, const char* name) // UTF-8
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -456,7 +455,9 @@ dsql_intlsym* METD_get_charset(dsql_req* request, USHORT length, const char* nam
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
dsql_dbb* dbb = request->req_dbb;
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
MetaName metaName(name, length);
|
||||
|
||||
// Start by seeing if symbol is already defined
|
||||
@ -472,13 +473,11 @@ dsql_intlsym* METD_get_charset(dsql_req* request, USHORT length, const char* nam
|
||||
|
||||
// Now see if it is in the database
|
||||
|
||||
validateTransaction(request);
|
||||
|
||||
symbol = NULL;
|
||||
|
||||
jrd_req* handle = CMP_find_request(tdbb, irq_charset, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE request->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$COLLATIONS
|
||||
CROSS Y IN RDB$CHARACTER_SETS OVER RDB$CHARACTER_SET_ID
|
||||
CROSS Z IN RDB$TYPES
|
||||
@ -516,7 +515,7 @@ dsql_intlsym* METD_get_charset(dsql_req* request, USHORT length, const char* nam
|
||||
}
|
||||
|
||||
|
||||
USHORT METD_get_charset_bpc(dsql_req* request, SSHORT charset_id)
|
||||
USHORT METD_get_charset_bpc(jrd_tra* transaction, SSHORT charset_id)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -534,7 +533,7 @@ USHORT METD_get_charset_bpc(dsql_req* request, SSHORT charset_id)
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
dsql_dbb* dbb = request->req_dbb;
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
|
||||
if (charset_id == CS_dynamic)
|
||||
charset_id = tdbb->getCharSet();
|
||||
@ -542,8 +541,8 @@ USHORT METD_get_charset_bpc(dsql_req* request, SSHORT charset_id)
|
||||
dsql_intlsym* symbol = NULL;
|
||||
if (!dbb->dbb_charsets_by_id.get(charset_id, symbol))
|
||||
{
|
||||
const MetaName cs_name = METD_get_charset_name(request, charset_id);
|
||||
symbol = METD_get_charset(request, cs_name.length(), cs_name.c_str());
|
||||
const MetaName cs_name = METD_get_charset_name(transaction, charset_id);
|
||||
symbol = METD_get_charset(transaction, cs_name.length(), cs_name.c_str());
|
||||
}
|
||||
|
||||
fb_assert(symbol);
|
||||
@ -552,7 +551,7 @@ USHORT METD_get_charset_bpc(dsql_req* request, SSHORT charset_id)
|
||||
}
|
||||
|
||||
|
||||
MetaName METD_get_charset_name(dsql_req* request, SSHORT charset_id)
|
||||
MetaName METD_get_charset_name(jrd_tra* transaction, SSHORT charset_id)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -569,7 +568,9 @@ MetaName METD_get_charset_name(dsql_req* request, SSHORT charset_id)
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
dsql_dbb* dbb = request->req_dbb;
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
|
||||
if (charset_id == CS_dynamic)
|
||||
charset_id = tdbb->getCharSet();
|
||||
@ -578,13 +579,11 @@ MetaName METD_get_charset_name(dsql_req* request, SSHORT charset_id)
|
||||
if (dbb->dbb_charsets_by_id.get(charset_id, sym))
|
||||
return sym->intlsym_name;
|
||||
|
||||
validateTransaction(request);
|
||||
|
||||
MetaName name;
|
||||
|
||||
jrd_req* handle = CMP_find_request(tdbb, irq_cs_name, IRQ_REQUESTS);
|
||||
|
||||
FOR (REQUEST_HANDLE handle TRANSACTION_HANDLE request->req_transaction)
|
||||
FOR (REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
Y IN RDB$CHARACTER_SETS
|
||||
WITH Y.RDB$CHARACTER_SET_ID EQ charset_id
|
||||
|
||||
@ -599,13 +598,13 @@ MetaName METD_get_charset_name(dsql_req* request, SSHORT charset_id)
|
||||
DSQL_REQUEST(irq_cs_name) = handle;
|
||||
|
||||
// put new charset into hash table if needed
|
||||
METD_get_charset(request, name.length(), name.c_str());
|
||||
METD_get_charset(transaction, name.length(), name.c_str());
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
dsql_str* METD_get_default_charset(dsql_req* request)
|
||||
dsql_str* METD_get_default_charset(jrd_tra* transaction)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -619,7 +618,9 @@ dsql_str* METD_get_default_charset(dsql_req* request)
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
dsql_dbb* dbb = request->req_dbb;
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
if (dbb->dbb_no_charset)
|
||||
return NULL;
|
||||
|
||||
@ -628,11 +629,9 @@ dsql_str* METD_get_default_charset(dsql_req* request)
|
||||
|
||||
// Now see if it is in the database
|
||||
|
||||
validateTransaction(request);
|
||||
|
||||
jrd_req* handle = CMP_find_request(tdbb, irq_default_cs, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE request->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
FIRST 1 DBB IN RDB$DATABASE
|
||||
WITH DBB.RDB$CHARACTER_SET_NAME NOT MISSING;
|
||||
|
||||
@ -659,7 +658,7 @@ dsql_str* METD_get_default_charset(dsql_req* request)
|
||||
}
|
||||
|
||||
|
||||
bool METD_get_domain(dsql_req* request, dsql_fld* field, const char* name) // UTF-8
|
||||
bool METD_get_domain(jrd_tra* transaction, dsql_fld* field, const char* name) // UTF-8
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -673,15 +672,15 @@ bool METD_get_domain(dsql_req* request, dsql_fld* field, const char* name) // UT
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
validateTransaction(request);
|
||||
validateTransaction(transaction);
|
||||
|
||||
bool found = false;
|
||||
|
||||
dsql_dbb* dbb = request->req_dbb;
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
|
||||
jrd_req* handle = CMP_find_request(tdbb, irq_domain, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE request->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
FLX IN RDB$FIELDS WITH FLX.RDB$FIELD_NAME EQ name
|
||||
|
||||
if (!DSQL_REQUEST(irq_domain))
|
||||
@ -724,11 +723,8 @@ bool METD_get_domain(dsql_req* request, dsql_fld* field, const char* name) // UT
|
||||
}
|
||||
|
||||
|
||||
USHORT METD_get_domain_default(dsql_req* request,
|
||||
const TEXT* domain_name,
|
||||
bool* has_default,
|
||||
UCHAR* buffer,
|
||||
USHORT buff_length)
|
||||
USHORT METD_get_domain_default(jrd_tra* transaction, const TEXT* domain_name, bool* has_default,
|
||||
UCHAR* buffer, USHORT buff_length)
|
||||
{
|
||||
/*************************************************************
|
||||
*
|
||||
@ -742,16 +738,16 @@ USHORT METD_get_domain_default(dsql_req* request,
|
||||
**************************************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
validateTransaction(request);
|
||||
validateTransaction(transaction);
|
||||
|
||||
*has_default = false;
|
||||
|
||||
dsql_dbb* dbb = request->req_dbb;
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
USHORT result = 0;
|
||||
|
||||
jrd_req* handle = CMP_find_request(tdbb, irq_domain_2, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE request->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME EQ domain_name
|
||||
|
||||
if (!DSQL_REQUEST(irq_domain_2))
|
||||
@ -768,8 +764,7 @@ USHORT METD_get_domain_default(dsql_req* request,
|
||||
|
||||
if (*has_default)
|
||||
{
|
||||
blb* blob_handle = BLB_open2(tdbb, request->req_transaction, blob_id,
|
||||
sizeof(blr_bpb), blr_bpb, true);
|
||||
blb* blob_handle = BLB_open2(tdbb, transaction, blob_id, sizeof(blr_bpb), blr_bpb, true);
|
||||
|
||||
// fetch segments. Assume buffer is big enough.
|
||||
UCHAR* ptr_in_buffer = buffer;
|
||||
@ -811,7 +806,7 @@ USHORT METD_get_domain_default(dsql_req* request,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request->req_dbb->dbb_db_SQL_dialect > SQL_DIALECT_V5)
|
||||
if (dbb->dbb_db_SQL_dialect > SQL_DIALECT_V5)
|
||||
buffer[0] = blr_version5;
|
||||
else
|
||||
buffer[0] = blr_version4;
|
||||
@ -828,7 +823,7 @@ USHORT METD_get_domain_default(dsql_req* request,
|
||||
}
|
||||
|
||||
|
||||
bool METD_get_exception(dsql_req* request, const dsql_str* name)
|
||||
bool METD_get_exception(jrd_tra* transaction, const dsql_str* name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -842,14 +837,14 @@ bool METD_get_exception(dsql_req* request, const dsql_str* name)
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
validateTransaction(request);
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_dbb* dbb = request->req_dbb;
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
bool found = false;
|
||||
|
||||
jrd_req* handle = CMP_find_request(tdbb, irq_exception, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE request->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$EXCEPTIONS WITH
|
||||
X.RDB$EXCEPTION_NAME EQ name->str_data;
|
||||
|
||||
@ -867,8 +862,8 @@ bool METD_get_exception(dsql_req* request, const dsql_str* name)
|
||||
}
|
||||
|
||||
|
||||
dsql_udf* METD_get_function(CompiledStatement* statement, const dsql_str* name,
|
||||
const dsql_str* package)
|
||||
dsql_udf* METD_get_function(jrd_tra* transaction, DsqlCompilerScratch* dsqlScratch,
|
||||
const dsql_str* name, const dsql_str* package)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -882,20 +877,23 @@ dsql_udf* METD_get_function(CompiledStatement* statement, const dsql_str* name,
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
dsql_dbb* dbb = statement->req_dbb;
|
||||
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
QualifiedName metaName(MetaName(name->str_data, name->str_length),
|
||||
(package ? MetaName(package->str_data, package->str_length) : NULL));
|
||||
|
||||
bool maybeUnqualified = statement->req_package.hasData() && metaName.qualifier.isEmpty();
|
||||
bool maybeUnqualified = dsqlScratch->package.hasData() && metaName.qualifier.isEmpty();
|
||||
if (maybeUnqualified)
|
||||
metaName.qualifier = statement->req_package;
|
||||
metaName.qualifier = dsqlScratch->package;
|
||||
|
||||
// Start by seeing if symbol is already defined
|
||||
|
||||
dsql_udf* userFunc = NULL;
|
||||
if (dbb->dbb_functions.get(metaName, userFunc))
|
||||
{
|
||||
if (userFunc->udf_private && metaName.qualifier != statement->req_package)
|
||||
if (userFunc->udf_private && metaName.qualifier != dsqlScratch->package)
|
||||
return NULL;
|
||||
|
||||
if (MET_dsql_cache_use(tdbb, SYM_udf, metaName.identifier, metaName.qualifier))
|
||||
@ -906,15 +904,13 @@ dsql_udf* METD_get_function(CompiledStatement* statement, const dsql_str* name,
|
||||
|
||||
// Now see if it is in the database
|
||||
|
||||
validateTransaction(statement);
|
||||
|
||||
USHORT return_arg = 0;
|
||||
|
||||
while (!userFunc)
|
||||
{
|
||||
jrd_req* handle1 = CMP_find_request(tdbb, irq_function, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle1 TRANSACTION_HANDLE statement->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle1 TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$FUNCTIONS WITH
|
||||
X.RDB$FUNCTION_NAME EQ name->str_data AND
|
||||
X.RDB$PACKAGE_NAME EQUIV NULLIF(metaName.qualifier.c_str(), '')
|
||||
@ -953,7 +949,7 @@ dsql_udf* METD_get_function(CompiledStatement* statement, const dsql_str* name,
|
||||
|
||||
jrd_req* handle2 = CMP_find_request(tdbb, irq_func_return, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle2 TRANSACTION_HANDLE statement->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle2 TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$FUNCTION_ARGUMENTS WITH
|
||||
X.RDB$FUNCTION_NAME EQ name->str_data AND
|
||||
X.RDB$PACKAGE_NAME EQUIV NULLIF(metaName.qualifier.c_str(), '')
|
||||
@ -1046,7 +1042,7 @@ dsql_udf* METD_get_function(CompiledStatement* statement, const dsql_str* name,
|
||||
|
||||
dbb->dbb_functions.put(userFunc->udf_name, userFunc);
|
||||
|
||||
if (userFunc->udf_private && metaName.qualifier != statement->req_package)
|
||||
if (userFunc->udf_private && metaName.qualifier != dsqlScratch->package)
|
||||
return NULL;
|
||||
|
||||
MET_dsql_cache_use(tdbb, SYM_udf, userFunc->udf_name.identifier, userFunc->udf_name.qualifier);
|
||||
@ -1055,7 +1051,7 @@ dsql_udf* METD_get_function(CompiledStatement* statement, const dsql_str* name,
|
||||
}
|
||||
|
||||
|
||||
dsql_nod* METD_get_primary_key(dsql_req* request, const dsql_str* relation_name)
|
||||
dsql_nod* METD_get_primary_key(jrd_tra* transaction, const dsql_str* relation_name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1071,15 +1067,15 @@ dsql_nod* METD_get_primary_key(dsql_req* request, const dsql_str* relation_name)
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
validateTransaction(request);
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_dbb* dbb = request->req_dbb;
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
|
||||
DsqlNodStack stack;
|
||||
|
||||
jrd_req* handle = CMP_find_request(tdbb, irq_primary_key, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE request->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$INDICES CROSS
|
||||
Y IN RDB$INDEX_SEGMENTS
|
||||
OVER RDB$INDEX_NAME CROSS
|
||||
@ -1103,8 +1099,8 @@ dsql_nod* METD_get_primary_key(dsql_req* request, const dsql_str* relation_name)
|
||||
}
|
||||
|
||||
|
||||
dsql_prc* METD_get_procedure(CompiledStatement* statement, const dsql_str* name,
|
||||
const dsql_str* package)
|
||||
dsql_prc* METD_get_procedure(jrd_tra* transaction, DsqlCompilerScratch* dsqlScratch,
|
||||
const dsql_str* name, const dsql_str* package)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1120,12 +1116,14 @@ dsql_prc* METD_get_procedure(CompiledStatement* statement, const dsql_str* name,
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
dsql_dbb* dbb = statement->req_dbb;
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
QualifiedName metaName(MetaName(name->str_data, name->str_length),
|
||||
(package ? MetaName(package->str_data, package->str_length) : ""));
|
||||
|
||||
// ASF: I've removed the code where we verify if the procedure being looked up is the one being
|
||||
// defined (statement->req_procedure). This code is totally incorrect, not considering
|
||||
// defined (dsqlScratch->procedure). This code is totally incorrect, not considering
|
||||
// transactions and savepoints, hence being incompatible with packages).
|
||||
// Example (with autocommit off):
|
||||
//
|
||||
@ -1158,16 +1156,16 @@ dsql_prc* METD_get_procedure(CompiledStatement* statement, const dsql_str* name,
|
||||
//
|
||||
// I hope for a solution, involving savepoint logic.
|
||||
|
||||
bool maybeUnqualified = statement->req_package.hasData() && metaName.qualifier.isEmpty();
|
||||
bool maybeUnqualified = dsqlScratch->package.hasData() && metaName.qualifier.isEmpty();
|
||||
if (maybeUnqualified)
|
||||
metaName.qualifier = statement->req_package;
|
||||
metaName.qualifier = dsqlScratch->package;
|
||||
|
||||
// Start by seeing if symbol is already defined
|
||||
|
||||
dsql_prc* procedure = NULL;
|
||||
if (dbb->dbb_procedures.get(metaName, procedure))
|
||||
{
|
||||
if (procedure->prc_private && metaName.qualifier != statement->req_package)
|
||||
if (procedure->prc_private && metaName.qualifier != dsqlScratch->package)
|
||||
return NULL;
|
||||
|
||||
if (MET_dsql_cache_use(tdbb, SYM_procedure, metaName.identifier, metaName.qualifier))
|
||||
@ -1178,13 +1176,11 @@ dsql_prc* METD_get_procedure(CompiledStatement* statement, const dsql_str* name,
|
||||
|
||||
// now see if it is in the database
|
||||
|
||||
validateTransaction(statement);
|
||||
|
||||
while (!procedure)
|
||||
{
|
||||
jrd_req* handle1 = CMP_find_request(tdbb, irq_procedure, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle1 TRANSACTION_HANDLE statement->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle1 TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$PROCEDURES
|
||||
WITH X.RDB$PROCEDURE_NAME EQ name->str_data AND
|
||||
X.RDB$PACKAGE_NAME EQUIV NULLIF(metaName.qualifier.c_str(), '')
|
||||
@ -1227,7 +1223,7 @@ dsql_prc* METD_get_procedure(CompiledStatement* statement, const dsql_str* name,
|
||||
|
||||
jrd_req* handle2 = CMP_find_request(tdbb, irq_parameters, IRQ_REQUESTS);
|
||||
|
||||
FOR (REQUEST_HANDLE handle2 TRANSACTION_HANDLE statement->req_transaction)
|
||||
FOR (REQUEST_HANDLE handle2 TRANSACTION_HANDLE transaction)
|
||||
PR IN RDB$PROCEDURE_PARAMETERS
|
||||
CROSS FLD IN RDB$FIELDS
|
||||
WITH FLD.RDB$FIELD_NAME EQ PR.RDB$FIELD_SOURCE AND
|
||||
@ -1315,7 +1311,7 @@ dsql_prc* METD_get_procedure(CompiledStatement* statement, const dsql_str* name,
|
||||
|
||||
dbb->dbb_procedures.put(procedure->prc_name, procedure);
|
||||
|
||||
if (procedure->prc_private && metaName.qualifier != statement->req_package)
|
||||
if (procedure->prc_private && metaName.qualifier != dsqlScratch->package)
|
||||
return NULL;
|
||||
|
||||
MET_dsql_cache_use(tdbb, SYM_procedure, procedure->prc_name.identifier,
|
||||
@ -1325,7 +1321,7 @@ dsql_prc* METD_get_procedure(CompiledStatement* statement, const dsql_str* name,
|
||||
}
|
||||
|
||||
|
||||
dsql_rel* METD_get_relation(CompiledStatement* statement, const dsql_str* name)
|
||||
dsql_rel* METD_get_relation(jrd_tra* transaction, DsqlCompilerScratch* dsqlScratch, const dsql_str* name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1340,12 +1336,14 @@ dsql_rel* METD_get_relation(CompiledStatement* statement, const dsql_str* name)
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
dsql_dbb* dbb = statement->req_dbb;
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
MetaName metaName(name->str_data, name->str_length);
|
||||
|
||||
// See if the relation is the one currently being defined in this statement
|
||||
|
||||
dsql_rel* temp = statement->req_relation;
|
||||
dsql_rel* temp = dsqlScratch->relation;
|
||||
if (temp != NULL && temp->rel_name == name->str_data)
|
||||
{
|
||||
return temp;
|
||||
@ -1365,13 +1363,11 @@ dsql_rel* METD_get_relation(CompiledStatement* statement, const dsql_str* name)
|
||||
// and this is a type of statement which does not use ids, prepare a
|
||||
// temporary relation block to provide information without caching it
|
||||
|
||||
validateTransaction(statement);
|
||||
|
||||
bool permanent = true;
|
||||
|
||||
jrd_req* handle1 = CMP_find_request(tdbb, irq_rel_ids, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle1 TRANSACTION_HANDLE statement->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle1 TRANSACTION_HANDLE transaction)
|
||||
REL IN RDB$RELATIONS
|
||||
CROSS RFR IN RDB$RELATION_FIELDS OVER RDB$RELATION_NAME
|
||||
WITH REL.RDB$RELATION_NAME EQ name->str_data
|
||||
@ -1395,7 +1391,7 @@ dsql_rel* METD_get_relation(CompiledStatement* statement, const dsql_str* name)
|
||||
|
||||
jrd_req* handle2 = CMP_find_request(tdbb, irq_relation, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle2 TRANSACTION_HANDLE statement->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle2 TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$RELATIONS WITH X.RDB$RELATION_NAME EQ name->str_data
|
||||
|
||||
if (!DSQL_REQUEST(irq_relation))
|
||||
@ -1410,7 +1406,7 @@ dsql_rel* METD_get_relation(CompiledStatement* statement, const dsql_str* name)
|
||||
relation = FB_NEW(pool) dsql_rel(pool);
|
||||
relation->rel_id = X.RDB$RELATION_ID;
|
||||
}
|
||||
else if (!DDL_ids(statement)) {
|
||||
else if (!DDL_ids(dsqlScratch)) {
|
||||
relation = FB_NEW(pool) dsql_rel(pool);
|
||||
}
|
||||
|
||||
@ -1446,7 +1442,7 @@ dsql_rel* METD_get_relation(CompiledStatement* statement, const dsql_str* name)
|
||||
|
||||
jrd_req* handle3 = CMP_find_request(tdbb, irq_fields, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle3 TRANSACTION_HANDLE statement->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle3 TRANSACTION_HANDLE transaction)
|
||||
FLX IN RDB$FIELDS CROSS
|
||||
RFR IN RDB$RELATION_FIELDS
|
||||
WITH FLX.RDB$FIELD_NAME EQ RFR.RDB$FIELD_SOURCE
|
||||
@ -1470,7 +1466,7 @@ dsql_rel* METD_get_relation(CompiledStatement* statement, const dsql_str* name)
|
||||
field = FB_NEW(pool) dsql_fld(pool);
|
||||
field->fld_id = RFR.RDB$FIELD_ID;
|
||||
}
|
||||
else if (!DDL_ids(statement))
|
||||
else if (!DDL_ids(dsqlScratch))
|
||||
field = FB_NEW(pool) dsql_fld(pool);
|
||||
|
||||
if (field)
|
||||
@ -1547,7 +1543,7 @@ dsql_rel* METD_get_relation(CompiledStatement* statement, const dsql_str* name)
|
||||
}
|
||||
|
||||
|
||||
bool METD_get_trigger(dsql_req* request, const dsql_str* name, dsql_str** relation, USHORT* trig_type)
|
||||
bool METD_get_trigger(jrd_tra* transaction, const dsql_str* name, dsql_str** relation, USHORT* trig_type)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1561,9 +1557,9 @@ bool METD_get_trigger(dsql_req* request, const dsql_str* name, dsql_str** relati
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
validateTransaction(request);
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_dbb* dbb = request->req_dbb;
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
|
||||
bool found = false;
|
||||
|
||||
@ -1572,7 +1568,7 @@ bool METD_get_trigger(dsql_req* request, const dsql_str* name, dsql_str** relati
|
||||
|
||||
jrd_req* handle = CMP_find_request(tdbb, irq_trigger, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE request->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$TRIGGERS WITH X.RDB$TRIGGER_NAME EQ name->str_data
|
||||
|
||||
if (!DSQL_REQUEST(irq_trigger))
|
||||
@ -1599,7 +1595,7 @@ bool METD_get_trigger(dsql_req* request, const dsql_str* name, dsql_str** relati
|
||||
}
|
||||
|
||||
|
||||
bool METD_get_type(dsql_req* request, const dsql_str* name, const char* field, SSHORT* value)
|
||||
bool METD_get_type(jrd_tra* transaction, const dsql_str* name, const char* field, SSHORT* value)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1613,14 +1609,14 @@ bool METD_get_type(dsql_req* request, const dsql_str* name, const char* field, S
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
validateTransaction(request);
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_dbb* dbb = request->req_dbb;
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
bool found = false;
|
||||
|
||||
jrd_req* handle = CMP_find_request(tdbb, irq_type, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE request->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$TYPES WITH
|
||||
X.RDB$FIELD_NAME EQ field AND X.RDB$TYPE_NAME EQ name->str_data;
|
||||
|
||||
@ -1639,9 +1635,8 @@ bool METD_get_type(dsql_req* request, const dsql_str* name, const char* field, S
|
||||
}
|
||||
|
||||
|
||||
dsql_rel* METD_get_view_base(CompiledStatement* statement,
|
||||
const char* view_name, // UTF-8
|
||||
MetaNamePairMap& fields)
|
||||
dsql_rel* METD_get_view_base(jrd_tra* transaction, DsqlCompilerScratch* dsqlScratch,
|
||||
const char* view_name, MetaNamePairMap& fields)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1660,11 +1655,11 @@ dsql_rel* METD_get_view_base(CompiledStatement* statement,
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
validateTransaction(statement);
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_rel* relation = NULL;
|
||||
|
||||
dsql_dbb* dbb = statement->req_dbb;
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
bool first = true;
|
||||
bool cont = true;
|
||||
MetaNamePairMap previousAux;
|
||||
@ -1675,7 +1670,7 @@ dsql_rel* METD_get_view_base(CompiledStatement* statement,
|
||||
{
|
||||
jrd_req* handle1 = CMP_find_request(tdbb, irq_view_base, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle1 TRANSACTION_HANDLE statement->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle1 TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$VIEW_RELATIONS
|
||||
WITH X.RDB$VIEW_NAME EQ view_name
|
||||
|
||||
@ -1695,7 +1690,7 @@ dsql_rel* METD_get_view_base(CompiledStatement* statement,
|
||||
fb_utils::exact_name(X.RDB$RELATION_NAME);
|
||||
|
||||
dsql_str* relation_name = MAKE_string(X.RDB$RELATION_NAME, strlen(X.RDB$RELATION_NAME));
|
||||
relation = METD_get_relation(statement, relation_name);
|
||||
relation = METD_get_relation(transaction, dsqlScratch, relation_name);
|
||||
delete relation_name;
|
||||
|
||||
Array<MetaName> ambiguities;
|
||||
@ -1709,7 +1704,7 @@ dsql_rel* METD_get_view_base(CompiledStatement* statement,
|
||||
|
||||
jrd_req* handle2 = CMP_find_request(tdbb, irq_view_base_flds, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle2 TRANSACTION_HANDLE statement->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle2 TRANSACTION_HANDLE transaction)
|
||||
RFL IN RDB$RELATION_FIELDS
|
||||
WITH RFL.RDB$RELATION_NAME EQ X.RDB$VIEW_NAME
|
||||
|
||||
@ -1783,9 +1778,8 @@ dsql_rel* METD_get_view_base(CompiledStatement* statement,
|
||||
}
|
||||
|
||||
|
||||
dsql_rel* METD_get_view_relation(CompiledStatement* statement,
|
||||
const char* view_name, // UTF-8
|
||||
const char* relation_or_alias) // UTF-8
|
||||
dsql_rel* METD_get_view_relation(jrd_tra* transaction, DsqlCompilerScratch* dsqlScratch,
|
||||
const char* view_name, const char* relation_or_alias)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1801,15 +1795,15 @@ dsql_rel* METD_get_view_relation(CompiledStatement* statement,
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
validateTransaction(statement);
|
||||
validateTransaction(transaction);
|
||||
|
||||
dsql_rel* relation = NULL;
|
||||
|
||||
dsql_dbb* dbb = statement->req_dbb;
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
|
||||
jrd_req* handle = CMP_find_request(tdbb, irq_view, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE statement->req_transaction)
|
||||
FOR(REQUEST_HANDLE handle TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$VIEW_RELATIONS WITH X.RDB$VIEW_NAME EQ view_name
|
||||
|
||||
if (!DSQL_REQUEST(irq_view))
|
||||
@ -1822,15 +1816,16 @@ dsql_rel* METD_get_view_relation(CompiledStatement* statement,
|
||||
!strcmp(X.RDB$CONTEXT_NAME, relation_or_alias))
|
||||
{
|
||||
dsql_str* relation_name = MAKE_string(X.RDB$RELATION_NAME, strlen(X.RDB$RELATION_NAME));
|
||||
relation = METD_get_relation(statement, relation_name);
|
||||
relation = METD_get_relation(transaction, dsqlScratch, relation_name);
|
||||
delete relation_name;
|
||||
return relation;
|
||||
}
|
||||
|
||||
relation = METD_get_view_relation(statement, X.RDB$RELATION_NAME, relation_or_alias);
|
||||
if (relation) {
|
||||
relation = METD_get_view_relation(transaction, dsqlScratch, X.RDB$RELATION_NAME,
|
||||
relation_or_alias);
|
||||
|
||||
if (relation)
|
||||
return relation;
|
||||
}
|
||||
|
||||
END_FOR
|
||||
|
||||
|
@ -37,36 +37,35 @@ namespace Jrd {
|
||||
|
||||
class dsql_req;
|
||||
class dsql_str;
|
||||
class CompiledStatement;
|
||||
class DsqlCompilerScratch;
|
||||
};
|
||||
|
||||
void METD_drop_charset(Jrd::dsql_req*, const Firebird::MetaName&);
|
||||
void METD_drop_collation(Jrd::dsql_req*, const Jrd::dsql_str*);
|
||||
void METD_drop_function(Jrd::dsql_req*, const Jrd::dsql_str*, const Firebird::MetaName&);
|
||||
void METD_drop_procedure(Jrd::dsql_req*, const Jrd::dsql_str*, const Firebird::MetaName&);
|
||||
void METD_drop_relation(Jrd::dsql_req*, const Jrd::dsql_str*);
|
||||
void METD_drop_charset(Jrd::jrd_tra*, const Firebird::MetaName&);
|
||||
void METD_drop_collation(Jrd::jrd_tra*, const Jrd::dsql_str*);
|
||||
void METD_drop_function(Jrd::jrd_tra*, const Jrd::dsql_str*, const Firebird::MetaName&);
|
||||
void METD_drop_procedure(Jrd::jrd_tra*, const Jrd::dsql_str*, const Firebird::MetaName&);
|
||||
void METD_drop_relation(Jrd::jrd_tra*, const Jrd::dsql_str*);
|
||||
|
||||
Jrd::dsql_intlsym* METD_get_charset(Jrd::dsql_req*, USHORT, const char* name); // UTF-8
|
||||
USHORT METD_get_charset_bpc(Jrd::dsql_req*, SSHORT);
|
||||
Firebird::MetaName METD_get_charset_name(Jrd::dsql_req*, SSHORT);
|
||||
Jrd::dsql_intlsym* METD_get_collation(Jrd::dsql_req*, const Jrd::dsql_str*, USHORT charset_id);
|
||||
USHORT METD_get_col_default(Jrd::dsql_req*, const char*, const char*, bool*, UCHAR*, USHORT);
|
||||
Jrd::dsql_str* METD_get_default_charset(Jrd::dsql_req*);
|
||||
bool METD_get_domain(Jrd::dsql_req*, class Jrd::dsql_fld*, const char* name); // UTF-8
|
||||
USHORT METD_get_domain_default(Jrd::dsql_req*, const TEXT*, bool*, UCHAR*, USHORT);
|
||||
bool METD_get_exception(Jrd::dsql_req*, const Jrd::dsql_str*);
|
||||
Jrd::dsql_udf* METD_get_function(Jrd::CompiledStatement*, const Jrd::dsql_str*, const Jrd::dsql_str*);
|
||||
Jrd::dsql_nod* METD_get_primary_key(Jrd::dsql_req*, const Jrd::dsql_str*);
|
||||
Jrd::dsql_prc* METD_get_procedure(Jrd::CompiledStatement*, const Jrd::dsql_str*, const Jrd::dsql_str*);
|
||||
Jrd::dsql_rel* METD_get_relation(Jrd::CompiledStatement*, const Jrd::dsql_str*);
|
||||
bool METD_get_trigger(Jrd::dsql_req*, const Jrd::dsql_str*, Jrd::dsql_str**, USHORT*);
|
||||
bool METD_get_type(Jrd::dsql_req*, const Jrd::dsql_str*, const char*, SSHORT*);
|
||||
Jrd::dsql_rel* METD_get_view_base(Jrd::CompiledStatement* request,
|
||||
const char* view_name, // UTF-8
|
||||
Jrd::MetaNamePairMap& fields);
|
||||
Jrd::dsql_rel* METD_get_view_relation(Jrd::CompiledStatement* request,
|
||||
const char* view_name, // UTF-8
|
||||
const char* relation_or_alias); // UTF-8
|
||||
Jrd::dsql_intlsym* METD_get_charset(Jrd::jrd_tra*, USHORT, const char* name);
|
||||
USHORT METD_get_charset_bpc(Jrd::jrd_tra*, SSHORT);
|
||||
Firebird::MetaName METD_get_charset_name(Jrd::jrd_tra*, SSHORT);
|
||||
Jrd::dsql_intlsym* METD_get_collation(Jrd::jrd_tra*, const Jrd::dsql_str*, USHORT charset_id);
|
||||
USHORT METD_get_col_default(Jrd::jrd_tra*, const char*, const char*, bool*, UCHAR*, USHORT);
|
||||
Jrd::dsql_str* METD_get_default_charset(Jrd::jrd_tra*);
|
||||
bool METD_get_domain(Jrd::jrd_tra*, class Jrd::dsql_fld*, const char* name);
|
||||
USHORT METD_get_domain_default(Jrd::jrd_tra*, const TEXT*, bool*, UCHAR*, USHORT);
|
||||
bool METD_get_exception(Jrd::jrd_tra*, const Jrd::dsql_str*);
|
||||
Jrd::dsql_udf* METD_get_function(Jrd::jrd_tra*, Jrd::DsqlCompilerScratch*, const Jrd::dsql_str*,
|
||||
const Jrd::dsql_str*);
|
||||
Jrd::dsql_nod* METD_get_primary_key(Jrd::jrd_tra*, const Jrd::dsql_str*);
|
||||
Jrd::dsql_prc* METD_get_procedure(Jrd::jrd_tra*, Jrd::DsqlCompilerScratch*, const Jrd::dsql_str*,
|
||||
const Jrd::dsql_str*);
|
||||
Jrd::dsql_rel* METD_get_relation(Jrd::jrd_tra*, Jrd::DsqlCompilerScratch*, const Jrd::dsql_str*);
|
||||
bool METD_get_trigger(Jrd::jrd_tra*, const Jrd::dsql_str*, Jrd::dsql_str**, USHORT*);
|
||||
bool METD_get_type(Jrd::jrd_tra*, const Jrd::dsql_str*, const char*, SSHORT*);
|
||||
Jrd::dsql_rel* METD_get_view_base(Jrd::jrd_tra*, Jrd::DsqlCompilerScratch*, const char* view_name,
|
||||
Jrd::MetaNamePairMap& fields);
|
||||
Jrd::dsql_rel* METD_get_view_relation(Jrd::jrd_tra*, Jrd::DsqlCompilerScratch*, const char* view_name,
|
||||
const char* relation_or_alias);
|
||||
|
||||
#endif // DSQL_METD_PROTO_H
|
||||
|
||||
|
2001
src/dsql/pass1.cpp
2001
src/dsql/pass1.cpp
File diff suppressed because it is too large
Load Diff
@ -25,12 +25,12 @@
|
||||
#define DSQL_PASS1_PROTO_H
|
||||
|
||||
void PASS1_check_unique_fields_names(Jrd::StrArray& names, const Jrd::dsql_nod* fields);
|
||||
Jrd::dsql_ctx* PASS1_make_context(Jrd::CompiledStatement* statement, const Jrd::dsql_nod* relation_node);
|
||||
Jrd::dsql_nod* PASS1_node(Jrd::CompiledStatement*, Jrd::dsql_nod*);
|
||||
Jrd::dsql_nod* PASS1_node_psql(Jrd::CompiledStatement*, Jrd::dsql_nod*, bool);
|
||||
Jrd::dsql_ctx* PASS1_make_context(Jrd::DsqlCompilerScratch* statement, const Jrd::dsql_nod* relation_node);
|
||||
Jrd::dsql_nod* PASS1_node(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);
|
||||
Jrd::dsql_nod* PASS1_node_psql(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*, bool);
|
||||
Jrd::dsql_nod* PASS1_resolve_variable_name(const Firebird::Array<Jrd::dsql_nod*>& variables,
|
||||
const Jrd::dsql_str* var_name);
|
||||
Jrd::dsql_nod* PASS1_rse(Jrd::CompiledStatement*, Jrd::dsql_nod*, Jrd::dsql_nod*);
|
||||
Jrd::dsql_nod* PASS1_statement(Jrd::CompiledStatement*, Jrd::dsql_nod*);
|
||||
Jrd::dsql_nod* PASS1_rse(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*, Jrd::dsql_nod*);
|
||||
Jrd::dsql_nod* PASS1_statement(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);
|
||||
|
||||
#endif // DSQL_PASS1_PROTO_H
|
||||
|
@ -1076,12 +1076,12 @@ static void xsqlvar_to_sqlvar(const XSQLVAR* xsqlvar, SQLVAR* sqlvar)
|
||||
|
||||
UCHAR DSqlDataTypeUtil::maxBytesPerChar(UCHAR charSet)
|
||||
{
|
||||
return METD_get_charset_bpc(statement, charSet);
|
||||
return METD_get_charset_bpc(dsqlScratch->getTransaction(), charSet);
|
||||
}
|
||||
|
||||
USHORT DSqlDataTypeUtil::getDialect() const
|
||||
{
|
||||
return statement->req_client_dialect;
|
||||
return dsqlScratch->clientDialect;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -46,13 +46,13 @@ SCHAR* UTLD_skip_sql_info(SCHAR*);
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
class CompiledStatement;
|
||||
class DsqlCompilerScratch;
|
||||
|
||||
class DSqlDataTypeUtil : public DataTypeUtilBase
|
||||
{
|
||||
public:
|
||||
explicit DSqlDataTypeUtil(CompiledStatement* aStatement)
|
||||
: statement(aStatement)
|
||||
explicit DSqlDataTypeUtil(DsqlCompilerScratch* aDsqlScratch)
|
||||
: dsqlScratch(aDsqlScratch)
|
||||
{
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ namespace Jrd {
|
||||
virtual USHORT getDialect() const;
|
||||
|
||||
private:
|
||||
CompiledStatement* statement;
|
||||
DsqlCompilerScratch* dsqlScratch;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -76,11 +76,13 @@ PreparedStatement::PreparedStatement(thread_db* tdbb, MemoryPool& pool,
|
||||
DSQL_prepare(tdbb, transaction, &request, text.length(), text.c_str(), dialect,
|
||||
0, NULL, 0, NULL, isInternalRequest);
|
||||
|
||||
if (request->req_send)
|
||||
parseDsqlMessage(request->req_send, inValues, inBlr, inMessage);
|
||||
DsqlCompiledStatement* statement = request->getStatement();
|
||||
|
||||
if (request->req_receive)
|
||||
parseDsqlMessage(request->req_receive, outValues, outBlr, outMessage);
|
||||
if (statement->sendMsg)
|
||||
parseDsqlMessage(statement->sendMsg, inValues, inBlr, inMessage);
|
||||
|
||||
if (statement->receiveMsg)
|
||||
parseDsqlMessage(statement->receiveMsg, outValues, outBlr, outMessage);
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
@ -129,7 +131,7 @@ void PreparedStatement::execute(thread_db* tdbb, jrd_tra* transaction)
|
||||
|
||||
ResultSet* PreparedStatement::executeQuery(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
fb_assert(resultSet == NULL && request->req_receive);
|
||||
fb_assert(resultSet == NULL && request->getStatement()->receiveMsg);
|
||||
return FB_NEW(getPool()) ResultSet(tdbb, this, transaction);
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,38 @@ public:
|
||||
jrd_tra* transaction, const Firebird::string& text, bool isInternalRequest);
|
||||
~PreparedStatement();
|
||||
|
||||
public:
|
||||
// Escape a metadata name accordingly to SQL rules.
|
||||
static Firebird::string escapeName(const Firebird::MetaName& s)
|
||||
{
|
||||
Firebird::string ret;
|
||||
|
||||
for (const char* p = s.begin(); p != s.end(); ++p)
|
||||
{
|
||||
ret += *p;
|
||||
if (*p == '\"')
|
||||
ret += '\"';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// Escape a string accordingly to SQL rules.
|
||||
template <typename T> static Firebird::string escapeString(const T& s)
|
||||
{
|
||||
Firebird::string ret;
|
||||
|
||||
for (const char* p = s.begin(); p != s.end(); ++p)
|
||||
{
|
||||
ret += *p;
|
||||
if (*p == '\'')
|
||||
ret += '\'';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public:
|
||||
void setDesc(thread_db* tdbb, unsigned param, const dsc& value);
|
||||
|
||||
|
@ -51,14 +51,14 @@ ResultSet::~ResultSet()
|
||||
|
||||
stmt->resultSet = NULL;
|
||||
|
||||
if (stmt->request->req_type != REQ_EXEC_PROCEDURE)
|
||||
if (stmt->request->getStatement()->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 && firstFetchDone)
|
||||
if (stmt->request->getStatement()->type == REQ_EXEC_PROCEDURE && firstFetchDone)
|
||||
return false;
|
||||
|
||||
memset(stmt->outMessage.begin(), 0, stmt->outMessage.getCount());
|
||||
|
@ -72,6 +72,7 @@
|
||||
#include "../common/utils_proto.h"
|
||||
#include "../dsql/DdlNodes.h"
|
||||
#include "../dsql/metd_proto.h"
|
||||
#include "../jrd/PreparedStatement.h"
|
||||
|
||||
using MsgFormat::SafeArg;
|
||||
|
||||
@ -114,6 +115,7 @@ void DYN_modify_database( Global* gbl, const UCHAR** ptr)
|
||||
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||
|
||||
jrd_req* request = NULL;
|
||||
|
||||
@ -180,9 +182,14 @@ void DYN_modify_database( Global* gbl, const UCHAR** ptr)
|
||||
|
||||
if (!DBB.RDB$CHARACTER_SET_NAME.NULL)
|
||||
{
|
||||
AlterCharSetNode node(*tdbb->getDefaultPool(), "",
|
||||
DBB.RDB$CHARACTER_SET_NAME, collation);
|
||||
node.execute(tdbb, gbl->gbl_transaction);
|
||||
string sql;
|
||||
sql.printf("alter character set \"%s\" set default collation \"%s\"",
|
||||
PreparedStatement::escapeName(DBB.RDB$CHARACTER_SET_NAME).c_str(),
|
||||
PreparedStatement::escapeName(collation).c_str());
|
||||
|
||||
AutoPtr<PreparedStatement> ps(attachment->prepareStatement(tdbb,
|
||||
*tdbb->getDefaultPool(), gbl->gbl_transaction, sql));
|
||||
ps->execute(tdbb, gbl->gbl_transaction);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -78,7 +78,7 @@ void ExecuteStatement::execute(Jrd::thread_db* tdbb, jrd_req* request, DSC* desc
|
||||
(1 << REQ_DDL) | (1 << REQ_SET_GENERATOR) | (1 << REQ_EXEC_PROCEDURE) |
|
||||
(1 << REQ_EXEC_BLOCK);
|
||||
|
||||
if (!((1 << stmt->getRequest()->req_type) & requests))
|
||||
if (!((1 << stmt->getRequest()->getStatement()->type) & requests))
|
||||
{
|
||||
UCharBuffer dst;
|
||||
|
||||
|
@ -376,9 +376,11 @@ void InternalStatement::doPrepare(thread_db* tdbb, const string& sql)
|
||||
raise(status, tdbb, "jrd8_prepare", &sql);
|
||||
}
|
||||
|
||||
if (m_request->req_send) {
|
||||
DsqlCompiledStatement* statement = m_request->getStatement();
|
||||
|
||||
if (statement->sendMsg) {
|
||||
try {
|
||||
PreparedStatement::parseDsqlMessage(m_request->req_send, m_inDescs, m_inBlr, m_in_buffer);
|
||||
PreparedStatement::parseDsqlMessage(statement->sendMsg, m_inDescs, m_inBlr, m_in_buffer);
|
||||
m_inputs = m_inDescs.getCount() / 2;
|
||||
}
|
||||
catch (const Exception&) {
|
||||
@ -389,9 +391,9 @@ void InternalStatement::doPrepare(thread_db* tdbb, const string& sql)
|
||||
m_inputs = 0;
|
||||
}
|
||||
|
||||
if (m_request->req_receive) {
|
||||
if (statement->receiveMsg) {
|
||||
try {
|
||||
PreparedStatement::parseDsqlMessage(m_request->req_receive, m_outDescs, m_outBlr, m_out_buffer);
|
||||
PreparedStatement::parseDsqlMessage(statement->receiveMsg, m_outDescs, m_outBlr, m_out_buffer);
|
||||
m_outputs = m_outDescs.getCount() / 2;
|
||||
}
|
||||
catch (const Exception&) {
|
||||
@ -403,7 +405,7 @@ void InternalStatement::doPrepare(thread_db* tdbb, const string& sql)
|
||||
}
|
||||
|
||||
m_stmt_selectable = false;
|
||||
switch (m_request->req_type)
|
||||
switch (statement->type)
|
||||
{
|
||||
case REQ_SELECT:
|
||||
case REQ_SELECT_UPD:
|
||||
|
@ -213,6 +213,11 @@ public:
|
||||
return tra_attachment;
|
||||
}
|
||||
|
||||
dsql_dbb* getDsqlAttachment()
|
||||
{
|
||||
return tra_attachment->att_dsql_instance;
|
||||
}
|
||||
|
||||
FB_API_HANDLE tra_public_handle; // Public handle
|
||||
Attachment* tra_attachment; // database attachment
|
||||
SLONG tra_number; // transaction number
|
||||
|
@ -184,7 +184,7 @@ int TraceSQLStatementImpl::getStmtID()
|
||||
|
||||
const char* TraceSQLStatementImpl::getText()
|
||||
{
|
||||
return m_stmt->req_sql_text->c_str();
|
||||
return m_stmt->getStatement()->sqlText->c_str();
|
||||
}
|
||||
|
||||
const char* TraceSQLStatementImpl::getPlan()
|
||||
|
@ -149,8 +149,8 @@ public:
|
||||
m_stmt(stmt),
|
||||
m_perf(perf),
|
||||
m_plan(NULL),
|
||||
m_inputs(*getDefaultMemoryPool(),
|
||||
m_stmt->req_send ? &m_stmt->req_send->msg_parameters : NULL)
|
||||
m_inputs(*getDefaultMemoryPool(), m_stmt->getStatement()->sendMsg ?
|
||||
&m_stmt->getStatement()->sendMsg->msg_parameters : NULL)
|
||||
{}
|
||||
|
||||
~TraceSQLStatementImpl();
|
||||
|
Loading…
Reference in New Issue
Block a user