From 871a3693ad700eaa14d09735fbeb015de9a4e4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Matczuk?= Date: Wed, 26 Jul 2017 09:10:35 +0200 Subject: [PATCH] compile named query: drop of loop over runes 30% performance improvement --- queryx.go | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/queryx.go b/queryx.go index 9587144..557aff0 100644 --- a/queryx.go +++ b/queryx.go @@ -6,18 +6,11 @@ import ( "fmt" "reflect" "strconv" - "unicode" "github.com/gocql/gocql" "github.com/jmoiron/sqlx/reflectx" ) -// Allow digits and letters in bind params; additionally runes are -// checked against underscores, meaning that bind params can have be -// alphanumeric with underscores. Mind the difference between unicode -// digits and numbers, where '5' is a digit but 'δΊ”' is not. -var allowedBindRunes = []*unicode.RangeTable{unicode.Letter, unicode.Digit} - // CompileNamedQuery compiles a named query into an unbound query using the // '?' bindvar and a list of names. func CompileNamedQuery(qs []byte) (stmt string, names []string, err error) { @@ -48,7 +41,7 @@ func CompileNamedQuery(qs []byte) (stmt string, names []string, err error) { inName = true name = []byte{} // if we're in a name, and this is an allowed character, continue - } else if inName && (unicode.IsOneOf(allowedBindRunes, rune(b)) || b == '_' || b == '.') && i != last { + } else if inName && (allowedBindRune(b) || b == '_' || b == '.') && i != last { // append the byte to the name if we are in a name and not on the last byte name = append(name, b) // if we're in a name and it's not an allowed character, the name is done @@ -56,7 +49,7 @@ func CompileNamedQuery(qs []byte) (stmt string, names []string, err error) { inName = false // if this is the final byte of the string and it is part of the name, then // make sure to add it to the name - if i == last && unicode.IsOneOf(allowedBindRunes, rune(b)) { + if i == last && allowedBindRune(b) { name = append(name, b) } // add the string representation to the names list @@ -66,7 +59,7 @@ func CompileNamedQuery(qs []byte) (stmt string, names []string, err error) { // add this byte to string unless it was not part of the name if i != last { rebound = append(rebound, b) - } else if !unicode.IsOneOf(allowedBindRunes, rune(b)) { + } else if !allowedBindRune(b) { rebound = append(rebound, b) } } else { @@ -78,6 +71,10 @@ func CompileNamedQuery(qs []byte) (stmt string, names []string, err error) { return string(rebound), names, err } +func allowedBindRune(b byte) bool { + return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9') +} + // Queryx is a wrapper around gocql.Query which adds struct binding capabilities. type Queryx struct { *gocql.Query