sqlx is a library which provides a set of extensions on go's standard database/sql library

Related tags

Database tools sqlx
Overview

sqlx

Build Status Coverage Status Godoc license

sqlx is a library which provides a set of extensions on go's standard database/sql library. The sqlx versions of sql.DB, sql.TX, sql.Stmt, et al. all leave the underlying interfaces untouched, so that their interfaces are a superset on the standard ones. This makes it relatively painless to integrate existing codebases using database/sql with sqlx.

Major additional concepts are:

  • Marshal rows into structs (with embedded struct support), maps, and slices
  • Named parameter support including prepared statements
  • Get and Select to go quickly from query to struct/slice

In addition to the godoc API documentation, there is also some user documentation that explains how to use database/sql along with sqlx.

Recent Changes

1.3.0:

  • sqlx.DB.Connx(context.Context) *sqlx.Conn
  • sqlx.BindDriver(driverName, bindType)
  • support for []map[string]interface{} to do "batch" insertions
  • allocation & perf improvements for sqlx.In

DB.Connx returns an sqlx.Conn, which is an sql.Conn-alike consistent with sqlx's wrapping of other types.

BindDriver allows users to control the bindvars that sqlx will use for drivers, and add new drivers at runtime. This results in a very slight performance hit when resolving the driver into a bind type (~40ns per call), but it allows users to specify what bindtype their driver uses even when sqlx has not been updated to know about it by default.

Backwards Compatibility

Compatibility with the most recent two versions of Go is a requirement for any new changes. Compatibility beyond that is not guaranteed.

Versioning is done with Go modules. Breaking changes (eg. removing deprecated API) will get major version number bumps.

install

go get github.com/jmoiron/sqlx

issues

Row headers can be ambiguous (SELECT 1 AS a, 2 AS a), and the result of Columns() does not fully qualify column names in queries like:

SELECT a.id, a.name, b.id, b.name FROM foos AS a JOIN foos AS b ON a.parent = b.id;

making a struct or map destination ambiguous. Use AS in your queries to give columns distinct names, rows.Scan to scan them manually, or SliceScan to get a slice of results.

usage

Below is an example which shows some common use cases for sqlx. Check sqlx_test.go for more usage.

package main

import (
    "database/sql"
    "fmt"
    "log"
    
    _ "github.com/lib/pq"
    "github.com/jmoiron/sqlx"
)

var schema = `
CREATE TABLE person (
    first_name text,
    last_name text,
    email text
);

CREATE TABLE place (
    country text,
    city text NULL,
    telcode integer
)`

type Person struct {
    FirstName string `db:"first_name"`
    LastName  string `db:"last_name"`
    Email     string
}

type Place struct {
    Country string
    City    sql.NullString
    TelCode int
}

