blob: acdc88f1be96fdcd6dd56bf7489df51a67bd2b09 [file] [log] [blame] [edit]
// 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:auto_submit/exception/bigquery_exception.dart';
import 'package:auto_submit/model/big_query_pull_request_record.dart';
import 'package:googleapis/bigquery/v2.dart';
import 'package:http/http.dart';
import 'access_client_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 {
const BigqueryService(this.accessClientProvider);
/// AccessClientProvider for OAuth 2.0 authenticated access client
final AccessClientProvider accessClientProvider;
/// Return a [TabledataResource] with an authenticated [client]
Future<TabledataResource> defaultTabledata() async {
final Client client = await accessClientProvider.createAccessClient(
scopes: const <String>[BigqueryApi.bigqueryScope],
);
return BigqueryApi(client).tabledata;
}
/// Return a [JobsResource] with an authenticated [client]
Future<JobsResource> defaultJobs() async {
final Client client = await accessClientProvider.createAccessClient(
scopes: const <String>[BigqueryApi.bigqueryScope],
);
return BigqueryApi(client).jobs;
}
/// Insert a new pull request record into the database.
Future<void> insertPullRequestRecord({
required String projectId,
required PullRequestRecord pullRequestRecord,
}) async {
final JobsResource jobsResource = await defaultJobs();
final QueryRequest 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 queryResponse = await jobsResource.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),
);
}
}