46
46
import com .google .common .base .MoreObjects ;
47
47
import com .google .common .collect .ImmutableList ;
48
48
import com .google .common .util .concurrent .Uninterruptibles ;
49
-
50
49
import org .joda .time .Duration ;
51
50
import org .slf4j .Logger ;
52
51
import org .slf4j .LoggerFactory ;
53
-
54
52
import java .io .IOException ;
55
53
import java .util .Collection ;
56
54
import java .util .Collections ;
61
59
import java .util .Objects ;
62
60
import java .util .Random ;
63
61
import java .util .concurrent .TimeUnit ;
64
-
65
62
import javax .annotation .Nullable ;
66
63
67
64
/**
@@ -73,6 +70,7 @@ public class BigQueryTableRowIterator implements AutoCloseable {
73
70
@ Nullable private TableReference ref ;
74
71
@ Nullable private final String projectId ;
75
72
@ Nullable private TableSchema schema ;
73
+ @ Nullable private final JobConfigurationQuery queryConfig ;
76
74
private final Bigquery client ;
77
75
private String pageToken ;
78
76
private Iterator <TableRow > iteratorOverCurrentBatch ;
@@ -89,25 +87,18 @@ public class BigQueryTableRowIterator implements AutoCloseable {
89
87
// following interval to check the status of query execution job
90
88
private static final Duration QUERY_COMPLETION_POLL_TIME = Duration .standardSeconds (1 );
91
89
92
- private final String query ;
93
- // Whether to flatten query results.
94
- private final boolean flattenResults ;
95
- // Whether to use the BigQuery legacy SQL dialect..
96
- private final boolean useLegacySql ;
97
90
// Temporary dataset used to store query results.
98
91
private String temporaryDatasetId = null ;
99
92
// Temporary table used to store query results.
100
93
private String temporaryTableId = null ;
101
94
102
95
private BigQueryTableRowIterator (
103
- @ Nullable TableReference ref , @ Nullable String query , @ Nullable String projectId ,
104
- Bigquery client , boolean flattenResults , boolean useLegacySql ) {
96
+ @ Nullable TableReference ref , @ Nullable JobConfigurationQuery queryConfig ,
97
+ @ Nullable String projectId , Bigquery client ) {
105
98
this .ref = ref ;
106
- this .query = query ;
99
+ this .queryConfig = queryConfig ;
107
100
this .projectId = projectId ;
108
101
this .client = checkNotNull (client , "client" );
109
- this .flattenResults = flattenResults ;
110
- this .useLegacySql = useLegacySql ;
111
102
}
112
103
113
104
/**
@@ -116,7 +107,7 @@ private BigQueryTableRowIterator(
116
107
public static BigQueryTableRowIterator fromTable (TableReference ref , Bigquery client ) {
117
108
checkNotNull (ref , "ref" );
118
109
checkNotNull (client , "client" );
119
- return new BigQueryTableRowIterator (ref , null , ref .getProjectId (), client , true , true );
110
+ return new BigQueryTableRowIterator (ref , null , ref .getProjectId (), client );
120
111
}
121
112
122
113
/**
@@ -135,23 +126,39 @@ public static BigQueryTableRowIterator fromQuery(
135
126
* Constructs a {@code BigQueryTableRowIterator} that reads from the results of executing the
136
127
* specified query in the specified project.
137
128
*/
129
+ @ Deprecated
138
130
public static BigQueryTableRowIterator fromQuery (
139
131
String query , String projectId , Bigquery client , @ Nullable Boolean flattenResults ,
140
132
@ Nullable Boolean useLegacySql ) {
141
133
checkNotNull (query , "query" );
142
134
checkNotNull (projectId , "projectId" );
143
135
checkNotNull (client , "client" );
144
- return new BigQueryTableRowIterator (null , query , projectId , client ,
145
- MoreObjects .firstNonNull (flattenResults , Boolean .TRUE ),
146
- MoreObjects .firstNonNull (useLegacySql , Boolean .TRUE ));
136
+ JobConfigurationQuery queryConfig = new JobConfigurationQuery ()
137
+ .setFlattenResults (MoreObjects .firstNonNull (flattenResults , Boolean .TRUE ))
138
+ .setPriority ("BATCH" )
139
+ .setQuery (query )
140
+ .setUseLegacySql (MoreObjects .firstNonNull (useLegacySql , Boolean .TRUE ));
141
+ return new BigQueryTableRowIterator (null , queryConfig , projectId , client );
142
+ }
143
+
144
+ /**
145
+ * Constructs a {@code BigQueryTableRowIterator} that reads from the results of executing the
146
+ * specified query in the specified project.
147
+ */
148
+ public static BigQueryTableRowIterator fromQuery (
149
+ JobConfigurationQuery queryConfig , String projectId , Bigquery client ) {
150
+ checkNotNull (queryConfig , "queryConfig" );
151
+ checkNotNull (projectId , "projectId" );
152
+ checkNotNull (client , "client" );
153
+ return new BigQueryTableRowIterator (null , queryConfig , projectId , client );
147
154
}
148
155
149
156
/**
150
157
* Opens the table for read.
151
158
* @throws IOException on failure
152
159
*/
153
160
public void open () throws IOException , InterruptedException {
154
- if (query != null ) {
161
+ if (queryConfig != null ) {
155
162
ref = executeQueryAndWaitForCompletion ();
156
163
}
157
164
// Get table schema.
@@ -401,15 +408,17 @@ private void deleteDataset(String datasetId) throws IOException, InterruptedExce
401
408
*/
402
409
private TableReference executeQueryAndWaitForCompletion ()
403
410
throws IOException , InterruptedException {
411
+ checkState (projectId != null , "Unable to execute a query without a configured project id" );
412
+ checkState (queryConfig != null , "Unable to execute a query without a configured query" );
404
413
// Dry run query to get source table location
405
414
Job dryRunJob = new Job ()
406
415
.setConfiguration (new JobConfiguration ()
407
- .setQuery (new JobConfigurationQuery ()
408
- .setQuery (query ))
416
+ .setQuery (queryConfig )
409
417
.setDryRun (true ));
410
418
JobStatistics jobStats = executeWithBackOff (
411
419
client .jobs ().insert (projectId , dryRunJob ),
412
- String .format ("Error when trying to dry run query %s." , query )).getStatistics ();
420
+ String .format ("Error when trying to dry run query %s." ,
421
+ queryConfig .toPrettyString ())).getStatistics ();
413
422
414
423
// Let BigQuery to pick default location if the query does not read any tables.
415
424
String location = null ;
@@ -428,30 +437,27 @@ private TableReference executeQueryAndWaitForCompletion()
428
437
createDataset (temporaryDatasetId , location );
429
438
Job job = new Job ();
430
439
JobConfiguration config = new JobConfiguration ();
431
- JobConfigurationQuery queryConfig = new JobConfigurationQuery ();
432
440
config .setQuery (queryConfig );
433
441
job .setConfiguration (config );
434
- queryConfig .setQuery (query );
435
- queryConfig .setAllowLargeResults (true );
436
- queryConfig .setFlattenResults (flattenResults );
437
- queryConfig .setUseLegacySql (useLegacySql );
438
-
439
442
440
443
TableReference destinationTable = new TableReference ();
441
444
destinationTable .setProjectId (projectId );
442
445
destinationTable .setDatasetId (temporaryDatasetId );
443
446
destinationTable .setTableId (temporaryTableId );
444
447
queryConfig .setDestinationTable (destinationTable );
448
+ queryConfig .setAllowLargeResults (Boolean .TRUE );
445
449
446
450
Job queryJob = executeWithBackOff (
447
451
client .jobs ().insert (projectId , job ),
448
- String .format ("Error when trying to execute the job for query %s." , query ));
452
+ String .format ("Error when trying to execute the job for query %s." ,
453
+ queryConfig .toPrettyString ()));
449
454
JobReference jobId = queryJob .getJobReference ();
450
455
451
456
while (true ) {
452
457
Job pollJob = executeWithBackOff (
453
458
client .jobs ().get (projectId , jobId .getJobId ()),
454
- String .format ("Error when trying to get status of the job for query %s." , query ));
459
+ String .format ("Error when trying to get status of the job for query %s." ,
460
+ queryConfig .toPrettyString ()));
455
461
JobStatus status = pollJob .getStatus ();
456
462
if (status .getState ().equals ("DONE" )) {
457
463
// Job is DONE, but did not necessarily succeed.
@@ -461,7 +467,9 @@ private TableReference executeQueryAndWaitForCompletion()
461
467
} else {
462
468
// There will be no temporary table to delete, so null out the reference.
463
469
temporaryTableId = null ;
464
- throw new IOException ("Executing query " + query + " failed: " + error .getMessage ());
470
+ throw new IOException (
471
+ String .format ("Executing query %s failed: %s" ,
472
+ queryConfig .toPrettyString (), error .getMessage ()));
465
473
}
466
474
}
467
475
Uninterruptibles .sleepUninterruptibly (
0 commit comments