tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

【git】git-secrets: 誤ってsecret, credential, ID/Passwordなどの秘匿情報をcommitしてしまうのを防ぐメモ

はじめに

gitやgithubでこんなときありますよね。

  • ID/Passwordなどの秘匿情報をリポジトに置きたい
  • がcommitはしたくない

通常は.gitignoreに指定しておけば良い。
しかし、一時的にファイル名を変えて使いたい時(たとえば一時的にID/Passファイルをコピーして使うなど)に.gitignoreをすり抜けてcommitしてしまうことがあります。

その状態で、もしcommit & pushしてしまうとgithub上にはログとして残ってしまうので面倒...!

そんなことを未然に防止するgit-secretのメモです。

(ちなみにこの記事はMac環境で試しています)

アジェンダ

1. git-secretsとは

git-secretsというものを使います。

公式は以下です。
https://github.com/awslabs/git-secrets

descriptionの通りですが以下が説明です。

git-secretsは、commits, commit messagesをスキャンして、gitリポジトリにシークレットが追加されないようにします。 commits, commit messagesが禁止されている正規表現パターンと一致する場合、コミットは拒否されます。

2. git-secretsのインストール

Mac環境であればbrewでインストールできます。楽ちん。

$ brew install git-secrets

3. git-secrets管理化にする

これも簡単で、対象のリポジトリでgit secrets --installとするだけです。

# 対象のリポジトリでinitかcloneをする
$ git clone / git init 

# 対象のリポジトリをgit secrets管理化にする
$ git secrets --install
✓ Installed commit-msg hook to .git/hooks/commit-msg
✓ Installed pre-commit hook to .git/hooks/pre-commit
✓ Installed prepare-commit-msg hook to .git/hooks/prepare-commit-msg

4. git-secretsにcommitさせたくない文字列を登録する

正規表現の形でマッチさせることができます。
複数登録できるので、マッチさせたい文字列ごとに登録します。

git secrets --add "BASIC_AUTH_ID\:\s*\".+\""

ちなみに、登録した検出パターンの確認は--listオプションで。

$ git secrets --list
secrets.patterns BASIC_AUTH_ID\:\s*".+

5. commit時にgit-secretsによりエラーになる確認

適当なファイルを作ってadd / commitしてみます。
commit時にエラーになることが確認できます。

今回は、BASIC認証のID/Passwordのファイルを置く必要があると想定します。
basic.yamlというファイルを作成し、add / commitします。

# basic.yamlを作成
$ vim basic.yaml
----vim追記----
BASIC_AUTH_ID: "hogehoge"
BASIC_AUTH_PW: "fugafuga"
--------------

# add / commit
$ git add basic.yaml
$ git commit -m 'sample commit'
basic.yaml:1:BASIC_AUTH_ID: "hogehoge"

[ERROR] Matched one or more prohibited patterns

Possible mitigations:
- Mark false positives as allowed using: git config --add secrets.allowed ...
- Mark false positives as allowed by adding regular expressions to .gitallowed at repository's root directory
- List your configured patterns: git config --get-all secrets.patterns
- List your configured allowed patterns: git config --get-all secrets.allowed
- List your configured allowed patterns in .gitallowed at repository's root directory
- Use --no-verify if this is a one-time false positive

無事、エラーになることが確認できました。

6. git-secretsに登録した文字列を削除する

公式には削除するオプションはなさげでした。
そのため手動で削除します。

まず、どこに登録されるのか。
それは[your repo]/.git/configに登録されます。

つまり、config内から直接消せばOKです。

# .git/configを確認してみる
$ tail -n 2 .git/config
[secrets]
    patterns = BASIC_AUTH_ID\\:\\s*\".+\"

# vimなりで直接消す
$ vim .git/config

# ↑で消したてい
# 再度確認してみる
git secrets --list

参考

おわりに

team開発で設定する場合はshなんかにしておきたいですね!

【BigQuery】GolangでGCSのCSVデータからBigQueryにデータを取り込むメモ

はじめに

GolangでBigQueryをざつに扱っています。

GolangでGCSにおいたCSVデータをBigQueryに取り込むメモです。

この記事のサンプルコードは以下においてあります。

アジェンダ

1. サンプルコード

いきなり本題ですが、サンプルコードです。

※ constでProjectID, Dataset, Table, GcsURIは指定していますがサンプルコードでは省いています。

