diff --git a/pgm.go b/pgm.go index b8e08db..c47c4c3 100644 --- a/pgm.go +++ b/pgm.go @@ -73,6 +73,16 @@ func (f Field) Trim() Field { return Field("TRIM(" + f.String() + ")") } +func (f Field) IsNull() Conditioner { + col := f.String() + return &Cond{Field: col, op: " IS NULL", len: len(col) + 8} +} + +func (f Field) IsNotNull() Conditioner { + col := f.String() + return &Cond{Field: col, op: " IS NOT NULL", len: len(col) + 12} +} + // Eq is equal func (f Field) Eq(val any) Conditioner { col := f.String() diff --git a/playground/qry_select_test.go b/playground/qry_select_test.go index e7facd2..beba10c 100644 --- a/playground/qry_select_test.go +++ b/playground/qry_select_test.go @@ -30,6 +30,7 @@ func TestQryBuilder2(t *testing.T) { Where( user.LastName.NEq(7), user.Phone.Like("%123%"), + user.UpdatedAt.IsNotNull(), user.Email.NotInSubQuery(db.User.Select(user.ID).Where(user.ID.Eq(123))), ). Limit(10). @@ -39,7 +40,7 @@ func TestQryBuilder2(t *testing.T) { expected := "SELECT users.email, users.first_name FROM users JOIN user_sessions ON users.id = user_sessions.user_id" + " JOIN branch_users ON users.id = branch_users.user_id WHERE users.id = $1 AND (users.status_id = $2 OR users.updated_at = $3)" + " AND users.mfa_kind = $4 AND (users.first_name = $5 OR users.middle_name = $6) AND users.last_name != $7 AND users.phone" + - " LIKE $8 AND users.email NOT IN(SELECT users.id FROM users WHERE users.id = $9) LIMIT 10 OFFSET 100" + " LIKE $8 AND users.updated_at IS NOT NULL AND users.email NOT IN(SELECT users.id FROM users WHERE users.id = $9) LIMIT 10 OFFSET 100" if expected != got { t.Errorf("\nexpected: %q\ngot: %q", expected, got) } diff --git a/qry.go b/qry.go index 0203a48..e396dec 100644 --- a/qry.go +++ b/qry.go @@ -208,12 +208,16 @@ func (cv *Cond) Condition(args *[]any, argIdx int) string { } // 2. normal condition - *args = append(*args, cv.Val) var op string - if strings.HasSuffix(cv.op, "$") { - op = cv.op + strconv.Itoa(argIdx+1) + if cv.Val != nil { + *args = append(*args, cv.Val) + if strings.HasSuffix(cv.op, "$") { + op = cv.op + strconv.Itoa(argIdx+1) + } else { + op = strings.Replace(cv.op, "$", "$"+strconv.Itoa(argIdx+1), 1) + } } else { - op = strings.Replace(cv.op, "$", "$"+strconv.Itoa(argIdx+1), 1) + op = cv.op } if cv.action == CondActionNeedToClose {