Compartir a través de


Controlador de Databricks SQL para Go

El controlador de Databricks SQL para Go es una biblioteca de Go que permite usar código de Go para ejecutar comandos SQL en recursos de proceso de Azure Databricks. Este artículo sirve de complemento al archivo LÉAME, la referencia de API y los ejemplos del controlador de Databricks SQL para Go.

Requisitos

Introducción al Controlador de Databricks SQL para Go

  1. En una máquina de desarrollo con Go versión 1.20 o posterior ya instalado, y un proyecto de código de Go existente ya creado, cree un archivo go.mod para hacer seguimiento de las dependencias del código de Go mediante la ejecución del comando go mod init; por ejemplo:

    go mod init sample
    
  2. Para tomar una dependencia del paquete del controlador Databricks SQL para Go, ejecute el comando go mod edit -require y reemplace v1.5.2 por la versión más reciente del paquete del controlador Databricks SQL para Go, que se muestra en Versiones:

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

    Ahora, el aspecto del archivo go.mod será parecido a este:

    module sample
    
    go 1.20
    
    require github.com/databricks/databricks-sql-go v1.5.2
    
  3. En el proyecto, cree un archivo de código de Go que importe el controlador Databricks SQL para Go. En el ejemplo siguiente, en un archivo denominado main.go con el contenido siguiente, se enumeran todos los clústeres del área de trabajo de 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)
      }
    }
    
  4. Ejecute el comando go mod tidy para agregar cualquier dependencia de módulo faltante:

    go mod tidy
    

    Nota:

    Si recibe el error go: warning: "all" matched no packages, se debe a que se le olvidó agregar un archivo de código de Go que importa el controlador Databricks SQL para Go.

  5. Ejecute el comando go mod vendor para hacer copias de todos los paquetes que se necesitan para admitir compilaciones y pruebas de paquetes en el módulo main:

    go mod vendor
    
  6. Modifique el código según sea necesario para establecer la variable de entorno DATABRICKS_DSN para la autenticación de Azure Databricks. Consulte también Conexión con una cadena de conexión de DSN.

  7. Ejecute el comando go run para ejecutar el archivo de código de Go (suponiendo que un archivo se denomina main.go):

    go run main.go
    
  8. Si no se devuelve ningún error, ha autenticado correctamente el controlador Databricks SQL para Go con el área de trabajo de Azure Databricks y se ha conectado al clúster de Azure Databricks en ejecución o SQL Warehouse en esa área de trabajo.

Conexión con una cadena de conexión de DSN

Para acceder a clústeres y almacenes de SQL, use sql.Open() para crear un manipulador de base de datos mediante una cadena de conexión de nombre de origen de datos (DSN). En este ejemplo de código se recupera la cadena de conexión de DSN de una variable de entorno denominada DATABRICKS_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)
  }
}

Para especificar la cadena de conexión de DSN en el formato correcto, consulte los ejemplos de cadenas de conexión de DSN en Autenticación. Por ejemplo, para la autenticación de tokens de acceso personal de Azure Databricks, use la sintaxis siguiente, donde:

  • <personal-access-token> es el token de acceso personal de Azure Databricks de los requisitos.
  • <server-hostname> es el valor de Nombre de host del servidor de los requisitos.
  • <port-number> es el valor de Puerto de los requisitos, que normalmente es 443.
  • <http-path> es el valor de Ruta de acceso HTTP de los requisitos.
  • <paramX=valueX> es uno o varios parámetros opcionales enumerados más adelante en este artículo.
token:<personal-access-token>@<server-hostname>:<port-number>/<http-path>?<param1=value1>&<param2=value2>

Por ejemplo, para un clúster:

token:dapi12345678901234567890123456789012@adb-1234567890123456.7.azuredatabricks.net:443/sql/protocolv1/o/1234567890123456/1234-567890-abcdefgh

Por ejemplo, para un almacén de SQL:

