Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions driver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Package airtablesql implements a Go SQL driver for Airtable
// Import package github.com/sclgo/airtable-sql/register to register
// a driver with default configuration automatically or use CreateDriver from this
// package and register it explicitly with sql.Register.
package airtablesql // import github.com/sclgo/airtable-sql

import (
"net/url"

drivere "github.com/dolthub/go-mysql-server/driver"
"github.com/dolthub/go-mysql-server/sql"
"github.com/mehanizm/airtable"
"github.com/sclgo/airtable-sql/internal/errhelp"
"github.com/sclgo/airtable-sql/provider"

"database/sql/driver"
)

func CreateDriver() interface {
driver.Driver
driver.DriverContext
} {
return drivere.New(factory{}, nil)
}

type factory struct{}

// Resolve implements driver.Provider
func (factory) Resolve(dsn string, _ *drivere.Options) (string, sql.DatabaseProvider, error) {
dsnUri, err := url.Parse(dsn)
if err != nil {
return "", nil, errhelp.Errorf("could not parse DSN %s: %w", dsn, err)
}
key := dsnUri.Query().Get("key")
if key == "" {
return "", nil, errhelp.Errorf("could not find key in DSN %s", dsn)
}
return dsn, provider.New(airtable.NewClient(key)), nil
}
26 changes: 26 additions & 0 deletions driver_integ_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package airtablesql_test

import (
"database/sql"
"os"
"testing"

airtablesql "github.com/sclgo/airtable-sql"
"github.com/stretchr/testify/require"
)

func TestCreateDriver(t *testing.T) {
t.Run("happy", func(t *testing.T) {
if os.Getenv("AIRTABLE_API_KEY") == "" {
t.Skip("skipping integration test; AIRTABLE_API_KEY not set")
}
drv := airtablesql.CreateDriver()
cnct, err := drv.OpenConnector("airtable:?key=" + os.Getenv("AIRTABLE_API_KEY"))
require.NoError(t, err)
db := sql.OpenDB(cnct)
row := db.QueryRow("SELECT `Part Name` FROM `Order Assembly`.Parts")
var part string
require.NoError(t, row.Scan(&part))
require.Equal(t, "Power Supply Unit", part)
})
}
7 changes: 4 additions & 3 deletions provider/airdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (
"github.com/mehanizm/airtable"
)

var _ sql.Database = (*AirDB)(nil)
var _ sql.Table = (*AirSqlTable)(nil)
var (
_ sql.Database = (*AirDB)(nil)
)

type AirDB struct {
client *airtable.Client
Expand All @@ -31,7 +32,7 @@ func (a *AirDB) GetTableInsensitive(ctx *sql.Context, tblName string) (sql.Table
for _, tbl := range tbls.Tables {
if strings.EqualFold(tblName, tbl.Name) {
return AirSqlTable{
tableClient: a.client.GetTable(a.dbId, tbl.Name),
tableClient: a.client.GetTable(a.dbId, tbl.Name),
airSchema: tbl,
schema: toSqlSchema(tbl),
}, true, nil
Expand Down
11 changes: 6 additions & 5 deletions provider/airsqltable.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ import (
"github.com/mehanizm/airtable"
)

var (
_ sql.RowIter = (*basicRowIter)(nil)
_ sql.Disposable = (*basicRowIter)(nil)
_ sql.Table = (*AirSqlTable)(nil)
)

type AirSqlTable struct {
tableClient *airtable.Table
airSchema *airtable.TableSchema
Expand Down Expand Up @@ -100,8 +106,3 @@ func (b *basicRowIter) Close(*sql.Context) error {
b.recs = nil
return nil
}

var (
_ sql.RowIter = (*basicRowIter)(nil)
_ sql.Disposable = (*basicRowIter)(nil)
)
11 changes: 11 additions & 0 deletions register/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package register

import (
"database/sql"

airtablesql "github.com/sclgo/airtable-sql"
)

func init() {
sql.Register("airtable", airtablesql.CreateDriver())
}