Golang Accessing SQL like Database (iii)--SQL package + Postgres driver source

Source: Internet
Author: User
Tags postgres database
This is a creation in Article, where the information may have evolved or changed.

Github.com/lib/pq

PG is a pure go write driver of the Postgres database. The author gave us a little joke, the PQ will always be habitually written PG there is no ... The installation method is as follows:

go get github.com/lib/pq

Register

As mentioned earlier, driver needs to call Sql.register to register the Driver.driver type interface driver implementation by name. The init function of the PQ driver in the source Pq/conn.go file, the init function calls Sql.register to register the driver data structure under the name "Postgres".

type drv struct{}func (d *drv)Open(name string)(dirver.Conn, error) {    return Open(name)}func init() {    sql.Register("postgres", &drv{})}

This postgres will be automatically registered when you import "GITHUB.COM/LIB/PQ" in your code.

The following will explain the code flow in a single query operation.

Sample

First, a sample code ( Note: The code is pseudo-code, only represents the process, not compiled execution ):

package mainimport (    "database/sql"    _ "github.com/lib/pq")func main() {    db, err := sql.Open("postgres", "postgres://user:pwd@server/database?sslmode=disable")    rows, err := db.Query("select * from table")    stmt, err := db.Prepare("update table set name=$1 where id=$2")    res, err := stmt.Exec("xiaoming", 2)}

SQL package to driver to SQL

As mentioned earlier, the database operation flow is:

Import Package, register driver

In the example above, the SQL package and PQ packages are first import. When the import PQ specifies that the package alias is "_", we just need to register driver with the INIT function of the import PQ package to automatically call the package, without having to use any interface of the package directly.

Sql. Register function in the Sql/sql.go file, the code is as follows, register driver to a global map[string]driver. The driver.

var (    driversMu sync.RWMutex    drivers   = make(map[string]driver.Driver))func Register(name string, driver driver.Driver) {    driversMu.Lock()    defer driversMu.Unlock()    if driver == nil {        panic("sql: Register driver is nil")    }    if _, dup := drivers[name]; dup {        panic("sql: Register called twice for driver " + name)    }    drivers[name] = driver}

User code–> SQL Package--Driver

sql.Open -> db.connectionOpener -> db.openNewConnection

Open first finds driver from drivers by drivername, finds a DB data type after it is found, assigns a value to Db.driver using driver, DataSourceName assigns DB.DSN to initialize the new db.

Then DB. Open calls Db.connectionopener, Db.connectionopener will facilitate all the channel and execute db.opennewconnection.

Db.opennewconnection will call Db.driver.Open (that is, Pq.drv.Open) to validate the DataSourceName, if the parameters in DataSourceName follow the correct format, And there are enough parameters that can be used to connect to the database to return a driver. Conn interface.

The main process of code in PQ is:

drv.Open -> Open -> DialOpen

Db.opennewconnection will wrap a mutex for the driver.conn after it obtains the Driver.open returned to prevent the interaction of concurrent calls to Driver.conn interface.

User Code->sql Package, driver-Sql

The above example code performs two complete operations on the database, one for the query operation, and one for the update operation. This article only explains the query process, which is similar to the update process, which allows readers to follow the code themselves.

The main process for query in SQL is:

sql.DB.Query    | -> sql.DB.query             | -> sql.DB.queryConn                     | -> driver.Conn.Prepare (dirver)                    | -> rowsiFromStatement                            | -> driver.Stmt.Query (driver)

Query primarily controls the number of connections retry, and then calls query to perform the actual query operation.

Query first gets the Driver.conn interface from the connection pool that is returned by the previous open based on the connection type (default Cachedornewconn). If there is a corresponding connection, call Queryconn to perform the query operation.

Queryconn is performing some verification, lockout operation wait, drop with driver. Conn prepare ready to statement. The process here has been successfully cut seamlessly into the driver section. After the driver layer is prepared by the PREPARE Function statement, control is returned to the SQL package again. After the statement type stmt is obtained, the same layer is encapsulated, and the rowsifromstatement is called.

After some mutex locking operations, rowsifromstatement switches to the driver layer again by calling Stmt.query, and operates on the database by driver the specifically implemented query function, reads rows and returns.

The prepare part of the Conn implementation in PQ is as follows:

func (cn *conn) Prepare(q string) (_ driver.Stmt, err error) {    if cn.bad {        return nil, driver.ErrBadConn    }    defer cn.errRecover(&err)    if len(q) >= 4 && strings.EqualFold(q[:4], "COPY") {        return cn.prepareCopyIn(q)    }    return cn.prepareTo(q, cn.gname()), nil}

The stmt implementation of the PQ in the query part of the source code is as follows:

func (st *stmt) Query(v []driver.Value) (r driver.Rows, err error)  {    if st.cn.bad {        return nil, driver.ErrBadConn    }    defer st.cn.errRecover(&err)    st.exec(v)    return &rows{        cn:       st.cn,        colNames: st.colNames,        colTyps:  st.colTyps,        colFmts:  st.colFmts,    }, nil}

Reference links

Https://golang.org/src/database/sql/doc.txt
Https://godoc.org/database/sql
https://golang.org/src/database/sql/
Https://godoc.org/github.com/lib/pq
Https://github.com/lib/pq
Https://godoc.org/github.com/lib/pq
http://jmoiron.github.io/sqlx/
Https://github.com/jmoiron/sqlx/blob/master/sqlx.go
Https://github.com/golang/go/wiki/SQLInterface
Https://github.com/golang/go/wiki/SQLDrivers

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.