func (c *driverConn) Prepare(query string) (driver.Stmt, error) { // Generate unique statement name. stmtname := strconv.Itoa(c.stmtNum) cstmtname := C.CString(stmtname) c.stmtNum++ defer C.free(unsafe.Pointer(cstmtname)) stmtstr := C.CString(query) defer C.free(unsafe.Pointer(stmtstr)) res := C.PQprepare(c.db, cstmtname, stmtstr, 0, nil) err := resultError(res) if err != nil { C.PQclear(res) return nil, err } stmtinfo := C.PQdescribePrepared(c.db, cstmtname) err = resultError(stmtinfo) if err != nil { C.PQclear(stmtinfo) return nil, err } defer C.PQclear(stmtinfo) nparams := int(C.PQnparams(stmtinfo)) statement := &driverStmt{stmtname, c.db, res, nparams} runtime.SetFinalizer(statement, (*driverStmt).Close) return statement, nil }
func (c *libpqConn) Prepare(query string) (driver.Stmt, error) { // check our connection's query cache to see if we've already prepared this cached, ok := c.stmtCache[query] if ok { return cached, nil } // create unique statement name // NOTE: do NOT free cname here because it is cached in c.stmtCache; // all cached statement names are freed in c.Close() cname := C.CString(strconv.Itoa(c.stmtNum)) c.stmtNum++ cquery := C.CString(query) defer C.free(unsafe.Pointer(cquery)) // initial query preparation cres := C.PQprepare(c.db, cname, cquery, 0, nil) defer C.PQclear(cres) if err := resultError(cres); err != nil { return nil, err } // get number of parameters in this query cinfo := C.PQdescribePrepared(c.db, cname) defer C.PQclear(cinfo) if err := resultError(cinfo); err != nil { return nil, err } nparams := int(C.PQnparams(cinfo)) // save statement in cache stmt := &libpqStmt{c: c, name: cname, query: query, nparams: nparams} c.stmtCache[query] = stmt return stmt, nil }
func (s *libpqStmt) exec(args []driver.Value) (*C.PGresult, error) { // if we have no arguments, use plain exec instead of more complicated PQexecPrepared if len(args) == 0 { if s.cquery == nil { s.cquery = C.CString(s.query) } cres := C.PQexec(s.c.db, s.cquery) if err := resultError(cres); err != nil { C.PQclear(cres) return nil, err } return cres, nil } // convert args into C array-of-strings cargs, err := buildCArgs(args) if err != nil { return nil, err } defer returnCharArrayToPool(len(args), cargs) // execute cres := C.PQexecPrepared(s.c.db, s.name, C.int(len(args)), cargs, nil, nil, 0) if err = resultError(cres); err != nil { C.PQclear(cres) return nil, err } return cres, nil }
func (s *driverStmt) Exec(args []driver.Value) (res driver.Result, err error) { cres := s.exec(args) if err = resultError(cres); err != nil { C.PQclear(cres) return } defer C.PQclear(cres) rowsAffected, err := strconv.ParseInt(C.GoString(C.PQcmdTuples(cres)), 10, 64) if err != nil { return } return driver.RowsAffected(rowsAffected), nil }
// Clear frees the memory associated with the result. Cleared results should // not be subsequently used. func (r *Result) Clear() { if r.res != nil { C.PQclear(r.res) r.res = nil runtime.SetFinalizer(r, nil) } }
func (s *driverStmt) Close() error { if s != nil && s.res != nil { C.PQclear(s.res) runtime.SetFinalizer(s, nil) } return nil }
// Execute a query with 1 or more parameters. func (c *libpqConn) execParams(cmd string, args []driver.Value) (driver.Result, error) { // convert args into C array-of-strings cargs, err := buildCArgs(args) if err != nil { return nil, err } defer returnCharArrayToPool(len(args), cargs) ccmd := C.CString(cmd) defer C.free(unsafe.Pointer(ccmd)) // execute cres := C.PQexecParams(c.db, ccmd, C.int(len(args)), nil, cargs, nil, nil, 0) defer C.PQclear(cres) if err = resultError(cres); err != nil { return nil, err } // get modified rows nrows, err := getNumRows(cres) if err != nil { return nil, err } return libpqResult(nrows), nil }
// Query executes the prepared statement with the given parameters, returning a // Result on successful execution. func (s *Statement) Query(params ...interface{}) (res *Result, err os.Error) { cres := s.exec(params...) if err = resultError(cres); err != nil { C.PQclear(cres) return } return newResult(cres), nil }
// Query executes the given SQL query with the given parameters, returning a // Result on successful execution. func (c *Conn) Query(query string, params ...interface{}) (res *Result, err os.Error) { cres := c.exec(query, params...) if err = resultError(cres); err != nil { C.PQclear(cres) return } return newResult(cres), nil }
func (r *driverRows) Close() error { if r.res != nil { C.PQclear(r.res) r.res = nil runtime.SetFinalizer(r, nil) } return nil }
func (c *driverConn) Exec(query string, args []driver.Value) (res driver.Result, err error) { cres := c.exec(query, args) if err = resultError(cres); err != nil { C.PQclear(cres) return } defer C.PQclear(cres) ns := C.GoString(C.PQcmdTuples(cres)) if ns == "" { return driver.ResultNoRows, nil } rowsAffected, err := strconv.ParseInt(ns, 10, 64) if err != nil { return } return driver.RowsAffected(rowsAffected), nil }
func (s *driverStmt) Query(args []driver.Value) (driver.Rows, error) { cres := s.exec(args) if err := resultError(cres); err != nil { C.PQclear(cres) return nil, err } return newResult(cres), nil }
func (s *libpqStmt) Exec(args []driver.Value) (driver.Result, error) { // execute prepared statement cres, err := s.exec(args) if err != nil { return nil, err } defer C.PQclear(cres) nrows, err := getNumRows(cres) if err != nil { return nil, err } return libpqResult(nrows), nil }
func (s *libpqStmt) exec(args []driver.Value) (*C.PGresult, error) { // convert args into C array-of-strings cargs, err := buildCArgs(args) if err != nil { return nil, err } defer returnCharArrayToPool(len(args), cargs) // execute cres := C.PQexecPrepared(s.c.db, s.name, C.int(len(args)), cargs, nil, nil, 0) if err = resultError(cres); err != nil { C.PQclear(cres) return nil, err } return cres, nil }
func (d *libpqDriver) getOids(db *C.PGconn, dsn string) (*pqoid, error) { var err error d.Lock() defer d.Unlock() // check cache if oids, ok := d.oids[dsn]; ok { return oids, nil } // not in cache - query the database oids := &pqoid{} names := []struct { kind string dest *int }{ {"'bytea'", &oids.Bytea}, {"'date'", &oids.Date}, {"'timestamp'", &oids.Timestamp}, {"'timestamp with time zone'", &oids.TimestampTz}, {"'time'", &oids.Time}, {"'time with time zone'", &oids.TimeTz}, } // fetch all the OIDs we care about for _, n := range names { ccmd := C.CString("SELECT " + n.kind + "::regtype::oid") defer C.free(unsafe.Pointer(ccmd)) cres := C.PQexec(db, ccmd) defer C.PQclear(cres) if err := resultError(cres); err != nil { return nil, err } sval := C.GoString(C.PQgetvalue(cres, 0, 0)) *n.dest, err = strconv.Atoi(sval) if err != nil { return nil, ErrFetchingOids } } // save in cache for next time d.oids[dsn] = oids return oids, nil }
// Prepare creates and returns a prepared statement with the given SQL statement. func (c *Conn) Prepare(stmt string) (*Statement, os.Error) { // Generate unique statement name. stmtname := strconv.Itoa(c.stmtNum) stmtnamestr := C.CString(stmtname) c.stmtNum++ defer C.free(unsafe.Pointer(stmtnamestr)) stmtstr := C.CString(stmt) defer C.free(unsafe.Pointer(stmtstr)) res := C.PQprepare(c.db, stmtnamestr, stmtstr, 0, nil) err := resultError(res) if err != nil { C.PQclear(res) return nil, err } statement := &Statement{stmtname, c.db, res} runtime.SetFinalizer(statement, (*Statement).Clear) return statement, nil }
// Execute a query, possibly getting a result object (unless the caller doesn't // want it, as in the case of BEGIN/COMMIT/ROLLBACK). // the caller doesn't care about that (e.g., Begin(), Commit(), Rollback()). //func (c *libpqConn) exec(cmd string, res *libpqResult) error { func (c *libpqConn) exec(cmd string, wantResult bool) (driver.Result, error) { ccmd := C.CString(cmd) defer C.free(unsafe.Pointer(ccmd)) cres := C.PQexec(c.db, ccmd) defer C.PQclear(cres) if err := resultError(cres); err != nil { return nil, err } if !wantResult { return nil, nil } nrows, err := getNumRows(cres) if err != nil { return nil, err } return libpqResult(nrows), nil }
func (s *libpqStmt) Query(args []driver.Value) (driver.Rows, error) { // execute prepared statement cres, err := s.exec(args) if err != nil { return nil, err } // check to see if this was a "LISTEN" if C.GoString(C.PQcmdStatus(cres)) == "LISTEN" { C.PQclear(cres) return &libpqListenRows{s.c}, nil } return &libpqRows{ s: s, res: cres, ncols: int(C.PQnfields(cres)), nrows: int(C.PQntuples(cres)), currRow: 0, cols: nil, }, nil }
// Exec executes the given SQL query with the given parameters. func (c *Conn) Exec(cmd string, params ...interface{}) os.Error { cres := c.exec(cmd, params...) defer C.PQclear(cres) return resultError(cres) }
// Exec executes the prepared statement with the given parameters. func (s *Statement) Exec(params ...interface{}) os.Error { cres := s.exec(params...) defer C.PQclear(cres) return resultError(cres) }
func pqclear(res *C.PGresult) { C.PQclear(res) }
func (r *libpqRows) Close() error { C.PQclear(r.res) return nil }
// Clear frees the memory associated with the statement. Cleared statements should // not be subsequently used. func (s *Statement) Clear() { if s != nil && s.res != nil { C.PQclear(s.res) runtime.SetFinalizer(s, nil) } }