good morning!!!!
Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
U
upper
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
1
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Container Registry
Harbor Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
open
upper
Commits
1713c426
Commit
1713c426
authored
9 years ago
by
José Carlos Nieto
Browse files
Options
Downloads
Patches
Plain Diff
Adding fmt.Stringer for other builder types and giving another try to Iterator.
parent
b7056bf5
No related branches found
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
builder.go
+7
-3
7 additions, 3 deletions
builder.go
postgresql/builder.go
+115
-66
115 additions, 66 deletions
postgresql/builder.go
postgresql/database_test.go
+76
-41
76 additions, 41 deletions
postgresql/database_test.go
postgresql/template.go
+7
-0
7 additions, 0 deletions
postgresql/template.go
with
205 additions
and
110 deletions
builder.go
+
7
−
3
View file @
1713c426
...
...
@@ -34,7 +34,7 @@ type QuerySelector interface {
Offset
(
int
)
QuerySelector
QueryGetter
Result
Iterator
Iterator
fmt
.
Stringer
}
...
...
@@ -43,6 +43,7 @@ type QueryInserter interface {
Columns
(
...
string
)
QueryInserter
QueryExecer
fmt
.
Stringer
}
type
QueryDeleter
interface
{
...
...
@@ -50,6 +51,7 @@ type QueryDeleter interface {
Limit
(
int
)
QueryDeleter
QueryExecer
fmt
.
Stringer
}
type
QueryUpdater
interface
{
...
...
@@ -58,6 +60,7 @@ type QueryUpdater interface {
Limit
(
int
)
QueryUpdater
QueryExecer
fmt
.
Stringer
}
type
QueryExecer
interface
{
...
...
@@ -69,9 +72,10 @@ type QueryGetter interface {
QueryRow
()
(
*
sqlx
.
Row
,
error
)
}
type
Result
Iterator
interface
{
type
Iterator
interface
{
All
(
interface
{})
error
Next
(
interface
{})
error
One
(
interface
{})
error
Next
(
interface
{})
bool
Err
()
error
Close
()
error
}
This diff is collapsed.
Click to expand it.
postgresql/builder.go
+
115
−
66
View file @
1713c426
...
...
@@ -28,64 +28,69 @@ type Builder struct {
}
func
(
b
*
Builder
)
SelectAllFrom
(
table
string
)
db
.
QuerySelector
{
return
&
QuerySelector
{
qs
:=
&
QuerySelector
{
builder
:
b
,
table
:
table
,
}
qs
.
stringer
=
&
stringer
{
qs
}
return
qs
}
func
(
b
*
Builder
)
Select
(
columns
...
interface
{})
db
.
QuerySelector
{
f
,
err
:=
columnFragments
(
columns
)
return
&
QuerySelector
{
qs
:=
&
QuerySelector
{
builder
:
b
,
columns
:
sqlgen
.
JoinColumns
(
f
...
),
err
:
err
,
}
qs
.
stringer
=
&
stringer
{
qs
}
return
qs
}
func
(
b
*
Builder
)
InsertInto
(
table
string
)
db
.
QueryInserter
{
return
&
QueryInserter
{
qi
:=
&
QueryInserter
{
builder
:
b
,
table
:
table
,
}
qi
.
stringer
=
&
stringer
{
qi
}
return
qi
}
func
(
b
*
Builder
)
DeleteFrom
(
table
string
)
db
.
QueryDeleter
{
return
&
QueryDeleter
{
qd
:=
&
QueryDeleter
{
builder
:
b
,
table
:
table
,
}
qd
.
stringer
=
&
stringer
{
qd
}
return
qd
}
func
(
b
*
Builder
)
Update
(
table
string
)
db
.
QueryUpdater
{
return
&
QueryUpdater
{
qu
:=
&
QueryUpdater
{
builder
:
b
,
table
:
table
,
}
qu
.
stringer
=
&
stringer
{
qu
}
return
qu
}
type
QueryInserter
struct
{
builder
*
Builder
table
string
values
[]
*
sqlgen
.
Values
columns
[]
sqlgen
.
Fragment
*
stringer
builder
*
Builder
table
string
values
[]
*
sqlgen
.
Values
columns
[]
sqlgen
.
Fragment
arguments
[]
interface
{}
}
func
(
qi
*
QueryInserter
)
Exec
()
(
sql
.
Result
,
error
)
{
stmt
:=
&
sqlgen
.
Statement
{
Type
:
sqlgen
.
Insert
,
Table
:
sqlgen
.
TableWithName
(
qi
.
table
),
}
if
len
(
qi
.
values
)
>
0
{
stmt
.
Values
=
sqlgen
.
JoinValueGroups
(
qi
.
values
...
)
}
if
len
(
qi
.
columns
)
>
0
{
stmt
.
Columns
=
sqlgen
.
JoinColumns
(
qi
.
columns
...
)
}
return
qi
.
builder
.
sess
.
Exec
(
stmt
)
return
qi
.
builder
.
sess
.
Exec
(
qi
.
statement
())
}
func
(
qi
*
QueryInserter
)
Columns
(
columns
...
string
)
db
.
QueryInserter
{
...
...
@@ -99,31 +104,49 @@ func (qi *QueryInserter) Columns(columns ...string) db.QueryInserter {
}
func
(
qi
*
QueryInserter
)
Values
(
values
...
interface
{})
db
.
QueryInserter
{
l
:=
len
(
values
)
f
:=
make
([]
sqlgen
.
Frag
ment
,
l
)
for
i
:=
0
;
i
<
l
;
i
++
{
if
_
,
ok
:=
values
[
i
]
.
(
db
.
Raw
);
ok
{
f
[
i
]
=
sqlgen
.
NewValue
(
sqlgen
.
RawValue
(
fmt
.
Sprintf
(
"%v"
,
values
[
i
]))
)
}
else
{
f
[
i
]
=
sqlgen
.
Ne
wValue
(
values
[
i
]
)
if
len
(
qi
.
columns
)
==
0
||
len
(
values
)
==
len
(
qi
.
columns
)
{
qi
.
arguments
=
append
(
qi
.
argu
ment
s
,
values
...
)
l
:=
len
(
values
)
placeholders
:=
make
([]
sqlgen
.
Fragment
,
l
)
for
i
:=
0
;
i
<
l
;
i
++
{
placeholders
[
i
]
=
sqlgen
.
Ra
wValue
(
`?`
)
}
qi
.
values
=
append
(
qi
.
values
,
sqlgen
.
NewValueGroup
(
placeholders
...
))
}
qi
.
values
=
append
(
qi
.
values
,
sqlgen
.
NewValueGroup
(
f
...
))
return
qi
}
func
(
qi
*
QueryInserter
)
statement
()
*
sqlgen
.
Statement
{
stmt
:=
&
sqlgen
.
Statement
{
Type
:
sqlgen
.
Insert
,
Table
:
sqlgen
.
TableWithName
(
qi
.
table
),
}
if
len
(
qi
.
values
)
>
0
{
stmt
.
Values
=
sqlgen
.
JoinValueGroups
(
qi
.
values
...
)
}
if
len
(
qi
.
columns
)
>
0
{
stmt
.
Columns
=
sqlgen
.
JoinColumns
(
qi
.
columns
...
)
}
return
stmt
}
type
QueryDeleter
struct
{
builder
*
Builder
table
string
limit
int
where
*
sqlgen
.
Where
args
[]
interface
{}
*
stringer
builder
*
Builder
table
string
limit
int
where
*
sqlgen
.
Where
arguments
[]
interface
{}
}
func
(
qd
*
QueryDeleter
)
Where
(
terms
...
interface
{})
db
.
QueryDeleter
{
where
,
arguments
:=
template
.
ToWhereWithArguments
(
terms
)
qd
.
where
=
&
where
qd
.
args
=
append
(
qd
.
args
,
arguments
...
)
qd
.
arg
ument
s
=
append
(
qd
.
arg
ument
s
,
arguments
...
)
return
qd
}
...
...
@@ -133,6 +156,10 @@ func (qd *QueryDeleter) Limit(limit int) db.QueryDeleter {
}
func
(
qd
*
QueryDeleter
)
Exec
()
(
sql
.
Result
,
error
)
{
return
qd
.
builder
.
sess
.
Exec
(
qd
.
statement
(),
qd
.
arguments
...
)
}
func
(
qd
*
QueryDeleter
)
statement
()
*
sqlgen
.
Statement
{
stmt
:=
&
sqlgen
.
Statement
{
Type
:
sqlgen
.
Delete
,
Table
:
sqlgen
.
TableWithName
(
qd
.
table
),
...
...
@@ -146,33 +173,43 @@ func (qd *QueryDeleter) Exec() (sql.Result, error) {
stmt
.
Limit
=
sqlgen
.
Limit
(
qd
.
limit
)
}
return
qd
.
builder
.
sess
.
Exec
(
stmt
,
qd
.
args
...
)
return
stmt
}
type
QueryUpdater
struct
{
*
stringer
builder
*
Builder
table
string
columnValues
*
sqlgen
.
ColumnValues
limit
int
where
*
sqlgen
.
Where
arg
s
[]
interface
{}
arg
uments
[]
interface
{}
}
func
(
qu
*
QueryUpdater
)
Set
(
terms
...
interface
{})
db
.
QueryUpdater
{
cv
,
args
:=
template
.
ToColumnValues
(
terms
)
cv
,
arg
ument
s
:=
template
.
ToColumnValues
(
terms
)
qu
.
columnValues
=
&
cv
qu
.
args
=
append
(
qu
.
args
,
args
...
)
qu
.
arg
ument
s
=
append
(
qu
.
arg
ument
s
,
arg
ument
s
...
)
return
qu
}
func
(
qu
*
QueryUpdater
)
Where
(
terms
...
interface
{})
db
.
QueryUpdater
{
where
,
arguments
:=
template
.
ToWhereWithArguments
(
terms
)
qu
.
where
=
&
where
qu
.
args
=
append
(
qu
.
args
,
arguments
...
)
qu
.
arg
ument
s
=
append
(
qu
.
arg
ument
s
,
arguments
...
)
return
qu
}
func
(
qu
*
QueryUpdater
)
Exec
()
(
sql
.
Result
,
error
)
{
return
qu
.
builder
.
sess
.
Exec
(
qu
.
statement
(),
qu
.
arguments
...
)
}
func
(
qu
*
QueryUpdater
)
Limit
(
limit
int
)
db
.
QueryUpdater
{
qu
.
limit
=
limit
return
qu
}
func
(
qu
*
QueryUpdater
)
statement
()
*
sqlgen
.
Statement
{
stmt
:=
&
sqlgen
.
Statement
{
Type
:
sqlgen
.
Update
,
Table
:
sqlgen
.
TableWithName
(
qu
.
table
),
...
...
@@ -187,15 +224,11 @@ func (qu *QueryUpdater) Exec() (sql.Result, error) {
stmt
.
Limit
=
sqlgen
.
Limit
(
qu
.
limit
)
}
return
qu
.
builder
.
sess
.
Exec
(
stmt
,
qu
.
args
...
)
}
func
(
qu
*
QueryUpdater
)
Limit
(
limit
int
)
db
.
QueryUpdater
{
qu
.
limit
=
limit
return
qu
return
stmt
}
type
QuerySelector
struct
{
*
stringer
mode
SelectMode
cursor
*
sqlx
.
Rows
// This is the main query cursor. It starts as a nil value.
builder
*
Builder
...
...
@@ -386,9 +419,6 @@ func (qs *QuerySelector) QueryRow() (*sqlx.Row, error) {
}
func
(
qs
*
QuerySelector
)
Close
()
(
err
error
)
{
if
qs
.
err
!=
nil
{
return
qs
.
err
}
if
qs
.
cursor
!=
nil
{
err
=
qs
.
cursor
.
Close
()
qs
.
cursor
=
nil
...
...
@@ -404,8 +434,6 @@ func (qs *QuerySelector) setCursor() (err error) {
}
func
(
qs
*
QuerySelector
)
One
(
dst
interface
{})
error
{
var
err
error
if
qs
.
err
!=
nil
{
return
qs
.
err
}
...
...
@@ -416,9 +444,11 @@ func (qs *QuerySelector) One(dst interface{}) error {
defer
qs
.
Close
()
err
=
qs
.
Next
(
dst
)
if
!
qs
.
Next
(
dst
)
{
return
qs
.
Err
()
}
return
err
return
nil
}
func
(
qs
*
QuerySelector
)
All
(
dst
interface
{})
error
{
...
...
@@ -446,28 +476,30 @@ func (qs *QuerySelector) All(dst interface{}) error {
return
err
}
func
(
qs
*
QuerySelector
)
Next
(
dst
interface
{})
(
err
error
)
{
func
(
qs
*
QuerySelector
)
Err
()
(
err
error
)
{
return
qs
.
err
}
func
(
qs
*
QuerySelector
)
Next
(
dst
interface
{})
bool
{
var
err
error
if
qs
.
err
!=
nil
{
return
qs
.
err
return
false
}
if
err
=
qs
.
setCursor
();
err
!=
nil
{
qs
.
err
=
err
qs
.
Close
()
return
err
return
false
}
if
err
=
sqlutil
.
FetchRow
(
qs
.
cursor
,
dst
);
err
!=
nil
{
qs
.
err
=
err
qs
.
Close
()
return
err
return
false
}
return
nil
}
func
(
qs
*
QuerySelector
)
String
()
string
{
q
:=
compileAndReplacePlaceholders
(
qs
.
statement
())
q
=
reInvisibleChars
.
ReplaceAllString
(
q
,
` `
)
return
strings
.
TrimSpace
(
q
)
return
true
}
func
columnFragments
(
columns
[]
interface
{})
([]
sqlgen
.
Fragment
,
error
)
{
...
...
@@ -477,7 +509,7 @@ func columnFragments(columns []interface{}) ([]sqlgen.Fragment, error) {
for
i
:=
0
;
i
<
l
;
i
++
{
switch
v
:=
columns
[
i
]
.
(
type
)
{
case
db
.
Raw
:
f
[
i
]
=
sqlgen
.
RawValue
(
fmt
.
Sprintf
(
"%v"
,
v
))
f
[
i
]
=
sqlgen
.
RawValue
(
fmt
.
Sprintf
(
"%v"
,
v
.
Value
))
case
sqlgen
.
Fragment
:
f
[
i
]
=
v
case
string
:
...
...
@@ -491,3 +523,20 @@ func columnFragments(columns []interface{}) ([]sqlgen.Fragment, error) {
return
f
,
nil
}
type
hasStatement
interface
{
statement
()
*
sqlgen
.
Statement
}
type
stringer
struct
{
i
hasStatement
}
func
(
s
*
stringer
)
String
()
string
{
if
s
!=
nil
&&
s
.
i
!=
nil
{
q
:=
compileAndReplacePlaceholders
(
s
.
i
.
statement
())
q
=
reInvisibleChars
.
ReplaceAllString
(
q
,
` `
)
return
strings
.
TrimSpace
(
q
)
}
return
""
}
This diff is collapsed.
Click to expand it.
postgresql/database_test.go
+
76
−
41
View file @
1713c426
...
...
@@ -1917,10 +1917,6 @@ func TestOptionTypeJsonbStruct(t *testing.T) {
func
TestQueryBuilder
(
t
*
testing
.
T
)
{
var
sess
db
.
Database
var
err
error
var
sel
db
.
QuerySelector
var
artist
artistType
assert
:=
assert
.
New
(
t
)
if
sess
,
err
=
db
.
Open
(
Adapter
,
settings
);
err
!=
nil
{
t
.
Fatal
(
err
)
...
...
@@ -1930,6 +1926,10 @@ func TestQueryBuilder(t *testing.T) {
b
:=
sess
.
Builder
()
assert
:=
assert
.
New
(
t
)
// Testing SELECT.
assert
.
Equal
(
`SELECT * FROM "artist"`
,
b
.
SelectAllFrom
(
"artist"
)
.
String
(),
...
...
@@ -2038,51 +2038,58 @@ func TestQueryBuilder(t *testing.T) {
b
.
SelectAllFrom
(
"artist"
)
.
Join
(
"publication"
)
.
Using
(
"id"
)
.
String
(),
)
// Should not work because we are using both "On()" and "Using()"
sel
=
b
.
Select
()
.
From
(
"artist a"
)
.
Join
(
"publications p"
)
.
On
(
"p1.id = a.id"
)
.
Using
(
"id"
)
assert
.
Error
(
sel
.
One
(
&
artist
))
assert
.
Equal
(
`SELECT DATE()`
,
b
.
Select
(
db
.
Raw
{
"DATE()"
})
.
String
(),
)
// Should not work because a Join() is missing before On().
sel
=
b
.
Select
()
.
From
(
"artist a"
)
.
On
(
"p1.id = a.id"
)
assert
.
Error
(
sel
.
One
(
&
artist
))
// Testing INSERT.
// INSERT INTO artist VALUES (10, 'Ryuichi Sakamoto'), (11, 'Alondra de la Parra')
if
_
,
err
=
b
.
InsertInto
(
"artist"
)
.
Values
(
10
,
"Ryuichi Sakamoto"
)
.
Values
(
11
,
"Alondra de la Parra"
)
.
Exec
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
assert
.
Equal
(
`INSERT INTO "artist" VALUES ($1, $2), ($3, $4), ($5, $6)`
,
b
.
InsertInto
(
"artist"
)
.
Values
(
10
,
"Ryuichi Sakamoto"
)
.
Values
(
11
,
"Alondra de la Parra"
)
.
Values
(
12
,
"Haruki Murakami"
)
.
String
(),
)
// INSERT INTO artist COLUMNS("name") VALUES('Chavela Vargas')
if
_
,
err
=
b
.
InsertInto
(
"artist"
)
.
Columns
(
"name"
,
"id"
)
.
Values
(
"Chavela Vargas"
,
1
2
)
.
Exec
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
assert
.
Equal
(
`INSERT INTO "artist" ("name", "id") VALUES ($1
,
$
2)
`
,
b
.
InsertInto
(
"artist"
)
.
Columns
(
"name"
,
"id"
)
.
Values
(
"Chavela Vargas"
,
12
)
.
String
(),
)
// DELETE FROM artist WHERE name = 'Chavela Vargas' LIMIT 1
if
_
,
err
=
b
.
DeleteFrom
(
"artist"
)
.
Where
(
"name = ?"
,
"Chavela Vargas"
)
.
Limit
(
1
)
.
Exec
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
// Testing DELETE.
// DELETE FROM artist WHERE id > 5
if
_
,
err
=
b
.
DeleteFrom
(
"artist"
)
.
Where
(
"id > 5"
)
.
Exec
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
assert
.
Equal
(
`DELETE FROM "artist" WHERE (name = $1) LIMIT 1`
,
b
.
DeleteFrom
(
"artist"
)
.
Where
(
"name = ?"
,
"Chavela Vargas"
)
.
Limit
(
1
)
.
String
(),
)
// UPDATE artist SET name = ?
if
_
,
err
=
b
.
Update
(
"artist"
)
.
Set
(
"name"
,
"Artist"
)
.
Exec
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
assert
.
Equal
(
`DELETE FROM "artist" WHERE (id > 5)`
,
b
.
DeleteFrom
(
"artist"
)
.
Where
(
"id > 5"
)
.
String
(),
)
// UPDATE artist SET name = ? WHERE id < 5
if
_
,
err
=
b
.
Update
(
"artist"
)
.
Set
(
"name = ?"
,
"Artist"
)
.
Where
(
"id < ?"
,
5
)
.
Exec
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
// Testing UPDATE.
// UPDATE artist SET name = ? || ' ' || ? || id, id = id + ? WHERE id > ?
if
_
,
err
=
b
.
Update
(
"artist"
)
.
Set
(
"name = ? || ' ' || ? || id"
,
"Artist"
,
"#"
,
"id = id + ?"
,
10
,
)
.
Where
(
"id > ?"
,
0
)
.
Exec
();
err
!=
nil
{
t
.
Fatal
(
err
)
}
assert
.
Equal
(
`UPDATE "artist" SET "name" = $1`
,
b
.
Update
(
"artist"
)
.
Set
(
"name"
,
"Artist"
)
.
String
(),
)
assert
.
Equal
(
`UPDATE "artist" SET "name" = $1 WHERE ("id" < $2)`
,
b
.
Update
(
"artist"
)
.
Set
(
"name = ?"
,
"Artist"
)
.
Where
(
"id <"
,
5
)
.
String
(),
)
assert
.
Equal
(
`UPDATE "artist" SET "name" = $1 || ' ' || $2 || id, "id" = id + $3 WHERE (id > $4)`
,
b
.
Update
(
"artist"
)
.
Set
(
"name = ? || ' ' || ? || id"
,
"Artist"
,
"#"
,
"id = id + ?"
,
10
,
)
.
Where
(
"id > ?"
,
0
)
.
String
(),
)
/*
// INSERT INTO artist (name) VALUES(? || ?)
...
...
@@ -2105,6 +2112,34 @@ func TestQueryBuilder(t *testing.T) {
}
*/
// Testing actual queries.
var
artist
artistType
var
artists
[]
artistType
err
=
b
.
SelectAllFrom
(
"artist"
)
.
All
(
&
artists
)
assert
.
NoError
(
err
)
assert
.
True
(
len
(
artists
)
>
0
)
err
=
b
.
SelectAllFrom
(
"artist"
)
.
One
(
&
artist
)
assert
.
NoError
(
err
)
assert
.
NotNil
(
artist
)
var
qs
db
.
QuerySelector
qs
=
b
.
SelectAllFrom
(
"artist"
)
for
qs
.
Next
(
&
artist
)
{
assert
.
Nil
(
qs
.
Err
())
assert
.
NotNil
(
artist
)
}
assert
.
Nil
(
qs
.
Close
())
qs
=
b
.
Select
()
.
From
(
"artist a"
)
.
Join
(
"publications p"
)
.
On
(
"p1.id = a.id"
)
.
Using
(
"id"
)
assert
.
Error
(
qs
.
One
(
&
artist
),
`Should not work because it attempts to use both "On()" and "Using()" in the same JOIN.`
)
qs
=
b
.
Select
()
.
From
(
"artist a"
)
.
On
(
"p1.id = a.id"
)
assert
.
Error
(
qs
.
One
(
&
artist
),
`Should not work because it should put a "Join()" before "On()".`
)
}
// TestExhaustConnections simulates a "too many connections" situation
...
...
This diff is collapsed.
Click to expand it.
postgresql/template.go
+
7
−
0
View file @
1713c426
...
...
@@ -114,6 +114,13 @@ const (
DELETE
FROM {{.Table}}
{{.Where}}
{{if .Limit}}
LIMIT {{.Limit}}
{{end}}
{{if .Offset}}
OFFSET {{.Offset}}
{{end}}
`
adapterUpdateLayout
=
`
UPDATE
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment