GithubHelp home page GithubHelp logo

philio / gomysql Goto Github PK

View Code? Open in Web Editor NEW
190.0 190.0 42.0 573 KB

The most complete and stable MySQL client library written completely in Go. For discussion, ideas, suggestions, feature requests etc, please visit the GoMySQL Google Group (link below). For any issues/bugs or need some help, please post an issue on Github.

Home Page: https://groups.google.com/group/gomysql

License: Other

Go 100.00%

gomysql's People

Contributors

davecheney avatar edsrzf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gomysql's Issues

Prepare statement hangs when result set has no fields

Running MySQL 5.1.49-1ubuntu8.1.

Upon create a prepared statement with the syntax below, the driver would hang. After enabling logging it appears the MySQL driver is waiting for another EOF packet to signify the end of the result fields.

INSERT INTO User ( Password , Username ) VALUES (?,?)

Making a small modification to check if it should wait for another EOF packet as per below fixed the hang. This was just a very quick hack to restore functionality, I have not run further tests on it yet.

if stmt.ParamCount > 0 && !stmt.paramsEOF {
    stmt.paramsEOF = true
    if len(stmt.result.Fields)==0 {
        stmt.result.fieldsEOF = true
    }
    if mysql.Logging {
        log.Print("End of param packets")
    }
}

GoMySQL doesn't build with current Go

I applied the followed gofmt transformations

gofmt -r 'log.Stdout -> log.Print' -w find . -name "*.go"
gofmt -r 'new([a]byte) -> make([]byte, a)' -w `find . -name "*.go"

and fixed the Makefile in order to build this package.

-include $(GOROOT)/src/Make.$(GOARCH)
+include $(GOROOT)/src/Make.inc

Is this thing still being maintained?

When packet length is more than in buffered

First many thanks for GoMySQL, it is great... I am using it as part of my Go project "goesmtp" which is a multi-node ESMTP server written on Go (http://code.google.com/p/goesmtp/). I haven't released any code yet as it is still in its infancy but I am getting there!

Anyway during my development I have noticed a couple of situations where GoMySQL just froze. I have tracked down the problem to the getResult() function in mysql.go.

The problem is with these lines:

   // Check data length
   if int(hdr.length) > mysql.reader.Buffered() {
           mysql.error(CR_MALFORMED_PACKET, CR_MALFORMED_PACKET_STR)
           return
   }

What is happening is that when the results are quite large (large number of rows) from the MySQL DB there can be a situation where the hdr.length is greater than the current bytes in the buffer, but they are on the way (network latency I guess). Since this just returns it leaves everything in a very unstable state as getResult() is called again and again after this.

Anyway by just commenting out the lines everything works fine and the data is retrieved and handled correctly. I guess this isn't a real solution but maybe you have an idea about how to handle this better.

Another place where the same things happens is in the Query function. Here the code says:

if (mysql.reader.Buffered() == 0) {
    break
}

Which breaks out the the main loop processing packets... Again due to network latency Buffered can be 0 but there is more on the way. This results in large result sets never getting returned at the look break prematurely before the EOF is received.

To work around this I changed the code to:

    if ((mysql.curRes == nil) && (mysql.reader.Buffered() == 0)) {
        break
    }

Again, not sure if this is the best solution but works!

Thanks and best regards,

Gary

issue with buffers when compiling

I got the following errors when compiling with latest versions of Go and GoMySQL:
mysql_packet.go:100: cannot use new([20]uint8) (type *[20]uint8) as type []uint8 in assignment
mysql_packet.go:178: cannot use new([21]uint8) (type *[21]uint8) as type []uint8 in assignment

I am a newb to Go and changed the lines to be:
pkt.scrambleBuff = make([]byte, 20)
pkt.scrambleBuff = make([]byte, 21)

and it compiled, not sure if it is a correct change.

Bug: statement.Execute() stops the control...

Please try the test code below, the 'stmt.Execute' at line 312 stops the test from going, with logs as following, the control stops after 'End of field packets'

========== mysql_test.go
/**
 *  Author: Duzy Chan 
 */

package mysql

import (
        "testing"
        "fmt"
)

func TestCreateInsertSelectComplex(t *testing.T) {
        sql := `
CREATE TABLE IF NOT EXISTS table_test_categories(
  f0 VARCHAR(32) PRIMARY KEY,
  f1 VARCHAR(128) NOT NULL
);
CREATE TABLE IF NOT EXISTS table_test_items(
  f00 VARCHAR(32) PRIMARY KEY,
  f01 VARCHAR(128) NOT NULL,
  f02 VARCHAR(32) NOT NULL,
  f03 VARCHAR(256),
  f04 VARCHAR(512),
  f05 VARCHAR(256),
  f06 VARCHAR(32),
  f07 VARCHAR(32),
  f08 VARCHAR(512),
  f09 VARCHAR(32),
  f10 VARCHAR(32),
  f11 VARCHAR(256),
  f12 FLOAT,
  f13 CHAR(3),
  f14 VARCHAR(32),
  f15 VARCHAR(256),
  f16 SMALLINT,
  f17 BIT(1),
  f18 BIT(1),
  f19 FLOAT,
  f20 CHAR(3),
  f21 FLOAT,
  f22 CHAR(3),
  f23 INT,
  f24 VARCHAR(256),
  f25 VARCHAR(24),
  f26 VARCHAR(30),
  f27 VARCHAR(30),
  f28 VARCHAR(32),
  f29 BIT(1),
  f30 BIT(1),
  f31 BIT(1),
  f32 BIT(1),
  f33 BIT(1)
)
`
        db := New()
        db.Logging = false
        err := db.Connect("localhost", "test", "abc", "dusell")
        if db.Errno != 0 { t.Errorf("Connect: [%d] %s", db.Errno, db.Error); return }
        if err != nil { t.Error(err); return }
        defer db.Close()

        _, err = db.Query(sql)
        if db.Errno != 0 { t.Errorf("Query: [%d] %s", db.Errno, db.Error); return }
        if err != nil { t.Error(err); return }

        sql = `