token:dapi12345678901234567890123456789012@adb-1234567890123456.7.azuredatabricks.net:443/sql/1.0/endpoints/a1b234c5678901d2

Nota:

Como procedimiento recomendado de seguridad, no debe codificar de forma rígida esta cadena de conexión de DSN en el código de Go. En su lugar, recupere esta cadena de conexión de DSN desde una ubicación segura. Por ejemplo, el código de ejemplo previo en este artículo ha usado una variable de entorno.

Parámetros opcionales

  • Los parámetros de conexión opcionales admitidos se pueden especificar en <param=value>. Algunos de los más usados incluyen:
    • catalog: establece el nombre de catálogo inicial en la sesión.
    • schema: establece el nombre de esquema inicial en la sesión.
    • maxRows: configura el número máximo de filas capturadas por solicitud. El valor predeterminado es 10000.
    • timeout: agrega el tiempo de espera (en segundos) para la ejecución de la consulta del servidor. El valor predeterminado es sin tiempo de espera.
    • userAgentEntry: se usa para identificar a los asociados. Para más información, consulte la documentación de su asociado.
  • Los parámetros de sesión opcionales admitidos se pueden especificar en param=value. Algunos de los más usados incluyen:
    • ansi_mode: una cadena booleana. true para que las instrucciones de sesión cumplan las reglas especificadas por la especificación ANSI SQL. El valor predeterminado del sistema es false.
    • timezone: cadena de bytes, por ejemplo, America/Los_Angeles. Establece la zona horaria de la sesión. El valor predeterminado del sistema es UTC.

Por ejemplo, para un almacén de 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

Conexión con la función NewConnector

Como alternativa, use sql.OpenDB() para crear un manipulador de base de datos mediante un nuevo objeto de conector creado con dbsql.NewConnector() (la conexión a clústeres de Azure Databricks y almacenes de SQL con un objeto de conector nuevo requiere la versión v1.0.0 o posterior del controlador de Databricks SQL para Go). Por ejemplo:

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)
  }
}

Para especificar el conjunto correcto de configuración NewConnector, consulte los ejemplos de Autenticación.

Nota:

Como procedimiento recomendado de seguridad, no debe codificar de forma rígida la configuración NewConnector en el código de Go. En su lugar, recupere estos valores desde una ubicación segura. Por ejemplo, el código anterior usa variables de entorno.

Algunas de las opciones funcionales más usadas son:

  • WithAccessToken(<access-token>): token de acceso personal de Azure Databricks de los requisitos. string requerido.
  • WithServerHostname(<server-hostname>): valor de Nombre de host del servidor de los requisitos. string requerido.
  • WithPort(<port>): número de puerto del servidor, normalmente 443. int requerido.
  • WithHTTPPath(<http-path>): valor de Ruta de acceso HTTP de los requisitos. string requerido.
  • WithInitialNamespace(<catalog>, <schema>):nombre del catálogo y del esquema en la sesión. string, string opcional.
  • WithMaxRows(<max-rows>): número máximo de filas capturadas por solicitud. El valor predeterminado es 10000. int opcional.
  • WithSessionParams(<params-map>): parámetros de sesión que incluyen "timezone" y "ansi_mode". map[string]string opcional.
  • WithTimeout(<timeout>). Tiempo de espera (en time.Duration) para la ejecución de la consulta del servidor. El valor predeterminado es sin tiempo de espera. Opcional.
  • WithUserAgentEntry(<isv-name-plus-product-name>). Se usa para identificar a los asociados. Para más información, consulte la documentación de su asociado. string opcional.

Por ejemplo:

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"),
)

Autenticación

El controlador Databricks SQL para Go admite los siguientes tipos de autenticación de Azure Databricks:

Databricks SQL Driver for Go aún no admite los siguientes tipos de autenticación de Azure Databricks:

Autenticación de token de acceso personal de Databricks

