-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(go/adbc/driver): add driver framework (#1081)
Fixes #996.
- Loading branch information
Showing
22 changed files
with
1,563 additions
and
1,224 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
// 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 driverbase | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/apache/arrow-adbc/go/adbc" | ||
"github.com/apache/arrow/go/v13/arrow/memory" | ||
"golang.org/x/exp/slog" | ||
) | ||
|
||
// DatabaseImpl is an interface that drivers implement to provide | ||
// vendor-specific functionality. | ||
type DatabaseImpl interface { | ||
adbc.GetSetOptions | ||
Base() *DatabaseImplBase | ||
Open(context.Context) (adbc.Connection, error) | ||
SetOptions(map[string]string) error | ||
} | ||
|
||
// DatabaseImplBase is a struct that provides default implementations of the | ||
// DatabaseImpl interface. It is meant to be used as a composite struct for a | ||
// driver's DatabaseImpl implementation. | ||
type DatabaseImplBase struct { | ||
Alloc memory.Allocator | ||
ErrorHelper ErrorHelper | ||
Logger *slog.Logger | ||
} | ||
|
||
// NewDatabaseImplBase instantiates DatabaseImplBase. name is the driver's | ||
// name and is used to construct error messages. alloc is an Arrow allocator | ||
// to use. | ||
func NewDatabaseImplBase(driver *DriverImplBase) DatabaseImplBase { | ||
return DatabaseImplBase{Alloc: driver.Alloc, ErrorHelper: driver.ErrorHelper, Logger: nilLogger()} | ||
} | ||
|
||
func (base *DatabaseImplBase) Base() *DatabaseImplBase { | ||
return base | ||
} | ||
|
||
func (base *DatabaseImplBase) GetOption(key string) (string, error) { | ||
return "", base.ErrorHelper.Errorf(adbc.StatusNotFound, "Unknown database option '%s'", key) | ||
} | ||
|
||
func (base *DatabaseImplBase) GetOptionBytes(key string) ([]byte, error) { | ||
return nil, base.ErrorHelper.Errorf(adbc.StatusNotFound, "Unknown database option '%s'", key) | ||
} | ||
|
||
func (base *DatabaseImplBase) GetOptionDouble(key string) (float64, error) { | ||
return 0, base.ErrorHelper.Errorf(adbc.StatusNotFound, "Unknown database option '%s'", key) | ||
} | ||
|
||
func (base *DatabaseImplBase) GetOptionInt(key string) (int64, error) { | ||
return 0, base.ErrorHelper.Errorf(adbc.StatusNotFound, "Unknown database option '%s'", key) | ||
} | ||
|
||
func (base *DatabaseImplBase) SetOption(key string, val string) error { | ||
return base.ErrorHelper.Errorf(adbc.StatusNotImplemented, "Unknown database option '%s'", key) | ||
} | ||
|
||
func (base *DatabaseImplBase) SetOptionBytes(key string, val []byte) error { | ||
return base.ErrorHelper.Errorf(adbc.StatusNotImplemented, "Unknown database option '%s'", key) | ||
} | ||
|
||
func (base *DatabaseImplBase) SetOptionDouble(key string, val float64) error { | ||
return base.ErrorHelper.Errorf(adbc.StatusNotImplemented, "Unknown database option '%s'", key) | ||
} | ||
|
||
func (base *DatabaseImplBase) SetOptionInt(key string, val int64) error { | ||
return base.ErrorHelper.Errorf(adbc.StatusNotImplemented, "Unknown database option '%s'", key) | ||
} | ||
|
||
// database is the implementation of adbc.Database. | ||
type database struct { | ||
impl DatabaseImpl | ||
} | ||
|
||
// NewDatabase wraps a DatabaseImpl to create an adbc.Database. | ||
func NewDatabase(impl DatabaseImpl) adbc.Database { | ||
return &database{ | ||
impl: impl, | ||
} | ||
} | ||
|
||
func (db *database) GetOption(key string) (string, error) { | ||
return db.impl.GetOption(key) | ||
} | ||
|
||
func (db *database) GetOptionBytes(key string) ([]byte, error) { | ||
return db.impl.GetOptionBytes(key) | ||
} | ||
|
||
func (db *database) GetOptionDouble(key string) (float64, error) { | ||
return db.impl.GetOptionDouble(key) | ||
} | ||
|
||
func (db *database) GetOptionInt(key string) (int64, error) { | ||
return db.impl.GetOptionInt(key) | ||
} | ||
|
||
func (db *database) SetOption(key string, val string) error { | ||
return db.impl.SetOption(key, val) | ||
} | ||
|
||
func (db *database) SetOptionBytes(key string, val []byte) error { | ||
return db.impl.SetOptionBytes(key, val) | ||
} | ||
|
||
func (db *database) SetOptionDouble(key string, val float64) error { | ||
return db.impl.SetOptionDouble(key, val) | ||
} | ||
|
||
func (db *database) SetOptionInt(key string, val int64) error { | ||
return db.impl.SetOptionInt(key, val) | ||
} | ||
|
||
func (db *database) Open(ctx context.Context) (adbc.Connection, error) { | ||
return db.impl.Open(ctx) | ||
} | ||
|
||
func (db *database) SetLogger(logger *slog.Logger) { | ||
if logger != nil { | ||
db.impl.Base().Logger = logger | ||
} else { | ||
db.impl.Base().Logger = nilLogger() | ||
} | ||
} | ||
|
||
func (db *database) SetOptions(opts map[string]string) error { | ||
return db.impl.SetOptions(opts) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// 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 driverbase provides a framework for implementing ADBC drivers in | ||
// Go. It intends to reduce boilerplate for common functionality and managing | ||
// state transitions. | ||
package driverbase | ||
|
||
import ( | ||
"github.com/apache/arrow-adbc/go/adbc" | ||
"github.com/apache/arrow/go/v13/arrow/memory" | ||
) | ||
|
||
// DriverImpl is an interface that drivers implement to provide | ||
// vendor-specific functionality. | ||
type DriverImpl interface { | ||
Base() *DriverImplBase | ||
NewDatabase(opts map[string]string) (adbc.Database, error) | ||
} | ||
|
||
// DatabaseImplBase is a struct that provides default implementations of the | ||
// DriverImpl interface. It is meant to be used as a composite struct for a | ||
// driver's DriverImpl implementation. | ||
type DriverImplBase struct { | ||
Alloc memory.Allocator | ||
ErrorHelper ErrorHelper | ||
} | ||
|
||
func NewDriverImplBase(name string, alloc memory.Allocator) DriverImplBase { | ||
if alloc == nil { | ||
alloc = memory.DefaultAllocator | ||
} | ||
return DriverImplBase{Alloc: alloc, ErrorHelper: ErrorHelper{DriverName: name}} | ||
} | ||
|
||
func (base *DriverImplBase) Base() *DriverImplBase { | ||
return base | ||
} | ||
|
||
// driver is the actual implementation of adbc.Driver. | ||
type driver struct { | ||
impl DriverImpl | ||
} | ||
|
||
// NewDatabase wraps a DriverImpl to create an adbc.Driver. | ||
func NewDriver(impl DriverImpl) adbc.Driver { | ||
return &driver{impl} | ||
} | ||
|
||
func (drv *driver) NewDatabase(opts map[string]string) (adbc.Database, error) { | ||
return drv.impl.NewDatabase(opts) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// 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 driverbase | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/apache/arrow-adbc/go/adbc" | ||
) | ||
|
||
// ErrorHelper helps format errors for ADBC drivers. | ||
type ErrorHelper struct { | ||
DriverName string | ||
} | ||
|
||
func (helper *ErrorHelper) Errorf(code adbc.Status, message string, format ...interface{}) error { | ||
msg := fmt.Sprintf(message, format...) | ||
return adbc.Error{ | ||
Code: code, | ||
Msg: fmt.Sprintf("[%s] %s", helper.DriverName, msg), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// 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 driverbase | ||
|
||
import ( | ||
"os" | ||
|
||
"golang.org/x/exp/slog" | ||
) | ||
|
||
func nilLogger() *slog.Logger { | ||
h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{ | ||
AddSource: false, | ||
Level: slog.LevelError, | ||
}) | ||
return slog.New(h) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.