8

I'm trying to test the behavior of passing arguments to the sql.DB.Query method (using the database/sql package, and the PostgreSQL driver at github.com/lib/pq). Is there any way to get the raw query string after it's been processed to see how the arguments were inserted? I was thinking, for example, of writing a prepared query and then inspecting the resulting statement. Any ideas? Thanks!

joshlf
  • 21,822
  • 11
  • 69
  • 96
  • An alternative - if the library does not allow you to do this - is to have Postgres handle it by logging the statements executed against it. Check out this solution: http://stackoverflow.com/questions/8208310/postgresql-how-to-see-which-queries-has-run –  Jan 03 '14 at 23:12

2 Answers2

5

The "raw query string" isn't parsed by the client and interpolated; it's passed on intact to the server.

If the query has no parameters, the client sends it as a simple query; if the query has parameters, the client sends it as an extended query with the parameters separate from the query. The server then parses the query and parameterizes it.

Go's database/sql doesn't include any logging, so you'll either have to write your own, sniff the traffic with Wireshark, or enable logging on the server side.

Coda Hale
  • 564
  • 2
  • 7
4

It doesn't look like it inserts parameters in the query itself. It sends the query, then waits for the response to send parameters. I forked pq and put some logging code in--this was the output for a simple query:

 wes-macbook:testpq go run testpq.go
2014/01/03 19:08:56 bytes: [0 0 0 84 0 3 0 0 101 120 116 114 97 95 102 108 111 97 116 95 100 105 103 105 116 115 0 50 0 99 108 105 101 110 116 95 101 110 99 111 100 105 110 103 0 85 84 70 56 0 100 97 116 101 115 116 121 108 101 0 73 83 79 44 32 77 68 89 0 117 115 101 114 0 119 102 114 101 101 109 97 110 0 0]
2014/01/03 19:08:56 string: Textra_float_digits2client_encodingUTF8datestyleISO, MDYuserwfreeman
2014/01/03 19:08:56 bytes: [80 0 0 0 45 0 115 101 108 101 99 116 32 42 32 102 114 111 109 32 116 101 115 116 32 119 104 101 114 101 32 116 101 115 116 46 110 97 109 101 61 36 49 0 0 0]
2014/01/03 19:08:56 string: P-select * from test where test.name=$1
2014/01/03 19:08:56 bytes: [68 0 0 0 6 83 0]
2014/01/03 19:08:56 string: DS
2014/01/03 19:08:56 bytes: [83 0 0 0 4]
2014/01/03 19:08:56 string: S
2014/01/03 19:08:56 bytes: [66 0 0 0 20 0 0 0 0 0 1 0 0 0 4 97 115 100 102 0 0]
2014/01/03 19:08:56 string: Basdf
2014/01/03 19:08:56 bytes: [69 0 0 0 9 0 0 0 0 0]
2014/01/03 19:08:56 string: E
2014/01/03 19:08:56 bytes: [83 0 0 0 4]
2014/01/03 19:08:56 string: S

All I did was tweak the send() code:

func (cn *conn) send(m *writeBuf) {
   b := (*m)[1:]
   binary.BigEndian.PutUint32(b, uint32(len(b)))

   if (*m)[0] == 0 {
      *m = b
   }

   // new code here
   log.Println("bytes:", *m)
   log.Println("string:", string(*m))

   _, err := cn.c.Write(*m)
   if err != nil {
      panic(err)
   }
}

My sample code, although it's pretty trivial: https://gist.github.com/8249430

Eve Freeman
  • 32,467
  • 4
  • 86
  • 101