Para usar el controlador Databricks SQL para Go con la autenticación de token de acceso personal de Azure Databricks, primero debe crear un token de acceso personal de Azure Databricks, como se indica a continuación:

  1. En el área de trabajo de Azure Databricks, haga clic en el nombre de usuario en la barra superior y seleccione Configuración en la lista desplegable.
  2. Haga clic en Desarrollador.
  3. Junto a Tokens de acceso, haga clic en Administrar.
  4. Haga clic en Generate new token (Generar nuevo token).
  5. (Opcional) Escriba un comentario que le ayude a identificar este token en el futuro y cambie la duración predeterminada del token de 90 días. Para crear un token sin duración (no recomendado), deje el cuadro Duración (días) vacío (en blanco).
  6. Haga clic en Generar.
  7. Copie el token mostrado en una ubicación segura y, a continuación, haga clic en Listo.

Nota:

Asegúrese de guardar el token copiado en una ubicación segura. No comparta el token copiado con otros usuarios. Si pierde el token copiado, no podrá volver a generar ese mismo token. Debe repetir el procedimiento para crear un nuevo token. Si pierde el token copiado o cree que el token se ha visto comprometido, Databricks recomienda eliminar inmediatamente ese token del área de trabajo haciendo clic en el icono de papelera (Revocar) situado junto al token en la página Tokens de acceso.

Si no puede crear o usar tokens en el área de trabajo, puede deberse a que el administrador del área de trabajo tiene tokens deshabilitados o no le ha concedido permiso para crear o usar tokens. Consulte el administrador del área de trabajo o los siguientes temas:

Para autenticar el controlador Databricks SQL para Go con una cadena de conexión DSN y el ejemplo de código en Conexión con una cadena de conexión DSN, use la siguiente sintaxis de cadena de conexión DSN, donde:

  • <personal-access-token> es el token de acceso personal de Azure Databricks de los requisitos.
  • <server-hostname> es el valor de Nombre de host del servidor de los requisitos.
  • <port-number> es el valor de Puerto de los requisitos, que normalmente es 443.
  • <http-path> es el valor de Ruta de acceso HTTP de los requisitos.

También puede anexar uno o varios Parámetros opcionales enumerados anteriormente en este artículo.

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

Para autenticar el controlador Databricks SQL para Go con la función NewConnector, use el siguiente fragmento de código y el ejemplo de código de Conexión con la función NewConnector, que supone que ha establecido las siguientes variables de entorno:

  • DATABRICKS_SERVER_HOSTNAMEestablecido en el valor de Nombre de host del servidor del clúster o almacén de SQL.
  • DATABRICKS_HTTP_PATH, establecido en el valor de Ruta de acceso HTTP del clúster o almacén del SQL.
  • DATABRICKS_TOKEN, establecido en el token de acceso personal de Azure Databricks.

Para establecer las variables de entorno, consulte la documentación del sistema operativo.

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")),
)

Autenticación de token de Microsoft Entra ID

El controlador Databricks SQL para Go admite tokens de Microsoft Entra ID para un usuario de Azure Databricks o una entidad de servicio de Microsoft Entra ID.

Para crear un token de acceso de Microsoft Entra ID, haga lo siguiente:

  • Para un usuario de Azure Databricks, puede usar la CLI de Azure. Consulte Obtención de tokens de Microsoft Entra ID para usuarios mediante la CLI de Azure.

    Los tokens de Microsoft Entra ID tienen una duración predeterminada de aproximadamente 1 hora. Para crear un nuevo token de Microsoft Entra ID, repita este proceso.

    Para autenticar el controlador Databricks SQL para Go con una cadena de conexión DSN y el ejemplo de código en Conexión con una cadena de conexión DSN, use la siguiente sintaxis de cadena de conexión DSN, donde:

    • <microsoft-entra-id-token> es el token de Microsoft Entra ID.
    • <server-hostname> es el valor de Nombre de host del servidor de los requisitos.
    • <port-number> es el valor de Puerto de los requisitos, que normalmente es 443.
    • <http-path> es el valor de Ruta de acceso HTTP de los requisitos.

    También puede anexar uno o varios Parámetros opcionales enumerados anteriormente en este artículo.

    token:<microsoft-entra-id-token>@<server-hostname>:<port-number>/<http-path>
    

    Para autenticar el controlador Databricks SQL para Go con la función NewConnector, use el siguiente fragmento de código y el ejemplo de código de Conexión con la función NewConnector, que supone que ha establecido las siguientes variables de entorno:

    • DATABRICKS_SERVER_HOSTNAMEestablecido en el valor de Nombre de host del servidor del clúster o almacén de SQL.
    • DATABRICKS_HTTP_PATH, establecido en el valor de Ruta de acceso HTTP del clúster o almacén del SQL.
    • DATABRICKS_TOKEN, se establece en el token de Microsoft Entra ID.

    Para establecer las variables de entorno, consulte la documentación del sistema operativo.

    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")),
    )
    