INSERT INTO table_test_items(
  f00,
  f01,
  f02,
  f03,
  f04,
  f05,
  f06,
  f07,
  f08,
  f09,
  f10,
  f11,
  f12,
  f13,
  f14,
  f15,
  f16,
  f17,
  f18,
  f19,
  f20,
  f21,
  f22,
  f23,
  f24,
  f25,
  f26,
  f27,
  f28,
  f29,
  f30,
  f31,
  f32,
  f33
) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
  ON DUPLICATE KEY UPDATE 
    f01=VALUES(f01),
    f02=VALUES(f02),
    f03=VALUES(f03),
    f04=VALUES(f04),
    f05=VALUES(f05),
    f06=VALUES(f06),
    f07=VALUES(f07),
    f08=VALUES(f08),
    f09=VALUES(f09),
    f10=VALUES(f10),
    f11=VALUES(f11),
    f12=VALUES(f12),
    f13=VALUES(f13),
    f14=VALUES(f14),
    f15=VALUES(f15),
    f16=VALUES(f16),
    f17=VALUES(f17),
    f18=VALUES(f18),
    f19=VALUES(f19),
    f20=VALUES(f20),
    f21=VALUES(f21),
    f22=VALUES(f22),
    f23=VALUES(f23),
    f24=VALUES(f24),
    f25=VALUES(f25),
    f26=VALUES(f26),
    f27=VALUES(f27),
    f28=VALUES(f28),
    f29=VALUES(f29),
    f30=VALUES(f30),
    f31=VALUES(f31),
    f32=VALUES(f32),
    f33=VALUES(f33)
`

        stmt, err := db.InitStmt()
        if err != nil { t.Errorf("InitStmt: [%d] %s", stmt.Errno, stmt.Error); return }

        err = stmt.Prepare(sql)
        if stmt.Errno != 0 {
                if stmt.Errno == 2014 {
                        // [2014] Commands out of sync; you can't run this command now
                        if err = db.Reconnect(); err != nil { t.Errorf("Reconnect: [%d] %s", db.Errno, db.Error); return }
                        err = stmt.Prepare(sql)
                } else {
                        t.Logf("Prepare: [%d] %s", stmt.Errno, stmt.Error);
                        t.Fail();
                        return
                }
        }
        if stmt.Errno != 0 { t.Errorf("Prepare: [%d] %s", stmt.Errno, stmt.Error); return }
        if err != nil { t.Errorf("Prepare: %v", err); return }

        params := make([]interface{}, 34)
        for n := 0; n < 34; n += 1 {
                params[n] = fmt.Sprintf("field %d",n);
        }

        if err = stmt.BindParams(params...); err != nil {
                t.Errorf("BindParams: [%d] %s", stmt.Errno, stmt.Error);
                return
        }
        if _, err = stmt.Execute(); err != nil {
                stmt.Close()
                t.Errorf("Execute: [%d] %s", stmt.Errno, stmt.Error);
                return
        }
        if err = stmt.Close(); err != nil {
                t.Errorf("Close: [%d] %s", stmt.Errno, stmt.Error);
                return
        }

        sql = `
SELECT
  f00,
  f01,
  f02,
  f03,
  f04,
  f05,
  f06,
  f07,
  f08,
  f09,
  f10,
  f11,
  f12,
  f13,
  f14,
  f15,
  f16,
  f17,
  f18,
  f19,
  f20,
  f21,
  f22,
  f23,
  f24,
  f25,
  f26,
  f27,
  f28,
  f29,
  f30,
  f31,
  f32,
  f33