func main() {
    // this Pings the database trying to connect
    // use sqlx.Open() for sql.Open() semantics
    db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
    if err != nil {
        log.Fatalln(err)
    }

    // exec the schema or fail; multi-statement Exec behavior varies between
    // database drivers;  pq will exec them all, sqlite3 won't, ymmv
    db.MustExec(schema)
    
    tx := db.MustBegin()
    tx.MustExec("INSERT INTO person (first_name, last_name, email) VALUES ($1, $2, $3)", "Jason", "Moiron", "[email protected]")
    tx.MustExec("INSERT INTO person (first_name, last_name, email) VALUES ($1, $2, $3)", "John", "Doe", "[email protected]")
    tx.MustExec("INSERT INTO place (country, city, telcode) VALUES ($1, $2, $3)", "United States", "New York", "1")
    tx.MustExec("INSERT INTO place (country, telcode) VALUES ($1, $2)", "Hong Kong", "852")
    tx.MustExec("INSERT INTO place (country, telcode) VALUES ($1, $2)", "Singapore", "65")
    // Named queries can use structs, so if you have an existing struct (i.e. person := &Person{}) that you have populated, you can pass it in as &person
    tx.NamedExec("INSERT INTO person (first_name, last_name, email) VALUES (:first_name, :last_name, :email)", &Person{"Jane", "Citizen", "[email protected]"})
    tx.Commit()

    // Query the database, storing results in a []Person (wrapped in []interface{})
    people := []Person{}
    db.Select(&people, "SELECT * FROM person ORDER BY first_name ASC")
    jason, john := people[0], people[1]

    fmt.Printf("%#v\n%#v", jason, john)
    // Person{FirstName:"Jason", LastName:"Moiron", Email:"[email protected]"}
    // Person{FirstName:"John", LastName:"Doe", Email:"[email protected]"}

    // You can also get a single result, a la QueryRow
    jason = Person{}
    err = db.Get(&jason, "SELECT * FROM person WHERE first_name=$1", "Jason")
    fmt.Printf("%#v\n", jason)
    // Person{FirstName:"Jason", LastName:"Moiron", Email:"[email protected]"}

    // if you have null fields and use SELECT *, you must use sql.Null* in your struct
    places := []Place{}
    err = db.Select(&places, "SELECT * FROM place ORDER BY telcode ASC")
    if err != nil {
        fmt.Println(err)
        return
    }
    usa, singsing, honkers := places[0], places[1], places[2]
    
    fmt.Printf("%#v\n%#v\n%#v\n", usa, singsing, honkers)
    // Place{Country:"United States", City:sql.NullString{String:"New York", Valid:true}, TelCode:1}
    // Place{Country:"Singapore", City:sql.NullString{String:"", Valid:false}, TelCode:65}
    // Place{Country:"Hong Kong", City:sql.NullString{String:"", Valid:false}, TelCode:852}

    // Loop through rows using only one struct
    place := Place{}
    rows, err := db.Queryx("SELECT * FROM place")
    for rows.Next() {
        err := rows.StructScan(&place)
        if err != nil {
            log.Fatalln(err)
        } 
        fmt.Printf("%#v\n", place)
    }
    // Place{Country:"United States", City:sql.NullString{String:"New York", Valid:true}, TelCode:1}
    // Place{Country:"Hong Kong", City:sql.NullString{String:"", Valid:false}, TelCode:852}
    // Place{Country:"Singapore", City:sql.NullString{String:"", Valid:false}, TelCode:65}

    // Named queries, using `:name` as the bindvar.  Automatic bindvar support
    // which takes into account the dbtype based on the driverName on sqlx.Open/Connect
    _, err = db.NamedExec(`INSERT INTO person (first_name,last_name,email) VALUES (:first,:last,:email)`, 
        map[string]interface{}{
            "first": "Bin",
            "last": "Smuth",
            "email": "[email protected]",
    })

    // Selects Mr. Smith from the database
    rows, err = db.NamedQuery(`SELECT * FROM person WHERE first_name=:fn`, map[string]interface{}{"fn": "Bin"})

    // Named queries can also use structs.  Their bind names follow the same rules
    // as the name -> db mapping, so struct fields are lowercased and the `db` tag
    // is taken into consideration.
    rows, err = db.NamedQuery(`SELECT * FROM person WHERE first_name=:first_name`, jason)
    
    
    // batch insert
    
    // batch insert with structs
    personStructs := []Person{
        {FirstName: "Ardie", LastName: "Savea", Email: "[email protected]"},
        {FirstName: "Sonny Bill", LastName: "Williams", Email: "[email protected]"},
        {FirstName: "Ngani", LastName: "Laumape", Email: "[email protected]"},
    }

    _, err = db.NamedExec(`INSERT INTO person (first_name, last_name, email)
        VALUES (:first_name, :last_name, :email)`, personStructs)

    // batch insert with maps
    personMaps := []map[string]interface{}{
        {"first_name": "Ardie", "last_name": "Savea", "email": "[email protected]"},
        {"first_name": "Sonny Bill", "last_name": "Williams", "email": "[email protected]"},
        {"first_name": "Ngani", "last_name": "Laumape", "email": "[email protected]"},
    }

    _, err = db.NamedExec(`INSERT INTO person (first_name, last_name, email)
        VALUES (:first_name, :last_name, :email)`, personMaps)
}
Comments
  • Close #238, support batch insert.

    Close #238, support batch insert.

    usage: places := []*Place{&place1, &place2} db.NamedExec("INSERT INTO place (country, telcode) VALUES (:country, :telcode)", places)

    opened by hmgle 52
  • StructScan infinite loop

    StructScan infinite loop

    I had a case earlier which made me pull my hair for a full day and half :

    Let's say we have the following structs :

    type Entity struct {
        ID int64 `db:"id"`
        Service *Service
    }
    
    type Service struct {
        Entity *Entity
    }
    
    func NewEntity(id int64) *Entity {
        e := &Entity{}
        e.Service = &Service{}
        e.Service.Entity = e
        return e
    }
    

    When StructScaning, the function tries to establish a field map by exploring the tree of embedded types of the struct. I my case, the exploration never end because of the pointers.

    This issue bring the following question to my mind : what is the point of exploring non-embedded fields ? It seem rather non-semantic to me… And independantly, why making a field map and not simply look for the fields as needed when scanning ?

    opened by elwinar 20
  • 1.8 Not Supported

    1.8 Not Supported

    Currently working on a project that uses vendoring. I updated all the references to the latest on master (even tried tagged versions) but it seems that I cannot build with this package in Go 1.8.1. When downgrading to 1.7.4_2 it works great. If I may advise to use sql/driver package as that was included in 1.8. There were some changes that they said were minor but maybe not but recommend driver packages to look at the above link Go1.8 Minor Changes.

    vendor/github.com/jmoiron/sqlx/sqlx_context.go:20: db.PingContext undefined (type *DB has no field or method PingContext)
    vendor/github.com/jmoiron/sqlx/sqlx_context.go:122: cannot use db (type *DB) as type namedPreparerContext in argument to prepareNamedContext:
    	*DB does not implement namedPreparerContext (missing PrepareContext method)
    vendor/github.com/jmoiron/sqlx/sqlx_context.go:128: cannot use db (type *DB) as type ExtContext in argument to NamedQueryContext:
    	*DB does not implement ExtContext (missing ExecContext method)
    vendor/github.com/jmoiron/sqlx/sqlx_context.go:134: cannot use db (type *DB) as type ExtContext in argument to NamedExecContext:
    	*DB does not implement ExtContext (missing ExecContext method)
    vendor/github.com/jmoiron/sqlx/sqlx_context.go:140: cannot use db (type *DB) as type QueryerContext in argument to SelectContext:
    	*DB does not implement QueryerContext (missing QueryContext method)
    vendor/github.com/jmoiron/sqlx/sqlx_context.go:147: cannot use db (type *DB) as type QueryerContext in argument to GetContext:
    	*DB does not implement QueryerContext (missing QueryContext method)
    vendor/github.com/jmoiron/sqlx/sqlx_context.go:155: cannot use db (type *DB) as type PreparerContext in argument to PreparexContext:
    	*DB does not implement PreparerContext (missing PrepareContext method)
    vendor/github.com/jmoiron/sqlx/sqlx_context.go:161: db.DB.QueryContext undefined (type *sql.DB has no field or method QueryContext)
    vendor/github.com/jmoiron/sqlx/sqlx_context.go:182: undefined: sql.TxOptions
    vendor/github.com/jmoiron/sqlx/sqlx_context.go:203: undefined: sql.TxOptions
    vendor/github.com/jmoiron/sqlx/sqlx_context.go:161: too many errors
    
    opened by dixonwille 15
  • Problem with a simple select/get

    Problem with a simple select/get

    Hi,

    Im using sqlx now, but i have problems on my first select/get.

    type Device struct {
        Id int64 `db:"id"`
    }
    
    var device = Device{}
    err := sqlx.Get(&device, "SELECT id FROM device WHERE imei = :imei LIMIT 1", imei)
    

    What is wrong with it?

    opened by paulocoutinhox 13
  • sqlx.Connect(

    sqlx.Connect("postgres", addr) freezes

    I'm building a docker image with a simple sqlx connection and running it in docker-compose. For some reason, the statement see snippet below does not connect or error out, it just freezes. No idea why. It is related to using alpine:latest docker base image. I have not tracked down the issue completely but connecting to the image from the psql cli works like a charm (with the same connection string as used for in the statement (addr).

    The code I've used in my setup:

    package main
    
    import (
    	"fmt"
    	"github.com/jmoiron/sqlx"
    	_ "github.com/lib/pq"
    	"os"
    )
    
    func main() {
    	addr := os.Getenv("DB")
    	fmt.Println("Postgres addr: " + addr)
    
    	_, err := sqlx.Connect("postgres", addr)
    
    	if err != nil {
    		fmt.Println("Could not connect...")
    	} else {
    		fmt.Println("Connecting successful")
    	}
    }
    

    As stated above, this code causes problem when building a go executable that is run within a container based on the image alpine:latest, together with *docker-compose`.

    I have set up a test project to reproduce the problems I am facing with: https://github.com/mraxus/mystery-golang-alpine

    Would love to get some help into this and hope this is an actual bug in your lib (otherwise I am wasting your time, which is not my intention)

    Cheers, Marcus

    opened by mraxus 12
  • compilation failed for go1.6rc2

    compilation failed for go1.6rc2

    Hi,

    I tried to run "go get github.com/jmoiron/sqlx" *_# runtime /usr/local/go/src/runtime/os2_linux_generic.go:12: _SS_DISABLE redeclared in this block previous declaration at /usr/local/go/src/runtime/os2_linux.go:8 /usr/local/go/src/runtime/os2_linux_generic.go:13: _NSIG redeclared in this block previous declaration at /usr/local/go/src/runtime/os2_linux.go:9 /usr/local/go/src/runtime/os2_linux_generic.go:14: _SI_USER redeclared in this block previous declaration at /usr/local/go/src/runtime/os2_linux.go:10 /usr/local/go/src/runtime/os2_linux_generic.go:15: _SIG_BLOCK redeclared in this block previous declaration at /usr/local/go/src/runtime/os2_linux.go:11 /usr/local/go/src/runtime/os2_linux_generic.go:16: _SIG_UNBLOCK redeclared in this block previous declaration at /usr/local/go/src/runtime/os2_linux.go:12 /usr/local/go/src/runtime/os2_linux_generic.go:17: _SIG_SETMASK redeclared in this block previous declaration at /usr/local/go/src/runtime/os2_linux.go:13 /usr/local/go/src/runtime/os2_linux_generic.go:18: RLIMIT_AS redeclared in this block previous declaration at /usr/local/go/src/runtime/os2_linux.go:14 /usr/local/go/src/runtime/os2_linux_generic.go:24: sigset redeclared in this block previous declaration at /usr/local/go/src/runtime/os2_linux.go:20 /usr/local/go/src/runtime/os2_linux_generic.go:26: rlimit redeclared in this block previous declaration at /usr/local/go/src/runtime/os2_linux.go:22 /usr/local/go/src/runtime/panic1.go:11: paniclk redeclared in this block previous declaration at /usr/local/go/src/runtime/panic.go:535 /usr/local/go/src/runtime/panic1.go:11: too many errors *

    Could you take a look.

    Best Regards,

    opened by Son-Lam 12
  • got XXXX parameters but the statement requires YY - potential BUG in 1.3.0

    got XXXX parameters but the statement requires YY - potential BUG in 1.3.0

    Hello,

    Seems after upgrading to version 1.3.0 this do not work anymore:

    // batch insert with structs
    
    personStructs := []Person{
        {FirstName: "Ardie", LastName: "Savea", Email: "[email protected]"},
        {FirstName: "Sonny Bill", LastName: "Williams", Email: "[email protected]"},
        {FirstName: "Ngani", LastName: "Laumape", Email: "[email protected]"},
    }
    
    _, err = db.NamedExec(`INSERT INTO person (first_name, last_name, email)
        VALUES (:first_name, :last_name, :email)`, personStructs)
    

    I on my queries getting: pq: got XXXX parameters but the statement requires YY

    but YY is not 65535 it is number of columns, in above example would be YY=3.

    This is since >=1.3.0 version, earlier versions everything works.

    Best regards, Alexandar

    opened by drsasa 11
  • Missing destination name id

    Missing destination name id

    I'm trying to get all rows from a table in a postgres database but I get the following error "Missing destination name id" even if the id exists on the model.

    Can anyone help?

    Thanks,

    opened by mahaben 11
  • LastInsertedId should be LastInsertedID?

    LastInsertedId should be LastInsertedID?

    opened by Narven 11
  • NamedStatement cast issues

    NamedStatement cast issues

    I have the following code:

        sql :=
        `UPDATE giftcards
              SET balance = balance + :purchase
              WHERE account =
                (SELECT account
                 FROM giftcards g JOIN giftcard_txs t ON g.id = t.giftcard_id
                 WHERE t.invoice_no = :invoice_no
                   AND t.ref_no = :ref_no
                   AND t.location_id = :location_id
                   AND t.command = :command
                   AND t.purchase = :purchase) AND org_id = :org_id AND issued = TRUE
            RETURNING *;`
        nstmt, err := tx.PrepareNamed(sql)
        if err != nil {
            return abandon(tx, err, "could not prepare named statement")
        }
        var card api.GiftCard
        params := map[string]interface{}{
            "purchase":    100.00,
            "invoice_no":  "1234567890",
            "ref_no":      "xl9gO6BvvhAIqg==",
            "location_id": 1,
            "command":     "Sale",
            "org_id":      1,
        }
        log.Debug(sql, "params", params)
        if err := nstmt.QueryRowx(params).StructScan(&card); err != nil {
            return abandon(tx, err, "could not update giftcard balance to void sale")
        }
    

    This code executes OK, and indeed, if I plug the query into psql and execute with values instead of named params, it executes fine.

    The trouble is when I construct the map like this (referencing fields off a go struct instead of pasting in literals like above):

    var purchase = gctx.Authorize + gctx.Gratuity
    params := map[string]interface{}{
        "purchase":    purchase,
        "invoice_no":  gctx.InvoiceNo,
        "ref_no":      gctx.RefNo,
        "location_id": loc.ID,
        "command":     api.Sale,
        "org_id":      loc.OrgID,
    }
    

    It errors out with: pq: syntax error at or near "invoice_no". It seems like it is casting InvoiceNo to a numeric type?

    When I print the params map with:

    fmt.Printf("\nMAP %#v\n", params)
    

    It prints as

    MAP map[string]interface {}{"location_id":1, "command":"Sale", "org_id":1, "purchase":100, "invoice_no":"1234567890", "ref_no":"DNoet3vY2RgBtQ=="}
    

    So, the types are there, and as expected, i.e. "invoice_no" is a string.

    The table structure in question giftcard_txs:

    +-------------+--------------------------+--------------------------------------------------+
    | Column      | Type                     | Modifiers                                        |
    |-------------+--------------------------+--------------------------------------------------|
    | id          | bigint                   | not null default nextval('txs_id_seq'::regclass) |
    | created_at  | timestamp with time zone | not null                                         |
    | command     | command                  | not null                                         |
    | invoice_no  | character varying(25)    | not null                                         |
    | ref_no      | character varying(25)    | not null                                         |
    | authorize   | numeric(10,2)            | not null                                         |
    | gratuity    | numeric(10,2)            | not null default 0.00                            |
    | purchase    | numeric(10,2)            | not null                                         |
    | memo        | character varying(50)    |                                                  |
    | terminal    | character varying(35)    |                                                  |
    | operator    | character varying(35)    |                                                  |
    | hash        | character varying(100)   | not null                                         |
    | voided      | boolean                  | default false                                    |
    | giftcard_id | integer                  | not null                                         |
    | location_id | integer                  | not null                                         |
    | void_id     | bigint                   |                                                  |
    +-------------+--------------------------+--------------------------------------------------+
    

    Any idea what the deal is here?

    opened by davisford 11
  • README updates.

    README updates.

    Just a couple of README fixes:

    • I've fixed the syntax error around sqlx.Open (which returns both a *DB and an error)
    • I've added an example for inserting a struct as although the README indicates it can be done, it doesn't show an example.

    I also wouldn't mind adding an example for using rows.Next() to scan into a slice of structs, but before I do that: is there any intention to provide a rows.ScanAll(interface{}) method to do this automatically?

    opened by elithrar 10
  • Cannot connect with postgres database when a password contains $ character.

    Cannot connect with postgres database when a password contains $ character.

    I cannot connect with postgres database when a password contains $ character. I am using version: github.com/jmoiron/sqlx v1.2.0 and Postgres 12. I am using MD5 authentication method. I tried three different connection strings. None of them worked.

    func TestConnection(t *testing.T) {
    	password := "post$gres"
    
    	connStr := fmt.Sprintf("host=postgresserver port=5432 user=postgres password=%s dbname=postgres sslmode=disable",
    		password)
    
    	//connStrUri1 := fmt.Sprintf("postgresql://postgres:%[email protected] :5432/postgres?sslmode=disable",
    	//	url.QueryEscape(password))
    	//connStrUri2 := fmt.Sprintf("postgresql://postgres:%[email protected] :5432/postgres?sslmode=disable",
    	//	password)
    
    	_, err := sqlx.Connect("pgx", connStr)
    	//_, err := sqlx.Connect("pgx", connStrUri1)
    	//_, err := sqlx.Connect("pgx", connStrUri2)
    	require.NoError(t, err)
    }
    
    

    I got error: FATAL: password authentication failed for user "postgres" (SQLSTATE 28P01).

    Could someone help me, please? What I should do to be able to use a $ character in a password.

    opened by pikoscielniak 0
  • Big error in mysql version 8.0.31

    Big error in mysql version 8.0.31

    This is my simple code to create two tables,I run it in centos7 or windows 10 ,It'll show the below error. If I just create one of the two table ,It can work fine. But If I create two table ,It'll will run error. I use the mysql command to execute this sql ,It works fine. Now I am very confused.

    package main 
    import (
    	"log"
    	_ "github.com/go-sql-driver/mysql"
    	"github.com/jmoiron/sqlx"
    )
    
    func main() {
    	d, err := sqlx.Connect("mysql", "monitor:[email protected](192.168.201.210:3306)/monitor")
    	if err != nil {
    		log.Fatalln("db connect error:%s", err.Error())
    		panic(err)
    	}
    	d.SetConnMaxIdleTime(10)
    	d.SetMaxOpenConns(30)
    	var schema = `
    	CREATE TABLE IF NOT EXISTS AlertGroup (
    	ID INT NOT NULL AUTO_INCREMENT,
    	time TIMESTAMP NOT NULL,
    	receiver VARCHAR(100) NOT NULL,
    	status VARCHAR(50) NOT NULL,
    	externalURL TEXT NOT NULL,
    	groupKey VARCHAR(255) NOT NULL,
    	PRIMARY KEY (ID)
    	) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    	CREATE TABLE IF NOT EXISTS GroupLabel (
    		ID INT NOT NULL AUTO_INCREMENT,
    		AlertGroupID INT NOT NULL,
    		GroupLabel VARCHAR ( 100 ) NOT NULL,
    		VALUE VARCHAR ( 1000 ) NOT NULL,
    		PRIMARY KEY ( ID )) ENGINE = INNODB DEFAULT CHARSET = utf8;
    		`
    	d.MustExec(schema)
    
    }
    

    panic: Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CREATE TABLE IF NOT EXISTS GroupLabel ( ID INT NOT NULL AUTO_INCREMENT, Aler' at line 11

    goroutine 1 [running]: github.com/jmoiron/sqlx.MustExec(...) C:/Users/cn200037790/go/pkg/mod/github.com/jmoiron/[email protected]/sqlx.go:722 github.com/jmoiron/sqlx.(*DB).MustExec(0xc000022c30?, {0xb3eb73?, 0xb3c739?}, {0x0?, 0xc000044000?, 0xc000115f70?}) C:/Users/cn200037790/go/pkg/mod/github.com/jmoiron/[email protected]/sqlx.go:366 +0x46 main.main() D:/workspace/go/test/test1/main.go:35 +0x85

    opened by chlinwei 2
  • sqlx.select method when specifying an interface slice as desination

    sqlx.select method when specifying an interface slice as desination

    Hi, If you specify an interface array as the destination in the sqlx.select method, the following error is returned: must pass a pointer, not a value, to StructScan destination.

    var clients []domain.IClient sqlx.Select(clients, SELECT * FROM clients WHERE user_id=$1, "1")

    When calling the sqlx.Get method with a single interface, everything works as expected.

    // domain.NewClient() // func NewClient() IClient { // return &client{} // } client := domain.NewClient() sqlx.Get(client, SELECT * FROM users WHERE id=$1, id)

    Is there a solution for this?

    p.s. The struct should not be used without an interface in this project, because certain setters exist here and only values should be set this way.

    type IClient interface { GetId() string GetKeyHash () string SetKeyHash (identity string) }

    type client struct { Id string json:"id" db:"id" KeyHash string json:"public_key_hash"db:"public_key_hash" }

    func NewClient() IClient { return &client{} }

    Best Regards Alex

    opened by alexanderruch 1
  • (Postgres) Driver : bad connection

    (Postgres) Driver : bad connection

    Hello everyone,

    I am new to golang and sqlx. Currently, I have an issue while using sqlx that connect to pgbouncer in my production. The error log that I got was : "driver : bad connection".

    I am looking for any documentation/blog/article that can explain the best practices while using sqlx and pgbouncer in production, but can't found it.

    If anyone of you had experienced the same issue , pls share with me. Any advices will be very appreciated. Thanks

    opened by budibong 1
  • Oracle Bulk Insert

    Oracle Bulk Insert

    I have found that you can not do a bulk insert into Oracle with NamedExec.
    Oracle is looking for

    insert into table (...) values (...);
    insert into table (...) values (...);
    insert into table (...) values (...);
    

    the script sqlx renders as follows:

    insert into table (...) values (...), values (...), values (...);
    

    I played around with the sqlx named.go file for bulk insert into oracle. However, (this is crude) it produces the desired sql script output with named parameters. I am still running it problems where Oracle does not recognize the sql script itself. and the error returned from Oracle is "ORA-00933: SQL command not properly ended\n"

    // repeat the query for oracle
    func fixBound(bound string, loop int) string {
      var valuesRg = regexp.MustCompile(`into`)
      loc := valuesRg.FindStringIndex(bound)
      // defensive guard when "VALUES (...)" not found
      if len(loc) < 2 {
        return bound
      }
    
      openingBracketIndex := loc[0]
      index := len(bound[openingBracketIndex:])
      // index := findMatchingClosingBracketIndex(bound[openingBracketIndex:])
      // defensive guard. must have closing bracket
      if index == 0 {
        return bound
      }
      // closingBracketIndex := openingBracketIndex + index
    
      var buffer bytes.Buffer
    
      buffer.WriteString(bound)
      for i := 0; i < loop-1; i++ {
        buffer.WriteString(" ")
        buffer.WriteString(bound[openingBracketIndex:])
      }
      // buffer.WriteString(bound[closingBracketIndex:])
      buffer.WriteString(" select * from dual;")
      return buffer.String()
    }
    

    I even modified the script to look like the following; which results in the same error ("ORA-00933: SQL command not properly ended\n")

    "insert all\n\tinto table (_date,\n    _group_code,\n    _code,\n    _cd)\nvalues\n  (:arg1,\n   :arg2,\n   :arg3,\n   :arg4)  into table (_date,\n    _group_code,\n    _code,\n    _cd)\nvalues\n  (:arg5,\n   :arg6,\n   :arg7,\n   :arg8)  select * from dual;"
    
    opened by wafflze 1
PolarDB Cluster Manager is the cluster management component of PolarDB for PostgreSQL, responsible for topology management, high availability, configuration management, and plugin extensions.

What is PolarDB Cluster Manager PolarDB Cluster Manager is the cluster management component of PolarDB for PostgreSQL, responsible for topology manage

null 7 Nov 9, 2022
write APIs using direct SQL queries with no hassle, let's rethink about SQL

SQLer SQL-er is a tiny portable server enables you to write APIs using SQL query to be executed when anyone hits it, also it enables you to define val

Mohammed Al Ashaal 2k Nov 23, 2022
Parses a file and associate SQL queries to a map. Useful for separating SQL from code logic

goyesql This package is based on nleof/goyesql but is not compatible with it any more. This package introduces support for arbitrary tag types and cha

null 0 Oct 20, 2021
Go-sql-reader - Go utility to read the externalised sql with predefined tags

go-sql-reader go utility to read the externalised sql with predefined tags Usage

null 0 Jan 25, 2022
A go Library for scan database/sql rows to struct、slice、other types. And it support multiple databases connection management

ploto A go Library for scan database/sql rows to struct、slice、other types. And it support multiple databases connection management It's not an ORM. wo

solar 3 Nov 3, 2022
Dumpling is a fast, easy-to-use tool written by Go for dumping data from the database(MySQL, TiDB...) to local/cloud(S3, GCP...) in multifarious formats(SQL, CSV...).

?? Dumpling Dumpling is a tool and a Go library for creating SQL dump from a MySQL-compatible database. It is intended to replace mysqldump and mydump

PingCAP 267 Nov 9, 2022
Additions to Go's database/sql for super fast performance and convenience.

gocraft/dbr (database records) gocraft/dbr provides additions to Go's database/sql for super fast performance and convenience. $ go get -u github.com/

null 1.7k Nov 30, 2022
Interceptors for database/sql

sqlmw sqlmw provides an absurdly simple API that allows a caller to wrap a database/sql driver with middleware. This provides an abstraction similar t

null 426 Nov 25, 2022
OpenTelemetry instrumentation for database/sql

otelsql It is an OpenTelemetry instrumentation for Golang database/sql, a port from https://github.com/open-telemetry/opentelemetry-go-contrib/pull/50

Sam Xie 123 Nov 29, 2022
Scan database/sql rows directly to structs, slices, and primitive types

Scan Scan standard lib database rows directly to structs or slices. For the most comprehensive and up-to-date docs see the godoc Examples Multiple Row

Brett Jones 318 Nov 21, 2022
Prometheus metrics for Go database/sql via VictoriaMetrics/metrics

sqlmetrics Prometheus metrics for Go database/sql via VictoriaMetrics/metrics Features Simple API. Easy to integrate. Install Go version 1.16+ go get

cristaltech 21 Nov 9, 2022
Attach hooks to any database/sql driver

sqlhooks Attach hooks to any database/sql driver. The purpose of sqlhooks is to provide a way to instrument your sql statements, making really easy to

Gustavo Chaín 595 Nov 30, 2022
Go database/sql

Go database/sql 源码阅读 基于 release-branch.go1.17 Benchmark 连接池测试 简单介绍 database/sql 库,包括结构体和主要的方法 介绍主要函数的调用逻辑 用OneNote看源码:Link 介绍最近几个版本的commit changes 结合实

x509 0 Dec 18, 2021
Sqlbench runs benchmarks on an SQL database

sqlbench runs benchmarks on an SQL database. Right now this works for PostgreSQL

Martin Tournoij 2 Oct 13, 2022
Lightweight SQL database written in Go for prototyping and playing with text (CSV, JSON) data

gopicosql Lightweight SQL database written in Go for prototyping and playing wit

null 2 Jul 27, 2022
BigQuery database/sql golang driver

BigQuery SQL Driver This library is compatible with Go 1.17+ Please refer to CHA

Viant, Inc 6 Aug 31, 2022
A minimal, single-table No-SQL database.

SimpleDB SimpleDB is a very basic No-SQL database format for long-term data storage in Golang. It is WIP, has a LOT of drawbacks, and definitely is no

Konnor Klashinsky 0 Jan 16, 2022
Otelsql - OpenTelemetry SQL database driver wrapper for Go

OpenTelemetry SQL database driver wrapper for Go Add a OpenTelemetry wrapper to

Nhat 37 Nov 29, 2022