{"action":"created","comment":{"url":"https://api.github.com/repos/go-sql-driver/mysql/pulls/comments/24299415","id":24299415,"diff_hunk":"@@ -162,28 +165,101 @@ func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) {\n \treturn stmt, err\n }\n \n+// https://github.com/mysql/mysql-server/blob/mysql-5.7.5/libmysql/libmysql.c#L1150-L1156\n+func (mc *mysqlConn) escapeBytes(v []byte) string {\n+\tvar escape func([]byte) []byte\n+\tif mc.status&statusNoBackslashEscapes == 0 {\n+\t\tescape = EscapeString\n+\t} else {\n+\t\tescape = EscapeQuotes\n+\t}\n+\treturn \"'\" + string(escape(v)) + \"'\"\n+}\n+\n+func (mc *mysqlConn) buildQuery(query string, args []driver.Value) (string, error) {\n+\tchunks := strings.Split(query, \"?\")\n+\tif len(chunks) != len(args)+1 {\n+\t\treturn \"\", driver.ErrSkip\n+\t}\n+\n+\tparts := make([]string, len(chunks)+len(args))\n+\tparts[0] = chunks[0]\n+\n+\tfor i, arg := range args {\n+\t\tpos := i*2 + 1\n+\t\tparts[pos+1] = chunks[i+1]\n+\t\tif arg == nil {\n+\t\t\tparts[pos] = \"NULL\"\n+\t\t\tcontinue\n+\t\t}\n+\t\tswitch v := arg.(type) {\n+\t\tcase int64:\n+\t\t\tparts[pos] = strconv.FormatInt(v, 10)\n+\t\tcase float64:\n+\t\t\tparts[pos] = strconv.FormatFloat(v, 'f', -1, 64)\n+\t\tcase bool:\n+\t\t\tif v {\n+\t\t\t\tparts[pos] = \"1\"\n+\t\t\t} else {\n+\t\t\t\tparts[pos] = \"0\"\n+\t\t\t}\n+\t\tcase time.Time:\n+\t\t\tif v.IsZero() {\n+\t\t\t\tparts[pos] = \"'0000-00-00'\"\n+\t\t\t} else {\n+\t\t\t\tfmt := \"'2006-01-02 15:04:05.999999'\"\n+\t\t\t\tparts[pos] = v.In(mc.cfg.loc).Format(fmt)\n+\t\t\t}\n+\t\tcase []byte:\n+\t\t\tif v == nil {\n+\t\t\t\tparts[pos] = \"NULL\"\n+\t\t\t} else {\n+\t\t\t\tparts[pos] = mc.escapeBytes(v)\n+\t\t\t}\n+\t\tcase string:","path":"connection.go","position":79,"original_position":106,"commit_id":"6c8484b12c0fffbd3ea0cd72881a0263f316b1ef","original_commit_id":"b4732595f010ffc0f234f94af2f01c24ea1c75cc","user":{"login":"methane","id":199592,"avatar_url":"https://avatars.githubusercontent.com/u/199592?v=3","gravatar_id":"","url":"https://api.github.com/users/methane","html_url":"https://github.com/methane","followers_url":"https://api.github.com/users/methane/followers","following_url":"https://api.github.com/users/methane/following{/other_user}","gists_url":"https://api.github.com/users/methane/gists{/gist_id}","starred_url":"https://api.github.com/users/methane/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/methane/subscriptions","organizations_url":"https://api.github.com/users/methane/orgs","repos_url":"https://api.github.com/users/methane/repos","events_url":"https://api.github.com/users/methane/events{/privacy}","received_events_url":"https://api.github.com/users/methane/received_events","type":"User","site_admin":false},"body":"I can't...\r\n`./connection.go:214: cannot convert v (type driver.Value) to type []byte: need type assertion`","created_at":"2015-02-08T15:44:27Z","updated_at":"2015-02-08T15:44:27Z","html_url":"https://github.com/go-sql-driver/mysql/pull/309#discussion_r24299415","pull_request_url":"https://api.github.com/repos/go-sql-driver/mysql/pulls/309","_links":{"self":{"href":"https://api.github.com/repos/go-sql-driver/mysql/pulls/comments/24299415"},"html":{"href":"https://github.com/go-sql-driver/mysql/pull/309#discussion_r24299415"},"pull_request":{"href":"https://api.github.com/repos/go-sql-driver/mysql/pulls/309"}}},"pull_request":{"url":"https://api.github.com/repos/go-sql-driver/mysql/pulls/309","id":28438877,"html_url":"https://github.com/go-sql-driver/mysql/pull/309","diff_url":"https://github.com/go-sql-driver/mysql/pull/309.diff","patch_url":"https://github.com/go-sql-driver/mysql/pull/309.patch","issue_url":"https://api.github.com/repos/go-sql-driver/mysql/issues/309","number":309,"state":"open","locked":false,"title":"[RFC] Placeholder substitution (sync with master + tests)","user":{"login":"arvenil","id":450355,"avatar_url":"https://avatars.githubusercontent.com/u/450355?v=3","gravatar_id":"","url":"https://api.github.com/users/arvenil","html_url":"https://github.com/arvenil","followers_url":"https://api.github.com/users/arvenil/followers","following_url":"https://api.github.com/users/arvenil/following{/other_user}","gists_url":"https://api.github.com/users/arvenil/gists{/gist_id}","starred_url":"https://api.github.com/users/arvenil/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arvenil/subscriptions","organizations_url":"https://api.github.com/users/arvenil/orgs","repos_url":"https://api.github.com/users/arvenil/repos","events_url":"https://api.github.com/users/arvenil/events{/privacy}","received_events_url":"https://api.github.com/users/arvenil/received_events","type":"User","site_admin":false},"body":"@methane did awesome job in https://github.com/go-sql-driver/mysql/pull/297 and since I'm highly interested in this PR I wanted to test it. However https://github.com/go-sql-driver/mysql/pull/297 was out of sync with master (\"This pull request contains merge conflicts that must be resolved.\") so I merged changes from master.\r\nSince I was already testing this. I've also:\r\n* added some basic tests for escape functions (100% code coverage)\r\n* exported escape functions (in case anyone would like to use them)\r\n* added some basic sql injection tests (including sql_mode=NO_BACKSLASH_ESCAPES)\r\n* referenced ported code to mysql source code (just in case if anyone like me;) would like to take a look if port is correct)\r\n\r\nFeel free to merge this or throw away, I did this mostly to verify correctness.\r\n\r\nOne more time thanks for this @methane !","created_at":"2015-02-01T22:56:56Z","updated_at":"2015-02-08T15:44:27Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b451bca5720619ca425d3b6063f981f7929e41bf","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/go-sql-driver/mysql/pulls/309/commits","review_comments_url":"https://api.github.com/repos/go-sql-driver/mysql/pulls/309/comments","review_comment_url":"https://api.github.com/repos/go-sql-driver/mysql/pulls/comments/{number}","comments_url":"https://api.github.com/repos/go-sql-driver/mysql/issues/309/comments","statuses_url":"https://api.github.com/repos/go-sql-driver/mysql/statuses/6c8484b12c0fffbd3ea0cd72881a0263f316b1ef","head":{"label":"arvenil:placeholder","ref":"placeholder","sha":"6c8484b12c0fffbd3ea0cd72881a0263f316b1ef","user":{"login":"arvenil","id":450355,"avatar_url":"https://avatars.githubusercontent.com/u/450355?v=3","gravatar_id":"","url":"https://api.github.com/users/arvenil","html_url":"https://github.com/arvenil","followers_url":"https://api.github.com/users/arvenil/followers","following_url":"https://api.github.com/users/arvenil/following{/other_user}","gists_url":"https://api.github.com/users/arvenil/gists{/gist_id}","starred_url":"https://api.github.com/users/arvenil/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arvenil/subscriptions","organizations_url":"https://api.github.com/users/arvenil/orgs","repos_url":"https://api.github.com/users/arvenil/repos","events_url":"https://api.github.com/users/arvenil/events{/privacy}","received_events_url":"https://api.github.com/users/arvenil/received_events","type":"User","site_admin":false},"repo":{"id":30120600,"name":"mysql","full_name":"arvenil/mysql","owner":{"login":"arvenil","id":450355,"avatar_url":"https://avatars.githubusercontent.com/u/450355?v=3","gravatar_id":"","url":"https://api.github.com/users/arvenil","html_url":"https://github.com/arvenil","followers_url":"https://api.github.com/users/arvenil/followers","following_url":"https://api.github.com/users/arvenil/following{/other_user}","gists_url":"https://api.github.com/users/arvenil/gists{/gist_id}","starred_url":"https://api.github.com/users/arvenil/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arvenil/subscriptions","organizations_url":"https://api.github.com/users/arvenil/orgs","repos_url":"https://api.github.com/users/arvenil/repos","events_url":"https://api.github.com/users/arvenil/events{/privacy}","received_events_url":"https://api.github.com/users/arvenil/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/arvenil/mysql","description":"Go-MySQL-Driver is a lightweight and fast MySQL-Driver for Go's (golang) database/sql package","fork":true,"url":"https://api.github.com/repos/arvenil/mysql","forks_url":"https://api.github.com/repos/arvenil/mysql/forks","keys_url":"https://api.github.com/repos/arvenil/mysql/keys{/key_id}","collaborators_url":"https://api.github.com/repos/arvenil/mysql/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/arvenil/mysql/teams","hooks_url":"https://api.github.com/repos/arvenil/mysql/hooks","issue_events_url":"https://api.github.com/repos/arvenil/mysql/issues/events{/number}","events_url":"https://api.github.com/repos/arvenil/mysql/events","assignees_url":"https://api.github.com/repos/arvenil/mysql/assignees{/user}","branches_url":"https://api.github.com/repos/arvenil/mysql/branches{/branch}","tags_url":"https://api.github.com/repos/arvenil/mysql/tags","blobs_url":"https://api.github.com/repos/arvenil/mysql/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/arvenil/mysql/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/arvenil/mysql/git/refs{/sha}","trees_url":"https://api.github.com/repos/arvenil/mysql/git/trees{/sha}","statuses_url":"https://api.github.com/repos/arvenil/mysql/statuses/{sha}","languages_url":"https://api.github.com/repos/arvenil/mysql/languages","stargazers_url":"https://api.github.com/repos/arvenil/mysql/stargazers","contributors_url":"https://api.github.com/repos/arvenil/mysql/contributors","subscribers_url":"https://api.github.com/repos/arvenil/mysql/subscribers","subscription_url":"https://api.github.com/repos/arvenil/mysql/subscription","commits_url":"https://api.github.com/repos/arvenil/mysql/commits{/sha}","git_commits_url":"https://api.github.com/repos/arvenil/mysql/git/commits{/sha}","comments_url":"https://api.github.com/repos/arvenil/mysql/comments{/number}","issue_comment_url":"https://api.github.com/repos/arvenil/mysql/issues/comments/{number}","contents_url":"https://api.github.com/repos/arvenil/mysql/contents/{+path}","compare_url":"https://api.github.com/repos/arvenil/mysql/compare/{base}...{head}","merges_url":"https://api.github.com/repos/arvenil/mysql/merges","archive_url":"https://api.github.com/repos/arvenil/mysql/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/arvenil/mysql/downloads","issues_url":"https://api.github.com/repos/arvenil/mysql/issues{/number}","pulls_url":"https://api.github.com/repos/arvenil/mysql/pulls{/number}","milestones_url":"https://api.github.com/repos/arvenil/mysql/milestones{/number}","notifications_url":"https://api.github.com/repos/arvenil/mysql/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/arvenil/mysql/labels{/name}","releases_url":"https://api.github.com/repos/arvenil/mysql/releases{/id}","created_at":"2015-01-31T17:53:47Z","updated_at":"2015-02-01T22:33:49Z","pushed_at":"2015-02-08T11:08:39Z","git_url":"git://github.com/arvenil/mysql.git","ssh_url":"git@github.com:arvenil/mysql.git","clone_url":"https://github.com/arvenil/mysql.git","svn_url":"https://github.com/arvenil/mysql","homepage":"http://godoc.org/github.com/go-sql-driver/mysql","size":838,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"go-sql-driver:master","ref":"master","sha":"8afc3be42072f568b4868b4afe97bff228a1fb32","user":{"login":"go-sql-driver","id":3002971,"avatar_url":"https://avatars.githubusercontent.com/u/3002971?v=3","gravatar_id":"","url":"https://api.github.com/users/go-sql-driver","html_url":"https://github.com/go-sql-driver","followers_url":"https://api.github.com/users/go-sql-driver/followers","following_url":"https://api.github.com/users/go-sql-driver/following{/other_user}","gists_url":"https://api.github.com/users/go-sql-driver/gists{/gist_id}","starred_url":"https://api.github.com/users/go-sql-driver/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/go-sql-driver/subscriptions","organizations_url":"https://api.github.com/users/go-sql-driver/orgs","repos_url":"https://api.github.com/users/go-sql-driver/repos","events_url":"https://api.github.com/users/go-sql-driver/events{/privacy}","received_events_url":"https://api.github.com/users/go-sql-driver/received_events","type":"Organization","site_admin":false},"repo":{"id":7083242,"name":"mysql","full_name":"go-sql-driver/mysql","owner":{"login":"go-sql-driver","id":3002971,"avatar_url":"https://avatars.githubusercontent.com/u/3002971?v=3","gravatar_id":"","url":"https://api.github.com/users/go-sql-driver","html_url":"https://github.com/go-sql-driver","followers_url":"https://api.github.com/users/go-sql-driver/followers","following_url":"https://api.github.com/users/go-sql-driver/following{/other_user}","gists_url":"https://api.github.com/users/go-sql-driver/gists{/gist_id}","starred_url":"https://api.github.com/users/go-sql-driver/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/go-sql-driver/subscriptions","organizations_url":"https://api.github.com/users/go-sql-driver/orgs","repos_url":"https://api.github.com/users/go-sql-driver/repos","events_url":"https://api.github.com/users/go-sql-driver/events{/privacy}","received_events_url":"https://api.github.com/users/go-sql-driver/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/go-sql-driver/mysql","description":"Go-MySQL-Driver is a lightweight and fast MySQL-Driver for Go's (golang) database/sql package","fork":false,"url":"https://api.github.com/repos/go-sql-driver/mysql","forks_url":"https://api.github.com/repos/go-sql-driver/mysql/forks","keys_url":"https://api.github.com/repos/go-sql-driver/mysql/keys{/key_id}","collaborators_url":"https://api.github.com/repos/go-sql-driver/mysql/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/go-sql-driver/mysql/teams","hooks_url":"https://api.github.com/repos/go-sql-driver/mysql/hooks","issue_events_url":"https://api.github.com/repos/go-sql-driver/mysql/issues/events{/number}","events_url":"https://api.github.com/repos/go-sql-driver/mysql/events","assignees_url":"https://api.github.com/repos/go-sql-driver/mysql/assignees{/user}","branches_url":"https://api.github.com/repos/go-sql-driver/mysql/branches{/branch}","tags_url":"https://api.github.com/repos/go-sql-driver/mysql/tags","blobs_url":"https://api.github.com/repos/go-sql-driver/mysql/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/go-sql-driver/mysql/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/go-sql-driver/mysql/git/refs{/sha}","trees_url":"https://api.github.com/repos/go-sql-driver/mysql/git/trees{/sha}","statuses_url":"https://api.github.com/repos/go-sql-driver/mysql/statuses/{sha}","languages_url":"https://api.github.com/repos/go-sql-driver/mysql/languages","stargazers_url":"https://api.github.com/repos/go-sql-driver/mysql/stargazers","contributors_url":"https://api.github.com/repos/go-sql-driver/mysql/contributors","subscribers_url":"https://api.github.com/repos/go-sql-driver/mysql/subscribers","subscription_url":"https://api.github.com/repos/go-sql-driver/mysql/subscription","commits_url":"https://api.github.com/repos/go-sql-driver/mysql/commits{/sha}","git_commits_url":"https://api.github.com/repos/go-sql-driver/mysql/git/commits{/sha}","comments_url":"https://api.github.com/repos/go-sql-driver/mysql/comments{/number}","issue_comment_url":"https://api.github.com/repos/go-sql-driver/mysql/issues/comments/{number}","contents_url":"https://api.github.com/repos/go-sql-driver/mysql/contents/{+path}","compare_url":"https://api.github.com/repos/go-sql-driver/mysql/compare/{base}...{head}","merges_url":"https://api.github.com/repos/go-sql-driver/mysql/merges","archive_url":"https://api.github.com/repos/go-sql-driver/mysql/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/go-sql-driver/mysql/downloads","issues_url":"https://api.github.com/repos/go-sql-driver/mysql/issues{/number}","pulls_url":"https://api.github.com/repos/go-sql-driver/mysql/pulls{/number}","milestones_url":"https://api.github.com/repos/go-sql-driver/mysql/milestones{/number}","notifications_url":"https://api.github.com/repos/go-sql-driver/mysql/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/go-sql-driver/mysql/labels{/name}","releases_url":"https://api.github.com/repos/go-sql-driver/mysql/releases{/id}","created_at":"2012-12-09T20:33:55Z","updated_at":"2015-02-07T10:32:15Z","pushed_at":"2015-02-06T08:18:13Z","git_url":"git://github.com/go-sql-driver/mysql.git","ssh_url":"git@github.com:go-sql-driver/mysql.git","clone_url":"https://github.com/go-sql-driver/mysql.git","svn_url":"https://github.com/go-sql-driver/mysql","homepage":"http://godoc.org/github.com/go-sql-driver/mysql","size":2329,"stargazers_count":1201,"watchers_count":1201,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":277,"mirror_url":null,"open_issues_count":20,"forks":277,"open_issues":20,"watchers":1201,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/go-sql-driver/mysql/pulls/309"},"html":{"href":"https://github.com/go-sql-driver/mysql/pull/309"},"issue":{"href":"https://api.github.com/repos/go-sql-driver/mysql/issues/309"},"comments":{"href":"https://api.github.com/repos/go-sql-driver/mysql/issues/309/comments"},"review_comments":{"href":"https://api.github.com/repos/go-sql-driver/mysql/pulls/309/comments"},"review_comment":{"href":"https://api.github.com/repos/go-sql-driver/mysql/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/go-sql-driver/mysql/pulls/309/commits"},"statuses":{"href":"https://api.github.com/repos/go-sql-driver/mysql/statuses/6c8484b12c0fffbd3ea0cd72881a0263f316b1ef"}}}}