FROM table_test_items
WHERE f00=?
LIMIT 1
`
        /*
        if err = db.Reconnect(); err != nil {
                t.Errorf("Reconnect: [%d] %s", db.Errno, db.Error);
                return
        }
         */

        stmt, err = db.InitStmt()
        if err != nil { t.Errorf("InitStmt: [%d] %s", stmt.Errno, stmt.Error); return }

        err = stmt.Prepare(sql)
        if stmt.Errno != 0 { t.Errorf("Prepare: [%d] %s", stmt.Errno, stmt.Error); return }
        if err != nil { t.Errorf("Prepare: %v", err); return }

        if err = stmt.BindParams("field 0"); err != nil {
                t.Errorf("BindParams: [%d] %s", stmt.Errno, stmt.Error);
                return
        }

        fmt.Printf("====\n");
        db.Logging = true
        if res, err := stmt.Execute(); err != nil {
                stmt.Close()
                t.Errorf("Execute: [%d] %s", stmt.Errno, stmt.Error);
                return
        } else {
                fmt.Printf("%v\n", res)
        }
        fmt.Printf("====.\n");

        if err = stmt.Close(); err != nil {
                t.Errorf("Close: [%d] %s", stmt.Errno, stmt.Error);
                return
        }
}

about log

this library is very useful.
can you close the log output by gomysql? or supply a variant to close it.

FetchMap() return []byte, not string.

As "Go row data formats" saying, "varchar" would be convert to "string", but I got []byte, which is really inconvenient to handle, please check it, thanks.

Infinite loop in MySQLStatement.Execute()

A check on stmt.result.rowsEOF was introduced in 61eeb6a... that results in a bug.

If you Execute() a prepared statement that does not return a ResultSet -- e.g. CREATE TABLE, INSERT, etc. -- the for loop in MySQLStatement.getExecuteResult() will never break. This happens because an EOF packet is never received for such queries (a ResultPacketOK is sent by the server instead).

Query hangs when receive header with len=0

Problem probably is in this method:

func (hdr *packetHeader) read(reader *bufio.Reader) (err os.Error) {
    // Read length
    num, err := hdr.readNumber(reader, 3)
    if err != nil {
        return
    }
    log.Println("DEB header length:", num)
    hdr.length = uint32(num)
    // Read sequence
    c, err := reader.ReadByte()
    if err != nil {
        return
    }
    hdr.sequence = uint8(c)
    return
}

As you can see, I added one line for a debug. Then I receive this log:

[cut]
2010/12/19 21:36:44 Query called with SQL: select warunek from kom_Warunek where nazwa= 'tvk'
2010/12/19 21:36:44 [0] Sent query command to server
2010/12/19 21:36:44 DEB header length: 1
2010/12/19 21:36:44 [1] Received result set packet from server
2010/12/19 21:36:44 DEB header length: 67
2010/12/19 21:36:44 [2] Received field packet from server
2010/12/19 21:36:44 DEB header length: 5
2010/12/19 21:36:44 [3] Received eof packet from server
2010/12/19 21:36:44 End of field packets
2010/12/19 21:36:44 DEB header length: 109
2010/12/19 21:36:44 [4] Received row data packet from server
2010/12/19 21:36:44 DEB header length: 0

Method hangs when is trying to read sequence byte.

Is the MySQL protocol allows the header lenght == 0?

Malformed Packet after MySQL server restart

My check MySQL ready function:

if (!MySQL.Ping()){
    Log("MySQL not open")
    if(!MySQL.Connect("127.0.0.1", "user", "password", "mysql")) {
        Log("Error: %v",MySQL.Error)
        return false
    }
    Log("MySQL ready")
}
return true

call CheckReady()

2010/04/24 12:16:55 MySQL not open
2010/04/24 12:16:55 Connect called
2010/04/24 12:16:55 Connected using TCP/IP
2010/04/24 12:16:55 [0] Received init packet from server
2010/04/24 12:16:55 [1] Sent auth packet to server
2010/04/24 12:16:55 [2] Received ok packet from server
2010/04/24 12:16:55 Current result set saved
2010/04/24 12:16:55 MySQL Ready

restart MySQL server

2010/04/24 12:17:13 MySQL not open
2010/04/24 12:17:13 Close called
2010/04/24 12:17:13 Connect called
2010/04/24 12:17:13 Error: Malformed Packet

How correct to restore connections after broke?

'if mysql.reader.Buffered() == 0' probably is a bug

Reader.Buffered method in GoMySQL code:

$ grep Buffered *.go
mysql.go:                 if mysql.resultSaved && mysql.reader.Buffered() == 0 {
mysql.go:                 if mysql.resultSaved && mysql.reader.Buffered() == 0 {
mysql_statement.go: if mysql.reader.Buffered() == 0 {
mysql_statement.go: if mysql.reader.Buffered() == 0 && stmt.resExecuted {

I think it is wrong to rely on if mysql.reader.Buffered() == 0 then there is end of data to read from connection. It is usually true for small replies but with big replies it isn't true.

If you are using buffered io (bufio), you must always to know how many data you need read from a connection and call Reader.Read method as long as you read all needed data from the connection or EOF/error occurs.

Can't connect to MySQL at 127.0.0.1 using TCP

When mysql.auth.host is "127.0.0.1" mysql.connect try establish connection via unix domain socket. It prevents intentionally connect to localhost via TCP. I think there will be enough to use unix socket when mysql.auth.host is "localhost". This allow connect to 127.0.0.1 from chroot environment, where MySQL unix socket is inaccessible.

Parsing of EOF packet not backward compatible

I wasn't able to use the package with mysql 4.1.25.
After some time I figured out what was wrong.

In file mysql_packet.go there should be:

/**

  • Read the EOF packet from the buffer
    */
    func (pkt *packetEOF) read(reader *bufio.Reader) (err os.Error) {
    // Read field count
    c, err := reader.ReadByte()
    if err != nil {
    return
    }
    pkt.fieldCount = uint8(c)
    if pkt.header.length == 1 {
    pkt.warningCount = 0
    pkt.serverStatus = 0x200
    return
    }
    // Read warning count
    ...

Query that returns error causes panic

2010/04/24 11:40:07 Query called
2010/04/24 11:40:07 [0] Sent query command to server
2010/04/24 11:40:07 [1] Received error packet from server
panic: runtime error: index out of range

statement.Execute() holds stopping things going...

Please try the test code below, the 'stmt.Execute' at line 312 stops the test from going, with logs as following, the control stops after 'End of field packets'

========== mysql_test.go
/**
 *  Author: Duzy Chan 
 */

package mysql

import (
        "testing"
        "fmt"
)

func TestCreateInsertSelectComplex(t *testing.T) {
        sql := `
