BigQueryのフィールド取得とクエリで利用できる型への変換
Table.Metadata 各フィールドのスキーマを取得する
cloud.google.com/go/bigqueryを利用すると、次のように BigQuery のテーブルのスキーマを取得できる。
md, err := client.Dataset("my_dataset").Table("my_table").Metadata(ctx)
for _, fs := range md.Schema { fmt.Printf("Name: %s, FieldType: %s\n", fs.Name, fs.Type)}FieldType を Google SQL で利用できる型に変換する
Table.Metadataで取得されるFieldTypeは、BigQuery でフィールドを定義する値であって、Google SQL*で利用できる型とは異なる場合がある。
*Google SQL : BigQuery の SQL は、Google SQL を採用している。
Google SQL の Data types についてのドキュメントを参照して、可能な限り BigQuery FieldType と同名の Google SQL Data Type を選択した変換表は次のようになる。
| BigQuery FieldType | Google SQL Data Type |
|---|---|
| STRING | STRING |
| BYTES | BYTES |
| INTEGER | INTEGER(alias) |
| FLOAT | FLOAT64 |
| BOOLEAN | BOOLEAN (alias) |
| TIMESTAMP | TIMESTAMP |
| RECORD | STRUCT |
| DATE | DATE |
| TIME | TIME |
| DATETIME | DATETIME |
| NUMERIC | NUMERIC |
| GEOGRAPHY | GEOGRAPHY |
| BIGNUMERIC | BIGNUMERIC |
| INTERVAL | INTERVAL |
| JSON | JSON |
| RAMGE | RANGE |
RECORD が当然として、FLOAT は FLOAT64 などへの変換が必要になる。INTEGER と BOOLEAN はそれぞれ同名のエイリアスがあるため、そのまま利用できる。
取得したスキーマを元に NULL を挿入するクエリを生成する場合を考える。STRING などの場合は、取得された FieldType をそのまま利用して次のようにすればいい。
fmt.Sprintf("CAST(NULL AS %s) AS %s", fs.Type, fs.Name)しかし、FLOAT の場合を考慮すると分岐が必要になる。
fieldType := fs.Typeif fs.Type == bigquery.FloatFieldType { fieldType = "FLOAT64"}fmt.Sprintf("CAST(NULL AS %s) AS %s", fieldType, fs.Name)RECORD を考慮する場合は、さらに Field のスキーマを見て、再帰的に処理する必要がある。 例えば、STRING 型の p1 と p2 というフィールドを持つ record_field の場合、次のようなクエリを生成すればいい。
CAST(NULL AS STRUCT<p1 STRING, p2 FLOAT64>) AS record_field