// Find an inactive incarnation of a system request. If necessary, clone it. jrd_req* Jrd::Attachment::findSystemRequest(thread_db* tdbb, USHORT id, USHORT which) { static const int MAX_RECURSION = 100; // If the request hasn't been compiled or isn't active, there're nothing to do. //Database::CheckoutLockGuard guard(this, dbb_cmp_clone_mutex); fb_assert(which == IRQ_REQUESTS || which == DYN_REQUESTS); JrdStatement* statement = (which == IRQ_REQUESTS ? att_internal[id] : att_dyn_req[id]); if (!statement) return NULL; // Look for requests until we find one that is available. for (int n = 0;; ++n) { if (n > MAX_RECURSION) { ERR_post(Arg::Gds(isc_no_meta_update) << Arg::Gds(isc_req_depth_exceeded) << Arg::Num(MAX_RECURSION)); // Msg363 "request depth exceeded. (Recursive definition?)" } jrd_req* clone = statement->getRequest(tdbb, n); if (!(clone->req_flags & (req_active | req_reserved))) { clone->req_flags |= req_reserved; return clone; } } }
// Turn a parsed scratch into an executable request. jrd_req* JrdStatement::makeRequest(thread_db* tdbb, CompilerScratch* csb, bool internalFlag) { JrdStatement* statement = makeStatement(tdbb, csb, internalFlag); return statement->getRequest(tdbb, 0); }
void InternalStatement::doPrepare(thread_db* tdbb, const string& sql) { m_inMetadata->reset(); m_outMetadata->reset(); JAttachment* att = m_intConnection.getJrdAtt(); JTransaction* tran = getIntTransaction()->getJrdTran(); FbLocalStatus status; if (m_request) { doClose(tdbb, true); fb_assert(!m_allocated); } { EngineCallbackGuard guard(tdbb, *this, FB_FUNCTION); CallerName save_caller_name(tran->getHandle()->tra_caller_name); if (m_callerPrivileges) { jrd_req* request = tdbb->getRequest(); JrdStatement* statement = request ? request->getStatement() : NULL; CallerName callerName; const Routine* routine; if (statement && statement->parentStatement) statement = statement->parentStatement; if (statement && statement->triggerName.hasData()) tran->getHandle()->tra_caller_name = CallerName(obj_trigger, statement->triggerName); else if (statement && (routine = statement->getRoutine()) && routine->getName().identifier.hasData()) { if (routine->getName().package.isEmpty()) { tran->getHandle()->tra_caller_name = CallerName(routine->getObjectType(), routine->getName().identifier); } else { tran->getHandle()->tra_caller_name = CallerName(obj_package_header, routine->getName().package); } } else tran->getHandle()->tra_caller_name = CallerName(); } m_request.assignRefNoIncr(att->prepare(&status, tran, sql.length(), sql.c_str(), m_connection.getSqlDialect(), 0)); m_allocated = (m_request != NULL); tran->getHandle()->tra_caller_name = save_caller_name; } if (status->getState() & IStatus::STATE_ERRORS) raise(&status, tdbb, "JAttachment::prepare", &sql); const DsqlCompiledStatement* statement = m_request->getHandle()->getStatement(); if (statement->getSendMsg()) { try { PreparedStatement::parseDsqlMessage(statement->getSendMsg(), m_inDescs, m_inMetadata, m_in_buffer); m_inputs = m_inMetadata->getCount(); } catch (const Exception&) { raise(tdbb->tdbb_status_vector, tdbb, "parse input message", &sql); } } else m_inputs = 0; if (statement->getReceiveMsg()) { try { PreparedStatement::parseDsqlMessage(statement->getReceiveMsg(), m_outDescs, m_outMetadata, m_out_buffer); m_outputs = m_outMetadata->getCount(); } catch (const Exception&) { raise(tdbb->tdbb_status_vector, tdbb, "parse output message", &sql); } } else m_outputs = 0; m_stmt_selectable = false; switch (statement->getType()) { case DsqlCompiledStatement::TYPE_SELECT: case DsqlCompiledStatement::TYPE_SELECT_UPD: case DsqlCompiledStatement::TYPE_SELECT_BLOCK: m_stmt_selectable = true; break; case DsqlCompiledStatement::TYPE_START_TRANS: case DsqlCompiledStatement::TYPE_COMMIT: case DsqlCompiledStatement::TYPE_ROLLBACK: case DsqlCompiledStatement::TYPE_COMMIT_RETAIN: case DsqlCompiledStatement::TYPE_ROLLBACK_RETAIN: case DsqlCompiledStatement::TYPE_CREATE_DB: Arg::Gds(isc_eds_expl_tran_ctrl).copyTo(&status); raise(&status, tdbb, "JAttachment::prepare", &sql); break; case DsqlCompiledStatement::TYPE_INSERT: case DsqlCompiledStatement::TYPE_DELETE: case DsqlCompiledStatement::TYPE_UPDATE: case DsqlCompiledStatement::TYPE_UPDATE_CURSOR: case DsqlCompiledStatement::TYPE_DELETE_CURSOR: case DsqlCompiledStatement::TYPE_DDL: case DsqlCompiledStatement::TYPE_EXEC_PROCEDURE: case DsqlCompiledStatement::TYPE_SET_GENERATOR: case DsqlCompiledStatement::TYPE_SAVEPOINT: case DsqlCompiledStatement::TYPE_EXEC_BLOCK: break; } }