func main() {
    // client
    ctx := context.Background()
    client, err := bigquery.NewClient(ctx, projectID)
    if err != nil {
        log.Printf("err: %+v", err)
    }
    defer client.Close()

    // create table from gcs csv
    gcsRef := bigquery.NewGCSReference(GcsURI)
    gcsRef.SkipLeadingRows = 1
    gcsRef.Schema = bigquery.Schema{
        {Name: "id", Required: true, Type: bigquery.StringFieldType},
        {Name: "name", Required: true, Type: bigquery.StringFieldType},
        {Name: "age", Required: true, Type: bigquery.IntegerFieldType},
    }
    loader := client.Dataset(dataset).Table(table).LoaderFrom(gcsRef)
    loader.WriteDisposition = bigquery.WriteEmpty

    job, err := loader.Run(ctx)
    if err != nil {
        log.Printf("err: %+v", err)
    }

    status, err := job.Wait(ctx)
    if err != nil {
        log.Printf("err: %+v", err)
    }

    if status.Err() != nil {
        log.Printf("job completed with error: %v", status.Err())
    }
}

2. 要点

Golangで普通にBigQueryのschema指定 + Table作成にGCSのデータをかませる感じです。

gcsRef := bigquery.NewGCSReference(GcsURI)GCSReference structを生成し、それをもとにごにょごにょする感じです。

また、Schemaはjsonファイルなどからも生成できます。
以下をご参照ください。

3. 確認

GCS CSVからBigQueryにデータ取り込み

$ go run main.go

tableを確認

$ bq show --format=prettyjson your-project:sample_csv_dataset.sample_csv_table
{
  "creationTime": "1619006997787",
  "etag": "LfUpW/GsO3bWS5M3GW/cBQ==",
  "id": "your-project:sample_csv_dataset.sample_csv_table",
  "kind": "bigquery#table",
  "lastModifiedTime": "1619006997787",
  "location": "US",
  "numBytes": "51",
  "numLongTermBytes": "0",
  "numRows": "3",
  "schema": {
    "fields": [
      {
        "mode": "REQUIRED",
        "name": "id",
        "type": "STRING"
      },
      {
        "mode": "REQUIRED",
        "name": "name",
        "type": "STRING"
      },
      {
        "mode": "REQUIRED",
        "name": "age",
        "type": "INTEGER"
      }
    ]
  },
  "selfLink": "https://bigquery.googleapis.com/bigquery/v2/projects/your-project/datasets/sample_csv_dataset/tables/sample_csv_table",
  "tableReference": {
    "datasetId": "sample_csv_dataset",
    "projectId": "your-project",
    "tableId": "sample_csv_table"
  },
  "type": "TABLE"
}

データを確認

$ bq query --use_legacy_sql=false 'SELECT id, name, age FROM your-project.sample_csv_dataset.sample_csv_table'
Waiting on bqjob_r2039930c1e6e05d_00000178f45820d3_1 ... (0s) Current status: DONE
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1  | hoge |  20 |
| 2  | fuga |  25 |
| 3  | piyo |  30 |
+----+------+-----+

おわりに

意外とサクッとできますね!

【BigQuery】bq コマンドでtableのschemaを取得するメモ

はじめに

掲題のとおりですが、bqコマンドにてBigQueryのtable schemaを取得するときの自分用メモです。

bq showコマンド

schemaの取得は以下のように行います。

$ bq show \
--schema \
--format=prettyjson \
project_id:dataset.table > path_to_file

おわりに

bqコマンドがなにげに便利!!

【BigQuery】GolangでBigQueryのTable Create時のSchema指定方法 - bigquery.Schema, bigquery.InferSchema, bigquery.SchemaFromJSON

はじめに

GolangでBigQueryをざつに扱っています。
GolangでBigQueryのtableを作成時のSchema指定方法についての自分メモです。

この記事のサンプルコードは以下においてあります。

アジェンダ

1. schemaの指定方法は何があるか

まずは基本的なtable create時のschema指定方法ですが、以下のように行います。

   schema := /* 何らかの方法でSchemaを生成 */
    metaData := &bigquery.TableMetadata{Schema: schema}
    t := client.Dataset(dataset).Table(table)
    if err := t.Create(ctx, metaData); err != nil {
        return err
    }