Autenticación de usuario a máquina (U2M) de OAuth

El controlador Databricks SQL para Go 1.5.0 y versiones posteriores admiten la autenticación de usuario a máquina (U2M) de OAuth.

Para usar el controlador Databricks SQL para Go con una cadena de conexión DSN y el ejemplo de código en Conexión con una cadena de conexión DSN, use la siguiente sintaxis de cadena de conexión DSN, donde:

  • <server-hostname> es el valor de Nombre de host del servidor de los requisitos.
  • <port-number> es el valor de Puerto de los requisitos, que normalmente es 443.
  • <http-path> es el valor de Ruta de acceso HTTP de los requisitos.

También puede anexar uno o varios Parámetros opcionales enumerados anteriormente en este artículo.

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

Para autenticar el controlador Databricks SQL para Go con la función NewConnector, primero debe agregar lo siguiente a la declaración import:

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

Use el siguiente fragmento de código y el ejemplo de código de Conexión con la función NewConnector, que supone que ha establecido las siguientes variables de entorno:

  • DATABRICKS_SERVER_HOSTNAMEestablecido en el valor de Nombre de host del servidor del clúster o almacén de SQL.
  • DATABRICKS_HTTP_PATH, establecido en el valor de Ruta de acceso HTTP del clúster o almacén del SQL.

Para establecer las variables de entorno, consulte la documentación del sistema operativo.

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),
)

Autenticación de máquina a máquina (M2M) de OAuth

El controlador Databricks SQL para Go, versiones 1.5.2 y posteriores, admite la autenticación de máquina a máquina (M2M) de OAuth.

Para usar el controlador Databricks SQL para Go con la autenticación M2M de OAuth, debe hacer lo siguiente:

  1. Cree una entidad de servicio de Azure Databricks en el área de trabajo de Azure Databricks y cree un secreto de OAuth para esa entidad de servicio.

    Para crear la entidad de servicio y su secreto de OAuth, consulte Autenticación del acceso a Azure Databricks con una entidad de servicio mediante OAuth (OAuth M2M). Anote los valores de UUID o Id. de la aplicación de la entidad de servicio, así como el valor de Secreto del secreto de OAuth de la entidad de servicio.

  2. Proporcione a esa entidad de servicio acceso al clúster o al almacenamiento.

    Para conceder a la entidad de servicio acceso al clúster o al almacenamiento, consulte Permisos de proceso o Administrar un almacén de SQL.

Para autenticar el controlador Databricks SQL para Go con una cadena de conexión DSN y el ejemplo de código en Conexión con una cadena de conexión DSN, use la siguiente sintaxis de cadena de conexión DSN, donde:

  • <server-hostname> es el valor de Nombre de host del servidor de los requisitos.
  • <port-number> es el valor de Puerto de los requisitos, que normalmente es 443.
  • <http-path> es el valor de Ruta de acceso HTTP de los requisitos.
  • <client-id> es el valor del UUID o Id. de aplicación de la entidad de servicio.
  • <client-secret> es el valor de Secreto del secreto de OAuth de la entidad de servicio.

También puede anexar uno o varios Parámetros opcionales enumerados anteriormente en este artículo.

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

