diff --git a/contrib/drivers/mysql/mysql_feature_model_join_test.go b/contrib/drivers/mysql/mysql_feature_model_join_test.go index 548d8b75095..af1acd993b9 100644 --- a/contrib/drivers/mysql/mysql_feature_model_join_test.go +++ b/contrib/drivers/mysql/mysql_feature_model_join_test.go @@ -83,6 +83,75 @@ func Test_Model_InnerJoinOnField(t *testing.T) { }) } +func Test_Model_LeftJoinOnFields(t *testing.T) { + var ( + table1 = gtime.TimestampNanoStr() + "_table1" + table2 = gtime.TimestampNanoStr() + "_table2" + ) + createInitTable(table1) + defer dropTable(table1) + createInitTable(table2) + defer dropTable(table2) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table1). + FieldsPrefix(table1, "*"). + LeftJoinOnFields(table2, "id", "=", "id"). + WhereIn("id", g.Slice{1, 2}). + Order("id asc").All() + t.AssertNil(err) + t.Assert(len(r), 2) + t.Assert(r[0]["id"], "1") + t.Assert(r[1]["id"], "2") + }) +} + +func Test_Model_RightJoinOnFields(t *testing.T) { + var ( + table1 = gtime.TimestampNanoStr() + "_table1" + table2 = gtime.TimestampNanoStr() + "_table2" + ) + createInitTable(table1) + defer dropTable(table1) + createInitTable(table2) + defer dropTable(table2) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table1). + FieldsPrefix(table1, "*"). + RightJoinOnFields(table2, "id", "=", "id"). + WhereIn("id", g.Slice{1, 2}). + Order("id asc").All() + t.AssertNil(err) + t.Assert(len(r), 2) + t.Assert(r[0]["id"], "1") + t.Assert(r[1]["id"], "2") + }) +} + +func Test_Model_InnerJoinOnFields(t *testing.T) { + var ( + table1 = gtime.TimestampNanoStr() + "_table1" + table2 = gtime.TimestampNanoStr() + "_table2" + ) + createInitTable(table1) + defer dropTable(table1) + createInitTable(table2) + defer dropTable(table2) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table1). + FieldsPrefix(table1, "*"). + InnerJoinOnFields(table2, "id", "=", "id"). + WhereIn("id", g.Slice{1, 2}). + Order("id asc").All() + t.AssertNil(err) + t.Assert(len(r), 2) + t.Assert(r[0]["id"], "1") + t.Assert(r[1]["id"], "2") + }) +} + func Test_Model_FieldsPrefix(t *testing.T) { var ( table1 = gtime.TimestampNanoStr() + "_table1" diff --git a/database/gdb/gdb_model_join.go b/database/gdb/gdb_model_join.go index 62387b66c19..ce4dbf1ab38 100644 --- a/database/gdb/gdb_model_join.go +++ b/database/gdb/gdb_model_join.go @@ -104,6 +104,57 @@ func (m *Model) InnerJoinOnField(table, field string) *Model { )) } +// LeftJoinOnFields performs as LeftJoin. It specifies different fields and comparison operator. +// +// Eg: +// Model("user").LeftJoinOnFields("order", "id", "=", "user_id") +// Model("user").LeftJoinOnFields("order", "id", ">", "user_id") +// Model("user").LeftJoinOnFields("order", "id", "<", "user_id") +func (m *Model) LeftJoinOnFields(table, firstField, operator, secondField string) *Model { + return m.doJoin("LEFT", table, fmt.Sprintf( + `%s.%s %s %s.%s`, + m.tablesInit, + m.db.GetCore().QuoteWord(firstField), + operator, + m.db.GetCore().QuoteWord(table), + m.db.GetCore().QuoteWord(secondField), + )) +} + +// RightJoinOnFields performs as RightJoin. It specifies different fields and comparison operator. +// +// Eg: +// Model("user").RightJoinOnFields("order", "id", "=", "user_id") +// Model("user").RightJoinOnFields("order", "id", ">", "user_id") +// Model("user").RightJoinOnFields("order", "id", "<", "user_id") +func (m *Model) RightJoinOnFields(table, firstField, operator, secondField string) *Model { + return m.doJoin("RIGHT", table, fmt.Sprintf( + `%s.%s %s %s.%s`, + m.tablesInit, + m.db.GetCore().QuoteWord(firstField), + operator, + m.db.GetCore().QuoteWord(table), + m.db.GetCore().QuoteWord(secondField), + )) +} + +// InnerJoinOnFields performs as InnerJoin. It specifies different fields and comparison operator. +// +// Eg: +// Model("user").InnerJoinOnFields("order", "id", "=", "user_id") +// Model("user").InnerJoinOnFields("order", "id", ">", "user_id") +// Model("user").InnerJoinOnFields("order", "id", "<", "user_id") +func (m *Model) InnerJoinOnFields(table, firstField, operator, secondField string) *Model { + return m.doJoin("INNER", table, fmt.Sprintf( + `%s.%s %s %s.%s`, + m.tablesInit, + m.db.GetCore().QuoteWord(firstField), + operator, + m.db.GetCore().QuoteWord(table), + m.db.GetCore().QuoteWord(secondField), + )) +} + // doJoin does "LEFT/RIGHT/INNER JOIN ... ON ..." statement on the model. // The parameter `table` can be joined table and its joined condition, // and also with its alias name.