I'm using firebird database driver from "github.com/nakagami/firebirdsql" with GO1.11 + FB2.5
But I can't get prepared SELECT to work, it throws "Error op_response:0" error when executing the 2nd QUERYROW(). Any ideas?
Is there any alternative driver? Or am I using incorrect driver?
func test1(tx *sql.Tx) {
sqlStr := "SELECT number FROM order WHERE id=?"
stmt, err := tx.Prepare(sqlStr)
if err != nil {
panic(err.Error())
}
var value string
err = stmt.QueryRow(123).Scan(&value)
if err != nil {
panic(err.Error())
}
fmt.Println(value)
err = stmt.QueryRow(200).Scan(&value)
if err != nil {
panic(err.Error())
}
fmt.Println(value)
}
Result:
INV20183121
panic: Error op_response:0
goroutine 1 [running]:
main.test1(0xc00009c000, 0xc0000a8200)
I can venture a guess. Looking at github.com/nakagami/firebirdsql sources, this seems to be the only code path which can produce this error. Looking here, it ignores any network errors returned by recvPackets, which means: any thing on the network socket breaks, and you get this error back (because that's what recvPackets returns in case of network error).
I'd suggest rebuilding your code with debugPrint code uncommented, and see what is actually going on on the network connection.
Related
i am trying to insert data after the connection, when i command the logic of INSERT... i was able to connect to the database, but when i uncommand them , i got error
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x40f8e2a]
here is my function :
func Connect() (*sql.DB, error) {
db, err := sql.Open("postgres", os.Getenv("PG_URL"))
if err != nil {
return nil, err
}
defer db.Close()
stmt, _ := db.Prepare("INSERT INTO users(name, email, password) VALUES(?,?,?)")
res, err := stmt.Exec("test", "test#mail.com", "12344")
if err != nil{
panic(err.Error())
}
fmt.Println(res)
fmt.Println("Successfully connected!")
return db, nil
}
I have tried to do the same thing also like this article go sql
and have the same issue
do I wrong implement this?
I bet a dollar/euro/frank that the NPE is on the line executing the prepared statement and that if you check the only error you ignored it won't be nil and it will tell you what's wrong.
I had the same problem with sqlite.
As Ivaylo Novakov described in his answer I had to log the err of the prepare statement (which i ignored like you before stmt, _)
For me it was running okay as long as i was developing but when I created my final binary i forgot to enable cgo).
The err got the hint:
Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub
Background
I am using the github.com/jmoiron/sqlx golang package with a Postgres database.
I have the following wrapper function to run SQL code in a transaction:
func (s *postgresStore) runInTransaction(ctx context.Context, fn func(*sqlx.Tx) error) error {
tx, err := s.db.Beginx()
if err != nil {
return err
}
defer func() {
if err != nil {
tx.Rollback()
return
}
err = tx.Commit()
}()
err = fn(tx)
return err
}
Given this, consider the following code:
func (s *store) SampleFunc(ctx context.Context) error {
err := s.runInTransaction(ctx,func(tx *sqlx.Tx) error {
// Point A: Do some database work
if err := tx.Commit(); err != nil {
return err
}
// Point B: Do some more database work, which may return an error
})
}
Desired behavior
If there is an error at Point A, then the transaction should have done zero work
If there is an error at Point B, then the transaction should still have completed the work at Point A.
Problem with current code
The code does not work as intended at the moment, because I am committing the transaction twice (once in runInTransaction, once in SampleFunc).
A Possible Solution
Where I commit the transaction, I could instead run something like tx.Exec("SAVEPOINT my_savepoint"), then defer tx.Exec("ROLLBACK TO SAVEPOINT my_savepoint")
After the code at Point B, I could run: tx.Exec("RELEASE SAVEPOINT my_savepoint")
So, if the code at Point B runs without error, I will fail to ROLLBACK to my savepoint.
Problems with Possible Solution
I'm not sure if using savepoints will mess with the database/sql package's behavior. Also, my solution seems a bit messy -- surely there is a cleaner way to do this!
Multiple transactions
You can split your work in two transactions:
func (s *store) SampleFunc(ctx context.Context) error {
err := s.runInTransaction(ctx,func(tx *sqlx.Tx) error {
// Point A: Do some database work
})
if err != nil {
return err
}
return s.runInTransaction(ctx,func(tx *sqlx.Tx) error {
// Point B: Do some more database work, which may return an error
})
}
I had the problem alike: I had a lots of steps in one transaction.
After starting transaction:
BEGIN
In loop:
SAVEPOINT s1
Some actions ....
If I get an error: ROLLBACK TO SAVEPOINT s1
If OK go to next step
Finally COMMIT
This approach gives me ability to perform all steps one-by-one. If some steps got failed I can throw away only them, keeping others. And finally commit all "good" work.
I just read the blog written by Rob Pike. I have a small question regarding this and may be I can be wrong too but would still like to get feedback and understand properly the Go.
In the blog there was a snippet code (which actually was written by #jxck_)
_, err = fd.Write(p0[a:b])
if err != nil {
return err
}
_, err = fd.Write(p1[c:d])
if err != nil {
return err
}
_, err = fd.Write(p2[e:f])
if err != nil {
return err
}
// and so on
a) As per my understanding the above code will return if error occurred at fd.Write(p0[a:b]), and will never execute fd.Write(p1[c:d]) , right?
And Rob suggested to write something like this
var err error
write := func(buf []byte) {
if err != nil {
return
}
_, err = w.Write(buf)
}
write(p0[a:b])
write(p1[c:d])
write(p2[e:f])
// and so on
if err != nil {
return err
}
b) Based on the above, looks like the error will return from the sub function. So this means if the error occurs at write(p0[a:b]) then still it will execute write(p1[c:d]), right? So this means logically both are not same, right?
Anybody explain.
No, they are the same. If an error occurs at fd.Write(p0[a:b]), the err variable will hold its value.
Now if you call write(p1[c:d]), then the write() func will first check if err != nil but since it already stores the error which occured in the previous call, it will return immediately and will not execute further code.
a) Yes, you are correct. If the error occures in the first write, it will return.
b) No. The write in this example is a closure. The err inside of it is the same as in the outer scope. So if the first write fails, the other will simply return, because the outer err is not nil anymore.
I've put together a golang func that takes an uploaded file and saves it to folder.
Just before os.Create() I am getting the following error :
http: panic serving [::1]:64373: runtime error: index out of range
My golang function is:
func webUploadHandler(w http.ResponseWriter, r *http.Request) {
file, header, err := r.FormFile("file") // the FormFile function takes in the POST input id file
if err != nil {
fmt.Fprintln(w, err)
return
}
defer file.Close()
// My error comes here
messageId := r.URL.Query()["id"][0]
out, err := os.Create("./upload/" + messageId + ".mp3")
if err != nil {
fmt.Fprintf(w, "Unable to create the file for writing. Check your write access privilege")
return
}
defer out.Close()
// write the content from POST to the file
_, err = io.Copy(out, file)
if err != nil {
fmt.Fprintln(w, err)
}
fmt.Fprintf(w,"File uploaded successfully : ")
fmt.Fprintf(w, header.Filename)
}
any ideas? much appreciate
You should at least check if r.URL.Query()["id"] has actually one element.
If len(r.URL.Query()["id"]), you could consider not accessing the index 0.
Easier, Ainar-G suggests in the comments to use the Get() method
Get gets the first value associated with the given key.
If there are no values associated with the key, Get returns the empty string.
To access multiple values, use the map directly.
We are trying to test locks. Basically, there are multiple clients trying to obtain a lock on a particular key. In the example below, we used the key "x".
I don't know how to test whether the locking is working. I can only read the logs to determine whether it is working.
The correct sequence of events should be:
client1 obtains lock on key "x"
client2 tries to obtain lock on key "x" (fmt.Println("2 getting lock")) - but is blocked and waits
client1 releases lock on key "x"
client2 obtains lock on key "x"
Q1: How could I automate the process and turn this into a test?
Q2: What are some of the tips to testing concurrency / mutex locking in general?
func TestLockUnlock(t *testing.T) {
client1, err := NewClient()
if err != nil {
t.Error("Unexpected new client error: ", err)
}
fmt.Println("1 getting lock")
id1, err := client1.Lock("x", 10*time.Second)
if err != nil {
t.Error("Unexpected lock error: ", err)
}
fmt.Println("1 got lock")
go func() {
client2, err := NewClient()
if err != nil {
t.Error("Unexpected new client error: ", err)
}
fmt.Println("2 getting lock")
id2, err := client2.Lock("x", 10*time.Second)
if err != nil {
t.Error("Unexpected lock error: ", err)
}
fmt.Println("2 got lock")
fmt.Println("2 releasing lock")
err = client2.Unlock("x", id2)
if err != nil {
t.Error("Unexpected Unlock error: ", err)
}
fmt.Println("2 released lock")
err = client2.Close()
if err != nil {
t.Error("Unexpected connection close error: ", err)
}
}()
fmt.Println("sleeping")
time.Sleep(2 * time.Second)
fmt.Println("finished sleeping")
fmt.Println("1 releasing lock")
err = client1.Unlock("x", id1)
if err != nil {
t.Error("Unexpected Unlock error: ", err)
}
fmt.Println("1 released lock")
err = client1.Close()
if err != nil {
t.Error("Unexpected connection close error: ", err)
}
time.Sleep(5 * time.Second)
}
func NewClient() *Client {
....
}
func (c *Client) Lock(lockKey string, timeout time.Duration) (lockId int64, err error){
....
}
func (c *Client) Unlock(lockKey string) err error {
....
}
Concurrency testing of lock-based code is hard, to the extent that provable-correct solutions are difficult to come by. Ad-hoc manual testing via print statements is not ideal.
There are four dynamic concurrency problems that are essentially untestable (more). Along with the testing of performance, a statistical approach is the best you can achieve via test code (e.g. establishing that the 90 percentile performance is better than 10ms or that deadlock is less than 1% likely).
This is one of the reasons that the Communicating Sequential Process (CSP) approach provided by Go is better to use than locks on share memory. Consider that your Goroutine under test provides a unit with specified behaviour. This can be tested against other Goroutines that provide the necessary test inputs via channels and monitor result outputs via channels.
With CSP, using Goroutines without any shared memory (and without any inadvertently shared memory via pointers) will guarantee that race conditions don't occur in any data accesses. Using certain proven design patterns (e.g. by Welch, Justo and WIllcock) can establish that there won't be deadlock between Goroutines. It then remains to establish that the functional behaviour is correct, for which the Goroutine test-harness mentioned above will do nicely.