This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new e023d77  feat(go/adbc/sqldriver): add simple FlightSQL database/sql 
driver wrapper (#480)
e023d77 is described below

commit e023d7782783c079a22dca66d90e600ca079b81c
Author: Jacob Marble <[email protected]>
AuthorDate: Thu Mar 2 07:27:44 2023 -0800

    feat(go/adbc/sqldriver): add simple FlightSQL database/sql driver wrapper 
(#480)
    
    Helps https://github.com/apache/arrow/issues/34332
    
    Golang/FlightSQL docs should be updated to point here for the canonical
    `database/sql` wrapper.
    
    ---------
    
    Co-authored-by: Matt Topol <[email protected]>
---
 go/adbc/sqldriver/doc.go                      |  36 ++++++++
 go/adbc/sqldriver/driver.go                   |  19 ++--
 go/adbc/sqldriver/flightsql/README.md         |  61 +++++++++++++
 go/adbc/sqldriver/flightsql/flightsql.go      |  30 +++++++
 go/adbc/sqldriver/flightsql/flightsql_test.go | 125 ++++++++++++++++++++++++++
 5 files changed, 257 insertions(+), 14 deletions(-)

diff --git a/go/adbc/sqldriver/doc.go b/go/adbc/sqldriver/doc.go
new file mode 100644
index 0000000..edddb33
--- /dev/null
+++ b/go/adbc/sqldriver/doc.go
@@ -0,0 +1,36 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// Package sqldriver is a wrapper around the ADBC (Arrow Database
+// Connectivity) interfaces to support the standard golang database/sql
+// package, described here: https://go.dev/src/database/sql/doc.txt
+//
+// This allows any ADBC driver implementation to also be used as-is
+// with the database/sql package of the standard library rather than
+// having to implement drivers for both separately.
+//
+// Registering the driver can be done by importing this and then running
+//
+//     sql.Register("drivername", sqldriver.Driver{adbcdriver})
+//
+// Additionally, the sqldriver/flightsql package simplifies registration
+// of the FlightSQL ADBC driver implementation, so that only a single
+// import statement is needed. See the example in that package.
+//
+// EXPERIMENTAL. The ADBC interfaces are subject to change and as such
+// this wrapper is also subject to change based on that.
+package sqldriver
diff --git a/go/adbc/sqldriver/driver.go b/go/adbc/sqldriver/driver.go
index e838db7..6cf65f4 100644
--- a/go/adbc/sqldriver/driver.go
+++ b/go/adbc/sqldriver/driver.go
@@ -15,20 +15,6 @@
 // specific language governing permissions and limitations
 // under the License.
 
-// Package sqldriver is a wrapper around the ADBC (Arrow Database
-// Connectivity) interfaces to support the standard golang database/sql
-// package.
-//
-// This allows any ADBC driver implementation to also be used as-is
-// with the database/sql package of the standard library rather than
-// having to implement drivers for both separately.
-//
-// Registering the driver can be done by importing this and then running
-//
-//             sql.Register("drivername", sqldriver.Driver{adbcdriver})
-//
-// EXPERIMENTAL. The ADBC interfaces are subject to change and as such
-// this wrapper is also subject to change based on that.
 package sqldriver
 
 import (
@@ -267,6 +253,11 @@ func (c *conn) PrepareContext(ctx context.Context, query 
string) (driver.Stmt, e
                return nil, err
        }
 
+       if err := s.Prepare(ctx); err != nil {
+               s.Close()
+               return nil, err
+       }
+
        paramSchema, err := s.GetParameterSchema()
        var adbcErr adbc.Error
        if errors.As(err, &adbcErr) {
diff --git a/go/adbc/sqldriver/flightsql/README.md 
b/go/adbc/sqldriver/flightsql/README.md
new file mode 100644
index 0000000..a9d3579
--- /dev/null
+++ b/go/adbc/sqldriver/flightsql/README.md
@@ -0,0 +1,61 @@
+<!---
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+# flightsql - A FlightSQL driver for the database/sql package
+
+[![Go 
Reference](https://pkg.go.dev/badge/github.com/apache/arrow-adbc/go/adbc/sqldriver/flightsql.svg)](https://pkg.go.dev/github.com/apache/arrow-adbc/go/adbc/sqldriver/flightsql)
+
+Golang database/sql driver for 
[FlightSQL](https://arrow.apache.org/docs/format/FlightSql.html).
+
+> Arrow Flight SQL is a protocol for interacting with SQL databases using
+> the Arrow in-memory format and the Flight RPC framework.
+
+## Technical Details
+
+This package is a thin wrapper over the
+[ADBC database/sql driver 
wrapper](https://pkg.go.dev/github.com/apache/arrow-adbc/go/adbc/sqldriver),
+which is itself database/sql wrapper driver for any
+[ADBC](https://arrow.apache.org/docs/format/ADBC.html) driver.
+
+This package simply registers the
+[FlightSQL ADBC 
driver](https://pkg.go.dev/github.com/apache/arrow-adbc/go/adbc/driver/flightsql)
+with the database/sql package.
+Understanding ADBC is not necessary to use this driver.
+
+## Example
+
+```golang
+package main
+
+import (
+       "database/sql"
+       _ "github.com/apache/arrow-adbc/go/adbc/sqldriver/flightsql"
+)
+
+func main() {
+       db, err := sql.Open("flightsql", "uri=grpc://localhost:12345")
+       if err != nil {
+               panic(err)
+       }
+
+       if err = db.Ping(); err != nil {
+               panic(err)
+       }
+}
+```
diff --git a/go/adbc/sqldriver/flightsql/flightsql.go 
b/go/adbc/sqldriver/flightsql/flightsql.go
new file mode 100644
index 0000000..f318cbb
--- /dev/null
+++ b/go/adbc/sqldriver/flightsql/flightsql.go
@@ -0,0 +1,30 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package flightsql
+
+import (
+       "database/sql"
+       "github.com/apache/arrow-adbc/go/adbc/driver/flightsql"
+       "github.com/apache/arrow-adbc/go/adbc/sqldriver"
+)
+
+func init() {
+       sql.Register("flightsql", sqldriver.Driver{
+               Driver: flightsql.Driver{},
+       })
+}
diff --git a/go/adbc/sqldriver/flightsql/flightsql_test.go 
b/go/adbc/sqldriver/flightsql/flightsql_test.go
new file mode 100644
index 0000000..86fdee3
--- /dev/null
+++ b/go/adbc/sqldriver/flightsql/flightsql_test.go
@@ -0,0 +1,125 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package flightsql_test
+
+import (
+       "database/sql"
+       "os"
+       "testing"
+
+       _ "github.com/apache/arrow-adbc/go/adbc/sqldriver/flightsql"
+       "github.com/apache/arrow/go/v12/arrow/flight"
+       "github.com/apache/arrow/go/v12/arrow/flight/flightsql"
+       "github.com/apache/arrow/go/v12/arrow/flight/flightsql/example"
+       "github.com/apache/arrow/go/v12/arrow/memory"
+       "github.com/stretchr/testify/suite"
+       "google.golang.org/grpc"
+)
+
+func Example() {
+       // Be sure to import the driver first:
+       // import _ "github.com/apache/arrow-adbc/go/adbc/sqldriver/flightsql"
+
+       db, err := sql.Open("flightsql", "uri=grpc://localhost:12345")
+       if err != nil {
+               panic(err)
+       }
+
+       if err = db.Ping(); err != nil {
+               panic(err)
+       }
+}
+
+type SQLDriverFlightSQLSuite struct {
+       suite.Suite
+
+       srv      *example.SQLiteFlightSQLServer
+       s        flight.Server
+       opts     []grpc.ServerOption
+       sqliteDB *sql.DB
+
+       done chan bool
+       mem  *memory.CheckedAllocator
+}
+
+func (suite *SQLDriverFlightSQLSuite) SetupTest() {
+       var err error
+
+       suite.sqliteDB, err = example.CreateDB()
+       suite.Require().NoError(err)
+
+       suite.mem = memory.NewCheckedAllocator(memory.DefaultAllocator)
+       suite.s = flight.NewServerWithMiddleware(nil, suite.opts...)
+       suite.Require().NoError(err)
+       suite.srv, err = example.NewSQLiteFlightSQLServer(suite.sqliteDB)
+       suite.Require().NoError(err)
+       suite.srv.Alloc = suite.mem
+
+       suite.s.RegisterFlightService(flightsql.NewFlightServer(suite.srv))
+       suite.Require().NoError(suite.s.Init("localhost:0"))
+       suite.s.SetShutdownOnSignals(os.Interrupt, os.Kill)
+       suite.done = make(chan bool)
+       go func() {
+               defer close(suite.done)
+               _ = suite.s.Serve()
+       }()
+}
+
+func (suite *SQLDriverFlightSQLSuite) TearDownTest() {
+       if suite.done == nil {
+               return
+       }
+
+       suite.s.Shutdown()
+       <-suite.done
+       suite.srv = nil
+       suite.mem.AssertSize(suite.T(), 0)
+       _ = suite.sqliteDB.Close()
+       suite.done = nil
+}
+
+func (suite *SQLDriverFlightSQLSuite) dsn() string {
+       return "uri=grpc+tcp://" + suite.s.Addr().String()
+}
+
+func (suite *SQLDriverFlightSQLSuite) TestQuery() {
+       db, err := sql.Open("flightsql", suite.dsn())
+       suite.Require().NoError(err)
+       defer db.Close()
+
+       _, err = db.Exec("CREATE TABLE t (k, v)")
+       suite.Require().NoError(err)
+       result, err := db.Exec("INSERT INTO t (k, v) VALUES ('one', 'alpha'), 
('two', 'bravo')")
+       suite.Require().NoError(err)
+
+       n, err := result.RowsAffected()
+       suite.Require().NoError(err)
+       suite.EqualValues(2, n)
+
+       var expected int = 2
+       var actual int
+       row := db.QueryRow("SELECT count(*) FROM t")
+       err = row.Scan(&actual)
+       if suite.NoError(err) {
+               suite.Equal(expected, actual)
+       }
+}
+
+func TestSQLDriverFlightSQL(t *testing.T) {
+       suite.Run(t, new(SQLDriverFlightSQLSuite))
+}

Reply via email to