table.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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. import (
  16. "fmt"
  17. "time"
  18. "golang.org/x/net/context"
  19. bq "google.golang.org/api/bigquery/v2"
  20. )
  21. // A Table is a reference to a BigQuery table.
  22. type Table struct {
  23. // ProjectID, DatasetID and TableID may be omitted if the Table is the destination for a query.
  24. // In this case the result will be stored in an ephemeral table.
  25. ProjectID string
  26. DatasetID string
  27. // TableID must contain only letters (a-z, A-Z), numbers (0-9), or underscores (_).
  28. // The maximum length is 1,024 characters.
  29. TableID string
  30. service service
  31. }
  32. // TableMetadata contains information about a BigQuery table.
  33. type TableMetadata struct {
  34. Description string // The user-friendly description of this table.
  35. Name string // The user-friendly name for this table.
  36. Schema Schema
  37. View string
  38. ID string // An opaque ID uniquely identifying the table.
  39. Type TableType
  40. // The time when this table expires. If not set, the table will persist
  41. // indefinitely. Expired tables will be deleted and their storage reclaimed.
  42. ExpirationTime time.Time
  43. CreationTime time.Time
  44. LastModifiedTime time.Time
  45. // The size of the table in bytes.
  46. // This does not include data that is being buffered during a streaming insert.
  47. NumBytes int64
  48. // The number of rows of data in this table.
  49. // This does not include data that is being buffered during a streaming insert.
  50. NumRows uint64
  51. }
  52. // Tables is a group of tables. The tables may belong to differing projects or datasets.
  53. type Tables []*Table
  54. // CreateDisposition specifies the circumstances under which destination table will be created.
  55. // Default is CreateIfNeeded.
  56. type TableCreateDisposition string
  57. const (
  58. // The table will be created if it does not already exist. Tables are created atomically on successful completion of a job.
  59. CreateIfNeeded TableCreateDisposition = "CREATE_IF_NEEDED"
  60. // The table must already exist and will not be automatically created.
  61. CreateNever TableCreateDisposition = "CREATE_NEVER"
  62. )
  63. func CreateDisposition(disp TableCreateDisposition) Option { return disp }
  64. func (opt TableCreateDisposition) implementsOption() {}
  65. func (opt TableCreateDisposition) customizeLoad(conf *bq.JobConfigurationLoad, projectID string) {
  66. conf.CreateDisposition = string(opt)
  67. }
  68. func (opt TableCreateDisposition) customizeCopy(conf *bq.JobConfigurationTableCopy, projectID string) {
  69. conf.CreateDisposition = string(opt)
  70. }
  71. func (opt TableCreateDisposition) customizeQuery(conf *bq.JobConfigurationQuery, projectID string) {
  72. conf.CreateDisposition = string(opt)
  73. }
  74. // TableWriteDisposition specifies how existing data in a destination table is treated.
  75. // Default is WriteAppend.
  76. type TableWriteDisposition string
  77. const (
  78. // Data will be appended to any existing data in the destination table.
  79. // Data is appended atomically on successful completion of a job.
  80. WriteAppend TableWriteDisposition = "WRITE_APPEND"
  81. // Existing data in the destination table will be overwritten.
  82. // Data is overwritten atomically on successful completion of a job.
  83. WriteTruncate TableWriteDisposition = "WRITE_TRUNCATE"
  84. // Writes will fail if the destination table already contains data.
  85. WriteEmpty TableWriteDisposition = "WRITE_EMPTY"
  86. )
  87. func WriteDisposition(disp TableWriteDisposition) Option { return disp }
  88. func (opt TableWriteDisposition) implementsOption() {}
  89. func (opt TableWriteDisposition) customizeLoad(conf *bq.JobConfigurationLoad, projectID string) {
  90. conf.WriteDisposition = string(opt)
  91. }
  92. func (opt TableWriteDisposition) customizeCopy(conf *bq.JobConfigurationTableCopy, projectID string) {
  93. conf.WriteDisposition = string(opt)
  94. }
  95. func (opt TableWriteDisposition) customizeQuery(conf *bq.JobConfigurationQuery, projectID string) {
  96. conf.WriteDisposition = string(opt)
  97. }
  98. // TableType is the type of table.
  99. type TableType string
  100. const (
  101. RegularTable TableType = "TABLE"
  102. ViewTable TableType = "VIEW"
  103. )
  104. func (t *Table) implementsSource() {}
  105. func (t *Table) implementsReadSource() {}
  106. func (t *Table) implementsDestination() {}
  107. func (ts Tables) implementsSource() {}
  108. func (t *Table) tableRefProto() *bq.TableReference {
  109. return &bq.TableReference{
  110. ProjectId: t.ProjectID,
  111. DatasetId: t.DatasetID,
  112. TableId: t.TableID,
  113. }
  114. }
  115. // FullyQualifiedName returns the ID of the table in projectID:datasetID.tableID format.
  116. func (t *Table) FullyQualifiedName() string {
  117. return fmt.Sprintf("%s:%s.%s", t.ProjectID, t.DatasetID, t.TableID)
  118. }
  119. // implicitTable reports whether Table is an empty placeholder, which signifies that a new table should be created with an auto-generated Table ID.
  120. func (t *Table) implicitTable() bool {
  121. return t.ProjectID == "" && t.DatasetID == "" && t.TableID == ""
  122. }
  123. func (t *Table) customizeLoadDst(conf *bq.JobConfigurationLoad, projectID string) {
  124. conf.DestinationTable = t.tableRefProto()
  125. }
  126. func (t *Table) customizeExtractSrc(conf *bq.JobConfigurationExtract, projectID string) {
  127. conf.SourceTable = t.tableRefProto()
  128. }
  129. func (t *Table) customizeCopyDst(conf *bq.JobConfigurationTableCopy, projectID string) {
  130. conf.DestinationTable = t.tableRefProto()
  131. }
  132. func (ts Tables) customizeCopySrc(conf *bq.JobConfigurationTableCopy, projectID string) {
  133. for _, t := range ts {
  134. conf.SourceTables = append(conf.SourceTables, t.tableRefProto())
  135. }
  136. }
  137. func (t *Table) customizeQueryDst(conf *bq.JobConfigurationQuery, projectID string) {
  138. if !t.implicitTable() {
  139. conf.DestinationTable = t.tableRefProto()
  140. }
  141. }
  142. func (t *Table) customizeReadSrc(cursor *readTableConf) {
  143. cursor.projectID = t.ProjectID
  144. cursor.datasetID = t.DatasetID
  145. cursor.tableID = t.TableID
  146. }
  147. // OpenTable creates a handle to an existing BigQuery table. If the table does not already exist, subsequent uses of the *Table will fail.
  148. func (c *Client) OpenTable(projectID, datasetID, tableID string) *Table {
  149. return &Table{ProjectID: projectID, DatasetID: datasetID, TableID: tableID, service: c.service}
  150. }
  151. // CreateTable creates a table in the BigQuery service and returns a handle to it.
  152. func (c *Client) CreateTable(ctx context.Context, projectID, datasetID, tableID string, options ...CreateTableOption) (*Table, error) {
  153. conf := &createTableConf{
  154. projectID: projectID,
  155. datasetID: datasetID,
  156. tableID: tableID,
  157. }
  158. for _, o := range options {
  159. o.customizeCreateTable(conf)
  160. }
  161. if err := c.service.createTable(ctx, conf); err != nil {
  162. return nil, err
  163. }
  164. return &Table{ProjectID: projectID, DatasetID: datasetID, TableID: tableID, service: c.service}, nil
  165. }
  166. // Metadata fetches the metadata for the table.
  167. func (t *Table) Metadata(ctx context.Context) (*TableMetadata, error) {
  168. return t.service.getTableMetadata(ctx, t.ProjectID, t.DatasetID, t.TableID)
  169. }
  170. // Delete deletes the table.
  171. func (t *Table) Delete(ctx context.Context) error {
  172. return t.service.deleteTable(ctx, t.ProjectID, t.DatasetID, t.TableID)
  173. }
  174. // A CreateTableOption is an optional argument to CreateTable.
  175. type CreateTableOption interface {
  176. customizeCreateTable(*createTableConf)
  177. }
  178. type tableExpiration time.Time
  179. // TableExpiration returns a CreateTableOption which will cause the created table to be deleted after the expiration time.
  180. func TableExpiration(exp time.Time) CreateTableOption { return tableExpiration(exp) }
  181. func (opt tableExpiration) customizeCreateTable(conf *createTableConf) {
  182. conf.expiration = time.Time(opt)
  183. }
  184. type viewQuery string
  185. // ViewQuery returns a CreateTableOption that causes the created table to be a virtual table defined by the supplied query.
  186. // For more information see: https://cloud.google.com/bigquery/querying-data#views
  187. func ViewQuery(query string) CreateTableOption { return viewQuery(query) }
  188. func (opt viewQuery) customizeCreateTable(conf *createTableConf) {
  189. conf.viewQuery = string(opt)
  190. }
  191. // TableMetadataPatch represents a set of changes to a table's metadata.
  192. type TableMetadataPatch struct {
  193. s service
  194. projectID, datasetID, tableID string
  195. conf patchTableConf
  196. }
  197. // Patch returns a *TableMetadataPatch, which can be used to modify specific Table metadata fields.
  198. // In order to apply the changes, the TableMetadataPatch's Apply method must be called.
  199. func (t *Table) Patch() *TableMetadataPatch {
  200. return &TableMetadataPatch{
  201. s: t.service,
  202. projectID: t.ProjectID,
  203. datasetID: t.DatasetID,
  204. tableID: t.TableID,
  205. }
  206. }
  207. // Description sets the table description.
  208. func (p *TableMetadataPatch) Description(desc string) {
  209. p.conf.Description = &desc
  210. }
  211. // Name sets the table name.
  212. func (p *TableMetadataPatch) Name(name string) {
  213. p.conf.Name = &name
  214. }
  215. // TODO(mcgreevy): support patching the schema.
  216. // Apply applies the patch operation.
  217. func (p *TableMetadataPatch) Apply(ctx context.Context) (*TableMetadata, error) {
  218. return p.s.patchTable(ctx, p.projectID, p.datasetID, p.tableID, &p.conf)
  219. }