Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ea25728
添加各类型的测试
liangfujian Jun 11, 2023
42e47e2
datetime timezone support
wangzuo Jun 9, 2023
5763d79
JSON for queryx.Integer
wangzuo Jun 9, 2023
fd65044
JSON support for queryx.Datetime
wangzuo Jun 9, 2023
de4c4ca
fix NewNullableJSON
wangzuo Jun 9, 2023
52f670a
添加测试用例
liangfujian Jun 13, 2023
b424ce0
Merge branch 'main' into hotfix/testType
liangfujian Jun 13, 2023
21fbab8
fix float
liangfujian Jun 13, 2023
b253e69
添加marshal,Unmarshal的实现已经测试
liangfujian Jun 14, 2023
cbba17a
实现字段排序
liangfujian Jun 14, 2023
74a6514
update UnmarshalJSON
liangfujian Jun 14, 2023
d637885
update UnmarshalJSON
liangfujian Jun 14, 2023
906bd06
update datetime_test
liangfujian Jun 14, 2023
8c56ca5
update datetime_test
liangfujian Jun 14, 2023
03010fb
json.Unmarshal => t.UnmarshalJSON
liangfujian Jun 14, 2023
bf75d52
update test
liangfujian Jun 14, 2023
6c005a8
update test
liangfujian Jun 14, 2023
3dfa416
update TestDatetimeValue
liangfujian Jun 15, 2023
968c72a
Merge branch 'main' into hotfix/testType
wangzuo Jun 15, 2023
256e2e8
update github linguist
wangzuo Jun 15, 2023
e467786
update for github linguist
wangzuo Jun 15, 2023
a6391a1
model associations with json tag
wangzuo Jun 17, 2023
a6a6f1a
support custom class_name and foreign_key in belongs_to
wangzuo Jun 17, 2023
a7407cc
add TestHasManyEmpty
wangzuo Jun 19, 2023
3d06a83
fix TestHasManyEmpty
liangfujian Jun 20, 2023
c7439e1
fmt tmpl
liangfujian Jun 20, 2023
a8b7e99
add test
liangfujian Jun 20, 2023
4da1124
add TestInEmptySlice
wangzuo Jun 20, 2023
570d7d2
添加测试用例
liangfujian Jun 20, 2023
66e5381
删除多余包
liangfujian Jun 20, 2023
464dece
fix action
liangfujian Jun 20, 2023
e11cffd
rename class_name to model_name
wangzuo Jun 21, 2023
5b8098e
fmt templates
wangzuo Jun 21, 2023
0a472b0
update test
liangfujian Jun 21, 2023
715adb0
fix bigint json and testing
wangzuo Jun 21, 2023
420e353
fmt
wangzuo Jun 21, 2023
c6f5f77
more type testing
wangzuo Jun 22, 2023
a0af23d
more type fix
wangzuo Jun 22, 2023
27391a2
fix test for query methods
wangzuo Jun 22, 2023
60740e2
fmt
wangzuo Jun 22, 2023
1c830e8
datetime utc in json
wangzuo Jun 22, 2023
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
3 changes: 2 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.gotmpl linguist-language=Go
*.go linguist-language=Go linguist-generated=false
*.gotmpl linguist-language=Go linguist-generated=false
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ test-postgresql: install
cd internal/integration && QUERYX_ENV=test queryx db:create --schema postgresql.hcl
cd internal/integration && QUERYX_ENV=test queryx db:migrate --schema postgresql.hcl
cd internal/integration && QUERYX_ENV=test queryx generate --schema postgresql.hcl
cd internal/integration && go test -v ./...
cd internal/integration && go test ./...
# cd internal/integration && QUERYX_ENV=test queryx db:drop --schema postgresql.hcl

test-mysql: install mysql-drop
Expand Down
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,21 @@ post, err := c.QueryPost().Where(c.PostTitle.EQ("post title")).First()

Queryx supports association definition in the schema file. It also generates corresponding preload query methods to avoid "N+1" query.

## has_one and belongs_to
## belongs_to

```hcl
model "Post" {
belongs_to "Author" {
model_name = "User"
}
}
```

```go
c.QueryPost().PreloadAuthor().All()
```