/* 何らかの方法でSchemaを生成 */ですが、
主には以下の3点があると思います。

  • bigquery.Schema: field個別にSchema指定
  • bigquery.InferSchema: struct + タグでSchema指定してみる
  • bigquery.SchemaFromJSON: jsonファイルでSchema指定

ということで、以下では3つの方法を試してみます。
おもむろにサンプルコードを載せて解説は省きます。

2. bigquery.Schema: field個別にSchema指定

fieldを個別にschemaを指定する方法です。

   // client
    ctx := context.Background()
    client, err := bigquery.NewClient(ctx, projectID)
    if err != nil {
        return err
    }

    // schema
    schema := bigquery.Schema{
        {Name: "id", Required: true, Type: bigquery.StringFieldType},
        {Name: "data", Required: false, Type: bigquery.StringFieldType},
        {Name: "timestamp", Required: false, Type: bigquery.TimestampFieldType},
    }
    metaData := &bigquery.TableMetadata{Schema: schema}

    // create table
    t := client.Dataset(dataset).Table(table1)
    if err := t.Create(ctx, metaData); err != nil {
        return err
    }

3. bigquery.InferSchema: struct + タグでSchema指定してみる

structにbigqueryタグを指定し、bigquery.InferSchemaでschemaを作成する方法です。

type Item struct {
    ID        string    `bigquery:"id"`
    Data      string    `bigquery:"data"`
    Timestamp time.Time `bigquery:"timestamp"`
}

func createTableBySchema2() error {
    // client
    ctx := context.Background()
    client, err := bigquery.NewClient(ctx, projectID)
    if err != nil {
        return err
    }

    // schema
    schema, err := bigquery.InferSchema(Item{})
    metaData := &bigquery.TableMetadata{Schema: schema}

    // create table
    t := client.Dataset(dataset).Table(table2)
    if err := t.Create(ctx, metaData); err != nil {
        return err
    }
    return nil
}

4. bigquery.SchemaFromJSON: jsonファイルでSchema指定

jsonからSchemaを作成する方法です。
ファイルでなくても大丈夫ですが、この例ではファイルから読み込んでいます。

   // client
    ctx := context.Background()
    client, err := bigquery.NewClient(ctx, projectID)
    if err != nil {
        return err
    }

    // schema
    path := "./schema/schemaSampleTable3.json"
    buf, err := ioutil.ReadFile(path)
    if err != nil {
        panic(err)
    }
    schema, err := bigquery.SchemaFromJSON(buf)
    metaData := &bigquery.TableMetadata{Schema: schema}

    // create table
    t := client.Dataset(dataset).Table(table3)
    if err := t.Create(ctx, metaData); err != nil {
        return err
    }

5. どれが良いのか?

1つのポイントとして、nullable指定したいか?がキーになりそうです。

InferSchema(struct + タグ)指定ですが、
以下のようにnullable指定ができません。(というかやり方を調べたけどわからなかった)

  • 2. bigquery.Schema: field個別にSchema指定のテーブル

f:id:tweeeety:20210405025757p:plain

  • 3. bigquery.InferSchema: struct + タグでSchema指定してみるのテーブル

f:id:tweeeety:20210405025806p:plain

  • 4. bigquery.SchemaFromJSON: jsonファイルでSchema指定のテーブル

f:id:tweeeety:20210405025815p:plain

そのため、nullを許容する場合はInferSchema以外が良さそうです。

なぜ今回の調査をしたか

なぜ今回調査をしたかですが、
「GolangでAPI(json形式)を受けて、その結果をBigQueryに保存したい」
という要件がありました。

この場合、APIの結果jsonとBigQueryのschemaのstructを一緒にできないか?と考えていました。

以下のような感じですね。

// APIの結果jsonとbigqueryのschemaを同じstructにしたい
type Item struct {
    ID        string    `json:"id" bigquery:"id",`
    Data      string    `json:"data" bigquery:"data"`
    Timestamp time.Time `json:"time_stamp" bigquery:"timestamp"`
}

ただし、nullableにできない(requiredになってしまう)という事に悩んだため、なくなく他の方法を探してみたという感じでした。

参照

試したコードスニペットと参考にした公式です。

おわりに

InferSchemaでNullalbeを指定する方法がわかったら知りたい...!!

