Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

join查询 #122

Merged
merged 29 commits into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
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
1 change: 0 additions & 1 deletion .deepsource.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,3 @@ enabled = true
[[analyzers]]
name = "sql"
enabled = true

2 changes: 2 additions & 0 deletions aggregate.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package eorm

// Aggregate represents aggregate expression, including AVG, MAX, MIN...
type Aggregate struct {
table TableReference
fn string
arg string
alias string
Expand All @@ -28,6 +29,7 @@ func (a Aggregate) As(alias string) Selectable {
fn: a.fn,
arg: a.arg,
alias: alias,
table: a.table,
}
}

Expand Down
28 changes: 14 additions & 14 deletions aggregate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,42 +26,42 @@ func TestAggregate(t *testing.T) {
testCases := []CommonTestCase{
{
name: "avg",
builder: NewSelector[TestModel](db).Select(Avg("Age")).From(&TestModel{}),
builder: NewSelector[TestModel](db).Select(Avg("Age")).From(TableOf(&TestModel{})),
wantSql: "SELECT AVG(`age`) FROM `test_model`;",
},
{
name: "max",
builder: NewSelector[TestModel](db).Select(Max("Age")).From(&TestModel{}),
builder: NewSelector[TestModel](db).Select(Max("Age")).From(TableOf(&TestModel{})),
wantSql: "SELECT MAX(`age`) FROM `test_model`;",
},
{
name: "min",
builder: NewSelector[TestModel](db).Select(Min("Age").As("min_age")).From(&TestModel{}),
builder: NewSelector[TestModel](db).Select(Min("Age").As("min_age")).From(TableOf(&TestModel{})),
wantSql: "SELECT MIN(`age`) AS `min_age` FROM `test_model`;",
},
{
name: "sum",
builder: NewSelector[TestModel](db).Select(Sum("Age")).From(&TestModel{}),
builder: NewSelector[TestModel](db).Select(Sum("Age")).From(TableOf(&TestModel{})),
wantSql: "SELECT SUM(`age`) FROM `test_model`;",
},
{
name: "count",
builder: NewSelector[TestModel](db).Select(Count("Age")).From(&TestModel{}),
builder: NewSelector[TestModel](db).Select(Count("Age")).From(TableOf(&TestModel{})),
wantSql: "SELECT COUNT(`age`) FROM `test_model`;",
},
{
name: "count distinct",
builder: NewSelector[TestModel](db).From(&TestModel{}).Select(CountDistinct("FirstName")),
builder: NewSelector[TestModel](db).From(TableOf(&TestModel{})).Select(CountDistinct("FirstName")),
wantSql: "SELECT COUNT(DISTINCT `first_name`) FROM `test_model`;",
},
{
name: "avg distinct",
builder: NewSelector[TestModel](db).From(&TestModel{}).Select(AvgDistinct("FirstName")),
builder: NewSelector[TestModel](db).From(TableOf(&TestModel{})).Select(AvgDistinct("FirstName")),
wantSql: "SELECT AVG(DISTINCT `first_name`) FROM `test_model`;",
},
{
name: "SUM distinct",
builder: NewSelector[TestModel](db).From(&TestModel{}).Select(SumDistinct("FirstName")),
builder: NewSelector[TestModel](db).From(TableOf(&TestModel{})).Select(SumDistinct("FirstName")),
wantSql: "SELECT SUM(DISTINCT `first_name`) FROM `test_model`;",
},
}
Expand All @@ -82,42 +82,42 @@ func TestAggregate(t *testing.T) {

func ExampleAggregate_As() {
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Avg("Age").As("avg_age")).From(&TestModel{}).Build()
query, _ := NewSelector[TestModel](db).Select(Avg("Age").As("avg_age")).From(TableOf(&TestModel{})).Build()
fmt.Println(query.SQL)
// Output: SELECT AVG(`age`) AS `avg_age` FROM `test_model`;
}

func ExampleAvg() {
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Avg("Age").As("avg_age")).From(&TestModel{}).Build()
query, _ := NewSelector[TestModel](db).Select(Avg("Age").As("avg_age")).From(TableOf(&TestModel{})).Build()
fmt.Println(query.SQL)
// Output: SELECT AVG(`age`) AS `avg_age` FROM `test_model`;
}

func ExampleCount() {
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Count("Age")).From(&TestModel{}).Build()
query, _ := NewSelector[TestModel](db).Select(Count("Age")).From(TableOf(&TestModel{})).Build()
fmt.Println(query.SQL)
// Output: SELECT COUNT(`age`) FROM `test_model`;
}

func ExampleMax() {
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Max("Age")).From(&TestModel{}).Build()
query, _ := NewSelector[TestModel](db).Select(Max("Age")).From(TableOf(&TestModel{})).Build()
fmt.Println(query.SQL)
// Output: SELECT MAX(`age`) FROM `test_model`;
}

