Go のための Databricks SQL ドライバ

Databricks SQL Driver for Go は、Go コードを使用して Databricks コンピュート リソースで SQL コマンドを実行できるようにする Go ライブラリです。この記事では、Databricks SQL Driver for Go の READMEAPI リファレンスを補足します。

要件

Databricks SQL Driver for Go の概要

  1. Go 1.20 以降が既にインストールされ、既存の Go コード プロジェクトが既に作成されている開発用マシンで、次のように go mod init コマンドを実行して、Go コードの依存関係を追跡するための go.mod ファイルを作成します。

    go mod init sample
    
  2. go mod edit -require コマンドを実行して Databricks SQL Driver for Go パッケージに依存し、リリースに記載されている最新バージョンの Databricks SQL Driver for Go パッケージに置き換えv1.5.2

    go mod edit -require github.com/databricks/databricks-sql-go@v1.5.2
    

    go.modファイルは次のようになります。

    module sample
    
    go 1.20
    
    require github.com/databricks/databricks-sql-go v1.5.2
    
  3. プロジェクトで、Databricks SQL Driver for Go をインポートする Go コード ファイルを作成します。 次の例では、次の内容の main.go という名前のファイルに、Databricks ワークスペース内のすべてのクラスターが一覧表示されます。

    package main
    
    import (
      "database/sql"
      "os"
      _ "github.com/databricks/databricks-sql-go"
    )
    
    func main() {
      dsn := os.Getenv("DATABRICKS_DSN")
    
      if dsn == "" {
        panic("No connection string found. " +
         "Set the DATABRICKS_DSN environment variable, and try again.")
      }
    
      db, err := sql.Open("databricks", dsn)
      if err != nil {
        panic(err)
      }
      defer db.Close()
    
      if err := db.Ping(); err != nil {
        panic(err)
      }
    }
    
  4. 不足しているモジュールの依存関係を追加するには、 go mod tidy コマンドを実行します。

    go mod tidy
    

    go: warning: "all" matched no packagesエラーが発生した場合は、Databricks SQL Driver for Go をインポートする Go コード ファイルを追加するのを忘れていました。

  5. go mod vendor コマンドを実行して、main モジュール内のパッケージのビルドとテストをサポートするために必要なすべてのパッケージのコピーを作成します。

    go mod vendor
    
  6. 必要に応じてコードを変更し、Databricks 認証DATABRICKS_DSN 環境変数を設定します。「 DSN 接続文字列を使用して接続する」も参照してください。

  7. go run コマンドを実行して、main.goという名前のファイルを想定して、Go コード ファイルを実行します。

    go run main.go
    
  8. エラーが返されない場合は、Databricks ワークスペースで Databricks SQL Driver for Go が正常に認証され、そのワークスペースで実行中の Databricks クラスターまたは SQLウェアハウスに接続されています。

DSN 接続文字列 を使用して接続する

クラスターと SQLウェアハウスにアクセスするには、 sql.Open() を使用して、データソース名 (DSN) 接続文字列を使用してデータベース ハンドルを作成します。 このコード例では、 DATABRICKS_DSNという名前の環境変数から DSN 接続文字列を取得します。

package main

import (
  "database/sql"
  "os"
  _ "github.com/databricks/databricks-sql-go"
)

func main() {
  dsn := os.Getenv("DATABRICKS_DSN")

  if dsn == "" {
    panic("No connection string found. " +
          "Set the DATABRICKS_DSN environment variable, and try again.")
  }

  db, err := sql.Open("databricks", dsn)
  if err != nil {
    panic(err)
  }
  defer db.Close()

  if err := db.Ping(); err != nil {
    panic(err)
  }
}

DSN 接続文字列を正しい形式で指定するには、「 認証」の DSN 接続文字列の例を参照してください。 たとえば、Databricks の個人用アクセストークン認証の場合は、次の構文を使用します。

  • <personal-access-token> 要件からのあなたのDatabricks個人アクセストークンです。

  • <server-hostname> は、要件の サーバ ホスト名 の値です。

  • <port-number> は要件の ポート 値で、通常は 443です。

  • <http-path> は、要件の HTTP パス 値です。

  • <paramX=valueX> は、この記事で後述する 1 つ以上の 省略可能なパラメーター です。

token:<personal-access-token>@<server-hostname>:<port-number>/<http-path>?<param1=value1>&<param2=value2>

たとえば、クラスターの場合:

token:dapi12345678901234567890123456789012@dbc-a1b2345c-d6e7.cloud.databricks.com:443/sql/protocolv1/o/1234567890123456/1234-567890-abcdefgh

