bigquery.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright 2015 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package bigquery
  15. // TODO(mcgreevy): support dry-run mode when creating jobs.
  16. import (
  17. "fmt"
  18. "net/http"
  19. "golang.org/x/net/context"
  20. bq "google.golang.org/api/bigquery/v2"
  21. )
  22. // A Source is a source of data for the Copy function.
  23. type Source interface {
  24. implementsSource()
  25. }
  26. // A Destination is a destination of data for the Copy function.
  27. type Destination interface {
  28. implementsDestination()
  29. }
  30. // An Option is an optional argument to Copy.
  31. type Option interface {
  32. implementsOption()
  33. }
  34. // A ReadSource is a source of data for the Read function.
  35. type ReadSource interface {
  36. implementsReadSource()
  37. }
  38. // A ReadOption is an optional argument to Read.
  39. type ReadOption interface {
  40. customizeRead(conf *pagingConf)
  41. }
  42. const Scope = "https://www.googleapis.com/auth/bigquery"
  43. // Client may be used to perform BigQuery operations.
  44. type Client struct {
  45. service service
  46. projectID string
  47. }
  48. // Note: many of the methods on *Client appear in the various *_op.go source files.
  49. // NewClient constructs a new Client which can perform BigQuery operations.
  50. // Operations performed via the client are billed to the specified GCP project.
  51. // The supplied http.Client is used for making requests to the BigQuery server and must be capable of
  52. // authenticating requests with Scope.
  53. func NewClient(client *http.Client, projectID string) (*Client, error) {
  54. bqService, err := newBigqueryService(client)
  55. if err != nil {
  56. return nil, fmt.Errorf("constructing bigquery client: %v", err)
  57. }
  58. c := &Client{
  59. service: bqService,
  60. projectID: projectID,
  61. }
  62. return c, nil
  63. }
  64. // initJobProto creates and returns a bigquery Job proto.
  65. // The proto is customized using any jobOptions in options.
  66. // The list of Options is returned with the jobOptions removed.
  67. func initJobProto(projectID string, options []Option) (*bq.Job, []Option) {
  68. job := &bq.Job{}
  69. var other []Option
  70. for _, opt := range options {
  71. if o, ok := opt.(jobOption); ok {
  72. o.customizeJob(job, projectID)
  73. } else {
  74. other = append(other, opt)
  75. }
  76. }
  77. return job, other
  78. }
  79. // Copy starts a BigQuery operation to copy data from a Source to a Destination.
  80. func (c *Client) Copy(ctx context.Context, dst Destination, src Source, options ...Option) (*Job, error) {
  81. switch dst := dst.(type) {
  82. case *Table:
  83. switch src := src.(type) {
  84. case *GCSReference:
  85. return c.load(ctx, dst, src, options)
  86. case *Table:
  87. return c.cp(ctx, dst, Tables{src}, options)
  88. case Tables:
  89. return c.cp(ctx, dst, src, options)
  90. case *Query:
  91. return c.query(ctx, dst, src, options)
  92. }
  93. case *GCSReference:
  94. if src, ok := src.(*Table); ok {
  95. return c.extract(ctx, dst, src, options)
  96. }
  97. }
  98. return nil, fmt.Errorf("no Copy operation matches dst/src pair: dst: %T ; src: %T", dst, src)
  99. }
  100. // Read fetches data from a ReadSource and returns the data via an Iterator.
  101. func (c *Client) Read(ctx context.Context, src ReadSource, options ...ReadOption) (*Iterator, error) {
  102. switch src := src.(type) {
  103. case *Job:
  104. return c.readQueryResults(src, options)
  105. case *Query:
  106. return c.executeQuery(ctx, src, options...)
  107. case *Table:
  108. return c.readTable(src, options)
  109. }
  110. return nil, fmt.Errorf("src (%T) does not support the Read operation", src)
  111. }
  112. // executeQuery submits a query for execution and returns the results via an Iterator.
  113. func (c *Client) executeQuery(ctx context.Context, q *Query, options ...ReadOption) (*Iterator, error) {
  114. dest := &Table{}
  115. job, err := c.Copy(ctx, dest, q, WriteTruncate)
  116. if err != nil {
  117. return nil, err
  118. }
  119. return c.Read(ctx, job, options...)
  120. }
  121. func (c *Client) Dataset(id string) *Dataset {
  122. return &Dataset{
  123. id: id,
  124. client: c,
  125. }
  126. }