【BigQuery】Golang x BigQueryでのCredentialの指定方法メモ

はじめに

GolangでBigQueryをざつに扱っています。

ローカルで開発するときはCredentialを指定しますが、
よく使う2つの方法を忘れがちなので自分メモ。

アジェンダ

1. Credentialの作成

これは必ずやることとして、Credentialを作成します。

具体的には、以下2つを行います。

  • Service Accountの作成
  • keyの作成(これがCredential)

ここは本旨ではないので軽く触れる程度で省きます。

Service Accountの作成は、以下から行います。

f:id:tweeeety:20210404004104p:plain

Service Accountを作成したら、Manage keysを選択します。

f:id:tweeeety:20210404004113p:plain

次の画面にてADD KEY > Create new keyでkeyを作成します。

f:id:tweeeety:20210404004123p:plain

keyのタイプはjsonを選択してください。
このあとつかうCredentialsファイルになります。

ブラウザのダウンロードが始まるのでプロジェクトルートなどに置いてください。
この記事ではファイル名をkey.jsonとして保存しています。

2. 環境変数で設定する

上記で作成した、credentialsファイルを環境設定で指定する方法です。

まんまなので以下のコマンドを打つだけです。

$ export GOOGLE_APPLICATION_CREDENTIALS=./key.json

環境変数に設定しておくことで、bigqueryパッケージが環境変数に設定されていれば読み込んでくれます。

ただし、端末やPCの再起動で設定は消えてしまうので再設定が必要です。

3. プログラムで指定する

こちらはプログラムに書くので再設定が必要ありません。
option.WithCredentialsFileを使ってcredensialsを読み込みます。

package main

import (
    "context"
    "fmt"
    "log"

    "cloud.google.com/go/bigquery"
    "google.golang.org/api/iterator"
    "google.golang.org/api/option"
)

const (
    key       = "./key.json"
    projectID = "your-project"
    query     = "select * from your-project.datasetName.tableName"
)

func main() {
    ctx := context.Background()

  // client作成時にoption.WithCredentialsFileでファイルを読み込む
    client, err := bigquery.NewClient(ctx, projectID, option.WithCredentialsFile(key))

    if err != nil {
        fmt.Printf("Failed to create client: %v", err)
    }
    defer client.Close()

    it, err := client.Query(query).Read(ctx)
    if err != nil {
        log.Printf("Failed to Read Query: %v", err)
    }

    for {
        var values []bigquery.Value
        err := it.Next(&values)
        if err == iterator.Done {
            break
        }
        if err != nil {
            fmt.Println("Failed to Iterate Query:%v", err)
        }
        fmt.Println(values)
    }
}

参照

試したコードスニペットをおいておきます

おわりに

BigQueryは触っていて楽しいですが、golangから扱うときにちょくちょく面倒なことがありますね!

【BigQuery】bqコマンドでdataset/table/partitionの作成から確認まで試すメモ

はじめに

最近、BigQueryを触っています。

bqコマンドでコマンドラインからアクセスする際の自分メモです。

この記事で使うschemaやcsvファイルは以下のリポジトリにおいてあります。
* https://github.com/tweeeety/bq-command-sample

アジェンダ

1. bqコマンドつかう前の確認

bqコマンドを使いはじめるにあたり確認です。

# bqコマンドのversionを確認
$ bq version
This is BigQuery CLI 2.0.65

# projectを確認
$ gcloud config list
[compute]
region = asia-northeast1
zone = asia-northeast1-b
[core]
account = [your account]
disable_usage_reporting = False
project = [your project]

Your active configuration is: [default]

# 設定されていない場合はprojectを設定してから行う
gcloud config set project [project name]

bqコマンドを使うには、cloud SDKをインストールする必要があります。
もしbq versionでコマンドが確認できない場合は、以下2点をやってみてください。

2. bqコマンドつかう前の設定

フラグ

bqコマンドは大きく2つのフラグがあります。

  1. グローバル フラグ(共通フラグ): すべてのコマンドで使用可
  2. コマンド固有のフラグ: 特定のコマンドに適用される

詳しくは以下をご参照ください。
* コマンドライン ツール リファレンス

.bigqueryrc

bqコマンドは予めフラグ(コマンドのオプション)を設定しておくことができます。

vim $HOME/.bigqueryrcに設定することで毎回オプションを指定せずに実行できるようになります。

