@@ -133,17 +133,6 @@ enum BatchMode {
133
133
DML
134
134
}
135
135
136
- /**
137
- * This query option is used internally to indicate that a query is executed by the library itself
138
- * to fetch metadata. These queries are specifically allowed to be executed even when a DDL batch
139
- * is active.
140
- */
141
- static final class InternalMetadataQuery implements QueryOption {
142
- static final InternalMetadataQuery INSTANCE = new InternalMetadataQuery ();
143
-
144
- private InternalMetadataQuery () {}
145
- }
146
-
147
136
/** The combination of all transaction modes and batch modes. */
148
137
enum UnitOfWorkType {
149
138
READ_ONLY_TRANSACTION {
@@ -1219,6 +1208,18 @@ private AsyncResultSet parseAndExecuteQueryAsync(
1219
1208
+ parsedStatement .getSqlWithoutComments ());
1220
1209
}
1221
1210
1211
+ private boolean isInternalMetadataQuery (QueryOption ... options ) {
1212
+ if (options == null ) {
1213
+ return false ;
1214
+ }
1215
+ for (QueryOption option : options ) {
1216
+ if (option instanceof InternalMetadataQuery ) {
1217
+ return true ;
1218
+ }
1219
+ }
1220
+ return false ;
1221
+ }
1222
+
1222
1223
@ Override
1223
1224
public long executeUpdate (Statement update ) {
1224
1225
Preconditions .checkNotNull (update );
@@ -1450,8 +1451,11 @@ private ResultSet internalExecuteQuery(
1450
1451
|| (statement .getType () == StatementType .UPDATE
1451
1452
&& (analyzeMode != AnalyzeMode .NONE || statement .hasReturningClause ())),
1452
1453
"Statement must either be a query or a DML mode with analyzeMode!=NONE or returning clause" );
1453
- UnitOfWork transaction = getCurrentUnitOfWorkOrStartNewUnitOfWork ();
1454
- if (autoPartitionMode && statement .getType () == StatementType .QUERY ) {
1454
+ boolean isInternalMetadataQuery = isInternalMetadataQuery (options );
1455
+ UnitOfWork transaction = getCurrentUnitOfWorkOrStartNewUnitOfWork (isInternalMetadataQuery );
1456
+ if (autoPartitionMode
1457
+ && statement .getType () == StatementType .QUERY
1458
+ && !isInternalMetadataQuery ) {
1455
1459
return runPartitionedQuery (
1456
1460
statement .getStatement (), PartitionOptions .getDefaultInstance (), options );
1457
1461
}
@@ -1475,7 +1479,8 @@ private AsyncResultSet internalExecuteQueryAsync(
1475
1479
ConnectionPreconditions .checkState (
1476
1480
!(autoPartitionMode && statement .getType () == StatementType .QUERY ),
1477
1481
"Partitioned queries cannot be executed asynchronously" );
1478
- UnitOfWork transaction = getCurrentUnitOfWorkOrStartNewUnitOfWork ();
1482
+ UnitOfWork transaction =
1483
+ getCurrentUnitOfWorkOrStartNewUnitOfWork (isInternalMetadataQuery (options ));
1479
1484
return ResultSets .toAsyncResultSet (
1480
1485
transaction .executeQueryAsync (
1481
1486
callType ,
@@ -1514,22 +1519,31 @@ private ApiFuture<long[]> internalExecuteBatchUpdateAsync(
1514
1519
callType , updates , mergeUpdateRequestOptions (mergeUpdateStatementTag (options )));
1515
1520
}
1516
1521
1522
+ private UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork () {
1523
+ return getCurrentUnitOfWorkOrStartNewUnitOfWork (false );
1524
+ }
1525
+
1517
1526
/**
1518
1527
* Returns the current {@link UnitOfWork} of this connection, or creates a new one based on the
1519
1528
* current transaction settings of the connection and returns that.
1520
1529
*/
1521
1530
@ VisibleForTesting
1522
- UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork () {
1531
+ UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork (boolean isInternalMetadataQuery ) {
1532
+ if (isInternalMetadataQuery ) {
1533
+ // Just return a temporary single-use transaction.
1534
+ return createNewUnitOfWork (true );
1535
+ }
1523
1536
if (this .currentUnitOfWork == null || !this .currentUnitOfWork .isActive ()) {
1524
- this .currentUnitOfWork = createNewUnitOfWork ();
1537
+ this .currentUnitOfWork = createNewUnitOfWork (false );
1525
1538
}
1526
1539
return this .currentUnitOfWork ;
1527
1540
}
1528
1541
1529
1542
@ VisibleForTesting
1530
- UnitOfWork createNewUnitOfWork () {
1531
- if (isAutocommit () && !isInTransaction () && !isInBatch ()) {
1543
+ UnitOfWork createNewUnitOfWork (boolean isInternalMetadataQuery ) {
1544
+ if (isInternalMetadataQuery || ( isAutocommit () && !isInTransaction () && !isInBatch () )) {
1532
1545
return SingleUseTransaction .newBuilder ()
1546
+ .setInternalMetadataQuery (isInternalMetadataQuery )
1533
1547
.setDdlClient (ddlClient )
1534
1548
.setDatabaseClient (dbClient )
1535
1549
.setBatchClient (batchClient )
@@ -1660,7 +1674,7 @@ public void startBatchDdl() {
1660
1674
!transactionBeginMarked , "Cannot start a DDL batch when a transaction has begun" );
1661
1675
this .batchMode = BatchMode .DDL ;
1662
1676
this .unitOfWorkType = UnitOfWorkType .DDL_BATCH ;
1663
- this .currentUnitOfWork = createNewUnitOfWork ();
1677
+ this .currentUnitOfWork = createNewUnitOfWork (false );
1664
1678
}
1665
1679
1666
1680
@ Override
@@ -1678,7 +1692,7 @@ public void startBatchDml() {
1678
1692
// Then create the DML batch.
1679
1693
this .batchMode = BatchMode .DML ;
1680
1694
this .unitOfWorkType = UnitOfWorkType .DML_BATCH ;
1681
- this .currentUnitOfWork = createNewUnitOfWork ();
1695
+ this .currentUnitOfWork = createNewUnitOfWork (false );
1682
1696
}
1683
1697
1684
1698
@ Override
0 commit comments