func ExampleMin() {
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Min("Age")).From(&TestModel{}).Build()
query, _ := NewSelector[TestModel](db).Select(Min("Age")).From(TableOf(&TestModel{})).Build()
fmt.Println(query.SQL)
// Output: SELECT MIN(`age`) FROM `test_model`;
}

func ExampleSum() {
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Sum("Age")).From(&TestModel{}).Build()
query, _ := NewSelector[TestModel](db).Select(Sum("Age")).From(TableOf(&TestModel{})).Build()
fmt.Println(query.SQL)
// Output: SELECT SUM(`age`) FROM `test_model`;
}
48 changes: 48 additions & 0 deletions builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ func (b *builder) space() {
_ = b.buffer.WriteByte(' ')
}

func (b *builder) pointStar() {
_, _ = b.buffer.WriteString(".*")
}
func (b *builder) point() {
_ = b.buffer.WriteByte('.')
liangzai202204 marked this conversation as resolved.
Show resolved Hide resolved
}

func (b *builder) writeString(val string) {
_, _ = b.buffer.WriteString(val)
}
Expand Down Expand Up @@ -160,6 +167,10 @@ func (b *builder) buildExpr(expr Expr) error {
case RawExpr:
b.buildRawExpr(e)
case Column:
//b.buildColumn(e)
if _, ok := e.table.(Table); ok {
return b.buildColumn(e)
}
if e.name != "" {
_, ok := b.aliases[e.name]
if ok {
Expand Down Expand Up @@ -289,3 +300,40 @@ func (q Querier[T]) GetMulti(ctx context.Context) ([]*T, error) {
}
return res.Result.([]*T), nil
}

func (b *builder) buildColumn(c Column) error {
switch table := c.table.(type) {
case nil:
liangzai202204 marked this conversation as resolved.
Show resolved Hide resolved
fd, ok := b.meta.FieldMap[c.name]
// 字段不对,或者说列不对
if !ok {
return errs.NewInvalidColumnError(c.name)
}
b.quote(fd.ColumnName)
if c.alias != "" {
b.writeString(" AS ")
b.quote(c.alias)
}
case Table:
m, err := b.metaRegistry.Get(table.entity)
if err != nil {
return err
}
fd, ok := m.FieldMap[c.name]
if !ok {
return errs.NewInvalidColumnError(c.name)
}
if table.alias != "" {
b.quote(table.alias)
b.writeByte('.')
}
b.quote(fd.ColumnName)
if c.alias != "" {
b.writeString(" AS ")
b.quote(c.alias)
}
default:
return errs.NewErrUnsupportedTable(table)
}
return nil
}
2 changes: 2 additions & 0 deletions column.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package eorm
// 1. specify the column in query
// 2. it's the start point of building complex expression
type Column struct {
table TableReference
name string
alias string
}
Expand Down Expand Up @@ -88,6 +89,7 @@ func (c Column) GTEQ(val interface{}) Predicate {
// As means alias
func (c Column) As(alias string) Selectable {
return Column{
table: c.table,
name: c.name,
alias: alias,
}
Expand Down
27 changes: 9 additions & 18 deletions column_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ import "fmt"

func ExampleC() {
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").EQ(18)).Build()
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(TableOf(&TestModel{})).Where(C("Id").EQ(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
Expand All @@ -31,8 +30,7 @@ Args: %v

func ExampleColumn_EQ() {
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").EQ(18)).Build()
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(TableOf(&TestModel{})).Where(C("Id").EQ(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
Expand All @@ -57,8 +55,7 @@ Args: %v

func ExampleColumn_As() {
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id").As("my_id")).From(tm).Build()
query, _ := NewSelector[TestModel](db).Select(C("Id").As("my_id")).From(TableOf(&TestModel{})).Build()
fmt.Printf(`
SQL: %s
Args: %v
Expand All @@ -70,8 +67,7 @@ Args: %v

func ExampleColumn_GT() {
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").GT(18)).Build()
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(TableOf(&TestModel{})).Where(C("Id").GT(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
Expand All @@ -83,8 +79,7 @@ Args: %v

func ExampleColumn_GTEQ() {
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").GTEQ(18)).Build()
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(TableOf(&TestModel{})).Where(C("Id").GTEQ(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
Expand All @@ -96,8 +91,7 @@ Args: %v

func ExampleColumn_LT() {
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").LT(18)).Build()
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(TableOf(&TestModel{})).Where(C("Id").LT(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
Expand All @@ -109,8 +103,7 @@ Args: %v

func ExampleColumn_LTEQ() {
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").LTEQ(18)).Build()
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(TableOf(&TestModel{})).Where(C("Id").LTEQ(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
Expand All @@ -135,8 +128,7 @@ Args: %v

func ExampleColumn_NEQ() {
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").NEQ(18)).Build()
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(TableOf(&TestModel{})).Where(C("Id").NEQ(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
Expand All @@ -148,8 +140,7 @@ Args: %v

func ExampleColumns() {
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(Columns("Id", "Age")).From(tm).Build()
query, _ := NewSelector[TestModel](db).Select(Columns("Id", "Age")).From(TableOf(&TestModel{})).Build()
fmt.Printf(`
SQL: %s
Args: %v
Expand Down
4 changes: 2 additions & 2 deletions db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ func BenchmarkQuerier_Get(b *testing.B) {
Creator: valuer.NewUnsafeValue,
}
for i := 0; i < b.N; i++ {
_, err = NewSelector[TestModel](orm).From(&TestModel{}).Get(context.Background())
_, err = NewSelector[TestModel](orm).From(TableOf(&TestModel{})).Get(context.Background())
if err != nil {
b.Fatal(err)
}
Expand All @@ -200,7 +200,7 @@ func BenchmarkQuerier_Get(b *testing.B) {
Creator: valuer.NewReflectValue,
}
for i := 0; i < b.N; i++ {
_, err = NewSelector[TestModel](orm).From(&TestModel{}).Get(context.Background())
_, err = NewSelector[TestModel](orm).From(TableOf(&TestModel{})).Get(context.Background())
if err != nil {
b.Fatal(err)
}
Expand Down
8 changes: 4 additions & 4 deletions expression_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,20 @@ func TestRawExpr_AsPredicate(t *testing.T) {
testCases := []CommonTestCase{
{
name: "simple",
builder: NewSelector[TestModel](db).From(&TestModel{}).Where(Raw("`id`<?", 12).AsPredicate()),
builder: NewSelector[TestModel](db).From(TableOf(&TestModel{})).Where(Raw("`id`<?", 12).AsPredicate()),
wantSql: "SELECT `id`,`first_name`,`age`,`last_name` FROM `test_model` WHERE `id`<?;",
wantArgs: []interface{}{12},
},
{
name: "and",
builder: NewSelector[TestModel](db).From(&TestModel{}).Where(Raw("`id`<?", 12).AsPredicate().
builder: NewSelector[TestModel](db).From(TableOf(&TestModel{})).Where(Raw("`id`<?", 12).AsPredicate().
And(Raw("`age`<?", 18).AsPredicate())),
wantSql: "SELECT `id`,`first_name`,`age`,`last_name` FROM `test_model` WHERE (`id`<?) AND (`age`<?);",
wantArgs: []interface{}{12, 18},
},
{
name: "Or",
builder: NewSelector[TestModel](db).From(&TestModel{}).Where(Raw("`id`<?", 12).AsPredicate().
builder: NewSelector[TestModel](db).From(TableOf(&TestModel{})).Where(Raw("`id`<?", 12).AsPredicate().
Or(Raw("`age`<?", 18).AsPredicate())),
wantSql: "SELECT `id`,`first_name`,`age`,`last_name` FROM `test_model` WHERE (`id`<?) OR (`age`<?);",
wantArgs: []interface{}{12, 18},
Expand All @@ -62,7 +62,7 @@ func TestRawExpr_AsPredicate(t *testing.T) {

func ExampleRawExpr_AsPredicate() {
pred := Raw("`id`<?", 12).AsPredicate()
query, _ := NewSelector[TestModel](memoryDB()).From(&TestModel{}).Where(pred).Build()
query, _ := NewSelector[TestModel](memoryDB()).From(TableOf(&TestModel{})).Where(pred).Build()
fmt.Println(query.string())
// Output:
// SQL: SELECT `id`,`first_name`,`age`,`last_name` FROM `test_model` WHERE `id`<?;
Expand Down
10 changes: 10 additions & 0 deletions internal/errs/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
)

var (
ErrPointerOnly = errors.New("eorm: 只支持指向结构体的一级指针")
errValueNotSet = errors.New("eorm: 值未设置")
ErrNoRows = errors.New("eorm: 未找到数据")
// ErrTooManyColumns 过多列
Expand Down Expand Up @@ -63,3 +64,12 @@ func NewUnsupportedTypeError(typ reflect.Type) error {
func NewUnsupportedDriverError(driver string) error {
return fmt.Errorf("eorm: 不支持driver类型 %s", driver)
}

// NewErrUnsupportedTable 不支持的TableReference类型
func NewErrUnsupportedTable(table any) error {
return fmt.Errorf("eorm: 不支持的TableReference类型 %v", table)
}

func NewErrUnknownField(name string) error {
return fmt.Errorf("eorm: 未知字段 %s", name)
}
Loading