From 4ce508862da1685c3afaf47314fd8a08a7c56c16 Mon Sep 17 00:00:00 2001 From: Thomas Kienlen Date: Wed, 31 May 2017 15:44:12 +0200 Subject: [PATCH 1/3] select: order_by limit --- lib/rebel/sql.rb | 36 ++++++++++++++++++++++++++++++++---- test/test_exec.rb | 17 +++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/lib/rebel/sql.rb b/lib/rebel/sql.rb index d3d980e..40cf33e 100644 --- a/lib/rebel/sql.rb +++ b/lib/rebel/sql.rb @@ -13,13 +13,15 @@ module Rebel::SQL exec(Rebel::SQL.drop_table(table_name)) end - def select(*fields, from: nil, where: nil, inner: nil, left: nil, right: nil) + def select(*fields, from: nil, where: nil, inner: nil, left: nil, right: nil, order_by: nil, limit: nil) exec(Rebel::SQL.select(*fields, from: from, where: where, inner: inner, left: left, - right: right)) + right: right, + order_by: order_by, + limit: limit)) end def insert_into(table_name, *rows) @@ -178,13 +180,15 @@ module Rebel::SQL SQL end - def select(*fields, from: nil, where: nil, inner: nil, left: nil, right: nil) + def select(*fields, from: nil, where: nil, inner: nil, left: nil, right: nil, order_by: nil, limit: nil) <<-SQL SELECT #{names(*fields)} FROM #{name(from)} #{inner?(inner)} #{left?(left)} #{right?(right)} - #{where?(where)}; + #{where?(where)} + #{order_by?(order_by)} + #{limit?(limit)}; SQL end @@ -304,10 +308,26 @@ module Rebel::SQL "#{name_or_value(l)} = #{name_or_value(r)}" end + def order(l, r) + "#{name(l)} #{value(raw(r.to_s))}" + end + def assign_clause(clause) list(clause.map { |k, v| equal(k, v) }) end + def order_by_clause(clause) + case clause + when Symbol, String + order_by_clause(name(clause) => nil) + when Hash + list(clause.map { |k, v| order(k, v) }) + when Array + list(clause.map { |c| order_by_clause(c) }) + else raise NotImplementedError, clause.class + end + end + def clause_term(left, right) case right when Array @@ -344,5 +364,13 @@ module Rebel::SQL def right?(join) join ? "RIGHT #{join}" : nil end + + def order_by?(*clause) + clause.any? ? "ORDER BY #{order_by_clause(*clause)}" : nil + end + + def limit?(count) + count ? "LIMIT #{count}" : nil + end end end diff --git a/test/test_exec.rb b/test/test_exec.rb index cf7c18c..66fb0f1 100644 --- a/test/test_exec.rb +++ b/test/test_exec.rb @@ -46,4 +46,21 @@ class TestExec < Minitest::Test insert_into :foo, id: 1, col: 'whatevs' assert_equal(select('*', from: :foo), [[1, 'whatevs']]) end + + def test_limit + create_table :foo, id: 'INT', col: 'VARCHAR(255)' + insert_into :foo, id: 1, col: 'whatevs' + insert_into :foo, id: 2, col: 'something else' + assert_equal(select('*', from: :foo, limit: 1), [[1, 'whatevs']]) + end + + def test_order_by + create_table :foo, id: 'INT', col: 'VARCHAR(255)', value: 'VARCHAR(255)' + insert_into :foo, id: 1, value: '2', col: 'whatevs' + insert_into :foo, id: 2, value: '2', col: 'something' + insert_into :foo, id: 3, value: '1', col: 'else' + assert_equal(select(:id, from: :foo, order_by: :col), [[3], [2], [1]]) + assert_equal(select(:id, from: :foo, order_by: {id: :desc}), [[3], [2], [1]]) + assert_equal(select(:id, from: :foo, order_by: [value: :asc, id: :asc]), [[3], [1], [2]]) + end end From 52ff7ffd506a90e45016ccbcb5cd78ad908bb90f Mon Sep 17 00:00:00 2001 From: Thomas Kienlen Date: Fri, 2 Jun 2017 15:02:25 +0200 Subject: [PATCH 2/3] review --- lib/rebel/sql.rb | 49 ++++++++++++++++++++++++++--------------------- test/test_exec.rb | 6 +++--- test/test_raw.rb | 14 ++++++++++++++ 3 files changed, 44 insertions(+), 25 deletions(-) diff --git a/lib/rebel/sql.rb b/lib/rebel/sql.rb index 40cf33e..0aa81e2 100644 --- a/lib/rebel/sql.rb +++ b/lib/rebel/sql.rb @@ -13,14 +13,14 @@ module Rebel::SQL exec(Rebel::SQL.drop_table(table_name)) end - def select(*fields, from: nil, where: nil, inner: nil, left: nil, right: nil, order_by: nil, limit: nil) + def select(*fields, from: nil, where: nil, inner: nil, left: nil, right: nil, order: nil, limit: nil) exec(Rebel::SQL.select(*fields, from: from, where: where, inner: inner, left: left, right: right, - order_by: order_by, + order: order, limit: limit)) end @@ -52,6 +52,10 @@ module Rebel::SQL Rebel::SQL.outer_join(table, on: on) end + def by(*clause) + Rebel::SQL.by(clause) + end + class Raw < String def wants_parens! @wants_parens = true @@ -143,6 +147,18 @@ module Rebel::SQL def like(n) Raw.new("#{self} LIKE #{Rebel::SQL.value(n)}") end + + def asc + Raw.new("#{self} ASC") + end + + def desc + Raw.new("#{self} DESC") + end + + def by(*clause) + Raw.new(Rebel::SQL.list(self, Rebel::SQL.names(*clause))) + end end @identifier_quote = '"' @@ -180,14 +196,14 @@ module Rebel::SQL SQL end - def select(*fields, from: nil, where: nil, inner: nil, left: nil, right: nil, order_by: nil, limit: nil) + def select(*fields, from: nil, where: nil, inner: nil, left: nil, right: nil, order: nil, limit: nil) <<-SQL SELECT #{names(*fields)} FROM #{name(from)} #{inner?(inner)} #{left?(left)} #{right?(right)} #{where?(where)} - #{order_by?(order_by)} + #{order?(order)} #{limit?(limit)}; SQL end @@ -259,6 +275,11 @@ module Rebel::SQL raw(right? outer_join(table, on: on)) end + def by(clause) + raw("BY #{names(*clause)}") + end + + ## Support def name(name) @@ -308,26 +329,10 @@ module Rebel::SQL "#{name_or_value(l)} = #{name_or_value(r)}" end - def order(l, r) - "#{name(l)} #{value(raw(r.to_s))}" - end - def assign_clause(clause) list(clause.map { |k, v| equal(k, v) }) end - def order_by_clause(clause) - case clause - when Symbol, String - order_by_clause(name(clause) => nil) - when Hash - list(clause.map { |k, v| order(k, v) }) - when Array - list(clause.map { |c| order_by_clause(c) }) - else raise NotImplementedError, clause.class - end - end - def clause_term(left, right) case right when Array @@ -365,8 +370,8 @@ module Rebel::SQL join ? "RIGHT #{join}" : nil end - def order_by?(*clause) - clause.any? ? "ORDER BY #{order_by_clause(*clause)}" : nil + def order?(clause) + clause ? "ORDER #{clause}" : nil end def limit?(count) diff --git a/test/test_exec.rb b/test/test_exec.rb index 66fb0f1..1b95d06 100644 --- a/test/test_exec.rb +++ b/test/test_exec.rb @@ -59,8 +59,8 @@ class TestExec < Minitest::Test insert_into :foo, id: 1, value: '2', col: 'whatevs' insert_into :foo, id: 2, value: '2', col: 'something' insert_into :foo, id: 3, value: '1', col: 'else' - assert_equal(select(:id, from: :foo, order_by: :col), [[3], [2], [1]]) - assert_equal(select(:id, from: :foo, order_by: {id: :desc}), [[3], [2], [1]]) - assert_equal(select(:id, from: :foo, order_by: [value: :asc, id: :asc]), [[3], [1], [2]]) + assert_equal(select(:id, from: :foo, order: by(:id).desc), [[3], [2], [1]]) + assert_equal(select(:id, from: :foo, order: by(:value, :id).asc), [[3], [1], [2]]) + assert_equal(select(:id, from: :foo, order: by(:value).asc.by(:id).desc), [[3], [2], [1]]) end end diff --git a/test/test_raw.rb b/test/test_raw.rb index d28f7a9..6ad1a1d 100644 --- a/test/test_raw.rb +++ b/test/test_raw.rb @@ -96,4 +96,18 @@ class TestRaw < Minitest::Test assert_str_equal(Rebel::SQL.value(DateTime.new(2016, 12, 31, 23, 59, 59)), "'2016-12-31T23:59:59+00:00'") assert_str_equal(Rebel::SQL.value(nil), 'NULL') end + + def test_asc + assert_str_equal(Rebel::SQL.raw("'FOO'").asc, "'FOO' ASC") + end + + def test_desc + assert_str_equal(Rebel::SQL.raw("'FOO'").desc, "'FOO' DESC") + end + + def test_by + assert_str_equal(Rebel::SQL.by(:foo), 'BY "foo"') + assert_str_equal(Rebel::SQL.by(:foo).desc, 'BY "foo" DESC') + assert_str_equal(Rebel::SQL.by(:foo).desc.by(:bar).asc, 'BY "foo" DESC, "bar" ASC') + end end From 3a33a695852514489796897ebe63f9785746ad30 Mon Sep 17 00:00:00 2001 From: Thomas Kienlen Date: Fri, 2 Jun 2017 17:13:26 +0200 Subject: [PATCH 3/3] need a better solution for: by(:foo).asc.by(:bar).desc --- lib/rebel/sql.rb | 6 +++--- test/test_exec.rb | 2 +- test/test_raw.rb | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/rebel/sql.rb b/lib/rebel/sql.rb index 0aa81e2..b425f6b 100644 --- a/lib/rebel/sql.rb +++ b/lib/rebel/sql.rb @@ -156,9 +156,9 @@ module Rebel::SQL Raw.new("#{self} DESC") end - def by(*clause) - Raw.new(Rebel::SQL.list(self, Rebel::SQL.names(*clause))) - end + # def by(*clause) + # Raw.new(Rebel::SQL.list(self, Rebel::SQL.names(*clause))) + # end end @identifier_quote = '"' diff --git a/test/test_exec.rb b/test/test_exec.rb index 1b95d06..bef1408 100644 --- a/test/test_exec.rb +++ b/test/test_exec.rb @@ -61,6 +61,6 @@ class TestExec < Minitest::Test insert_into :foo, id: 3, value: '1', col: 'else' assert_equal(select(:id, from: :foo, order: by(:id).desc), [[3], [2], [1]]) assert_equal(select(:id, from: :foo, order: by(:value, :id).asc), [[3], [1], [2]]) - assert_equal(select(:id, from: :foo, order: by(:value).asc.by(:id).desc), [[3], [2], [1]]) + # assert_equal(select(:id, from: :foo, order: by(:value).asc.by(:id).desc), [[3], [2], [1]]) end end diff --git a/test/test_raw.rb b/test/test_raw.rb index 6ad1a1d..575556f 100644 --- a/test/test_raw.rb +++ b/test/test_raw.rb @@ -108,6 +108,6 @@ class TestRaw < Minitest::Test def test_by assert_str_equal(Rebel::SQL.by(:foo), 'BY "foo"') assert_str_equal(Rebel::SQL.by(:foo).desc, 'BY "foo" DESC') - assert_str_equal(Rebel::SQL.by(:foo).desc.by(:bar).asc, 'BY "foo" DESC, "bar" ASC') + # assert_str_equal(Rebel::SQL.by(:foo).desc.by(:bar).asc, 'BY "foo" DESC, "bar" ASC') end end