CREATE TABLE IF NOT EXISTS table_test_categories(
  f0 VARCHAR(32) PRIMARY KEY,
  f1 VARCHAR(128) NOT NULL
);
CREATE TABLE IF NOT EXISTS table_test_items(
  f00 VARCHAR(32) PRIMARY KEY,
  f01 VARCHAR(128) NOT NULL,
  f02 VARCHAR(32) NOT NULL,
  f03 VARCHAR(256),
  f04 VARCHAR(512),
  f05 VARCHAR(256),
  f06 VARCHAR(32),
  f07 VARCHAR(32),
  f08 VARCHAR(512),
  f09 VARCHAR(32),
  f10 VARCHAR(32),
  f11 VARCHAR(256),
  f12 FLOAT,
  f13 CHAR(3),
  f14 VARCHAR(32),
  f15 VARCHAR(256),
  f16 SMALLINT,
  f17 BIT(1),
  f18 BIT(1),
  f19 FLOAT,
  f20 CHAR(3),
  f21 FLOAT,
  f22 CHAR(3),
  f23 INT,
  f24 VARCHAR(256),
  f25 VARCHAR(24),
  f26 VARCHAR(30),
  f27 VARCHAR(30),
  f28 VARCHAR(32),
  f29 BIT(1),
  f30 BIT(1),
  f31 BIT(1),
  f32 BIT(1),
  f33 BIT(1)
)
`
        db := New()
        db.Logging = false
        err := db.Connect("localhost", "test", "abc", "dusell")
        if db.Errno != 0 { t.Errorf("Connect: [%d] %s", db.Errno, db.Error); return }
        if err != nil { t.Error(err); return }
        defer db.Close()

        _, err = db.Query(sql)
        if db.Errno != 0 { t.Errorf("Query: [%d] %s", db.Errno, db.Error); return }
        if err != nil { t.Error(err); return }

        sql = `
INSERT INTO table_test_items(
  f00,
  f01,
  f02,
  f03,
  f04,
  f05,
  f06,
  f07,
  f08,
  f09,
  f10,
  f11,
  f12,
  f13,
  f14,
  f15,
  f16,
  f17,
  f18,
  f19,
  f20,
  f21,
  f22,
  f23,
  f24,
  f25,
  f26,
  f27,
  f28,
  f29,
  f30,
  f31,
  f32,
  f33
) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
  ON DUPLICATE KEY UPDATE 
    f01=VALUES(f01),
    f02=VALUES(f02),
    f03=VALUES(f03),
    f04=VALUES(f04),
    f05=VALUES(f05),
    f06=VALUES(f06),
    f07=VALUES(f07),
    f08=VALUES(f08),
    f09=VALUES(f09),
    f10=VALUES(f10),
    f11=VALUES(f11),
    f12=VALUES(f12),
    f13=VALUES(f13),
    f14=VALUES(f14),
    f15=VALUES(f15),
    f16=VALUES(f16),
    f17=VALUES(f17),
    f18=VALUES(f18),
    f19=VALUES(f19),
    f20=VALUES(f20),
    f21=VALUES(f21),
    f22=VALUES(f22),
    f23=VALUES(f23),
    f24=VALUES(f24),
    f25=VALUES(f25),
    f26=VALUES(f26),
    f27=VALUES(f27),
    f28=VALUES(f28),
    f29=VALUES(f29),
    f30=VALUES(f30),
    f31=VALUES(f31),
    f32=VALUES(f32),
    f33=VALUES(f33)
`

        stmt, err := db.InitStmt()
        if err != nil { t.Errorf("InitStmt: [%d] %s", stmt.Errno, stmt.Error); return }

        err = stmt.Prepare(sql)
        if stmt.Errno != 0 {
                if stmt.Errno == 2014 {
                        // [2014] Commands out of sync; you can't run this command now
                        if err = db.Reconnect(); err != nil { t.Errorf("Reconnect: [%d] %s", db.Errno, db.Error); return }
                        err = stmt.Prepare(sql)
                } else {
                        t.Logf("Prepare: [%d] %s", stmt.Errno, stmt.Error);
                        t.Fail();
                        return
                }
        }
        if stmt.Errno != 0 { t.Errorf("Prepare: [%d] %s", stmt.Errno, stmt.Error); return }
        if err != nil { t.Errorf("Prepare: %v", err); return }

        params := make([]interface{}, 34)
        for n := 0; n < 34; n += 1 {
                params[n] = fmt.Sprintf("field %d",n);
        }

        if err = stmt.BindParams(params...); err != nil {
                t.Errorf("BindParams: [%d] %s", stmt.Errno, stmt.Error);
                return
        }
        if _, err = stmt.Execute(); err != nil {
                stmt.Close()
                t.Errorf("Execute: [%d] %s", stmt.Errno, stmt.Error);
                return
        }
        if err = stmt.Close(); err != nil {
                t.Errorf("Close: [%d] %s", stmt.Errno, stmt.Error);
                return
        }

        sql = `
SELECT
  f00,
  f01,
  f02,
  f03,
  f04,
  f05,
  f06,
  f07,
  f08,
  f09,
  f10,
  f11,
  f12,
  f13,
  f14,
  f15,
  f16,
  f17,
  f18,
  f19,
  f20,
  f21,
  f22,
  f23,
  f24,
  f25,
  f26,
  f27,
  f28,
  f29,
  f30,
  f31,
  f32,
  f33