## has_one

```hcl
model "User" {
Expand All @@ -199,7 +213,7 @@ c.QueryUser().PreloadAccount().All()
c.QueryAccount().PreloadUser().All()
```

## has_many and belongs_to
## has_many

```hcl
model "User" {
Expand Down
4 changes: 2 additions & 2 deletions generator/client/golang/templates/[model].gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ type {{ $.model.Name }} struct {
{{ $b.Name | pascal }} *{{ $b.ModelName }} `json:"{{ camel $b.Name }}"`
{{- end }}
{{- range $h := $.model.HasMany }}
{{ $h.Name | pascal }} []*{{ $h.ModelName }}
{{ $h.Name | pascal }} []*{{ $h.ModelName }} `json:"{{ $h.Name | camel }}"`
{{- end }}
{{- range $h := $.model.HasOne }}
{{ $h.Name | pascal }} *{{ $h.ModelName }}
{{ $h.Name | pascal }} *{{ $h.ModelName }} `json:"{{ $h.Name | camel }}"`
{{- end }}

schema *queryx.Schema
Expand Down
30 changes: 21 additions & 9 deletions generator/client/golang/templates/[model]_query.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ func (q *{{ $.model.Name }}Query) Preload{{ pascal $b.Name }}() *{{ $.model.Name
func (q *{{ $.model.Name }}Query) preload{{ pascal $b.Name }}(rows []*{{ $.model.Name }}) error {
ids := []int64{}
for _, r := range rows {
if !r.{{ $b.ModelName }}ID.Null {
ids = append(ids, r.{{ $b.ModelName }}ID.Val)
if !r.{{ $b.ForeignKey | pascal }}.Null {
ids = append(ids, r.{{ $b.ForeignKey | pascal }}.Val)
}
}
rows1, err := q.queries.Query{{ $b.ModelName }}().Where(q.schema.{{ $b.ModelName }}ID.In(ids)).All()
Expand All @@ -207,8 +207,8 @@ func (q *{{ $.model.Name }}Query) preload{{ pascal $b.Name }}(rows []*{{ $.model
m[r.ID] = r
}
for _, r := range rows {
if !r.{{ $b.ModelName }}ID.Null {
r.{{ $b.ModelName }} = m[r.{{ $b.ModelName }}ID.Val]
if !r.{{ $b.ForeignKey | pascal }}.Null {
r.{{ $b.Name | pascal }} = m[r.{{ $b.ForeignKey | pascal }}.Val]
}
}

Expand Down Expand Up @@ -240,7 +240,11 @@ func (q *{{ $.model.Name }}Query) preload{{ pascal $h.Name }}(rows []*{{ $.model
m1[r.{{ $.model.Name }}ID.Val] = append(m1[r.{{ $.model.Name }}ID.Val], r)
}
for _, r := range rows {
r.{{ $h.Through | pascal }} = m1[r.ID]
if m1[r.ID] != nil {
r.{{ $h.Through | pascal }} = m1[r.ID]
} else {
r.{{ $h.Through | pascal }} = make([]*{{ $m }}, 0)
}
}

ids1 := []int64{}
Expand All @@ -264,7 +268,11 @@ func (q *{{ $.model.Name }}Query) preload{{ pascal $h.Name }}(rows []*{{ $.model
m3[r.{{ $.model.Name }}ID.Val] = append(m3[r.{{ $.model.Name }}ID.Val], r.{{ $h.ModelName }})
}
for _, r := range rows {
r.{{ $h.Name | pascal }} = m3[r.ID]
if m3[r.ID] != nil {
r.{{ $h.Name | pascal }} = m3[r.ID]
} else {
r.{{ $h.Name | pascal }} = make([]*{{ $h.ModelName }},0)
}
}
{{- else }}
rows1, err := q.queries.Query{{ $h.ModelName }}().Where(q.schema.{{ $h.ModelName }}{{ $.model.Name }}ID.In(ids)).All()
Expand All @@ -277,7 +285,11 @@ func (q *{{ $.model.Name }}Query) preload{{ pascal $h.Name }}(rows []*{{ $.model
m[r.{{ $.model.Name }}ID.Val] = append(m[r.{{ $.model.Name }}ID.Val], r)
}
for _, r := range rows {
r.{{ $h.Name | pascal }} = m[r.ID]
if m[r.ID] != nil {
r.{{ $h.Name | pascal }} = m[r.ID]
} else {
r.{{ $h.Name | pascal }} = make([]*{{ $h.ModelName }}, 0)
}
}
{{- end }}

Expand Down Expand Up @@ -320,15 +332,15 @@ func (q *{{.model.Name}}Query) All() ([]*{{.model.Name}}, error) {
}
var rows []{{ $.model.Name }}
{{- $var1 := $.model.Name | camel | plural }}
var {{ $var1 }} []*{{ $.model.Name }}
{{ $var1 }} := make([]*{{ $.model.Name }}, 0)
query, args := q.selectStatement.ToSQL()
err := q.adapter.Query(query, args...).Scan(&rows)
if err != nil {
return nil, err
}

if len(rows) == 0 {
return nil, err
return {{ $var1 }}, nil
}

for i := range rows {
Expand Down
17 changes: 15 additions & 2 deletions generator/client/golang/templates/queryx/bigint.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package queryx
import (
"database/sql"
"database/sql/driver"
"encoding/json"
)

type BigInt struct {
Expand Down Expand Up @@ -43,10 +44,22 @@ func (b BigInt) Value() (driver.Value, error) {
return b.Val, nil
}

// MarshalJSON implements the json.Marshaler interface.
func (b BigInt) MarshalJSON() ([]byte, error) {
return nil, nil
if b.Null {
return json.Marshal(nil)
}
return json.Marshal(b.Val)
}

func (b *BigInt) UnmarshalJSON(text []byte) error {
// UnmarshalJSON implements the json.Unmarshaler interface.
func (b *BigInt) UnmarshalJSON(data []byte) error {
if string(data) == "null" {
b.Null = true
return nil
}
if err := json.Unmarshal(data, &b.Val); err != nil {
return err
}
return nil
}
5 changes: 5 additions & 0 deletions generator/client/golang/templates/queryx/bigint_column.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ func (c *BigIntColumn) GE(v int64) *Clause {
}

func (c *BigIntColumn) In(v []int64) *Clause {
if len(v) == 0 {
return &Clause{
fragment: fmt.Sprintf("1=0"),
}
}
return &Clause{
fragment: fmt.Sprintf("%s.%s IN (?)", c.Table.Name, c.Name),
args: []interface{}{v},
Expand Down
40 changes: 40 additions & 0 deletions generator/client/golang/templates/queryx/bigint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Code generated by queryx, DO NOT EDIT.

package queryx

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/require"
)

func TestNewBigInt(t *testing.T) {
b1 := NewBigInt(2)
require.Equal(t, int64(2), b1.Val)
require.Equal(t, false, b1.Null)

b2 := NewNullableBigInt(nil)
require.Equal(t, true, b2.Null)
}

func TestBigIntJSON(t *testing.T) {
type Foo struct {
X BigInt `json:"x"`
Y BigInt `json:"y"`
}
x := NewBigInt(2)
y := NewNullableBigInt(nil)
s := `{"x":2,"y":null}`

f1 := Foo{X: x, Y: y}
b, err := json.Marshal(f1)
require.NoError(t, err)
require.Equal(t, s, string(b))

var f2 Foo
err = json.Unmarshal([]byte(s), &f2)
require.NoError(t, err)
require.Equal(t, x, f2.X)
require.Equal(t, y, f2.Y)
}
21 changes: 21 additions & 0 deletions generator/client/golang/templates/queryx/boolean.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package queryx
import (
"database/sql"
"database/sql/driver"
"encoding/json"
)

type Boolean struct {
Expand Down Expand Up @@ -42,3 +43,23 @@ func (b Boolean) Value() (driver.Value, error) {
}
return b.Val, nil
}

// MarshalJSON implements the json.Marshaler interface.
func (b Boolean) MarshalJSON() ([]byte, error) {
if b.Null {
return json.Marshal(nil)
}
return json.Marshal(b.Val)
}

// UnmarshalJSON implements the json.Unmarshaler interface.
func (b *Boolean) UnmarshalJSON(data []byte) error {
if string(data) == "null" {
b.Null = true
return nil
}
if err := json.Unmarshal(data, &b.Val); err != nil {
return err
}
return nil
}
8 changes: 8 additions & 0 deletions generator/client/golang/templates/queryx/boolean_column.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,11 @@ func (c *BooleanColumn) NE(v bool) *Clause {
args: []interface{}{v},
}
}

func (b *BooleanColumn) Asc() string {
return fmt.Sprintf("%s.%s ASC", b.Table.Name, b.Name)
}

func (b *BooleanColumn) Desc() string {
return fmt.Sprintf("%s.%s DESC", b.Table.Name, b.Name)
}
40 changes: 40 additions & 0 deletions generator/client/golang/templates/queryx/boolean_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Code generated by queryx, DO NOT EDIT.

package queryx

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/require"
)

func TestNewBoolean(t *testing.T) {
b1 := NewBoolean(true)
require.Equal(t, true, b1.Val)
require.Equal(t, false, b1.Null)

b2 := NewNullableBoolean(nil)
require.Equal(t, true, b2.Null)
}

func TestBooleanJSON(t *testing.T) {
type Foo struct {
X Boolean `json:"x"`
Y Boolean `json:"y"`
}
x := NewBoolean(true)
y := NewNullableBoolean(nil)
s := `{"x":true,"y":null}`

f1 := Foo{X: x, Y: y}
b, err := json.Marshal(f1)
require.NoError(t, err)
require.Equal(t, s, string(b))

var f2 Foo
err = json.Unmarshal([]byte(s), &f2)
require.NoError(t, err)
require.Equal(t, x, f2.X)
require.Equal(t, y, f2.Y)
}
19 changes: 17 additions & 2 deletions generator/client/golang/templates/queryx/date.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,28 @@ func (d Date) Value() (driver.Value, error) {
return d.Val, nil
}

// MarshalJSON implements the json.Marshaler interface.
func (d Date) MarshalJSON() ([]byte, error) {
if d.Null {
return json.Marshal(nil)
}
return json.Marshal(d.Val)
return json.Marshal(d.Val.Format("2006-01-02"))
}

func (d *Date) UnmarshalJSON(text []byte) error {
// UnmarshalJSON implements the json.Unmarshaler interface.
func (d *Date) UnmarshalJSON(data []byte) error {
s := string(data)
if s == "null" || s == "" {
d.Null = true
return nil
}

s = s[len(`"`) : len(s)-len(`"`)]
t, err := parseDate(s)
if err != nil {
return err
}

d.Val = *t
return nil
}
8 changes: 8 additions & 0 deletions generator/client/golang/templates/queryx/date_column.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,11 @@ func (c *DateColumn) GT(v string) *Clause {
err: err,
}
}

func (c *DateColumn) Asc() string {
return fmt.Sprintf("%s.%s ASC", c.Table.Name, c.Name)
}

func (c *DateColumn) Desc() string {
return fmt.Sprintf("%s.%s DESC", c.Table.Name, c.Name)
}
40 changes: 40 additions & 0 deletions generator/client/golang/templates/queryx/date_test.gotmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Code generated by queryx, DO NOT EDIT.

package queryx

import (
"testing"
"time"

"github.com/stretchr/testify/require"
)

func TestNewDate(t *testing.T) {
d1 := NewDate("2012-11-10")
require.Equal(t, "2012-11-10", d1.Val.Format("2006-01-02"))
require.Equal(t, false, d1.Null)

d2 := NewNullableDate(nil)
require.Equal(t, true, d2.Null)
}

func TestDateJSON(t *testing.T) {
type Foo struct {
X Date `json:"x"`
Y Date `json:"y"`
}
x := NewDate("2012-11-10")
y := NewNullableDate(nil)
s := `{"x":"2012-11-10","y":null}`

f1 := Foo{X: x, Y: y}
b, err := json.Marshal(f1)
require.NoError(t, err)
require.Equal(t, s, string(b))

var f2 Foo
err = json.Unmarshal([]byte(s), &f2)
require.NoError(t, err)
require.Equal(t, x, f2.X)
require.Equal(t, y, f2.Y)
}
Loading