たとえば、SQLウェアハウスの場合:

token:dapi12345678901234567890123456789012@dbc-a1b2345c-d6e7.cloud.databricks.com:443/sql/1.0/endpoints/a1b234c5678901d2

セキュリティのベスト プラクティスとして、この DSN 接続文字列を Go コードにハードコーディングしないでください。 代わりに、この DSN 接続文字列を安全な場所から取得する必要があります。 たとえば、この記事の前半のコード例では、環境変数を使用しました。

省略可能なパラメーター

  • サポートされているオプションの接続パラメーターは、 <param=value>で指定できます。 より頻繁に使用されるものには、次のようなものがあります。

    • catalog: セッションの初期カタログ名を設定します。

    • schema: セッションの初期スキーマ名を設定します。

    • maxRows: 要求ごとにフェッチされる行の最大数を設定します。 デフォルトは 10000です。

    • timeout: サーバークエリー実行のタイムアウト (秒単位) を追加します。 デフォルトはタイムアウトなしです。

    • userAgentEntry: パートナーを識別するために使用されます。 詳細については、パートナーのドキュメントを参照してください。

  • サポートされているオプションのセッション・パラメーターは、 param=valueで指定できます。 より頻繁に使用されるものには、次のようなものがあります。

    • ansi_mode: Boolean 文字列。 セッション ステートメントが ANSI SQL 仕様で指定された規則に従うようにtrue します。システムのデフォルトは false です。

    • timezone: 文字列 ( America/Los_Angelesなど)。 セッションのタイムゾーンを設定します。 システムのデフォルトは UTC です。

たとえば、SQLウェアハウスの場合:

token:dapi12345678901234567890123456789012@dbc-a1b2345c-d6e7.cloud.databricks.com:443/sql/1.0/endpoints/a1b234c5678901d2?catalog=hive_metastore&schema=example&maxRows=100&timeout=60&timezone=America/Sao_Paulo&ansi_mode=true

NewConnector機能で接続する

または、 sql.OpenDB() を使用して、 dbsql.NewConnector() で作成された新しいコネクタ オブジェクトを介してデータベース ハンドルを作成します (新しいコネクタ オブジェクトを使用して Databricks クラスターと SQLウェアハウスに接続するには、v1.0.0 以降の Databricks SQL Driver for Go が必要です)。 例えば:

package main

import (
  "database/sql"
  "os"
  dbsql "github.com/databricks/databricks-sql-go"
)

func main() {
  connector, err := dbsql.NewConnector(
    dbsql.WithAccessToken(os.Getenv("DATABRICKS_ACCESS_TOKEN")),
    dbsql.WithServerHostname(os.Getenv("DATABRICKS_HOST")),
    dbsql.WithPort(443),
    dbsql.WithHTTPPath(os.Getenv("DATABRICKS_HTTP_PATH")),
  )
  if err != nil {
    panic(err)
  }

  db := sql.OpenDB(connector)
  defer db.Close()

  if err := db.Ping(); err != nil {
    panic(err)
  }
}

正しい NewConnector 設定セットを指定するには、「 認証」の例を参照してください。

セキュリティのベストプラクティスとして、 NewConnector 設定をGoコードにハードコーディングしないでください。 代わりに、これらの値を安全な場所から取得する必要があります。 たとえば、上記のコードでは環境変数を使用しています。

