| // Copyright 2022 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:async'; |
| |
| import 'package:googleapis/bigquery/v2.dart'; |
| |
| import 'big_query_pull_request_record.dart'; |
| import 'google_auth_provider.dart'; |
| |
| const String _insertPullRequestDml = r''' |
| INSERT INTO `flutter-dashboard.autosubmit.pull_requests` ( |
| pr_created_timestamp, |
| pr_landed_timestamp, |
| organization, |
| repository, |
| author, |
| pr_number, |
| pr_commit, |
| pr_request_type |
| ) VALUES ( |
| @PR_CREATED_TIMESTAMP, |
| @PR_LANDED_TIMESTAMP, |
| @ORGANIZATION, |
| @REPOSITORY, |
| @AUTHOR, |
| @PR_NUMBER, |
| @PR_COMMIT, |
| @PR_REQUEST_TYPE |
| ) |
| '''; |
| |
| class BigqueryService { |
| /// Creates a [BigqueryService] using Google API authentication. |
| static Future<BigqueryService> from(GoogleAuthProvider authProvider) async { |
| final client = await authProvider.createClient( |
| scopes: const [BigqueryApi.bigqueryScope], |
| ); |
| return BigqueryService.forTesting(BigqueryApi(client).jobs); |
| } |
| |
| const BigqueryService.forTesting(this._defaultJobs); |
| final JobsResource _defaultJobs; |
| |
| /// Insert a new pull request record into the database. |
| Future<void> insertPullRequestRecord({ |
| required String projectId, |
| required PullRequestRecord pullRequestRecord, |
| }) async { |
| final queryRequest = QueryRequest( |
| query: _insertPullRequestDml, |
| queryParameters: <QueryParameter>[ |
| _createIntegerQueryParameter( |
| 'PR_CREATED_TIMESTAMP', |
| pullRequestRecord.prCreatedTimestamp!.millisecondsSinceEpoch, |
| ), |
| _createIntegerQueryParameter( |
| 'PR_LANDED_TIMESTAMP', |
| pullRequestRecord.prLandedTimestamp!.millisecondsSinceEpoch, |
| ), |
| _createStringQueryParameter( |
| 'ORGANIZATION', |
| pullRequestRecord.organization, |
| ), |
| _createStringQueryParameter('REPOSITORY', pullRequestRecord.repository), |
| _createStringQueryParameter('AUTHOR', pullRequestRecord.author), |
| _createIntegerQueryParameter('PR_NUMBER', pullRequestRecord.prNumber), |
| _createStringQueryParameter('PR_COMMIT', pullRequestRecord.prCommit), |
| _createStringQueryParameter( |
| 'PR_REQUEST_TYPE', |
| pullRequestRecord.prRequestType, |
| ), |
| ], |
| useLegacySql: false, |
| ); |
| |
| final queryResponse = await _defaultJobs.query(queryRequest, projectId); |
| if (!queryResponse.jobComplete!) { |
| throw BigQueryException( |
| 'Insert pull request $pullRequestRecord did not complete.', |
| ); |
| } |
| |
| if (queryResponse.numDmlAffectedRows != null && |
| int.parse(queryResponse.numDmlAffectedRows!) != 1) { |
| throw BigQueryException( |
| 'There was an error inserting $pullRequestRecord into the table.', |
| ); |
| } |
| } |
| |
| /// Create an int parameter for query substitution. |
| QueryParameter _createIntegerQueryParameter(String name, int? value) { |
| return QueryParameter( |
| name: name, |
| parameterType: QueryParameterType(type: 'INT64'), |
| parameterValue: QueryParameterValue(value: value.toString()), |
| ); |
| } |
| |
| /// Create a String parameter for query substitution. |
| QueryParameter _createStringQueryParameter(String name, String? value) { |
| return QueryParameter( |
| name: name, |
| parameterType: QueryParameterType(type: 'STRING'), |
| parameterValue: QueryParameterValue(value: value), |
| ); |
| } |
| } |
| |
| class BigQueryException implements Exception { |
| /// Create a custom exception for Big Query Errors. |
| BigQueryException(this.cause); |
| |
| final String cause; |
| |
| @override |
| String toString() => cause; |
| } |