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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ func main() {
}
```

You can attach a reservation to the DSN via a query parameter:

```
bigquery://projectid/dataset?reservation=projects/<project>/locations/<location>/reservations/<reservation>
```

When a reservation is set, the driver prefixes each query with a `SET @@reservation` statement and uses multi-statement scripting.

## Gorm Usage

Opening a Gorm bigquery db
Expand Down
9 changes: 9 additions & 0 deletions driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type bigQueryConfig struct {
disableAuth bool
credentialFile string
credentialJSON []byte
reservation string
}

func (b bigQueryDriver) Open(uri string) (driver.Conn, error) {
Expand Down Expand Up @@ -90,6 +91,7 @@ func configFromUri(uri string) (*bigQueryConfig, error) {
endpoint: u.Query().Get("endpoint"),
disableAuth: u.Query().Get("disable_auth") == "true",
credentialFile: u.Query().Get("credential_file"),
reservation: getReservation(u.Query()),
}

if u.Query().Get("credential_json") != "" {
Expand All @@ -116,6 +118,13 @@ func getScopes(query url.Values) []string {
return strings.Split(q, ",")
}

func getReservation(query url.Values) string {
if reservation := query.Get("reservation"); reservation != "" {
return reservation
}
return query.Get("reservation_id")
}

func invalidConnectionStringError(uri string) error {
return fmt.Errorf("invalid connection string: %s", uri)
}
19 changes: 18 additions & 1 deletion driver/statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import (
"context"
"database/sql/driver"
"errors"
"fmt"
"strings"

"github.com/sirupsen/logrus"
"gorm.io/driver/bigquery/adaptor"
)
Expand Down Expand Up @@ -144,7 +147,8 @@ func (statement bigQueryStatement) Query(args []driver.Value) (driver.Rows, erro

func (statement bigQueryStatement) buildQuery(args []driver.Value) (*bigquery.Query, error) {

query, err := statement.connection.query(statement.query)
queryText := applyReservation(statement.query, statement.connection.config.reservation)
query, err := statement.connection.query(queryText)
if err != nil {
return nil, err
}
Expand All @@ -157,6 +161,19 @@ func (statement bigQueryStatement) buildQuery(args []driver.Value) (*bigquery.Qu
return query, err
}

func applyReservation(query, reservation string) string {
if reservation == "" {
return query
}
trimmed := strings.TrimSpace(query)
upper := strings.ToUpper(trimmed)
if strings.HasPrefix(upper, "SET @@RESERVATION=") || strings.HasPrefix(upper, "SET @@RESERVATION ") {
return query
}
escaped := strings.ReplaceAll(reservation, "'", "''")
return fmt.Sprintf("SET @@reservation='%s';\n%s", escaped, query)
}

func (statement bigQueryStatement) buildParameters(args []driver.Value) ([]bigquery.QueryParameter, error) {
if args == nil {
return nil, nil
Expand Down
7 changes: 6 additions & 1 deletion test/common_text.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"gorm.io/driver/bigquery"
"gorm.io/gorm"
"log"
"os"
)

type GormTestSuite struct {
Expand All @@ -18,7 +19,11 @@ func (suite *GormTestSuite) SetupSuite() {
logrus.SetLevel(logrus.DebugLevel)

var err error
suite.db, err = gorm.Open(bigquery.Open("bigquery://go-bigquery-driver/playground"), &gorm.Config{})
dsn := os.Getenv("BIGQUERY_TEST_DSN")
if dsn == "" {
dsn = "bigquery://go-bigquery-driver/playground"
}
suite.db, err = gorm.Open(bigquery.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
Expand Down