より頻繁に使用される機能オプションには、次のようなものがあります。

  • WithAccessToken(<access-token>): 要件からの Databricks 個人用アクセストークン。 必須 string.

  • WithServerHostname(<server-hostname>): 要件の サーバーホスト名 の値。 必須 string.

  • WithPort(<port>): サーバーのポート番号 (通常は 443)。 必須 int.

  • WithHTTPPath(<http-path>): 要件の HTTP パス 値。 必須 string.

  • WithInitialNamespace(<catalog>, <schema>):セッション内のカタログ名とスキーマ名。 省略可能な string, string

  • WithMaxRows(<max-rows>): 要求ごとにフェッチされる最大行数。 デフォルトは [オプション 10000. intです。

  • WithSessionParams(<params-map>): "timezone" と "ansi_mode" を含むセッション パラメーター。 省略可能な map[string]string

  • WithTimeout(<timeout>).サーバークエリー実行のタイムアウト ( time.Duration単位)。 デフォルトはタイムアウトなしです。 随意。

  • WithUserAgentEntry(<isv-name-plus-product-name>).パートナーを識別するために使用されます。 詳細については、パートナーのドキュメントを参照してください。 省略可能な string

例:

connector, err := dbsql.NewConnector(
  dbsql.WithAccessToken(os.Getenv("DATABRICKS_ACCESS_TOKEN")),
  dbsql.WithServerHostname(os.Getenv("DATABRICKS_HOST")),
  dbsql.WithPort(443),
  dbsql.WithHTTPPath(os.Getenv("DATABRICKS_HTTP_PATH")),
  dbsql.WithInitialNamespace("samples", "nyctaxi"),
  dbsql.WithMaxRows(100),
  dbsql.SessionParams(map[string]string{"timezone": "America/Sao_Paulo", "ansi_mode": "true"}),
  dbsql.WithTimeout(time.Minute),
  dbsql.WithUserAgentEntry("example-user"),
)

認証

Databricks SQL Driver for Go では、次の Databricks 認証の種類がサポートされています。

Databricks SQL Driver for Go では、Databricks のユーザー名とパスワード ( 基本とも呼ばれます) 認証はサポートされていません。

Databricks個人用アクセストークン認証

Databricks 個人用アクセストークン認証で Databricks SQL Driver for Go を使用するには、まず次のように Databricks 個人 用アクセストークンを作成する必要があります。

  1. Databricks ワークスペースで、上部のバーにある Databricks ユーザー名をクリックし、ドロップダウンから[設定]を選択します。

  2. [ 開発者] をクリックします。

  3. [アクセストークン] の横にある [管理] をクリックします。

  4. [ 新しいトークンの生成] をクリックします。

  5. (任意)今後このトークンを識別するのに役立つコメントを入力し、トークンのデフォルトの有効期間である90日を変更します。有効期間のないトークンを作成するには(非推奨)、[有効期間 (日) ] ボックスを空白のままにしてください。

  6. [生成] をクリックします。

  7. 表示されたトークンを安全な場所にコピーし、[完了] をクリックします。

コピーしたトークンは、必ず安全な場所に保存してください。 コピーしたトークンを他のユーザーと共有しないでください。 コピーしたトークンを紛失した場合、まったく同じトークンを再生成することはできません。 代わりに、この手順を繰り返して新しいトークンを作成する必要があります。 コピーしたトークンを紛失した場合、またはトークンが侵害されたと思われる場合は、アクセストークン ページでトークンの横にあるごみ箱 (取り消し) アイコンをクリックして、ワークスペースからそのトークンをすぐに削除することを強くお勧めします。

ワークスペースでトークンを作成または使用できない場合は、ワークスペース管理者がトークンを無効にしたか、トークンを作成または使用する権限を与えていないことが原因である可能性があります。ワークスペース管理者に問い合わせるか、以下をご覧ください。

DSN 接続文字列と「DSN 接続文字列を使用して接続する」のコード例を使用して Databricks SQL Driver for Go を認証するには、次の DSN 接続文字列構文を使用します。

  • <personal-access-token> 要件からのあなたのDatabricks個人アクセストークンです。

  • <server-hostname> は、要件の サーバ ホスト名 の値です。

  • <port-number> は要件の ポート 値で、通常は 443です。

  • <http-path> は、要件の HTTP パス 値です。

また、この記事で前述した 1 つ以上の 省略可能なパラメーター を追加することもできます。

token:<personal-access-token>@<server-hostname>:<port-number>/<http-path>

NewConnector 関数を使用して Databricks SQL Driver for Go を認証するには、次のコード スニペットと NewConnector 関数を使用した接続 のコード例を使用します (次の環境変数が設定されていることを前提としています)。

  • DATABRICKS_SERVER_HOSTNAMEをクラスターまたは SQLウェアハウスの [Server Hostname ] の値に設定します。

  • DATABRICKS_HTTP_PATHで、クラスターまたは SQLウェアハウスの HTTP パス 値に設定します。

  • DATABRICKS_TOKENを Databricks personal アクセストークンに設定します。

環境変数を設定するには、ご利用になっているオペレーティングシステムのドキュメントを参照してください。

connector, err := dbsql.NewConnector(
  dbsql.WithServerHostname(os.Getenv("DATABRICKS_SERVER_HOSTNAME")),
  dbsql.WithHTTPPath(os.Getenv("DATABRICKS_HTTP_PATH")),
  dbsql.WithPort(443),
  dbsql.WithAccessToken(os.Getenv("DATABRICKS_TOKEN")),
)

OAuthユーザー対マシン(U2M)認証

Databricks SQL Driver for Go バージョン 1.5.0 以降では、 OAuth ユーザーとマシン (U2M) 認証がサポートされています。

Databricks SQL Driver for Go を DSN 接続文字列と共に使用し、「DSN 接続文字列を使用して接続する」のコード例を使用するには、次の DSN 接続文字列構文を使用します。

  • <server-hostname> は、要件の サーバ ホスト名 の値です。

  • <port-number> は要件の ポート 値で、通常は 443です。

  • <http-path> は、要件の HTTP パス 値です。

また、この記事で前述した 1 つ以上の 省略可能なパラメーター を追加することもできます。

<server-hostname>:<port-number>/<http-path>?authType=OauthU2M

NewConnector 関数を使用して Databricks SQL Driver for Go を認証するには、まず import 宣言に以下を追加する必要があります。

"github.com/databricks/databricks-sql-go/auth/oauth/u2m"

次に、次のコード スニペットと「 NewConnector 関数を使用した接続」のコード例を使用して、次の環境変数が設定されていることを前提としています。

  • DATABRICKS_SERVER_HOSTNAMEをクラスターまたは SQLウェアハウスの [Server Hostname ] の値に設定します。

  • DATABRICKS_HTTP_PATHで、クラスターまたは SQLウェアハウスの HTTP パス 値に設定します。

環境変数を設定するには、ご利用になっているオペレーティングシステムのドキュメントを参照してください。

authenticator, err := u2m.NewAuthenticator(os.Getenv("DATABRICKS_SERVER_HOSTNAME"), 1*time.Minute)
if err != nil {
  panic(err)
}

connector, err := dbsql.NewConnector(
  dbsql.WithServerHostname(os.Getenv("DATABRICKS_SERVER_HOSTNAME")),
  dbsql.WithHTTPPath(os.Getenv("DATABRICKS_HTTP_PATH")),
  dbsql.WithPort(443),
  dbsql.WithAuthenticator(authenticator),
)

OAuthマシン間(M2M)認証

Databricks SQL Driver for Go バージョン 1.5.2 以降では、 OAuth マシン間 (M2M) 認証がサポートされています。

OAuth M2M 認証で Databricks SQL Driver for Go を使用するには、次の操作を行う必要があります。

  1. Databricks ワークスペースに Databricks サービスプリンシパルを作成し、そのサービスプリンシパルの OAuth シークレットを作成します。

    サービスプリンシパルとその OAuth シークレットを作成するには、 「OAuth マシン間 (M2M) 認証」を参照してください。 サービスプリンシパルのUUIDまたはアプリケーション ID の値と、サービスプリンシパルの OAuth シークレットのシークレット値をメモします。

  2. そのサービスプリンシパルにクラスターまたはウェアハウスへのアクセス権を付与します。

    サービスプリンシパルにクラスターまたはウェアハウスへのアクセスを許可するには、 「コンピュート権限」または「SQL ウェアハウスの管理」を参照してください。

DSN 接続文字列と「DSN 接続文字列を使用して接続する」のコード例を使用して Databricks SQL Driver for Go を認証するには、次の DSN 接続文字列構文を使用します。

  • <server-hostname> は、要件の サーバ ホスト名 の値です。

  • <port-number> は要件の ポート 値で、通常は 443です。

  • <http-path> は、要件の HTTP パス 値です。

  • <client-id> は、サービスプリンシパルの UUID または アプリケーション ID の値です。

  • <client-secret> は、サービスプリンシパルの OAuth シークレットの Secret 値です。

また、この記事で前述した 1 つ以上の 省略可能なパラメーター を追加することもできます。

<server-hostname>:<port-number>/<http-path>?authType=OAuthM2M&clientID=<client-id>&clientSecret=<client-secret>

NewConnector 関数を使用して Databricks SQL Driver for Go を認証するには、まず import 宣言に以下を追加する必要があります。

"github.com/databricks/databricks-sql-go/auth/oauth/m2m"

次に、次のコード スニペットと「 NewConnector 関数を使用した接続」のコード例を使用して、次の環境変数が設定されていることを前提としています。

  • DATABRICKS_SERVER_HOSTNAMEをクラスターまたは SQLウェアハウスの [Server Hostname ] の値に設定します。

  • DATABRICKS_HTTP_PATHで、クラスターまたは SQLウェアハウスの HTTP パス 値に設定します。

  • DATABRICKS_CLIENT_IDは、サービスプリンシパルの UUID または アプリケーション ID の値に設定されます。

  • DATABRICKS_CLIENT_SECRETで、サービスプリンシパルの OAuth シークレットの Secret 値に設定します。

環境変数を設定するには、ご利用になっているオペレーティングシステムのドキュメントを参照してください。

authenticator := m2m.NewAuthenticator(
  os.Getenv("DATABRICKS_CLIENT_ID"),
  os.Getenv("DATABRICKS_CLIENT_SECRET"),
  os.Getenv("DATABRICKS_SERVER_HOSTNAME"),
)

connector, err := dbsql.NewConnector(
  dbsql.WithServerHostname(os.Getenv("DATABRICKS_SERVER_HOSTNAME")),
  dbsql.WithHTTPPath(os.Getenv("DATABRICKS_HTTP_PATH")),
  dbsql.WithPort(443),
  dbsql.WithAuthenticator(authenticator),
)

データのクエリー

次のコード例は、Databricks コンピュート リソースに対して基本的な SQL クエリーを実行するために Databricks SQL Driver for Go を呼び出す方法を示しています。 このコマンドは、samples カタログのnyctaxiスキーマのtripsテーブルから最初の 2 行を返します。

このコード例では、DATABRICKS_DSNという名前の環境変数から DSN 接続文字列を取得します。

package main

import (
  "database/sql"
  "fmt"
  "os"
  "time"

  _ "github.com/databricks/databricks-sql-go"
)

func main() {
  dsn := os.Getenv("DATABRICKS_DSN")

  if dsn == "" {
    panic("No connection string found." +
          "Set the DATABRICKS_DSN environment variable, and try again.")
  }

  db, err := sql.Open("databricks", dsn)
  if err != nil {
    panic(err)
  }

  defer db.Close()

  var (
    tpep_pickup_datetime  time.Time
    tpep_dropoff_datetime time.Time
    trip_distance         float64
    fare_amount           float64
    pickup_zip            int
    dropoff_zip           int
  )

  rows, err := db.Query("SELECT * FROM samples.nyctaxi.trips LIMIT 2")
  if err != nil {
    panic(err)
  }

  defer rows.Close()

  fmt.Print("tpep_pickup_datetime,",
    "tpep_dropoff_datetime,",
    "trip_distance,",
    "fare_amount,",
    "pickup_zip,",
    "dropoff_zip\n")

  for rows.Next() {
    err := rows.Scan(&tpep_pickup_datetime,
      &tpep_dropoff_datetime,
      &trip_distance,
      &fare_amount,
      &pickup_zip,
      &dropoff_zip)
    if err != nil {
      panic(err)
    }

    fmt.Print(tpep_pickup_datetime, ",",
      tpep_dropoff_datetime, ",",
      trip_distance, ",",
      fare_amount, ",",
      pickup_zip, ",",
      dropoff_zip, "\n")
  }

  err = rows.Err()
  if err != nil {
    panic(err)
  }
}

アウトプット:

tpep_pickup_datetime,tpep_dropoff_datetime,trip_distance,fare_amount,pickup_zip,dropoff_zip
2016-02-14 16:52:13 +0000 UTC,2016-02-14 17:16:04 +0000 UTC,4.94,19,10282,10171
2016-02-04 18:44:19 +0000 UTC,2016-02-04 18:46:00 +0000 UTC,0.28,3.5,10110,10110

その他の例については、GitHub の databricks/databricks-sql-go リポジトリにある examples フォルダーを参照してください。

伐採

Databricks SQL Driver for Go が発行するメッセージをログに記録するには、 github.com/databricks/databricks-sql-go/loggerを使用します。 次のコード例では、 sql.Open()を使用して、DSN 接続文字列を通じてデータベース ハンドルを作成します。 このコード例は、 DATABRICKS_DSNという名前の環境変数から DSN 接続文字列を取得します。 debugレベル以下で出力されるすべてのログメッセージは、results.logファイルに書き込まれます。

package main

import (
  "database/sql"
  "io"
  "log"
  "os"

  _ "github.com/databricks/databricks-sql-go"
  dbsqllog "github.com/databricks/databricks-sql-go/logger"
)

func main() {
  dsn := os.Getenv("DATABRICKS_DSN")

  // Use the specified file for logging messages to.
  file, err := os.Create("results.log")
  if err != nil {
    log.Fatal(err)
  }
  defer file.Close()

  writer := io.Writer(file)

  // Log messages at the debug level and below.
  if err := dbsqllog.SetLogLevel("debug"); err != nil {
    log.Fatal(err)
  }

  // Log messages to the file.
  dbsqllog.SetLogOutput(writer)

  if dsn == "" {
    panic("Error: Cannot connect. No connection string found. " +
      "Set the DATABRICKS_DSN environment variable, and try again.")
  }

  db, err := sql.Open("databricks", dsn)
  if err != nil {
    panic(err)
  }
  defer db.Close()

  if err := db.Ping(); err != nil {
    panic(err)
  }
}

関連リソース