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 }