From f93636eab0105ab08a995fc73716dec456b1dbcb Mon Sep 17 00:00:00 2001 From: go-jet Date: Wed, 17 Aug 2022 13:03:03 +0200 Subject: [PATCH] Add missing sqlite conditional functions. --- sqlite/functions.go | 8 +++- tests/mysql/select_test.go | 86 +++++++++++++++++++++++++++++++++++ tests/postgres/select_test.go | 86 +++++++++++++++++++++++++++++++++++ tests/sqlite/select_test.go | 72 +++++++++++++++++++++++++++++ 4 files changed, 251 insertions(+), 1 deletion(-) diff --git a/sqlite/functions.go b/sqlite/functions.go index d714274..47a0a5b 100644 --- a/sqlite/functions.go +++ b/sqlite/functions.go @@ -342,7 +342,13 @@ func UNIX_TIMESTAMP(str StringExpression) TimestampExpression { return jet.NewTimestampFunc("UNIX_TIMESTAMP", str) } -//----------- Comparison operators ---------------// +// --------------- Conditional Expressions Functions -------------// + +// COALESCE function returns the first of its arguments that is not null. +var COALESCE = jet.COALESCE + +// NULLIF function returns a null value if value1 equals value2; otherwise it returns value1. +var NULLIF = jet.NULLIF // EXISTS checks for existence of the rows in subQuery var EXISTS = jet.EXISTS diff --git a/tests/mysql/select_test.go b/tests/mysql/select_test.go index 024d941..d6f7bcb 100644 --- a/tests/mysql/select_test.go +++ b/tests/mysql/select_test.go @@ -1103,3 +1103,89 @@ func TestScanIntoCustomBaseTypes(t *testing.T) { require.Equal(t, testutils.ToJSON(films), testutils.ToJSON(myFilms)) } + +func TestConditionalFunctions(t *testing.T) { + stmt := SELECT( + EXISTS( + Film.SELECT(Film.FilmID).WHERE(Film.RentalDuration.GT(Int(100))), + ).AS("exists"), + CASE(Film.Length.GT(Int(120))). + WHEN(Bool(true)).THEN(String("long film")). + ELSE(String("short film")).AS("case"), + COALESCE(Film.Description, String("none")).AS("coalesce"), + NULLIF(Film.ReleaseYear, Int(200)).AS("null_if"), + GREATEST(Film.RentalDuration, Int(4), Int(5)).AS("greatest"), + LEAST(Film.RentalDuration, Int(7), Int(6)).AS("least"), + ).FROM( + Film, + ).WHERE( + Film.FilmID.LT(Int(5)), + ).ORDER_BY( + Film.FilmID, + ) + + testutils.AssertDebugStatementSql(t, stmt, ` +SELECT (EXISTS ( + SELECT film.film_id AS "film.film_id" + FROM dvds.film + WHERE film.rental_duration > 100 + )) AS "exists", + (CASE (film.length > 120) WHEN TRUE THEN 'long film' ELSE 'short film' END) AS "case", + COALESCE(film.description, 'none') AS "coalesce", + NULLIF(film.release_year, 200) AS "null_if", + GREATEST(film.rental_duration, 4, 5) AS "greatest", + LEAST(film.rental_duration, 7, 6) AS "least" +FROM dvds.film +WHERE film.film_id < 5 +ORDER BY film.film_id; +`) + + var res []struct { + Exists string + Case string + Coalesce string + NullIf string + Greatest string + Least string + } + + err := stmt.Query(db, &res) + require.NoError(t, err) + + testutils.AssertJSON(t, res, ` +[ + { + "Exists": "0", + "Case": "short film", + "Coalesce": "A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies", + "NullIf": "2006", + "Greatest": "6", + "Least": "6" + }, + { + "Exists": "0", + "Case": "short film", + "Coalesce": "A Astounding Epistle of a Database Administrator And a Explorer who must Find a Car in Ancient China", + "NullIf": "2006", + "Greatest": "5", + "Least": "3" + }, + { + "Exists": "0", + "Case": "short film", + "Coalesce": "A Astounding Reflection of a Lumberjack And a Car who must Sink a Lumberjack in A Baloon Factory", + "NullIf": "2006", + "Greatest": "7", + "Least": "6" + }, + { + "Exists": "0", + "Case": "short film", + "Coalesce": "A Fanciful Documentary of a Frisbee And a Lumberjack who must Chase a Monkey in A Shark Tank", + "NullIf": "2006", + "Greatest": "5", + "Least": "5" + } +] +`) +} diff --git a/tests/postgres/select_test.go b/tests/postgres/select_test.go index dce9b87..5f34daa 100644 --- a/tests/postgres/select_test.go +++ b/tests/postgres/select_test.go @@ -2723,6 +2723,92 @@ func TestScanUsingConn(t *testing.T) { }) } +func TestConditionalFunctions(t *testing.T) { + stmt := SELECT( + EXISTS( + Film.SELECT(Film.FilmID).WHERE(Film.RentalDuration.GT(Int(100))), + ).AS("exists"), + CASE(Film.Length.GT(Int(120))). + WHEN(Bool(true)).THEN(String("long film")). + ELSE(String("short film")).AS("case"), + COALESCE(Film.Description, String("none")).AS("coalesce"), + NULLIF(Film.ReleaseYear, Int(200)).AS("null_if"), + GREATEST(Film.RentalDuration, Int(4), Int(5)).AS("greatest"), + LEAST(Film.RentalDuration, Int(7), Int(6)).AS("least"), + ).FROM( + Film, + ).WHERE( + Film.FilmID.LT(Int(5)), + ).ORDER_BY( + Film.FilmID, + ) + + testutils.AssertDebugStatementSql(t, stmt, ` +SELECT (EXISTS ( + SELECT film.film_id AS "film.film_id" + FROM dvds.film + WHERE film.rental_duration > 100 + )) AS "exists", + (CASE (film.length > 120) WHEN TRUE::boolean THEN 'long film'::text ELSE 'short film'::text END) AS "case", + COALESCE(film.description, 'none'::text) AS "coalesce", + NULLIF(film.release_year, 200) AS "null_if", + GREATEST(film.rental_duration, 4, 5) AS "greatest", + LEAST(film.rental_duration, 7, 6) AS "least" +FROM dvds.film +WHERE film.film_id < 5 +ORDER BY film.film_id; +`) + + var res []struct { + Exists bool + Case string + Coalesce string + NullIf string + Greatest string + Least string + } + + err := stmt.Query(db, &res) + require.NoError(t, err) + + testutils.AssertJSON(t, res, ` +[ + { + "Exists": false, + "Case": "short film", + "Coalesce": "A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies", + "NullIf": "2006", + "Greatest": "6", + "Least": "6" + }, + { + "Exists": false, + "Case": "short film", + "Coalesce": "A Astounding Epistle of a Database Administrator And a Explorer who must Find a Car in Ancient China", + "NullIf": "2006", + "Greatest": "5", + "Least": "3" + }, + { + "Exists": false, + "Case": "short film", + "Coalesce": "A Astounding Reflection of a Lumberjack And a Car who must Sink a Lumberjack in A Baloon Factory", + "NullIf": "2006", + "Greatest": "7", + "Least": "6" + }, + { + "Exists": false, + "Case": "short film", + "Coalesce": "A Fanciful Documentary of a Frisbee And a Lumberjack who must Chase a Monkey in A Shark Tank", + "NullIf": "2006", + "Greatest": "5", + "Least": "5" + } +] +`) +} + var customer0 = model.Customer{ CustomerID: 1, StoreID: 1, diff --git a/tests/sqlite/select_test.go b/tests/sqlite/select_test.go index 657fb3a..5f093ce 100644 --- a/tests/sqlite/select_test.go +++ b/tests/sqlite/select_test.go @@ -810,3 +810,75 @@ func TestScanNumericToNumber(t *testing.T) { require.Equal(t, number.Float32, float32(1.234568e+09)) require.Equal(t, number.Float64, float64(1.234567890111e+09)) } + +func TestConditionalFunctions(t *testing.T) { + stmt := SELECT( + EXISTS( + Film.SELECT(Film.FilmID).WHERE(Film.RentalDuration.GT(Int(5))), + ).AS("exists"), + CASE(Film.Length.GT(Int(120))). + WHEN(Bool(true)).THEN(String("long film")). + ELSE(String("short film")).AS("case"), + COALESCE(Film.Description, String("none")).AS("coalesce"), + NULLIF(Film.ReleaseYear, Int(200)).AS("null_if"), + ).FROM( + Film, + ).WHERE( + Film.FilmID.LT(Int(5)), + ).ORDER_BY( + Film.FilmID, + ) + + testutils.AssertDebugStatementSql(t, stmt, ` +SELECT (EXISTS ( + SELECT film.film_id AS "film.film_id" + FROM film + WHERE film.rental_duration > 5 + )) AS "exists", + (CASE (film.length > 120) WHEN TRUE THEN 'long film' ELSE 'short film' END) AS "case", + COALESCE(film.description, 'none') AS "coalesce", + NULLIF(film.release_year, 200) AS "null_if" +FROM film +WHERE film.film_id < 5 +ORDER BY film.film_id; +`) + + var res []struct { + Exists bool + Case string + Coalesce string + NullIf string + } + + err := stmt.Query(db, &res) + require.NoError(t, err) + + testutils.AssertJSON(t, res, ` +[ + { + "Exists": true, + "Case": "short film", + "Coalesce": "A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies", + "NullIf": "2006" + }, + { + "Exists": true, + "Case": "short film", + "Coalesce": "A Astounding Epistle of a Database Administrator And a Explorer who must Find a Car in Ancient China", + "NullIf": "2006" + }, + { + "Exists": true, + "Case": "short film", + "Coalesce": "A Astounding Reflection of a Lumberjack And a Car who must Sink a Lumberjack in A Baloon Factory", + "NullIf": "2006" + }, + { + "Exists": true, + "Case": "short film", + "Coalesce": "A Fanciful Documentary of a Frisbee And a Lumberjack who must Chase a Monkey in A Shark Tank", + "NullIf": "2006" + } +] +`) +}