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

feat: apply ModelTableExpr for SELECT query #975

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 12 additions & 0 deletions internal/dbtest/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1545,6 +1545,18 @@ func TestQuery(t *testing.T) {
return db.NewInsert().Model(new(Model))
},
},
{
id: 167,
query: func(db *bun.DB) schema.QueryAppender {
return db.NewSelect().Model(new(Model)).ModelTableExpr("renamed")
},
},
{
id: 168,
query: func(db *bun.DB) schema.QueryAppender {
return db.NewSelect().Model(new(Model)).ModelTableExpr("renamed AS r")
},
},
}

timeRE := regexp.MustCompile(`'2\d{3}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(\.\d+)?(\+\d{2}:\d{2})?'`)
Expand Down
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mariadb-167
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT renamed.`id`, renamed.`str` FROM renamed
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mariadb-168
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT r.`id`, r.`str` FROM renamed AS r
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mssql2019-167
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT renamed."id", renamed."str" FROM renamed
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mssql2019-168
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT r."id", r."str" FROM renamed AS r
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql5-167
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT renamed.`id`, renamed.`str` FROM renamed
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql5-168
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT r.`id`, r.`str` FROM renamed AS r
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql8-167
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT renamed.`id`, renamed.`str` FROM renamed
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-mysql8-168
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT r.`id`, r.`str` FROM renamed AS r
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pg-167
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT renamed."id", renamed."str" FROM renamed
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pg-168
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT r."id", r."str" FROM renamed AS r
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pgx-167
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT renamed."id", renamed."str" FROM renamed
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-pgx-168
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT r."id", r."str" FROM renamed AS r
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-sqlite-167
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT renamed."id", renamed."str" FROM renamed
1 change: 1 addition & 0 deletions internal/dbtest/testdata/snapshots/TestQuery-sqlite-168
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT r."id", r."str" FROM renamed AS r
67 changes: 67 additions & 0 deletions internal/tableparser/parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package tableparser

import "strings"

type Table struct {
name string
alias string
}

func (t Table) IsZero() bool {
return t.name == "" && t.alias == ""
}

func (t Table) Name() string {
if t.alias != "" {
return t.alias
}
return t.name
}

func Parse(query string) Table {
if query == "" {
return Table{}
}
cleanedQuery := cleanQuery(query)
table := parseQuery(cleanedQuery)
return table
}

func cleanQuery(query string) string {
// Trim the query to remove any leading or trailing spaces.
trimmedQuery := strings.TrimSpace(query)

// Lowercase the keyword AS
cleanedQuery := strings.ReplaceAll(trimmedQuery, " AS ", " as ")

return cleanedQuery
}

func parseQuery(query string) Table {
if hasAlias(query) {
return parseWithAlias(query)
}
return Table{
name: query,
}
}

func hasAlias(query string) bool {
return strings.Contains(query, " as ") ||
strings.Contains(query, " ")
}

func parseWithAlias(query string) Table {
if strings.Contains(query, " as ") {
sp := strings.Split(query, " as ")
return Table{
name: strings.TrimSpace(sp[0]),
alias: strings.TrimSpace(sp[1]),
}
}
sp := strings.Split(query, " ")
return Table{
name: strings.TrimSpace(sp[0]),
alias: strings.TrimSpace(sp[1]),
}
}
209 changes: 209 additions & 0 deletions internal/tableparser/parser_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
package tableparser

import (
"testing"

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

func TestTable_IsZero(t *testing.T) {
type fields struct {
name string
alias string
}
tests := []struct {
name string
fields fields
want bool
}{
{
name: "return true if both name and alias are empty",
fields: fields{
name: "",
alias: "",
},
want: true,
},
{
name: "return false if name is not empty",
fields: fields{
name: "users",
alias: "",
},
want: false,
},
{
name: "return false if alias is not empty",
fields: fields{
name: "",
alias: "u",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
table := Table{
name: tt.fields.name,
alias: tt.fields.alias,
}
got := table.IsZero()
require.Equal(t, tt.want, got)
})
}
}

func TestTable_Name(t *testing.T) {
type fields struct {
name string
alias string
}
tests := []struct {
name string
fields fields
want string
}{
{
name: "return alias if alias is not empty",
fields: fields{
name: "users",
alias: "u",
},
want: "u",
},
{
name: "return name if alias is empty",
fields: fields{
name: "users",
alias: "",
},
want: "users",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
table := Table{
name: tt.fields.name,
alias: tt.fields.alias,
}
got := table.Name()
require.Equal(t, tt.want, got)
})
}

}