FROM table_test_items
WHERE f00=?
LIMIT 1
`
        /*
        if err = db.Reconnect(); err != nil {
                t.Errorf("Reconnect: [%d] %s", db.Errno, db.Error);
                return
        }
         */

        stmt, err = db.InitStmt()
        if err != nil { t.Errorf("InitStmt: [%d] %s", stmt.Errno, stmt.Error); return }

        err = stmt.Prepare(sql)
        if stmt.Errno != 0 { t.Errorf("Prepare: [%d] %s", stmt.Errno, stmt.Error); return }
        if err != nil { t.Errorf("Prepare: %v", err); return }

        if err = stmt.BindParams("field 0"); err != nil {
                t.Errorf("BindParams: [%d] %s", stmt.Errno, stmt.Error);
                return
        }

        fmt.Printf("====\n");
        db.Logging = true
        if res, err := stmt.Execute(); err != nil {
                stmt.Close()
                t.Errorf("Execute: [%d] %s", stmt.Errno, stmt.Error);
                return
        } else {
                fmt.Printf("%v\n", res)
        }
        fmt.Printf("====.\n");

        if err = stmt.Close(); err != nil {
                t.Errorf("Close: [%d] %s", stmt.Errno, stmt.Error);
                return
        }
}

interface conversion error INT -> int32

When I try to fetch an INT value from the database and convert it using the interface{} to Go int32 I get the following runtime error.

panic: interface conversion: interface is int64, not int

This is what I try to do:
value := row["someColumn"].(int32)

Judging from the conversion table in the README.markdown database INT types will be converted to the Go datatype int32. When I try row["someColumn"].(int) it fails with the same error.

Received unknown packet from server

In my test of my ESMTP server (http://code.google.com/p/goesmtp), I came across an odd error when trying to get the MAX() on an empty table. The resulting debug shows that GoMySQL receives an unknown packet from the server!

Here is the debug output:

2010/05/31 17:35:10 Connect called
2010/05/31 17:35:10 Connected using TCP/IP
2010/05/31 17:35:11 [0] Received init packet from server
2010/05/31 17:35:11 [1] Sent auth packet to server
2010/05/31 17:35:11 [2] Received ok packet from server
2010/05/31 17:35:11 Current result set saved
2010/05/31 17:35:11 Query called with SQL: CREATE TABLE IF NOT EXISTS `bugtest` (id int not NULL)
2010/05/31 17:35:11 [0] Sent query command to server
2010/05/31 17:35:11 [1] Received ok packet from server
2010/05/31 17:35:11 Current result set saved
2010/05/31 17:35:11 Query called with SQL: SELECT max(id) FROM bugtest
2010/05/31 17:35:11 [0] Sent query command to server
2010/05/31 17:35:11 [1] Received result set packet from server
2010/05/31 17:35:11 [2] Received field packet from server
2010/05/31 17:35:11 [3] Received eof packet from server
2010/05/31 17:35:11 End of field packets
2010/05/31 17:35:11 [4] Received unknown packet from server
Error 0 

Here is a test program which demonstrates this problem:

package main

import (
    "mysql"
    "fmt"
    "os"
)

func main() {
    // Create new instance
    db := mysql.New()
    // Enable logging
    db.Logging = true
    // Connect to database
    db.Connect("localhost", "user", "password", "gotesting")
    if db.Errno != 0 {
        fmt.Printf("Error #%d %s\n", db.Errno, db.Error)
        os.Exit(1)
    }

    // Create TABLE
    _, errc := db.Query("CREATE TABLE IF NOT EXISTS `bugtest` (id int not NULL)")
    if errc != nil {
        fmt.Printf("Error #%d %s\n", db.Errno, db.Error)
    }


    // Query database
    res, err := db.Query("SELECT max(id) FROM bugtest")
    if err != nil {
        fmt.Printf("Error #%d %s\n", db.Errno, db.Error)
        os.Exit(1)
    }
    // Display results
    var row map[string]interface{}
    for {
        row = res.FetchMap()
        if row == nil {
            break
        }
        for key, value := range row {
            fmt.Printf("%s:%v\n", key, value)
        }
    }
    // Close connection
    db.Close()
}

A better $TARG

A minor one, but for those of us using & developing against goinstall (http://golang.org/cmd/goinstall/), is there any possibility that TARG could be changed from "mysql" to "github.com/Philio/GoMySQL" in the Makefile?

Only a minor niggle, and only one that bothers me when I'm hacking on GoMySQL directly because "make install" installs to src/pkg/mysql instead of src/pkg/github.com/Philio/GoMySQL -- have to remember to copy over to the canonical directory.

See https://github.com/thomaslee/go-dbd-mysql/blob/master/Makefile for an example from a project I'm working on.

Commands out of sync; you can't run this command now

I get error 2014: "Commands out of sync; you can't run this command now" when execute query like:
SELECT String FROM Table
There is 2270 rows in Table. String is varchar(50). When I set MySQL.Logging to true and add this line to func (mysql *MySQL) getResult() (err os.Error):
fmt.Printf("MCH mysql: seq=%d, hdr: seq=%d len=%d\n", mysql.sequence, hdr.sequence, hdr.length)
I get:
[cut]
MCH mysql: seq=98, hdr: seq=98 len=7
2010/08/18 20:45:22 [98] Received row data packet from server
MCH mysql: seq=99, hdr: seq=99 len=10
2010/08/18 20:45:22 [99] Received row data packet from server
MCH mysql: seq=100, hdr: seq=100 len=9
2010/08/18 20:45:22 [100] Received row data packet from server
MCH mysql: seq=101, hdr: seq=101 len=7
2010/08/18 20:45:22 [101] Received row data packet from server
MCH mysql: seq=102, hdr: seq=102 len=1
2010/08/18 20:45:22 [102] Received ok packet from server
2010/08/18 20:45:22 Current result set saved
MCH mysql: seq=103, hdr: seq=197 len=4544321
2010/08/18 20:45:22 DB error 2014: Commands out of sync; you can't run this command now
When I change order in result, modifying query like this:
SELECT String FROM Table ORDER BY String
I get same error but less logs:
2010/08/18 20:47:00 Connect called
2010/08/18 20:47:00 Connected using TCP/IP
2010/08/18 20:47:00 [0] Received init packet from server
2010/08/18 20:47:00 [1] Sent auth packet to server
MCH mysql: seq=2, hdr: seq=2 len=7
2010/08/18 20:47:00 [2] Received ok packet from server
2010/08/18 20:47:00 Current result set saved
2010/08/18 20:47:00 Query called with SQL: set names utf8
2010/08/18 20:47:00 [0] Sent query command to server
MCH mysql: seq=1, hdr: seq=1 len=7
2010/08/18 20:47:00 [1] Received ok packet from server
2010/08/18 20:47:00 Current result set saved
2010/08/18 20:47:00 web.go serving 10.128.101.7:8080
2010/08/18 20:47:03 GET /
2010/08/18 20:47:03 Query called with SQL: select imie from Osoby order by imie
2010/08/18 20:47:03 [0] Sent query command to server
MCH mysql: seq=1, hdr: seq=1 len=1
2010/08/18 20:47:03 [1] Received result set packet from server
MCH mysql: seq=2, hdr: seq=2 len=45
2010/08/18 20:47:03 [2] Received field packet from server
MCH mysql: seq=3, hdr: seq=3 len=5
2010/08/18 20:47:03 [3] Received eof packet from server
2010/08/18 20:47:03 End of field packets
MCH mysql: seq=4, hdr: seq=4 len=1
2010/08/18 20:47:03 [4] Received ok packet from server
2010/08/18 20:47:03 Current result set saved
MCH mysql: seq=5, hdr: seq=0 len=393216
2010/08/18 20:47:03 DB error 2014: Commands out of sync; you can't run this command now
When I add primary key to SELECT, like this:
SELECT Id, String FROM Table
I get no errors.

There is 21 fields in My real table. I get this error when I select any varchar field or fields, without primary key field. There is no errors when I select date, datetime or enum fields.

Authenticate packet not compatible with 5.1.45-51

We use the mysql server from http://www.percona.com/ .

Server version: 5.1.45-51-log Percona SQL Server (GPL), XtraDB 10.2

After the Authenticate packet is sent, getResult gets an EOF packet, which implies a malformed auth packet. I'm not familiar with the mysql protocol, so I wouldn't know if there's an easy fix.

go install and make returns error on OS X

Is it possible to make i compatible with latest go-tools?

$go install github.com/Philio/GoMySQL
# github.com/Philio/GoMySQL
/usr/local/go/src/pkg/github.com/Philio/GoMySQL/handler.go:281: err is shadowed during return
/usr/local/go/src/pkg/github.com/Philio/GoMySQL/handler.go:289: err is shadowed during return
/usr/local/go/src/pkg/github.com/Philio/GoMySQL/handler.go:311: err is shadowed during return
/usr/local/go/src/pkg/github.com/Philio/GoMySQL/handler.go:333: err is shadowed during return
/usr/local/go/src/pkg/github.com/Philio/GoMySQL/mysql.go:796: err is shadowed during return
/usr/local/go/src/pkg/github.com/Philio/GoMySQL/mysql.go:822: err is shadowed during return
/usr/local/go/src/pkg/github.com/Philio/GoMySQL/packet.go:616: err is shadowed during return
/usr/local/go/src/pkg/github.com/Philio/GoMySQL/statement.go:82: err is shadowed during return
/usr/local/go/src/pkg/github.com/Philio/GoMySQL/statement.go:657: err is shadowed during return
/usr/local/go/src/pkg/github.com/Philio/GoMySQL/statement.go:683: err is shadowed during return
/usr/local/go/src/pkg/github.com/Philio/GoMySQL/statement.go:683: too many errors
$make
Makefile:1: /usr/local/go/src/Make.inc: No such file or directory
Makefile:17: /usr/local/go/src/Make.pkg: No such file or directory
make: *** No rule to make target `/usr/local/go/src/Make.pkg'.  Stop.