グローバルフラグは直で、
コマンド固有のフラグは[command]でセクションをきって指定します。

$ vim ~/.bigqueryrc
---- vim ----
--credential_file="[path to file]/key.json"

[query]
--use_legacy_sql=false

[mk]
--use_legacy_sql=false
-------------

デバッグ フラグ

特に使いそうなbqフラグにログとステータスを表示することものがあります。

うまくいかないときは設定してみると良いでしょう。

  • --apilog=path_to_file: ログ・ファイルを指定
  • --format=prettyjson: レスポンスをJSON形式で出力

3. bqコマンドでprojectの確認

# projectの確認
$ gcloud config list

4. bqコマンドでdatasetの作成/確認

bqコマンドでデータセットを作成します。

# 東京:asia-northeast1 にデータセットを作成
$ bq mk --data_location=asia-northeast1 bq_command_dataset
Dataset '[your project]:bq_command_dataset' successfully created.

# データセットの確認
$ bq ls
      datasetId
 --------------------
  hogehoge
  fugafuga
  bq_command_dataset

5. bqコマンドでパーティション無し/有りtableの作成

bqコマンドにてテーブルを作成します。
schemaはjson形式にて記述したローカルのファイルを参照できます。

まずは、bqコマンドにてパーティション無しのテーブルを作成します。

$ bq mk \
--table \
--description "no partition table" \
--label hoge:fuga \
--schema ./schema.json \
hoge-project:bq_command_dataset.bq_command_no_pt_table

以下は、今回のschema.jsonのサンプルです。
BigQueryでのデータ型は以下を参照してください。
* 標準 SQL のデータ型

$ cat schema.json
[
  {
    "mode": "NULLABLE",
    "name": "employee_id",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "name",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "attendance",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "partition_date",
    "type": "date"
  }
]

テーブルが作成されました。
consoleでもデータセットとテーブルが確認できます。

f:id:tweeeety:20210329233321p:plain

また、Detailsタブを開くとno partition tableと表示されてるのが確認できます。

f:id:tweeeety:20210329233335p:plain

次に、bqコマンドにてパーティション有りのテーブルを作成してみます。

$ bq mk \
--table \
--description hogehoge \
--schema ./schema.json \
--label hoge:piyo\
--require_partition_filter \
--time_partitioning_field partition_date \
--time_partitioning_type DAY \
hoge-project:bq_command_dataset.bq_command_pt_table

上記フラグはこんな感じの意味です。

  • --require_partition_filter: クエリを実行するパーティションを指定するためにWHERE句の使用を必須にする。
  • --time_partitioning_type: DAY/HOUR/MONTH/YEARを指定。デフォルトDAY。
  • --time_partitioning_field: パーティションに利用するカラムの指定

再度、consoleにて確認してみます。

f:id:tweeeety:20210329233524p:plain

また、detailsタブをひらくと、今度はパーティションについての情報が表示されるのが確認できます。

f:id:tweeeety:20210329233534p:plain

6. bqコマンドでdataset/table/パーティション情報の確認

consoleで確認しても良いですが、
毎回ブラウザを開いてはリロードで確認するのは面倒です。

そこで、コマンドラインにてbq showでテーブルの情報を確認します。

# dataset/table情報の確認
$ bq show \
--format=prettyjson \
hoge-project:bq_command_dataset.bq_command_pt_table

{
  "creationTime": "1617024639811",
  "description": "hogehoge",
  "etag": "Q/5/uQq/jZawUbYZchsKvw==",
  "id": "hoge-project:bq_command_dataset.bq_command_pt_table",
  "kind": "bigquery#table",
  "labels": {
    "hoge": "piyo--require_partition_filter"
  },
  "lastModifiedTime": "1617025188641",
  "location": "asia-northeast1",
  "numBytes": "168",
  "numLongTermBytes": "0",
  "numRows": "8",
  "schema": {
    "fields": [
      {
        "mode": "NULLABLE",
        "name": "employee_id",
        "type": "STRING"
      },
      {
        "mode": "NULLABLE",
        "name": "name",
        "type": "STRING"
      },
      {
        "mode": "NULLABLE",
        "name": "attendance",
        "type": "BOOLEAN"
      },
      {
        "mode": "NULLABLE",
        "name": "partition_date",
        "type": "DATE"
      }
    ]
  },
  "selfLink": "https://bigquery.googleapis.com/bigquery/v2/projects/hoge-project/datasets/bq_command_dataset/tables/bq_command_pt_table",
  "tableReference": {
    "datasetId": "bq_command_dataset",
    "projectId": "hoge-project",
    "tableId": "bq_command_pt_table"
  },
  "timePartitioning": {
    "field": "partition_date",
    "type": "DAY"
  },
  "type": "TABLE"
}