Para autenticar el controlador Databricks SQL para Go con la función NewConnector, primero debe agregar lo siguiente a la declaración import:

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

Use el siguiente fragmento de código y el ejemplo de código de Conexión con la función NewConnector, que supone que ha establecido las siguientes variables de entorno:

  • DATABRICKS_SERVER_HOSTNAMEestablecido en el valor de Nombre de host del servidor del clúster o almacén de SQL.
  • DATABRICKS_HTTP_PATH, establecido en el valor de Ruta de acceso HTTP del clúster o almacén del SQL.
  • DATABRICKS_CLIENT_ID, establecido en el valor del UUID o Id. de aplicación de la entidad de servicio.
  • DATABRICKS_CLIENT_SECRET, establecido en el Secreto del secreto de OAuth de la entidad de servicio.

Para establecer las variables de entorno, consulte la documentación del sistema operativo.

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),
)

Consultar datos

En el ejemplo de código siguiente se muestra cómo llamar al controlador de Databricks SQL para Go para ejecutar una consulta SQL básica en un recurso de proceso de Azure Databricks. Este comando devuelve las dos primeras filas de la tabla trips del esquema nyctaxi del catálogo samples.

En este ejemplo de código se recupera la cadena de conexión de DSN de una variable de entorno denominada DATABRICKS_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)
  }
}

Administrar archivos en volúmenes del Unity Catalog

El controlador SQL de Databricks permite escribir archivos locales en los Volúmenes de Unity Catalog, descargar archivos de volúmenes y eliminar archivos de volúmenes, como se muestra en el ejemplo siguiente:

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()
}

Registro

Use github.com/databricks/databricks-sql-go/logger para registrar los mensajes que emite el controlador de Databricks SQL para Go. En el siguiente ejemplo de código se usa sql.Open() para crear un identificador de base de datos a través de una cadena de conexión DSN. En este ejemplo de código se recupera la cadena de conexión de DSN de una variable de entorno denominada DATABRICKS_DSN. Todos los mensajes de registro que se emiten en el nivel debug y por debajo se escriben en el archivo 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)
  }
}

Prueba

Para probar el código, use marcos de pruebas de Go, como la biblioteca estándar de pruebas. Para probar el código en condiciones simuladas sin llamar a puntos de conexión de la API de REST de Azure Databricks ni cambiar el estado de las cuentas o áreas de trabajo de Azure Databricks, use bibliotecas simuladas de Go como testfify.

Por ejemplo, dado el siguiente archivo denominado helpers.go que contiene una función GetDBWithDSNPAT que devuelve una conexión de área de trabajo de Azure Databricks, una función GetNYCTaxiTrips que devuelve datos de la tabla trips del esquema nyctaxi del catálogo de samples y un PrintNYCTaxiTrips que imprime los datos devueltos:

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)
  }
}

Y dado el siguiente archivo denominado main.go que llama a estas funciones:

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)
}

El siguiente archivo denominado helpers_test.go comprueba si la función GetNYCTaxiTrips devuelve la respuesta esperada. En lugar de crear una conexión real al área de trabajo de destino, esta prueba simula un objeto sql.DB. La prueba también simula algunos datos que se ajustan al esquema y los valores que se encuentran en los datos reales. La prueba devuelve los datos ficticios a través de la conexión simulada y, a continuación, comprueba si uno de los valores de filas de datos simulados coincide con el valor esperado.

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)
}

Dado que la función GetNYCTaxiTrips contiene una instrucción SELECT y por tanto, no cambia el estado de la tabla trips, la simulación no es absolutamente necesaria en este ejemplo. Sin embargo, la simulación le permite ejecutar rápidamente las pruebas sin esperar a que se realice una conexión real con el área de trabajo. Además, la simulación permite ejecutar pruebas simuladas varias veces para las funciones que podrían cambiar el estado de una tabla, como INSERT INTO, UPDATE, y DELETE FROM.

Recursos adicionales