Roadmap [0.3]

Goals for next release:

  • Resolve all outstanding bugs, complete any outstanding enhancements.
  • Change of library structure to be more "go-like".
    • Change MySQL struct to become Conn.
    • Merge New and Connect to form single Connect function.
    • Usage like: conn := mysql.Connect(params...)
    • Drop 'MySQL' in front of other structs.
  • New packet handling process.
    • Read packet header.
    • Obtain packet length.
    • Read entire packet.
  • New generic packet parser / processor.
    • Remove mass-duplicated existing packet processing code.

[WORK IN PROGRESS!]

Prepared statement rebind/execute returns invalid result

Reported via email by James Robinson

2010/07/10 21:20:39 Initialise statement called
2010/07/10 21:20:39 Prepare statement called
2010/07/10 21:20:39 [0] Sent prepare command to server
2010/07/10 21:20:39 [1] Received ok for prepared statement packet from server
2010/07/10 21:20:39 [2] Received param packet from server (ignored)
2010/07/10 21:20:39 [3] Received eof packet from server
2010/07/10 21:20:39 End of param packets
2010/07/10 21:20:39 [4] Received field packet from server
2010/07/10 21:20:39 [5] Received field packet from server
2010/07/10 21:20:39 [6] Received eof packet from server
2010/07/10 21:20:39 End of field packets
2010/07/10 21:20:39 Bind params called
2010/07/10 21:20:39 Execute statement called
2010/07/10 21:20:39 [0] Sent execute statement to server
2010/07/10 21:20:39 [1] Received result set packet from server
2010/07/10 21:20:39 [2] Received field packet from server
2010/07/10 21:20:39 [3] Received field packet from server
2010/07/10 21:20:39 [4] Received eof packet from server
2010/07/10 21:20:39 End of field packets
2010/07/10 21:20:39 [5] Received binary row data packet from server
2010/07/10 21:20:39 [6] Received eof packet from server
2010/07/10 21:20:39 End of row packets
got: id:1
got: path:/svc.atom
2010/07/10 21:20:39 Bind params called
2010/07/10 21:20:39 Execute statement called
2010/07/10 21:20:39 [0] Sent execute statement to server
2010/07/10 21:20:39 [1] Received unknown packet from server with first byte: 2
Error #0
2010/07/10 21:20:39 Close statement called
2010/07/10 21:20:39 [0] Sent close statement command to server
2010/07/10 21:20:39 Close called
2010/07/10 21:20:39 [0] Sent quit command to server
2010/07/10 21:20:39 Closed connection to server

