From 5ecb9e05cd740863c95adcdd1f1df3ed421263c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Nieto?= <jose.carlos@menteslibres.net> Date: Tue, 10 Jun 2014 19:24:15 -0500 Subject: [PATCH] Some cleaning, also moving debug function to sqlutil package. --- postgresql/collection.go | 204 +++++++++++++++++------------------- postgresql/database.go | 93 ++++++++-------- postgresql/database_test.go | 42 ++++---- postgresql/result.go | 44 ++++---- postgresql/tx.go | 21 ++++ util/sqlutil/main.go | 22 ++-- 6 files changed, 210 insertions(+), 216 deletions(-) diff --git a/postgresql/collection.go b/postgresql/collection.go index cbbf386d..33fc113e 100644 --- a/postgresql/collection.go +++ b/postgresql/collection.go @@ -1,25 +1,23 @@ -/* - Copyright (c) 2012-2014 José Carlos Nieto, https://menteslibres.net/xiam - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ +// Copyright (c) 2012-2014 José Carlos Nieto, https://menteslibres.net/xiam +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package postgresql @@ -35,14 +33,88 @@ import ( "upper.io/db/util/sqlutil" ) -// Represents a PostgreSQL table. +const defaultOperator = `=` + type Table struct { sqlutil.T source *Source names []string } -const defaultOperator = `=` +func whereValues(term interface{}) (where sqlgen.Where, args []interface{}) { + + args = []interface{}{} + + switch t := term.(type) { + case []interface{}: + l := len(t) + where = make(sqlgen.Where, 0, l) + for _, cond := range t { + w, v := whereValues(cond) + args = append(args, v...) + where = append(where, w...) + } + case db.And: + and := make(sqlgen.And, 0, len(t)) + for _, cond := range t { + k, v := whereValues(cond) + args = append(args, v...) + and = append(and, k...) + } + where = append(where, and) + case db.Or: + or := make(sqlgen.Or, 0, len(t)) + for _, cond := range t { + k, v := whereValues(cond) + args = append(args, v...) + or = append(or, k...) + } + where = append(where, or) + case db.Raw: + if s, ok := t.Value.(string); ok == true { + where = append(where, sqlgen.Raw{s}) + } + case db.Cond: + k, v := conditionValues(t) + args = append(args, v...) + for _, kk := range k { + where = append(where, kk) + } + } + + return where, args +} + +func interfaceArgs(value interface{}) (args []interface{}) { + + if value == nil { + return nil + } + + value_v := reflect.ValueOf(value) + + switch value_v.Type().Kind() { + case reflect.Slice: + var i, total int + + total = value_v.Len() + if total > 0 { + args = make([]interface{}, total) + + for i = 0; i < total; i++ { + args[i] = toInternal(value_v.Index(i).Interface()) + } + + return args + } else { + return nil + } + default: + args = []interface{}{toInternal(value)} + } + + return args +} func conditionValues(cond db.Cond) (columnValues sqlgen.ColumnValues, args []interface{}) { @@ -103,50 +175,6 @@ func conditionValues(cond db.Cond) (columnValues sqlgen.ColumnValues, args []int return columnValues, args } -func whereValues(term interface{}) (where sqlgen.Where, args []interface{}) { - - args = []interface{}{} - - switch t := term.(type) { - case []interface{}: - l := len(t) - where = make(sqlgen.Where, 0, l) - for _, cond := range t { - w, v := whereValues(cond) - args = append(args, v...) - where = append(where, w...) - } - case db.And: - and := make(sqlgen.And, 0, len(t)) - for _, cond := range t { - k, v := whereValues(cond) - args = append(args, v...) - and = append(and, k...) - } - where = append(where, and) - case db.Or: - or := make(sqlgen.Or, 0, len(t)) - for _, cond := range t { - k, v := whereValues(cond) - args = append(args, v...) - or = append(or, k...) - } - where = append(where, or) - case db.Raw: - if s, ok := t.Value.(string); ok == true { - where = append(where, sqlgen.Raw{s}) - } - case db.Cond: - k, v := conditionValues(t) - args = append(args, v...) - for _, kk := range k { - where = append(where, kk) - } - } - - return where, args -} - func (self *Table) Find(terms ...interface{}) db.Result { where, arguments := whereValues(terms) @@ -249,10 +277,6 @@ func (self *Table) Name() string { return strings.Join(self.names, `, `) } -func toInternalInterface(val interface{}) interface{} { - return toInternal(val) -} - // Converts a Go value into internal database representation. func toInternal(val interface{}) interface{} { switch t := val.(type) { @@ -271,39 +295,3 @@ func toInternal(val interface{}) interface{} { } return to.String(val) } - -// Convers a database representation (after auto-conversion) into a Go value. -func toNative(val interface{}) interface{} { - return val -} - -func interfaceArgs(value interface{}) (args []interface{}) { - - if value == nil { - return nil - } - - value_v := reflect.ValueOf(value) - - switch value_v.Type().Kind() { - case reflect.Slice: - var i, total int - - total = value_v.Len() - if total > 0 { - args = make([]interface{}, total) - - for i = 0; i < total; i++ { - args[i] = toInternal(value_v.Index(i).Interface()) - } - - return args - } else { - return nil - } - default: - args = []interface{}{toInternal(value)} - } - - return args -} diff --git a/postgresql/database.go b/postgresql/database.go index 32ad943d..360611a1 100644 --- a/postgresql/database.go +++ b/postgresql/database.go @@ -1,25 +1,23 @@ -/* - Copyright (c) 2012-2014 José Carlos Nieto, https://menteslibres.net/xiam - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ +// Copyright (c) 2012-2014 José Carlos Nieto, https://menteslibres.net/xiam +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package postgresql @@ -27,30 +25,29 @@ import ( "database/sql" "fmt" _ "github.com/xiam/gopostgresql" - "log" "os" "reflect" "regexp" "strings" "upper.io/db" "upper.io/db/util/sqlgen" + "upper.io/db/util/sqlutil" ) -// Format for saving dates. -var DateFormat = "2006-01-02 15:04:05" - -// Format for saving times. -var TimeFormat = "%d:%02d:%02d.%d" - -var SSLMode = "disable" - -var columnPattern = regexp.MustCompile(`^([a-z]+)\(?([0-9,]+)?\)?\s?([a-z]*)?`) - -var sqlPlaceholder = sqlgen.Value{sqlgen.Raw{`?`}} +const Driver = `postgresql` -var reInvisibleChars = regexp.MustCompile(`[\s\r\n\t]+`) +var ( + // Format for saving dates. + DateFormat = "2006-01-02 15:04:05" + // Format for saving times. + TimeFormat = "%d:%02d:%02d.%d" + SSLMode = "disable" +) -const Driver = `postgresql` +var ( + columnPattern = regexp.MustCompile(`^([a-z]+)\(?([0-9,]+)?\)?\s?([a-z]*)?`) + sqlPlaceholder = sqlgen.Value{sqlgen.Raw{`?`}} +) type Source struct { config db.Settings @@ -59,6 +56,11 @@ type Source struct { tx *sql.Tx } +type columnSchema_t struct { + ColumnName string `db:"column_name"` + DataType string `db:"data_type"` +} + func debugEnabled() bool { if os.Getenv(db.EnvEnableDebug) != "" { return true @@ -70,12 +72,6 @@ func init() { db.Register(Driver, &Source{}) } -func debugLogQuery(s string, args []interface{}) { - s = reInvisibleChars.ReplaceAllString(s, ` `) - s = strings.TrimSpace(s) - log.Printf("\n\tSQL: %s\n\tARGS: %v\n\n", s, args) -} - func (self *Source) doExec(stmt sqlgen.Statement, args ...interface{}) (sql.Result, error) { if self.session == nil { @@ -90,7 +86,7 @@ func (self *Source) doExec(stmt sqlgen.Statement, args ...interface{}) (sql.Resu } if debugEnabled() == true { - debugLogQuery(query, args) + sqlutil.DebugQuery(query, args) } if self.tx != nil { @@ -113,7 +109,7 @@ func (self *Source) doQuery(stmt sqlgen.Statement, args ...interface{}) (*sql.Ro } if debugEnabled() == true { - debugLogQuery(query, args) + sqlutil.DebugQuery(query, args) } if self.tx != nil { @@ -136,7 +132,7 @@ func (self *Source) doQueryRow(stmt sqlgen.Statement, args ...interface{}) (*sql } if debugEnabled() == true { - debugLogQuery(query, args) + sqlutil.DebugQuery(query, args) } if self.tx != nil { @@ -327,11 +323,6 @@ func (self *Source) tableExists(names ...string) error { return nil } -type pgColumnSchema struct { - ColumnName string `db:"column_name"` - DataType string `db:"data_type"` -} - // Returns a collection instance by name. func (self *Source) Collection(names ...string) (db.Collection, error) { @@ -346,7 +337,7 @@ func (self *Source) Collection(names ...string) (db.Collection, error) { col.PrimaryKey = `id` - columns_t := []pgColumnSchema{} + columns_t := []columnSchema_t{} for _, name := range names { chunks := strings.SplitN(name, " ", 2) diff --git a/postgresql/database_test.go b/postgresql/database_test.go index 70125420..69b60627 100644 --- a/postgresql/database_test.go +++ b/postgresql/database_test.go @@ -1,25 +1,23 @@ -/* - Copyright (c) 2012-2014 José Carlos Nieto, https://menteslibres.net/xiam - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ +// Copyright (c) 2012-2014 José Carlos Nieto, https://menteslibres.net/xiam +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package postgresql diff --git a/postgresql/result.go b/postgresql/result.go index 3e8459ea..57235ff5 100644 --- a/postgresql/result.go +++ b/postgresql/result.go @@ -1,25 +1,23 @@ -/* - Copyright (c) 2012-2014 José Carlos Nieto, https://menteslibres.net/xiam - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ +// Copyright (c) 2012-2014 José Carlos Nieto, https://menteslibres.net/xiam +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package postgresql @@ -37,12 +35,12 @@ type counter struct { type Result struct { table *Table cursor *sql.Rows // This is the main query cursor. It starts as a nil value. - arguments []interface{} limit sqlgen.Limit offset sqlgen.Offset columns sqlgen.Columns where sqlgen.Where orderBy sqlgen.OrderBy + arguments []interface{} } // Executes a SELECT statement that can feed Next(), All() or One(). diff --git a/postgresql/tx.go b/postgresql/tx.go index 149e036a..c28e20a8 100644 --- a/postgresql/tx.go +++ b/postgresql/tx.go @@ -1,3 +1,24 @@ +// Copyright (c) 2012-2014 José Carlos Nieto, https://menteslibres.net/xiam +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + package postgresql type Tx struct { diff --git a/util/sqlutil/main.go b/util/sqlutil/main.go index 445d4ec3..e41c3b09 100644 --- a/util/sqlutil/main.go +++ b/util/sqlutil/main.go @@ -25,25 +25,28 @@ package sqlutil import ( "database/sql" + "log" "menteslibres.net/gosexy/to" "reflect" + "regexp" "strings" "upper.io/db" "upper.io/db/util" ) +var ( + reInvisibleChars = regexp.MustCompile(`[\s\r\n\t]+`) +) + type T struct { PrimaryKey string ColumnTypes map[string]reflect.Kind } -type QueryChunks struct { - Fields []string - Limit string - Offset string - Sort string - Conditions string - Arguments []interface{} +func DebugQuery(s string, args []interface{}) { + s = reInvisibleChars.ReplaceAllString(s, ` `) + s = strings.TrimSpace(s) + log.Printf("\n\tSQL: %s\n\tARGS: %v\n\n", s, args) } func (self *T) ColumnLike(s string) string { @@ -352,8 +355,3 @@ func (self *T) FieldValues(item interface{}, convertFn func(interface{}) interfa return fields, values, nil } - -func NewQueryChunks() *QueryChunks { - self := &QueryChunks{} - return self -} -- GitLab