I read this official guide about error handling
i applied it
err := db.connection.QueryRow("INSERT INTO articles(uri) VALUES ($1)", article.URI).Scan()
if err != nil {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
fmt.Println(pgErr.Message) // => syntax error at end of input
fmt.Println(pgErr.Code) // => 42601
}
}
Code doesn't work, my app doens't print anything. But postgres log has ERROR: duplicate key value violates unique constraint "articles_uri_key"
Ok, i can use standart golang method:
err := db.connection.QueryRow("INSERT INTO articles(uri) VALUES ($1)", article.URI).Scan()
if err != nil {
fmt.Println(err)
}
One problem, it prints no rows in result set when no errors in postgres log.
I tried replace
if err != nil with if err != errors.New("no rows in result set"),
it still prints no rows in result set
Use pgx.ErrNoRows
if err != pgx.ErrNoRows {
fmt.Println(err)
}
Please modify your question and make it appropriate.
Duplicate key value is a valid error. If you want to remove the error either you should avoid duplicate entry or remove unique constraint from it.
Using pgx with database/sql, pgx is simply acting as driver.The sql.ErrNoRows error is being returned from the database/sql library. pgx.ErrNoRows is only returned when calling a pgx function directly. As database/sql will bubble up some errors from the driver.
sqlStatement := `
INSERT INTO articles (uri)
VALUES ($1)
RETURNING id`
id := 0
//make sure what type of data you want to scan you should pass it inside scan()
err = db.QueryRow(sqlStatement, article.URI).Scan(&id)
if err != nil {
if err == sql.ErrNoRows { //pgx.ErrNoRows
// there were no rows, but otherwise no error occurred
} else {
log.Fatal(err)
}
}
fmt.Println("New record ID is:", id)
For better understanding or for multiple rows please refer this link : How to get row value(s) back after db insert?
I know it's old question, but I just found the solution
do not use
var pgErr *pgconn.PgError
try to use
var pgErr pgx.PgError
instead
Related
I am trying to run this insert query statement using golang which should return an id
INSERT INTO users (u_email,u_phone,u_password_hash) VALUES (?,?,?) RETURNING u_user_id;
it seems there is no support for that in MonetDB.
Well i tried to get the id by unique email when the insert is done without the "RETURNING u_user_id" part as below
func GetByEmail(db *sql.DB) {
userid := `SELECT u_user_id FROM users WHERE u_email = ?;`
var id UserResponse
email := `baicmr#email.com`
stmt, err := db.Prepare(userid)
if err != nil {
log.Panic(err)
}
defer stmt.Close()
result := stmt.QueryRow(email)
if getErr := result.Scan(&id.ID); getErr != nil {
log.Panic(getErr)
}
fmt.Printf("id.ID: %v\n", id.ID)
}
the result.Scan() line panics
panic: runtime error: index out of range [0] with length 0
What am i doing which is wrong
Can you please open a issue/feature request over at: https://github.com/MonetDB/MonetDB-Go ? This looks like a bug.
I wrote a very simple database query function in golang. The pseudocode is like this:
var ctx = context.Background()
conn, _ := sql.Open("firebirdsql", "SYSDBA:masterkey#localhost/"+BdLocation)
defer conn.Close()
rows, err := conn.QueryContext(ctx,"<sql query>")
// my first attempt was to detect empty result here
switch {
case err == sql.ErrNoRows:
< empty result logic >
rows.Close()
return
case err != nil:
log.Fatal(err)
}
defer rows.Close()
// very 'primitive' logic, the only one that worked
var count int = 0
for rows.Next() {
< process row >
count ++
}
// tried do get empty result here also
if err := rows.Err(); err != nil {
if err == sql.ErrNoRows {
log.Println("Zero rows found")
} else {
panic(err)
}
}
// this worked
if count == 0 {
< empty result logic >
} else{
< return result for processing >
}
Compilation is ok, and it works, but only because I used the "count" variable as a flag. I think I'm following the documentation (and examples) correctly, but err is always nil, even with an empty result. Just as a test I inserted syntax errors in the query, and they were detected.
Am I missing something? Or it just does not work the way I think it does?
Thanks for your help.
You can check for a sql.ErrNoRows (https://golang.org/pkg/database/sql/#pkg-variables)
BUT as you are using a firebird sql driver... It could be another error.
We assume that all drivers implements and returns what was specified by golang... But that could not be true.
Check the actual error and verify it on the Firebird driver.
After executing a cockroachDB transaction which creates a row, I would like to return that id to my application.
I am currently defining a transaction using the database/sql golang package. I then use the crdb client to execute the transaction against CockroachDB.
I cannot return anything from the crdb transaction except for an error relating to the crdb transaction itself. How do people retrieving their most recently created rows if the interface does not provide a way to return a new row id?
I have some transaction that executes two inserts. I get the resulting ids of those inserts and return a response with both of those id values.
func myTransaction(ctx context.Context, tx *sql.Tx) (MyTxnResponse, error) {
var aResult string
if err := tx.QueryRowContext(ctx, `INSERT INTO foo (a,b,c) VALUES (1,2,3) RETURNING foo_id`).Scan(&aResult); err != nil { ... }
var bResult string
if err := tx.QueryRowContext(ctx, `INSERT INTO bar (d,e,f) VALUES (4,5,6) RETURNING bar_id`).Scan(&bResult); err != nil { ... }
return MyTxnResponse{A: aResult, B: bResult}
}
Now, I want to execute the transaction against CRDB
var responseStruct MyTxnResponse
err := crdb.ExecuteTx(ctx.Background(), db, nil, func(tx *sql.Tx) error {
res, err := myTransaction(ctx,tx)
// This is what I am currently doing... it seems bad
responseStruct.A = res.A
responseStruct.B = res.B
return err
}
... use responseStruct for something
I am able to get the result of the transaction by using this external var solution and just mutating it's state in the closure, but that seems like a really bad pattern. I'm sure I'm missing something that will blow up in my face if I keep this pattern.
Is there a standard way to return something from a transaction?
You've got the right idea: declare variables outside the transaction and assign them inside the transaction closure. This is the idiomatic way to "return" things in Go from a closure like this, since the only alternative is to have the function return an interface{} which would need a runtime cast to be useful.
There are a couple of shortcuts available here: since responseStruct and res are the same type, you don't need to list all the fields. You can simply say responseStruct = res.
You can even assign the result of myTransaction directly to responseStruct, avoiding the temporary res entirely. However, you have to be careful with your variable scopes here - you can't use := because that would create a new responseStruct inside the closure. Instead, you must declare all other variables (here, err) so that you can use the plain = assignment:
var responseStruct MyTxnResponse
err := crdb.ExecuteTx(context.Background(), db, nil, func(tx *sql.Tx) error {
var err error
responseStruct, err = myTransaction(ctx, tx)
return err
})
// use responseStruct (but only if err is nil)
I am trying to read images (in long raw datatype) from external Oracle database using Golang code.
When sql's row.Next() is called following error is caught:
ORA-01406: fetched column value was truncated
row.Next works fine for reading blob images from mssql DB.
Example code:
db, err := sql.Open("oci8", getDSN()) //function to get connection details
if err != nil {
fmt.Println(err)
return
}
defer db.Close()
rows, err := db.Query("SELECT image FROM sysadm.all_images")
if err != nil {
fmt.Println(err)
return
}
defer rows.Close()
for rows.Next() {
var id string
var data []byte
rows.Scan(&id, &data)
}
fmt.Println("Total errors", rows.Err())
}
I hope someone can help me to fix this issue or pinpoint to problem area.
I assume you are using go-oci8 as the driver.
Based on this issue https://github.com/mattn/go-oci8/pull/71 there are someone who get the same error like yours, and then managed to fix it by modifying some codes on the driver.
As per this commit, the problem is already solved by increasing the value of oci8cols[i].size on file $GOPATH/src/github.com/mattn/go-oci8/oci8.go. I think in your case you have bigger blob data, that's why the revision is still not working.
case C.SQLT_NUM:
oci8cols[i].kind = C.SQLT_CHR
oci8cols[i].size = int(lp * 4) // <==== THIS VALUE
oci8cols[i].pbuf = C.malloc(C.size_t(oci8cols[i].size) + 1)
So, try to increase the multiplier, like:
oci8cols[i].size = int(lp * 12) // <==== OR GREATER
I'm trying to insert a map value into my Cassandra database. I'm using Go to write my client. Currently its throwing the error "can not marshal string into map(varchar, varchar)". I understand what the error is, but I can't resolve it. Here is the code that I've written.
if err := session.Query("INSERT INTO emergency_records
(mapColumn)
VALUES (?)",
"{'key' : 'value'}").Exec();
err != nil {
log.Fatal(err)
}
What I don't get is that I've written one query as a whole unbroken string and it works fine without throwing this error. Yet breaking it down with the question mark it throws the error. I know this is something simple that I'm just overlooking and couldn't find in the documentation, but any help would be great thanks.
I haven't used Go casandra client before but I guess passing map as a map instead of string should work:
mapValue := map[string]string{"key": "value"}
if err := session.Query("INSERT INTO emergency_records (mapColumn) VALUES (?)", mapValue).Exec(); err != nil {
log.Fatal(err)
}