SELECT numerous columns issue.

When I SELECT data from a table which has numerous columns, it would return an empty Resultset, if I delete some columns( just some 'int' columns), then it worked.

The output shows it stopped after "Received row packet":

2011/03/01 10:13:58 Reading result packet from server
2011/03/01 10:13:58 [54] Received field packet
2011/03/01 10:13:58 Reading result packet from server
2011/03/01 10:13:58 [55] Received field packet
2011/03/01 10:13:58 Reading result packet from server
2011/03/01 10:13:58 [56] Received EOF packet
2011/03/01 10:13:58 === Server Status ===
2011/03/01 10:13:58 In transaction: 0
2011/03/01 10:13:58 Auto commit enabled: 1
2011/03/01 10:13:58 More results exist: 0
2011/03/01 10:13:58 No good indexes were used: 0
2011/03/01 10:13:58 No indexes were used: 1
2011/03/01 10:13:58 Cursor exists: 0
2011/03/01 10:13:58 Last row has been sent: 0
2011/03/01 10:13:58 Database dropped: 0
2011/03/01 10:13:58 No backslash escapes: 0
2011/03/01 10:13:58 Metadata has changed: 0
2011/03/01 10:13:58 === Begin store result ===
2011/03/01 10:13:58 Reading result packet from server
2011/03/01 10:13:58 [57] Received row packet
Execute RowCount:0 sql: SELECT Water,Arg,
//The last line was output from my own code.

Refactoring of type names

Hello Phil,

I was wondering if it is an option to rename the public types in the package to conform a little more with the Go way of doing things.

Specifically: mysql.MySQLServerInfo, mysql.MySQLStatement, etc. Basically all the types that start with MySQL. This causes some unnecessary 'stuttering' when using the package. You always have to specify the package name along with the type when using it, and Go style therefor accepts that you don't need to repeat the package name in the types themselves. I would suggest something like this:

mysql.MySQL -> mysql.Connection
mysql.MySQLServerInfo -> mysql.ServerInfo
mysql.MySQLAuth -> mysql.Auth
mysql.MySQLResult -> mysql.Result
mysql.MySQLField -> mysql.Field
mysql.MySQLFieldFlags -> mysql.FieldFlags
mysql.MySQLRow -> mysql.Row
mysql.MySQLStatement -> mysql.Statement
mysql.MySQLParam -> mysql.Param

I realize that this will break everyone's code so far, but I believe it makes the whole thing that much more elegant and fits with what the rest of the Go package lib looks/behaves like. Since the package is also still in development, I believe this would be the best time do go ahead with a major change like this.

I already tried this in my test branch, and it works without any problems. There are no name collisions.

GoMySQL doesn't play nice with goinstall

Everytime I update my Go installation, I am unable to build my programs which rely on GoMySQL, e.g.

$ make
6g -o go.6 warden.go scrape.go
warden.go:22: can't find import: mysql
make: *** [go.6] Error 1

I think this problem occurs because GoMySQL installs it's target to $GOROOT/pkg/$GOOS-$GOARCH/mysql.a. The base library directory gets wiped out when running $GOROOT/src/all.bash.

I think the solution to this problem is to change the Makefile so that

TARG=githib.com/Philio/GoMySQL

and change any imports to

import "github.com/Philio/GoMySQL"

It's less visually pleasing than import "mysql", but it keeps my build from breaking every time I update the Go compiler, not to mention preventing name clashes with anyone else who might call their package "mysql".

