Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
golang版本的mysql_escape_string()
golang version of mysql_escape_string()

参考了mysql的C版本api
refer to mysql C api's escape_string_for_mysql function : https://github.com/twitter/mysql/blob/865aae5f23e2091e1316ca0e6c6651d57f786c76/mysys/charset.c

tested with some simple manual written data and compare with php5's mysql_escape_string.
49 changes: 14 additions & 35 deletions mysql_escape.go
Original file line number Diff line number Diff line change
@@ -1,61 +1,40 @@
package main
package mysql_escape

import (
"errors"
"fmt"
)

func mysql_escape(source string) (string, error) {
var j int = 0
func MysqlEscapeString(source string) string {
if len(source) == 0 {
return "", errors.New("source is null")
return ""
}
tempStr := source[:]

var j int = 0
desc := make([]byte, len(tempStr)*2)
for i := 0; i < len(tempStr); i++ {
flag := false
var escape byte
escape = 0
switch tempStr[i] {
case 0:
escape = '0'
case '\r':
flag = true
escape = '\r'
break
escape = 'r'
case '\n':
flag = true
escape = '\n'
break
escape = 'n'
case '\\':
flag = true
escape = '\\'
break
case '\'':
flag = true
escape = '\''
break
case '"':
flag = true
escape = '"'
break
case '\032':
flag = true
escape = 'Z'
break
default:
}
if flag {
if escape != 0 {
desc[j] = '\\'
desc[j+1] = escape
j = j + 2
j += 2
} else {
desc[j] = tempStr[i]
j = j + 1
j += 1
}
}
return string(desc[0:j]), nil
}

func main() {
if str, err := mysql_escape(`SELECT * FROM users WHERE user=20 AND password='%s'`); err == nil {
fmt.Println(str)
}
return string(desc[0:j])
}
65 changes: 65 additions & 0 deletions mysql_escape_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package mysql_escape

import (
"bytes"
. "github.com/smartystreets/goconvey/convey"
"io/ioutil"
"testing"
)

var phpCode string = `// use z to seperate, so no z in data
$src = array(
"normal",
"aaa\ro", // \r
"iam\0ooo", // \0
"\"shou\x08ldbe", // " and \b
"+123",
"'youyou'", // '
"\n gogogo",
"\026haha",
"tab \t iam tab",
"yoyo\\ yoyo",
"heros never die",
"heros%",
"heros_",
"heros$(&&^*&$##%^(*(*&$##&^^&(*)",
"??>><<>><?<:||)(&___*((*&%@%@$@#GJGJGFDOIUO*&*JKJKL137813"
);
$dest ="";

foreach ($src as $s){
$dest = $dest."z".$s."z".mysql_escape_string($s);
}
file_put_contents("sql_util_test.dat", $dest);
`

// the test data is generated by php, using mysql_escape_string. // data are sperated by 'z'
// phpCode are pasted above.

func TestMysqlEscapeString(t *testing.T) {
Convey("testMysqlEscape", t, func() {
data, err := ioutil.ReadFile("test.dat")
So(err, ShouldBeNil)
pairs := bytes.Split(data, []byte("z"))
pairs = pairs[1:]
for i := 0; i < len(pairs); i += 2 {
originalData := pairs[i]
destData := pairs[i+1]
escaped := MysqlEscapeString(string(originalData))
byteEqual(t, []byte(escaped), destData)
}
})
}

func byteEqual(t *testing.T, src, dest []byte) {
t.Log(src)
t.Log(dest)
if len(src) != len(dest) {
t.Error("len check fail")
}
for i, v := range src {
if dest[i] != v {
t.Error("fail in index %v", i)
}
}
}
Binary file added test.dat
Binary file not shown.