func Test_cleanQuery(t *testing.T) {
type args struct {
query string
}
tests := []struct {
name string
args args
want string
}{
{
name: "check if the query without alias is trimmed",
args: args{
query: " users ",
},
want: "users",
},
{
name: "check if the query with alias is trimmed",
args: args{
query: " users as u ",
},
want: "users as u",
},
{
name: "check if the keyword AS is lowercase",
args: args{
query: "users AS u",
},
want: "users as u",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := cleanQuery(tt.args.query)
require.Equal(t, tt.want, got)
})
}
}

func Test_hasAlias(t *testing.T) {
type args struct {
query string
}
tests := []struct {
name string
args args
want bool
}{
{
name: "check if the query has alias with keyword",
args: args{
query: "users as u",
},
want: true,
},
{
name: "check if the query has alias without keyword",
args: args{
query: "users u",
},
want: true,
},
{
name: "check if the query has no alias",
args: args{
query: "users",
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := hasAlias(tt.args.query)
require.Equal(t, tt.want, got)
})
}
}

func Test_parseWithAlias(t *testing.T) {
type args struct {
query string
}
tests := []struct {
name string
args args
want Table
}{
{
name: "parse query with keyword",
args: args{
query: "users as u",
},
want: Table{
name: "users",
alias: "u",
},
},
{
name: "parse query without keyword",
args: args{
query: "users u",
},
want: Table{
name: "users",
alias: "u",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := parseWithAlias(tt.args.query)
require.Equal(t, tt.want, got)
})
}
}
25 changes: 11 additions & 14 deletions query_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ type baseQuery struct {

tableModel TableModel
table *schema.Table
modelTable schema.ModelTable // store table info specified by ModelTableExpr method

with []withQuery
modelTableName schema.QueryWithArgs
tables []schema.QueryWithArgs
columns []schema.QueryWithArgs
with []withQuery
tables []schema.QueryWithArgs
columns []schema.QueryWithArgs

flags internal.Flag
}
Expand Down Expand Up @@ -132,8 +132,8 @@ func (q *baseQuery) GetTableName() string {
}
}

if q.modelTableName.Query != "" {
return q.modelTableName.Query
if q.modelTable.HasTableName() {
return q.modelTable.GetTableName(q.db.fmter)
}

if len(q.tables) > 0 {
Expand Down Expand Up @@ -382,10 +382,7 @@ func (q *baseQuery) _excludeColumn(column string) bool {
//------------------------------------------------------------------------------

func (q *baseQuery) modelHasTableName() bool {
if !q.modelTableName.IsZero() {
return q.modelTableName.Query != ""
}
return q.table != nil
return q.modelTable.HasTableName() || q.table != nil
}

func (q *baseQuery) hasTables() bool {
Expand All @@ -410,8 +407,8 @@ func (q *baseQuery) _appendTables(
startLen := len(b)

if q.modelHasTableName() {
if !q.modelTableName.IsZero() {
b, err = q.modelTableName.AppendQuery(fmter, b)
if !q.modelTable.IsZero() {
b, err = q.modelTable.AppendQuery(fmter, b)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -450,8 +447,8 @@ func (q *baseQuery) appendFirstTableWithAlias(
func (q *baseQuery) _appendFirstTable(
fmter schema.Formatter, b []byte, withAlias bool,
) ([]byte, error) {
if !q.modelTableName.IsZero() {
return q.modelTableName.AppendQuery(fmter, b)
if !q.modelTable.IsZero() {
return q.modelTable.AppendQuery(fmter, b)
}

if q.table != nil {
Expand Down
2 changes: 1 addition & 1 deletion query_column_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (q *AddColumnQuery) TableExpr(query string, args ...interface{}) *AddColumn
}

func (q *AddColumnQuery) ModelTableExpr(query string, args ...interface{}) *AddColumnQuery {
q.modelTableName = schema.SafeQuery(query, args)
q.modelTable = schema.NewModelTable(query, args...)
return q
}

Expand Down
Loading
Loading