diff --git a/Examples/query.go b/Examples/query.go
index b1e6c53..d623908 100644
--- a/Examples/query.go
+++ b/Examples/query.go
@@ -3,7 +3,7 @@
 package main
 
 import (
-       "mysql"
+       "github.com/Philio/GoMySQL"
        "fmt"
        "os"
        "flag"
diff --git a/Examples/reconnect.go b/Examples/reconnect.go
index a798e7b..3cef7d9 100644
--- a/Examples/reconnect.go
+++ b/Examples/reconnect.go
@@ -4,7 +4,7 @@
 package main
 
 import (
-       "mysql"
+       "github.com/Philio/GoMySQL"
        "fmt"
        "os"
        "time"
diff --git a/Examples/statement.go b/Examples/statement.go
index c5ab2a1..593407b 100644
--- a/Examples/statement.go
+++ b/Examples/statement.go
@@ -3,7 +3,7 @@
 package main
 
 import (
-       "mysql"
+       "github.com/Philio/GoMySQL"
        "fmt"
        "os"
        "flag"
diff --git a/Makefile b/Makefile
index 23488ae..dba4471 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 include $(GOROOT)/src/Make.inc
  
-TARG=mysql
+TARG=github.com/Philio/GoMySQL
 GOFILES=mysql.go mysql_const.go mysql_error.go mysql_packet.go mysql_result.go mysql_statement.go
  
 include $(GOROOT)/src/Make.pkg 

mysql.Query consistently errors from valid input

I'm using Ubuntu 10.10 x64
MySQL version 5.1.49-1ubuntu8.1 (mysql-server)

The small test script I'm using as an example is below:

package main
import (
    "fmt"
    "mysql"
)
func main() {
    db := mysql.New()
    err := db.Connect("localhost", "root", "password", "db_name")
    if err != nil { panic(err) }
    res, err := db.Query("SET NAMES utf8") 
    if err != nil { panic(err) }
    res, err = db.Query("SELECT * FROM S_A")
    if err != nil { panic(err) }
    fmt.Printf("selected %v", res)
}

And the output after enabling mysql.Logging is below. The number of rows I was expecting to receive was 2807. GoMySQL consistently gives an error after ~100-200 row data packets for any table that I try to query. The error corresponds to mysql.go line 559.

2010/12/18 13:58:18 Connect called
2010/12/18 13:58:18 Connected using unix socket
2010/12/18 13:58:18 [0] Received init packet from server
2010/12/18 13:58:18 [1] Sent auth packet to server
2010/12/18 13:58:18 [2] Received ok packet from server
2010/12/18 13:58:18 Current result set saved
2010/12/18 13:58:18 Query called with SQL: SET NAMES utf8
2010/12/18 13:58:18 [0] Sent query command to server
2010/12/18 13:58:18 [1] Received ok packet from server
2010/12/18 13:58:18 Current result set saved
2010/12/18 13:58:18 Query called with SQL: SELECT * FROM S_A
2010/12/18 13:58:18 [0] Sent query command to server
2010/12/18 13:58:18 [1] Received result set packet from server
2010/12/18 13:58:18 [2] Received field packet from server
2010/12/18 13:58:18 [3] Received field packet from server
2010/12/18 13:58:18 [4] Received field packet from server
2010/12/18 13:58:18 [5] Received field packet from server
2010/12/18 13:58:18 [6] Received field packet from server
2010/12/18 13:58:18 [7] Received eof packet from server
2010/12/18 13:58:18 End of field packets
2010/12/18 13:58:18 [8] Received row data packet from server
2010/12/18 13:58:18 [9] Received row data packet from server
2010/12/18 13:58:18 [10] Received row data packet from server
2010/12/18 13:58:18 [11] Received row data packet from server
2010/12/18 13:58:18 [12] Received row data packet from server
....
2010/12/18 13:58:18 [174] Received row data packet from server
2010/12/18 13:58:18 [175] Received row data packet from server
2010/12/18 13:58:18 [176] Received row data packet from server
2010/12/18 13:58:18 [177] Received row data packet from server
panic: An error occured receiving packet from MySQL 2

panic PC=0x7f3b304ecfe8
runtime.panic+0xa7 /home/kevin/go/src/pkg/runtime/proc.c:1032
    runtime.panic(0x492bf0, 0x7f3b305e42f0)
main.main+0x28d /home/kevin/Desktop/sqltest.go:16
    main.main()
runtime.mainstart+0xf /home/kevin/go/src/pkg/runtime/amd64/asm.s:77
    runtime.mainstart()
runtime.goexit /home/kevin/go/src/pkg/runtime/proc.c:148
    runtime.goexit()

goroutine 2 [3]:
runtime.entersyscall+0x28 /home/kevin/go/src/pkg/runtime/proc.c:572
    runtime.entersyscall()
syscall.Syscall6+0x5 /home/kevin/go/src/pkg/syscall/asm_linux_amd64.s:40
    syscall.Syscall6()
syscall.EpollWait+0x8d /home/kevin/go/src/pkg/syscall/zsyscall_linux_amd64.go:188
    syscall.EpollWait(0x7f3b00000006, 0x7f3b30530450, 0x100000001, 0xffffffff, 0xc, ...)
net.*pollster·WaitFD+0xfe /home/kevin/go/src/pkg/net/fd_linux.go:116
    net.*pollster·WaitFD(0x7f3b30530340, 0x0, 0x7f3b00000072, 0x0, 0x0, ...)
net.*pollServer·Run+0xa3 /home/kevin/go/src/pkg/net/fd.go:207
    net.*pollServer·Run(0x7f3b304fb740, 0x0)
runtime.goexit /home/kevin/go/src/pkg/runtime/proc.c:148
    runtime.goexit()

Date fields are not supported

Hi i am trying to use your API but it seems DATE fields are not supported.
To fix this problem, i added in function :

func handleRow(p *packetRowData, c *Client, r *Result) (err os.Error) {

this piece of code :

// Date
case FIELD_TYPE_DATE :
field,_ = time.Parse("2006-01-02", string(p.row[i].([]byte)))

Thanx for your work

goinstall version is not the latest

I installed the GoMySQL using goinstall

goinstall github.com/Philio/GoMySQL

And cloned a version from github, the diff on statement.go shows on

612c612
<   err = s.c.command(COM_STMT_RESET, s.statementId)

---
>   err = s.c.command(COM_STMT_CLOSE, s.statementId)

Which exactly what thomas has commited for the latest version.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.