Execute a dynamic SQL statement.
| 134 | |
| 135 | // Execute a dynamic SQL statement. |
| 136 | void DSQL_execute(thread_db* tdbb, |
| 137 | jrd_tra** tra_handle, |
| 138 | DsqlRequest* dsqlRequest, |
| 139 | IMessageMetadata* in_meta, const UCHAR* in_msg, |
| 140 | IMessageMetadata* out_meta, UCHAR* out_msg) |
| 141 | { |
| 142 | SET_TDBB(tdbb); |
| 143 | |
| 144 | Jrd::ContextPoolHolder context(tdbb, &dsqlRequest->getPool()); |
| 145 | |
| 146 | const auto statement = dsqlRequest->getDsqlStatement(); |
| 147 | |
| 148 | if (statement->getFlags() & DsqlStatement::FLAG_ORPHAN) |
| 149 | { |
| 150 | ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) << |
| 151 | Arg::Gds(isc_bad_req_handle)); |
| 152 | } |
| 153 | |
| 154 | // Only allow NULL trans_handle if we're starting a transaction or set session properties |
| 155 | |
| 156 | if (!*tra_handle && |
| 157 | statement->getType() != DsqlStatement::TYPE_START_TRANS && |
| 158 | statement->getType() != DsqlStatement::TYPE_SESSION_MANAGEMENT) |
| 159 | { |
| 160 | ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) << |
| 161 | Arg::Gds(isc_bad_trans_handle)); |
| 162 | } |
| 163 | |
| 164 | // A select with a non zero output length is a singleton select |
| 165 | const bool singleton = statement->isCursorBased() && out_msg; |
| 166 | |
| 167 | // If the request is a SELECT or blob statement then this is an open. |
| 168 | // Make sure the cursor is not already open. |
| 169 | |
| 170 | if (statement->isCursorBased()) |
| 171 | { |
| 172 | if (dsqlRequest->req_cursor) |
| 173 | { |
| 174 | ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-502) << |
| 175 | Arg::Gds(isc_dsql_cursor_open_err)); |
| 176 | } |
| 177 | |
| 178 | if (!singleton) |
| 179 | (Arg::Gds(isc_random) << "Cannot execute SELECT statement").raise(); |
| 180 | } |
| 181 | |
| 182 | dsqlRequest->req_transaction = *tra_handle; |
| 183 | dsqlRequest->execute(tdbb, tra_handle, in_meta, in_msg, out_meta, out_msg, singleton); |
| 184 | } |
| 185 | |
| 186 | |
| 187 | /** |
no test coverage detected