--schemaフラグをつけることで、スキーマ情報のみを取得することも可能です。

# schemaのみを取得
$ bq show \
--schema \
--format=prettyjson \
hoge-project:bq_command_dataset.bq_command_pt_table

[
  {
    "mode": "NULLABLE",
    "name": "employee_id",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "name",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "attendance",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "partition_date",
    "type": "date"
  }
]

また、bq lsコマンドにてテーブルの一覧表示を確認できます。

$ bq ls \
--format=prettyjson \
hoge-project:bq_command_dataset
[
  {
    "creationTime": "1617024216763",
    "id": "hoge-project:bq_command_dataset.bq_command_no_pt_table",
    "kind": "bigquery#table",
    "labels": {
      "hoge": "fuga"
    },
    "tableReference": {
      "datasetId": "bq_command_dataset",
      "projectId": "hoge-project",
      "tableId": "bq_command_no_pt_table"
    },
    "type": "TABLE"
  },
  {
    "creationTime": "1617024639811",
    "id": "hoge-project:bq_command_dataset.bq_command_pt_table",
    "kind": "bigquery#table",
    "labels": {
      "hoge": "piyo--require_partition_filter"
    },
    "tableReference": {
      "datasetId": "bq_command_dataset",
      "projectId": "hoge-project",
      "tableId": "bq_command_pt_table"
    },
    "timePartitioning": {
      "field": "partition_date",
      "type": "DAY"
    },
    "type": "TABLE"
  }
]

__PARTITIONS_SUMMARY__メタテーブルを使うとパーティションに関する情報を取得できます。

$ bq query \
--use_legacy_sql=true \
'SELECT
  partition_id
FROM
  [bq_command_dataset.bq_command_pt_table$__PARTITIONS_SUMMARY__]'

Waiting on bqjob_r3c1cbe985379d7e7_000001787e541b29_1 ... (0s) Current status: DONE
+--------------+
| partition_id |
+--------------+
| 20210101     |
| 20210102     |
+--------------+

7. bqコマンドでdataのinsert

これまで作成したデータセットとテーブルにデータを入れてみます。

今回はcsvですが、json形式でも大丈夫です。

# 01.csvを読み込む
$ bq load \
    --replace \
    --source_format=CSV \
    --schema=./schema.json \
    hoge-project:bq_command_dataset.bq_command_pt_table \
    ./source01.csv
   
Upload complete.
Waiting on bqjob_r78d80973f8b7b92c_000001787e35fed2_1 ... (0s) Current status: DONE

# 02.csvを読み込む
$ bq load \
    --source_format=CSV \
    --schema=./schema.json \
    hoge-project:bq_command_dataset.bq_command_pt_table \
    ./source02.csv

Upload complete.
Waiting on bqjob_r448ceceb57f44638_000001787e3639bc_1 ... (0s) Current status: DONE

--replaceフラグを追加すると、データの追加ではなく上書きになります。
delete or insertのような感じでしょうか。

8. bqコマンドでdataのselect

bqコマンドにてselectする方法は主に2つあります。

  • bqコマンドに生SQLを書く
  • bqコマンドにSQLファイルを読み込ませる

まず最初に、生SQLでのbqコマンドでのselectです。

# bqコマンドに生SQL
$ bq query \
--use_legacy_sql=false \
'SELECT
  employee_id,
  name,
  attendance,
  partition_date
FROM
  `bq_command_dataset.bq_command_pt_table`'

次に、SQL文を記載したSQLファイルを読み込んでのselectです。

  • SQLファイル
SELECT
  employee_id,name
FROM
  bq_command_dataset.bq_command_pt_table
WHERE
  _PARTITIONDATE = "2021-01-01"
  • コマンド
# bqコマンドにSQLファイルを読み込ませる
$ bq query \
--use_legacy_sql=false \
< query.sql

