Databricks SQL Driver for Go
Databricks SQL Driver for Go は、Go コードを使用して Azure Databricks コンピューティング リソースで SQL コマンドを実行できる Go ライブラリです。 この記事は、Databricks SQL Driver for Go の README、API リファレンス、例を補足するものです。
要件
- Go バージョン 1.20 以上を実行している開発マシン。 インストールされているバージョンの Go を印刷するには、コマンド
go version
を実行します。 Go をダウンロードしてインストールします。 - 既存のクラスターまたは SQL ウェアハウス。
- 既存のクラスターまたは SQL ウェアハウスのサーバーホスト名、ポート、HTTP パスの値。
Databricks SQL Driver for Go の概要
Go 1.20 以上が既にインストールされ、既存の Go コード プロジェクトが既に作成されている開発マシンで、
go mod init
コマンドを実行して、Go コードの依存関係を追跡するgo.mod
ファイルを作成します。例:go mod init sample
go mod edit -require
コマンドを実行して、Databricks SQL Driver for Go パッケージへの依存関係を設定します。v1.5.2
は、リリースに記載されている Databricks SQL Driver for Go パッケージの最新バージョンに置き換えてください。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
プロジェクト内で、Databricks SQL Driver for Go をインポートする Go コード ファイルを作成します。 次の例では、次のコンテンツの
main.go
という名前のファイルで、Azure 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) } }
go mod tidy
コマンドを実行して、不足しているモジュール依存関係を追加します。go mod tidy
Note
エラー
go: warning: "all" matched no packages
が発生した場合は、Databricks SQL Driver for Go をインポートする Go コード ファイルを追加するのを忘れています。go mod vendor
コマンドを実行して、main
モジュール内のパッケージのビルドとテストをサポートするために必要なすべてのパッケージのコピーを作成します。go mod vendor
必要に応じて、Azure Databricks 認証のための
DATABRICKS_DSN
環境変数を設定するコードを変更します。 「DSN 接続文字列を使用して接続する」も参照してください。go run
コマンドを実行して、main.go
という名前のファイルを想定して Go コード ファイルを実行します。go run main.go
エラーが返されない場合は、Azure Databricks ワークスペースで Databricks SQL Driver for Go を正常に認証し、そのワークスペース内の実行中の Azure 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 接続文字列の例を参照してください。 たとえば、Azure Databricks 個人用アクセス トークン認証の場合、次の構文を使用します。ここで各部分は次のとおりです。
<personal-access-token>
は、要件の Azure 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@adb-1234567890123456.7.azuredatabricks.net:443/sql/protocolv1/o/1234567890123456/1234-567890-abcdefgh
たとえば、SQL ウェアハウスの場合:
token:dapi12345678901234567890123456789012@adb-1234567890123456.7.azuredatabricks.net:443/sql/1.0/endpoints/a1b234c5678901d2
注意
セキュリティのベスト プラクティスとして、この DSN 接続文字列を Go コードにハードコーディングすることは避けてください。 代わりに、セキュリティで保護された場所からこの DSN 接続文字列を取得する必要があります。 たとえば、この記事の前半のコード例では環境変数が使用されています。
省略可能なパラメーター
- サポートされる省略可能な接続パラメータを、
<param=value>
に指定できます。 よく使われるものには、次が含まれます。catalog
: セッションの初期カタログ名を設定します。schema
: セッションの初期スキーマ名を設定します。maxRows
: 要求ごとにフェッチされる行の最大数を設定します。 既定では、10000
です。timeout
: サーバー クエリ実行のタイムアウト (秒単位) を追加します。 既定では、タイムアウトはありません。userAgentEntry
: パートナーを識別するために使用されます。 詳細については、パートナーのドキュメントを参照してください。
- サポートされる省略可能なセッション パラメータを、
param=value
に指定できます。 よく使われるものには、次が含まれます。ansi_mode
: ブール値の文字列。 セッション ステートメントが ANSI SQL 仕様で指定された規則に従う場合はtrue
。 システムの既定値は false です。timezone
: 文字列 (例:America/Los_Angeles
)。 セッションのタイムゾーンを設定します。 システムの既定値は UTC です。
たとえば、SQL ウェアハウスの場合:
token:dapi12345678901234567890123456789012@adb-1234567890123456.7.azuredatabricks.net: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()
で作成された新しいコネクタ オブジェクトを介してデータベース ハンドルを作成します (新しいコネクタ オブジェクトを使用して Azure 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
設定を指定するには、「認証」の例を参照してください。
Note
セキュリティのベスト プラクティスとして、NewConnector
設定を Go コードにハードコーディングしないようにする必要があります。 代わりに、セキュリティで保護された場所からこれらの値を取得する必要があります。 たとえば、上記のコードでは環境変数が使用されています。
より頻繁に使用される関数オプションには、次が含まれます。
WithAccessToken(<access-token>)
: 要件の Azure 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 は、次の Azure Databricks 認証の種類をサポートしています。
Databricks SQL Driver for Go では、次の Azure Databricks 認証の種類はまだサポートされません。
Databricks 個人用アクセス トークン認証
Databricks SQL Driver for Go を Azure Databricks 個人アクセス トークン認証で使用するには最初に Azure Databricks の個人用アクセス トークンを作成する必要があります。 この手順の詳細については、「 ワークスペース ユーザーの Azure Databricks 個人用アクセス トークンを参照してください。
DSN 接続文字列および「DSN 接続文字列を使用して接続する」のコード例を使用して Databricks SQL Driver for Go を認証するには、次の DSN 接続文字列構文を使用します。ここで各部分は次のとおりです。
<personal-access-token>
は、要件の Azure 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 ウェアハウスのサーバー ホスト名の値に設定されていること。DATABRICKS_HTTP_PATH
が、クラスターまたは SQL ウェアハウスの HTTP パスの値に設定されていること。DATABRICKS_TOKEN
が、Azure Databricks 個人用アクセス トークンに設定されていること。
環境変数を設定するには、オペレーティング システムのドキュメントを参照してください。
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")),
)
Microsoft Entra ID トークン認証
Databricks SQL Driver for Go は、Azure Databricks ユーザーまたは Microsoft Entra ID サービス プリンシパルの Microsoft Entra ID トークンをサポートします。
Microsoft Entra ID アクセス トークンを作成するには、次の操作を行います。
Azure Databricks ユーザーの場合は、Azure CLI を使用できます。 「Azure CLI を使用してユーザーの Microsoft Entra ID トークンを取得する」を参照してください。
- Microsoft Entra ID サービス プリンシパルについては、「Azure CLI を使用して Microsoft Entra ID アクセス トークンを取得する」を参照してください。 Microsoft Entra ID マネージド サービス プリンシパルを作成するには、「サービス プリンシパルを管理する」をご参照ください。
Microsoft Entra ID トークンの既定の有効期間は約 1 時間です。 新しい Microsoft Entra ID トークンを作成するには、このプロセスを繰り返します。
DSN 接続文字列および「DSN 接続文字列を使用して接続する」のコード例を使用して Databricks SQL Driver for Go を認証するには、次の DSN 接続文字列構文を使用します。ここで各部分は次のとおりです。
<microsoft-entra-id-token>
は、ご使用の Microsoft Entra ID トークンです。<server-hostname>
は要件のサーバー ホスト名の値です。<port-number>
は、要件のポートの値です。通常443
です。<http-path>
は要件の HTTP パスの値です。
この記事で前に挙げた 1 つ以上の省略可能なパラメーターを追加することもできます。
token:<microsoft-entra-id-token>@<server-hostname>:<port-number>/<http-path>
NewConnector
関数を使用して Databricks SQL Driver for Go を認証するには、次のコード スニペットおよび「NewConnector 関数を使用して接続する」のコード例を使用します。これは、次の環境変数を設定していることを想定しています。DATABRICKS_SERVER_HOSTNAME
が、クラスターまたは SQL ウェアハウスのサーバー ホスト名の値に設定されていること。DATABRICKS_HTTP_PATH
が、クラスターまたは SQL ウェアハウスの HTTP パスの値に設定されていること。DATABRICKS_TOKEN
が、Microsoft Entra ID トークンに設定されていること。
環境変数を設定するには、オペレーティング システムのドキュメントを参照してください。
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) 認証をサポートしています。
DSN 接続文字列および「DSN 接続文字列を使用して接続する」のコード例を使用して Databricks SQL Driver for Go を使用するには、次の 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 ウェアハウスのサーバー ホスト名の値に設定されていること。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 を使用するには、次を行う必要があります。
Azure Databricks ワークスペースで Azure Databricks サービス プリンシパルを作成し、そのサービス プリンシパルの OAuth シークレットを作成します。
サービスプリンシパルと OAuth シークレットを作成するには、「OAuth(OAuth M2M)を使用してサービスプリンシパルで Azure Databricks へのアクセスを認証する」を参照してください。 サービス プリンシパルの UUID またはアプリケーション ID の値と、サービス プリンシパルの OAuth シークレットのシークレットを書き留めておいてください。
そのサービス プリンシパルにクラスターまたはウェアハウスへのアクセス権を付与します。
サービス プリンシパルにクラスターまたはウェアハウスへのアクセス権を付与するには、「コンピューティングのアクセス許可」または「SQL ウェアハウスを管理する」を参照してください。
DSN 接続文字列および「DSN 接続文字列を使用して接続する」のコード例を使用して Databricks SQL Driver for Go を認証するには、次の DSN 接続文字列構文を使用します。ここで各部分は次のとおりです。
<server-hostname>
は要件のサーバー ホスト名の値です。<port-number>
は、要件のポートの値です。通常443
です。<http-path>
は要件の HTTP パスの値です。<client-id>
は、サービス プリンシパルの UUID またはアプリケーション ID の値です。<client-secret>
は、サービス プリンシパルの OAuth シークレットの [シークレット] 値です。
この記事で前に挙げた 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 ウェアハウスのサーバー ホスト名の値に設定されていること。DATABRICKS_HTTP_PATH
が、クラスターまたは SQL ウェアハウスの HTTP パスの値に設定されていること。DATABRICKS_CLIENT_ID
。サービス プリンシパルの UUID またはアプリケーション ID の値に設定します。DATABRICKS_CLIENT_SECRET
が、サービス プリンシパルの OAuth シークレットの [シークレット] 値に設定されていること。
環境変数を設定するには、オペレーティング システムのドキュメントを参照してください。
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 Driver for Go を呼び出して、Azure Databricks コンピューティング リソースで基本的な SQL クエリを実行する方法を示します。 このコマンドを使用すると、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)
}
}
Unity Catalog ボリューム内のファイルを管理する
Databricks SQL Driver を使用すると、次の例に示すように、Unity Catalog ボリュームにローカル ファイルを書き込み、ボリュームからファイルをダウンロードし、ボリュームからファイルを削除できるようになります。
package main
import (
"context"
"database/sql"
"os"
_ "github.com/databricks/databricks-sql-go"
"github.com/databricks/databricks-sql-go/driverctx"
)
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()
// For writing local files to volumes and downloading files from volumes,
// you must first specify the path to the local folder that contains the
// files to be written or downloaded.
// For multiple folders, add their paths to the following string array.
// For deleting files in volumes, this string array is ignored but must
// still be provided, so in that case its value can be set for example
// to an empty string.
ctx := driverctx.NewContextWithStagingInfo(
context.Background(),
[]string{"/tmp/"},
)
// Write a local file to the path in the specified volume.
// Specify OVERWRITE to overwrite any existing file in that path.
db.ExecContext(ctx, "PUT '/tmp/my-data.csv' INTO '/Volumes/main/default/my-volume/my-data.csv' OVERWRITE")
// Download a file from the path in the specified volume.
db.ExecContext(ctx, "GET '/Volumes/main/default/my-volume/my-data.csv' TO '/tmp/my-downloaded-data.csv'")
// Delete a file from the path in the specified volume.
db.ExecContext(ctx, "REMOVE '/Volumes/main/default/my-volume/my-data.csv'")
db.Close()
}
ログ機能
github.com/databricks/databricks-sql-go/logger
を使用し、Databricks SQL Driver for Go から出力されるメッセージをログに記録します。 次のコード例では、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)
}
}
テスト
コードをテストするには、testing 標準ライブラリなどの Go テスト フレームワークを使用します。 Azure Databricks REST API エンドポイントを呼び出したり、Azure Databricks アカウントまたはワークスペースの状態を変更したりせずに、シミュレートされた条件下でコードをテストするには、testfify などの Go モック ライブラリを使用します。
たとえば、Azure Databricks ワークスペース接続を返す GetDBWithDSNPAT
関数、samples
カタログの nyctaxi
スキーマの trips
テーブルからデータを返す GetNYCTaxiTrips
関数、返されたデータを出力する PrintNYCTaxiTrips
を含む、helpers.go
という名前の次のファイルがあるとします。
package main
import (
"database/sql"
"fmt"
"strconv"
"time"
)
func GetDBWithDSNPAT(dsn string) (*sql.DB, error) {
db, err := sql.Open("databricks", dsn)
if err != nil {
return nil, err
}
return db, nil
}
func GetNYCTaxiTrips(db *sql.DB, numRows int) (*sql.Rows, error) {
rows, err := db.Query("SELECT * FROM samples.nyctaxi.trips LIMIT " + strconv.Itoa(numRows))
if err != nil {
return nil, err
}
return rows, nil
}
func PrintNYCTaxiTrips(rows *sql.Rows) {
var (
tpep_pickup_datetime time.Time
tpep_dropoff_datetime time.Time
trip_distance float64
fare_amount float64
pickup_zip int
dropoff_zip int
)
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)
}
}
また、これらの関数を呼び出す、main.go
という名前の次のファイルがあるとします。
package main
import (
"os"
)
func main() {
db, err := GetDBWithDSNPAT(os.Getenv("DATABRICKS_DSN"))
if err != nil {
panic(err)
}
rows, err := GetNYCTaxiTrips(db, 2)
if err != nil {
panic(err)
}
PrintNYCTaxiTrips(rows)
}
helpers_test.go
という名前の次のファイルは、GetNYCTaxiTrips
関数が、想定される応答を返すかどうかをテストします。 このテストでは、ターゲット ワークスペースへの実際の接続を作成するのではなく、sql.DB
オブジェクトをモックします。 また、このテストでは、実際のデータ内にあるスキーマと値に準拠するデータをモックします。 テストでは、モックされた接続を介してモックされたデータが返され、モックされたデータ行の値のいずれかが期待値と一致するかどうかを確認します。
package main
import (
"database/sql"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
// Define an interface that contains a method with the same signature
// as the real GetNYCTaxiTrips function that you want to test.
type MockGetNYCTaxiTrips interface {
GetNYCTaxiTrips(db *sql.DB, numRows int) (*sql.Rows, error)
}
// Define a struct that represents the receiver of the interface's method
// that you want to test.
type MockGetNYCTaxiTripsObj struct {
mock.Mock
}
// Define the behavior of the interface's method that you want to test.
func (m *MockGetNYCTaxiTripsObj) GetNYCTaxiTrips(db *sql.DB, numRows int) (*sql.Rows, error) {
args := m.Called(db, numRows)
return args.Get(0).(*sql.Rows), args.Error(1)
}
func TestGetNYCTaxiTrips(t *testing.T) {
// Instantiate the receiver.
mockGetNYCTaxiTripsObj := new(MockGetNYCTaxiTripsObj)
// Define how the mock function should be called and what it should return.
// We're not concerned with whether the actual database is connected to--just
// what is returned.
mockGetNYCTaxiTripsObj.On("GetNYCTaxiTrips", mock.Anything, mock.AnythingOfType("int")).Return(&sql.Rows{}, nil)
// Call the mock function that you want to test.
rows, err := mockGetNYCTaxiTripsObj.GetNYCTaxiTrips(nil, 2)
// Assert that the mock function was called as expected.
mockGetNYCTaxiTripsObj.AssertExpectations(t)
// Assert that the mock function returned what you expected.
assert.NotNil(t, rows)
assert.Nil(t, err)
}
GetNYCTaxiTrips
関数には SELECT
ステートメントが含まれ、そのため、trips
テーブルの状態が変更されないため、モックはこの例では完全に不要です。 ただし、モックの場合、ワークスペースとの実際の接続が行われるのを待つことなく、テストを速やかに実行できます。 また、モックの場合、INSERT INTO
、UPDATE
、DELETE FROM
など、テーブルの状態を変更する可能性のある関数に対してシミュレーション テストを複数回実行できます。
その他のリソース
- GitHub の Databricks SQL Driver for Go リポジトリ
- database/sql パッケージ ホームページ
- GitHub の Databricks SQL Driver for Go 例