2121#include " google/cloud/odbc/bq_driver/internal/odbc_sql_type_info.h"
2222#include " google/cloud/odbc/bq_driver/internal/odbc_transactions.h"
2323#include " google/cloud/odbc/bq_driver/internal/trace_utils.h"
24+ #include " google/cloud/odbc/bq_driver/internal/utils.h"
2425#include " google/cloud/odbc/internal/status_record_or.h"
2526
2627namespace google ::cloud::odbc_bq_driver_internal {
@@ -213,8 +214,14 @@ StatusRecord StatementHandle::PrepareQuery(std::string const& query) {
213214 }
214215 ConnectionHandle& conn_handle = *GetConnectionHandle ();
215216
217+ std::string processed_query = query;
218+ auto noscan_attr = GetAttribute (SQL_ATTR_NOSCAN );
219+ if (!noscan_attr || *noscan_attr != SQL_NOSCAN_ON ) {
220+ processed_query = TranslateOdbcEscapeSequences (query);
221+ }
222+
216223 Job req;
217- req.configuration .query .query = query ;
224+ req.configuration .query .query = processed_query ;
218225 req.configuration .query .use_query_cache = conn_handle.GetDsn ().is_query_cache ;
219226 req.configuration .dry_run = true ;
220227 req.configuration .query .use_legacy_sql =
@@ -233,7 +240,7 @@ StatusRecord StatementHandle::PrepareQuery(std::string const& query) {
233240 // to be used during table creation. Subsequent operations on the table will
234241 // automatically use the KMS key without the application sending it.
235242 std::string kms_key_name = conn_handle.GetDsn ().kms_key_name ;
236- if (IsInsertQuery (query ) || IsSelectQuery (query )) {
243+ if (IsInsertQuery (processed_query ) || IsSelectQuery (processed_query )) {
237244 if (!kms_key_name.empty ()) {
238245 req.configuration .query .destination_encryption_configuration
239246 .kms_key_name = kms_key_name;
@@ -243,8 +250,8 @@ StatusRecord StatementHandle::PrepareQuery(std::string const& query) {
243250 if (!conn_handle.GetDsn ().is_bq_legacy_sql ) {
244251 // Detect POSITIONAL (`?`) and NAMED (`[:@]\w+`) parameter markers using
245252 // RE2 instead of a manual character scan.
246- bool has_positional = re2::RE2::PartialMatch (query , R"( \?)" );
247- bool has_named = re2::RE2::PartialMatch (query , R"( [:@]\w+)" );
253+ bool has_positional = re2::RE2::PartialMatch (processed_query , R"( \?)" );
254+ bool has_named = re2::RE2::PartialMatch (processed_query , R"( [:@]\w+)" );
248255 if (has_positional) {
249256 req.configuration .query .parameter_mode = " POSITIONAL" ;
250257 }
@@ -330,7 +337,7 @@ StatusRecord StatementHandle::PrepareQuery(std::string const& query) {
330337 conn_handle.SetSessionId (response->statistics .session_info .session_id );
331338 }
332339
333- query_str_ = query ;
340+ query_str_ = processed_query ;
334341 prepared_job_ = *response;
335342 return StatusRecord::Ok ();
336343}
@@ -551,6 +558,10 @@ StatusRecord StatementHandle::PopulateIpd(DescriptorHandle& handle,
551558void StatementHandle::CloseCursor () {
552559 ResultSet result_set;
553560 result_set_ = result_set;
561+ #if (!defined(_WIN32) || defined(_WIN64)) && !defined(NO_ARROW)
562+ ClearReadRowsStream ();
563+ ClearReadRowsIterator ();
564+ #endif
554565 if (StatementPrepared ()) {
555566 SetStmtState (StmtStates::kStatementPrepared );
556567 } else {
0 commit comments