Waiting on bqjob_r4ce8a710bfc9077f_000001787de9e611_1 ... (0s) Current status: DONE
+-------------+------+------------+----------------+
| employee_id | name | attendance | partition_date |
+-------------+------+------------+----------------+
| 1001        | hoge |       true |     2021-01-02 |
| 1002        | fuga |       true |     2021-01-02 |
| 1003        | piyo |       true |     2021-01-02 |
| 1004        | fufu |      false |     2021-01-02 |
| 1001        | hoge |       true |     2021-01-01 |
| 1002        | fuga |       true |     2021-01-01 |
| 1003        | piyo |       true |     2021-01-01 |
| 1004        | fufu |       true |     2021-01-01 |
+-------------+------+------------+----------------+

consoleからパーティションを指定したSQLで容量が変わるかを確認してみます。

まずは、パーティションの指定無しSQLから。
168Bと表示されているのがわかります。

f:id:tweeeety:20210329233618p:plain

次に、パーティションを2つとも指定したSQL。
こちらも168Bと表示されています。まぁそうですよね。

f:id:tweeeety:20210329233629p:plain

最後に、パーティションを1つだけ指定したSQL。
84Bと表示されました。指定カラムをそのままでも容量が減っている事が確認できます。

f:id:tweeeety:20210329233637p:plain

9. bqコマンドでtableのdelete

最後は、作成したtableを削除して終わりにします。

$ bq rm \
-f \
-t \
hoge-project:bq_command_dataset.bq_command_no_pt_table

参照

おわりに

bqコマンドが以外に便利だという事がわかりました!!enjoy!

【BigQuery】BigQueryへのDATA型のINSERT時に`Could not parse'20210101' as DATE for field partition_date`と怒られるエラー

はじめに

表題のとおりですが、bqコマンドなんかを使用してDATE型の値をINSERTしようとすると以下のようなエラーになりました。

この原因と対処法について。

どういうエラーか

まず、INSERTするSchemaとdataです。

schema

$ cat ./schema.json
[
  {
    "mode": "NULLABLE",
    "name": "employee_id",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "birthday",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "name",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "partition_date",
    "type": "DATE"
  }
]

data

$ cat ./source.csv
1001,20210101,hoge,20210101
1002,20210303,fuga,20210101
1003,20210505,piyo,20210101
1004,20210707,fufu,20210101

つぎにINSERTです。
以下のようにエラーで怒られます。

$ bq load \
>     --replace \
>     --source_format=CSV \
>     --schema=./schema.json \
>     [your project]:bq_command_dataset.bq_command_pt_table \
>     ./source.csv
Upload complete.
Waiting on bqjob_r187e4b6bf330eafd_000001781872232f_1 ... (0s) Current status: DONE
BigQuery error in load operation: Error processing job '[your project]:bqjob_r187e4b6bf330eafd_000001781872232f_1': Error while reading data, error message: Could not parse
'20210101' as DATE for field partition_date (position 3) starting at location 0  with message 'Unable to parse'
Failure details:
- Error while reading data, error message: CSV processing encountered
too many errors, giving up. Rows: 1; errors: 1; max bad: 0; error
percent: 0
- query: Could not parse '20210101' as DATE for field partition_date
(position 3) starting at location 0  with message 'Unable to parse'

対処法

公式サイトに記載がありますが、YYYY-MM-DD形式が必須らしいです。

CSV データまたは JSON データを読み込む場合、DATE 列の値に区切りとしてダッシュ(-)を使用し、YYYY-MM-DD(年-月-日)の形式にする必要があります。

ということで、YYYY-MM-DDに変えてやるとINSERTが成功します。

# YYYYMMDDに変更する
$ cat source.csv
1001,20210101,hoge,2021-01-01
1002,20210303,fuga,2021-01-01
1003,20210505,piyo,2021-01-01
1004,20210707,fufu,2021-01-01

# 成功する
$ bq load \
>     --replace \
>     --source_format=CSV \
>     --schema=./schema.json \
>     [your project]:bq_command_dataset.bq_command_pt_table \
>     ./source.csv

Upload complete.
Waiting on bqjob_rc9c3d4712ae526_00000178187453d6_1 ... (0s) Current status: DONE

おわりに

BigQuery,とくにbqコマンドはオプションやルールがたくさんあるので公式を良く読むのが吉ですね!