BigQueryのフィールド取得とクエリで利用できる型への変換
取得できるBigQueryのフィールドの型のいくつかは、クエリにそのまま利用することが出来ない。Golangの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)
}
https://pkg.go.dev/cloud.google.com/go/bigquery#FieldSchema
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.Type
if 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