Prepare a statement for execution. Note: caller is responsible for pool handling.
| 491 | // Prepare a statement for execution. |
| 492 | // Note: caller is responsible for pool handling. |
| 493 | static RefPtr<DsqlStatement> prepareStatement(thread_db* tdbb, dsql_dbb* database, jrd_tra* transaction, |
| 494 | ULONG textLength, const TEXT* text, USHORT clientDialect, bool isInternalRequest, ntrace_result_t* traceResult) |
| 495 | { |
| 496 | Database* const dbb = tdbb->getDatabase(); |
| 497 | |
| 498 | if (text && textLength == 0) |
| 499 | textLength = static_cast<ULONG>(strlen(text)); |
| 500 | |
| 501 | if (clientDialect > SQL_DIALECT_CURRENT) |
| 502 | { |
| 503 | ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) << |
| 504 | Arg::Gds(isc_wish_list)); |
| 505 | } |
| 506 | |
| 507 | if (!text || textLength == 0) |
| 508 | { |
| 509 | ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << |
| 510 | // Unexpected end of command |
| 511 | // CVC: Nothing will be line 1, column 1 for the user. |
| 512 | Arg::Gds(isc_command_end_err2) << Arg::Num(1) << Arg::Num(1)); |
| 513 | } |
| 514 | |
| 515 | // Get rid of the trailing ";" if there is one. |
| 516 | |
| 517 | for (const TEXT* p = text + textLength; p-- > text;) |
| 518 | { |
| 519 | if (*p != ' ') |
| 520 | { |
| 521 | if (*p == ';') |
| 522 | textLength = p - text; |
| 523 | break; |
| 524 | } |
| 525 | } |
| 526 | |
| 527 | if (textLength > MAX_SQL_LENGTH) |
| 528 | { |
| 529 | ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-902) << |
| 530 | Arg::Gds(isc_imp_exc) << |
| 531 | Arg::Gds(isc_sql_too_long) << Arg::Num(MAX_SQL_LENGTH)); |
| 532 | } |
| 533 | |
| 534 | string textStr(text, textLength); |
| 535 | const bool isStatementCacheActive = database->dbb_statement_cache->isActive(); |
| 536 | |
| 537 | RefPtr<DsqlStatement> dsqlStatement; |
| 538 | |
| 539 | if (isStatementCacheActive) |
| 540 | { |
| 541 | dsqlStatement = database->dbb_statement_cache->getStatement(tdbb, textStr, clientDialect, isInternalRequest); |
| 542 | |
| 543 | if (dsqlStatement) |
| 544 | return dsqlStatement; |
| 545 | } |
| 546 | |
| 547 | // allocate the statement block, then prepare the statement |
| 548 | |
| 549 | MemoryPool* scratchPool = nullptr; |
| 550 | DsqlCompilerScratch* scratch = nullptr; |
no test coverage detected