Permalink
Browse files

Raise Errors if EXCEPT/INTERSECT is used when not supported

This adds a couple of modules to Sequel::Dataset that can be included
in adapters that don't support EXCEPT/INTERSECT.
UnsupportedIntersectExcept raises an error if EXCEPT/INTERSECT is
used, and UnsupportedIntersectExceptAll raises an error if
EXCEPT ALL/INTERSECT ALL is used (but EXCEPT/INTERSECT is allowed).
The Informix, MySQL, MSSQL, and Progress adapters use
UnsupportedIntersectExcept and the Oracle and SQLite adapters use
UnsupportedIntersectExceptAll.

Similar code was already in the MSSQL and Progress adapters, this
commit removes that code.  Also, it removes some commented out code
from the Informix adapter.
  • Loading branch information...
1 parent c790367 commit 3a1a628eabb987998482670101c4cbce27cd54ec @jeremyevans committed Dec 1, 2008
View
@@ -1,5 +1,7 @@
=== HEAD
+* Raise errors when EXCEPT/INTERSECT is used when not supported (jeremyevans)
+
* Fix ordering of UNION, INTERSECT, and EXCEPT statements (jeremyevans) (#253)
* Support aliasing subselects in the Oracle adapter (jeremyevans)
@@ -5,12 +5,6 @@ module Informix
class Database < Sequel::Database
set_adapter_scheme :informix
- # AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
- #
- # def auto_increment_sql
- # AUTO_INCREMENT
- # end
-
def connect(server)
opts = server_opts(server)
::Informix.connect(opts[:database], opts[:user], opts[:password])
@@ -39,7 +33,9 @@ def execute(sql, opts={})
end
class Dataset < Sequel::Dataset
- SELECT_CLAUSE_ORDER = %w'limit distinct columns from join where group having order union intersect except'.freeze
+ include UnsupportedIntersectExcept
+
+ SELECT_CLAUSE_ORDER = %w'limit distinct columns from join where having group union order'.freeze
def literal(v)
case v
@@ -35,7 +35,9 @@ def rollback_transaction_sql
end
module DatasetMethods
- SELECT_CLAUSE_ORDER = %w'intersect except limit distinct columns from with join where group order having union'.freeze
+ include Dataset::UnsupportedIntersectExcept
+
+ SELECT_CLAUSE_ORDER = %w'limit distinct columns from with join where group order having union'.freeze
def complex_expression_sql(op, args)
case op
@@ -83,16 +85,6 @@ def select_clause_order
SELECT_CLAUSE_ORDER
end
- # EXCEPT is not supported by MSSQL
- def select_except_sql(sql, opts)
- raise(Error, "EXCEPT not supported") if opts[:except]
- end
-
- # INTERSECT is not supported by MSSQL
- def select_intersect_sql(sql, opts)
- raise(Error, "INTERSECT not supported") if opts[:intersect]
- end
-
# MSSQL uses TOP for limit, with no offset support
def select_limit_sql(sql, opts)
raise(Error, "OFFSET not supported") if opts[:offset]
@@ -95,6 +95,8 @@ def schema_parse_table(table_name, opts)
# Dataset methods shared by datasets that use MySQL databases.
module DatasetMethods
+ include UnsupportedIntersectExcept
+
BOOL_TRUE = '1'.freeze
BOOL_FALSE = '0'.freeze
COMMA_SEPARATOR = ', '.freeze
@@ -13,6 +13,8 @@ def table_exists?(name)
end
module DatasetMethods
+ include Dataset::UnsupportedIntersectExceptAll
+
SELECT_CLAUSE_ORDER = %w'distinct columns from join where group having union intersect except order limit'.freeze
def empty?
@@ -10,24 +10,16 @@ def dataset(opts = nil)
end
module DatasetMethods
- SELECT_CLAUSE_ORDER = %w'intersect except limit distinct columns from join where group order having union'.freeze
+ include Dataset::UnsupportedIntersectExcept
+
+ SELECT_CLAUSE_ORDER = %w'limit distinct columns from join where group order having union'.freeze
private
def select_clause_order
SELECT_CLAUSE_ORDER
end
- # EXCEPT is not supported by Progress
- def select_except_sql(sql, opts)
- raise(Error, "EXCEPT not supported") if opts[:except]
- end
-
- # INTERSECT is not supported by Progress
- def select_intersect_sql(sql, opts)
- raise(Error, "INTERSECT not supported") if opts[:intersect]
- end
-
# Progress uses TOP for limit, but it is only supported in Progress 10.
# The Progress adapter targets Progress 9, so it silently ignores the option.
def select_limit_sql(sql, opts)
@@ -105,6 +105,8 @@ def schema_parse_table(table_name, opts)
# Instance methods for datasets that connect to an SQLite database
module DatasetMethods
+ include Dataset::UnsupportedIntersectExceptAll
+
# SQLite does not support pattern matching via regular expressions.
# SQLite is case insensitive (depending on pragma), so use LIKE for
# ILIKE.
@@ -1,4 +1,4 @@
-%w'callback convenience pagination prepared_statements query schema sql'.each do |f|
+%w'callback convenience pagination prepared_statements query schema sql unsupported'.each do |f|
require "sequel_core/dataset/#{f}"
end
@@ -0,0 +1,31 @@
+class Sequel::Dataset
+ # This module should be included in the dataset class for all databases that
+ # don't support INTERSECT or EXCEPT.
+ module UnsupportedIntersectExcept
+ # Raise an Error if EXCEPT is used
+ def except(ds, all=false)
+ raise(Sequel::Error, "EXCEPT not supported")
+ end
+
+ # Raise an Error if INTERSECT is used
+ def intersect(ds, all=false)
+ raise(Sequel::Error, "INTERSECT not supported")
+ end
+ end
+
+ # This module should be included in the dataset class for all databases that
+ # don't support INTERSECT ALL or EXCEPT ALL.
+ module UnsupportedIntersectExceptAll
+ # Raise an Error if EXCEPT is used
+ def except(ds, all=false)
+ raise(Sequel::Error, "EXCEPT ALL not supported") if all
+ super(ds)
+ end
+
+ # Raise an Error if INTERSECT is used
+ def intersect(ds, all=false)
+ raise(Sequel::Error, "INTERSECT ALL not supported") if all
+ super(ds)
+ end
+ end
+end
@@ -3243,3 +3243,32 @@ def @ds.fetch_rows(sql)
end
end
end
+
+context Sequel::Dataset::UnsupportedIntersectExcept do
+ before do
+ @ds = Sequel::Dataset.new(nil).from(:items)
+ @ds2 = Sequel::Dataset.new(nil).from(:i)
+ @ds.extend(Sequel::Dataset::UnsupportedIntersectExcept)
+ end
+
+ specify "should raise an error if INTERSECT or EXCEPT is USED" do
+ @ds.union(@ds2).sql.should == 'SELECT * FROM items UNION SELECT * FROM i'
+ proc{@ds.intersect(@ds2)}.should raise_error(Sequel::Error)
+ proc{@ds.except(@ds2)}.should raise_error(Sequel::Error)
+ end
+end
+
+context Sequel::Dataset::UnsupportedIntersectExceptAll do
+ before do
+ @ds = Sequel::Dataset.new(nil).from(:items)
+ @ds2 = Sequel::Dataset.new(nil).from(:i)
+ @ds.extend(Sequel::Dataset::UnsupportedIntersectExceptAll)
+ end
+
+ specify "should raise an error if INTERSECT or EXCEPT is USED" do
+ @ds.intersect(@ds2).sql.should == 'SELECT * FROM items INTERSECT SELECT * FROM i'
+ @ds.except(@ds2).sql.should == 'SELECT * FROM items EXCEPT SELECT * FROM i'
+ proc{@ds.intersect(@ds2, true)}.should raise_error(Sequel::Error)
+ proc{@ds.except(@ds2, true)}.should raise_error(Sequel::Error)
+ end
+end

0 comments on commit 3a1a628

Please sign in to comment.