diff --git a/lib/sequel/dataset/prepared_statements.rb b/lib/sequel/dataset/prepared_statements.rb index c9f847deae..413ef5defb 100644 --- a/lib/sequel/dataset/prepared_statements.rb +++ b/lib/sequel/dataset/prepared_statements.rb @@ -201,7 +201,9 @@ def run(&block) when :insert_pk fetch_rows(prepared_sql){|r| return r.values.first} when Array + # :nocov: case prepared_type[0] + # :nocov: when :map, :as_hash, :to_hash, :to_hash_groups public_send(*prepared_type, &block) end diff --git a/lib/sequel/dataset/sql.rb b/lib/sequel/dataset/sql.rb index bcd53592e3..79c8d2d113 100644 --- a/lib/sequel/dataset/sql.rb +++ b/lib/sequel/dataset/sql.rb @@ -971,7 +971,9 @@ def complex_expression_arg_pairs_append(sql, args, &block) # operators unsupported by some databases. Used by adapters for databases # that don't support the operators natively. def complex_expression_emulate_append(sql, op, args) + # :nocov: case op + # :nocov: when :% complex_expression_arg_pairs_append(sql, args){|a, b| Sequel.function(:MOD, a, b)} when :>> diff --git a/lib/sequel/extensions/date_arithmetic.rb b/lib/sequel/extensions/date_arithmetic.rb index 6558373714..c6bf781400 100644 --- a/lib/sequel/extensions/date_arithmetic.rb +++ b/lib/sequel/extensions/date_arithmetic.rb @@ -113,12 +113,12 @@ def date_add_sql_append(sql, da) end when :mssql, :h2, :access, :sqlanywhere units = case db_type - when :mssql, :sqlanywhere - MSSQL_DURATION_UNITS when :h2 H2_DURATION_UNITS when :access ACCESS_DURATION_UNITS + else + MSSQL_DURATION_UNITS end each_valid_interval_unit(h, units) do |value, sql_unit| expr = Sequel.function(:DATEADD, sql_unit, value, expr) diff --git a/lib/sequel/extensions/migration.rb b/lib/sequel/extensions/migration.rb index 8329f8ce15..927dc7a249 100644 --- a/lib/sequel/extensions/migration.rb +++ b/lib/sequel/extensions/migration.rb @@ -68,7 +68,9 @@ def method_missing(method_sym, *args, &block) # Allow calling private methods for backwards compatibility @db.send(method_sym, *args, &block) end + # :nocov: ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true) + # :nocov: # This object responds to all methods the database responds to. def respond_to_missing?(meth, include_private) diff --git a/lib/sequel/extensions/query.rb b/lib/sequel/extensions/query.rb index c3acb4a484..0ffe283ad0 100644 --- a/lib/sequel/extensions/query.rb +++ b/lib/sequel/extensions/query.rb @@ -74,7 +74,9 @@ def method_missing(method, *args, &block) raise(Sequel::Error, "method #{method.inspect} did not return a dataset") unless @dataset.is_a?(Dataset) self end + # :nocov: ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true) + # :nocov: end end diff --git a/lib/sequel/model/base.rb b/lib/sequel/model/base.rb index e01409723f..3e70def84b 100644 --- a/lib/sequel/model/base.rb +++ b/lib/sequel/model/base.rb @@ -508,7 +508,9 @@ def plugin(plugin, *args, &block) m.configure(self, *args, &block) if m.respond_to?(:configure) end + # :nocov: ruby2_keywords(:plugin) if respond_to?(:ruby2_keywords, true) + # :nocov: # Returns primary key attribute hash. If using a composite primary key # value such be an array with values for each primary key in the correct @@ -757,7 +759,9 @@ def def_model_dataset_method(meth) else define_singleton_method(meth){|*args, &block| dataset.public_send(meth, *args, &block)} end + # :nocov: singleton_class.send(:ruby2_keywords, meth) if respond_to?(:ruby2_keywords, true) + # :nocov: end # Get the schema from the database, fall back on checking the columns diff --git a/lib/sequel/model/plugins.rb b/lib/sequel/model/plugins.rb index e9d38e4027..68b16a29ef 100644 --- a/lib/sequel/model/plugins.rb +++ b/lib/sequel/model/plugins.rb @@ -31,7 +31,9 @@ module Plugins def self.def_dataset_methods(mod, meths) Array(meths).each do |meth| mod.class_eval("def #{meth}(*args, &block); dataset.#{meth}(*args, &block) end", __FILE__, __LINE__) + # :nocov: mod.send(:ruby2_keywords, meth) if respond_to?(:ruby2_keywords, true) + # :nocov: end end @@ -141,6 +143,8 @@ def self._define_sequel_method_arg_numbers(callable) keyword = :required when :key, :keyrest keyword ||= true + else + raise Error, "invalid arg_type passed to _define_sequel_method_arg_numbers: #{arg_type}" end end arity = callable.arity diff --git a/lib/sequel/plugins/association_proxies.rb b/lib/sequel/plugins/association_proxies.rb index 33b6539698..b0eda532b4 100644 --- a/lib/sequel/plugins/association_proxies.rb +++ b/lib/sequel/plugins/association_proxies.rb @@ -99,7 +99,9 @@ def method_missing(meth, *args, &block) end v.public_send(meth, *args, &block) end + # :nocov: ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true) + # :nocov: end module ClassMethods diff --git a/lib/sequel/plugins/constraint_validations.rb b/lib/sequel/plugins/constraint_validations.rb index ae317fed76..c841797737 100644 --- a/lib/sequel/plugins/constraint_validations.rb +++ b/lib/sequel/plugins/constraint_validations.rb @@ -220,7 +220,8 @@ def constraint_validation_like_to_regexp(arg, case_insensitive) '%' when '%' '.*' - when '_' + else + #when '_' '.' end end diff --git a/lib/sequel/plugins/pg_array_associations.rb b/lib/sequel/plugins/pg_array_associations.rb index bcd7da156c..f0595247b0 100644 --- a/lib/sequel/plugins/pg_array_associations.rb +++ b/lib/sequel/plugins/pg_array_associations.rb @@ -520,7 +520,9 @@ module DatasetMethods def many_to_pg_array_association_filter_expression(op, ref, obj) pk = ref.qualify(model.table_name, ref.primary_key) key = ref[:key] + # :nocov: expr = case obj + # :nocov: when Sequel::Model if (assoc_pks = obj.get_column_value(key)) && !assoc_pks.empty? Sequel[pk=>assoc_pks.to_a] @@ -540,7 +542,9 @@ def many_to_pg_array_association_filter_expression(op, ref, obj) # Support filtering by pg_array_to_many associations using a subquery. def pg_array_to_many_association_filter_expression(op, ref, obj) key = ref.qualify(model.table_name, ref[:key_column]) + # :nocov: expr = case obj + # :nocov: when Sequel::Model if pkv = obj.get_column_value(ref.primary_key_method) Sequel.pg_array_op(key).contains(Sequel.pg_array([pkv], ref.array_type)) diff --git a/lib/sequel/plugins/pg_auto_constraint_validations.rb b/lib/sequel/plugins/pg_auto_constraint_validations.rb index ba78d942a3..11080d5d3c 100644 --- a/lib/sequel/plugins/pg_auto_constraint_validations.rb +++ b/lib/sequel/plugins/pg_auto_constraint_validations.rb @@ -250,7 +250,9 @@ def check_pg_constraint_error(ds) messages = model.pg_auto_constraint_validations_messages unless override + # :nocov: case e + # :nocov: when Sequel::NotNullConstraintViolation if column = info[:column] add_pg_constraint_validation_error([m.call(column)], messages[:not_null]) diff --git a/spec/core/database_spec.rb b/spec/core/database_spec.rb index 440fe66c08..fc5e50d8f2 100644 --- a/spec/core/database_spec.rb +++ b/spec/core/database_spec.rb @@ -2741,6 +2741,7 @@ def db.views(*) end it "should handle converting many default formats" do db = Sequel::Database.new p = lambda{|d,t| db.send(:column_schema_to_ruby_default, d, t)} + p['any', :unknown].must_be_nil p[nil, :integer].must_be_nil p[1, :integer].must_equal 1 p['1', :integer].must_equal 1 @@ -2758,6 +2759,7 @@ def db.views(*) end p['false', :boolean].must_equal false p["'t'", :boolean].must_equal true p["'f'", :boolean].must_equal false + p["'x'", :boolean].must_be_nil p["'a'", :string].must_equal 'a' p["'a'", :blob].must_equal Sequel.blob('a') p["'a'", :blob].must_be_kind_of(Sequel::SQL::Blob) @@ -2948,6 +2950,8 @@ def database_exception_sqlstate(exception, opts={}) proc{@db.get(:a)}.must_raise(Sequel::CheckConstraintViolation) @db.sql_state = '40001' proc{@db.get(:a)}.must_raise(Sequel::SerializationFailure) + @db.sql_state = '41245' + proc{@db.get(:a)}.must_raise(Sequel::DatabaseError) def @db.database_specific_error_class_from_sqlstate(_) end (@db.get(:a) rescue $!.class).must_equal(Sequel::DatabaseError) @db.sql_state = nil diff --git a/spec/core/dataset_spec.rb b/spec/core/dataset_spec.rb index 5bf9e19752..3af131b686 100644 --- a/spec/core/dataset_spec.rb +++ b/spec/core/dataset_spec.rb @@ -2892,6 +2892,11 @@ def supports_cte_in_subselect?; false end @d.order(:c, :d).last.must_equal(:s=>'SELECT * FROM test ORDER BY c DESC, d DESC LIMIT 1') @d.order(Sequel.desc(:e), :f).last.must_equal(:s=>'SELECT * FROM test ORDER BY e ASC, f DESC LIMIT 1') end + + it "should raise an error for multiple arguments" do + proc{@d.first(1, :z=>10)}.must_raise Sequel::Error + proc{@d.last(1, :z=>10)}.must_raise Sequel::Error + end end describe "Dataset #first!" do diff --git a/spec/extensions/columns_introspection_spec.rb b/spec/extensions/columns_introspection_spec.rb index 4874609fe1..84a6e092a1 100644 --- a/spec/extensions/columns_introspection_spec.rb +++ b/spec/extensions/columns_introspection_spec.rb @@ -52,6 +52,11 @@ @db.sqls.length.must_equal 0 end + it "should handle LiteralStrings in FROM tables by issuing a query" do + @ds.from(Sequel.lit('x')).columns.must_equal [] + @db.sqls.must_equal ["SELECT * FROM x LIMIT 1"] + end + it "should handle selecting * from a single subselect with no joins without a database query if the subselect's columns can be handled" do @ds.select(:x).from_self.columns.must_equal [:x] @db.sqls.length.must_equal 0 diff --git a/spec/extensions/dataset_associations_spec.rb b/spec/extensions/dataset_associations_spec.rb index 4f7c8d3db2..e52f65aab6 100644 --- a/spec/extensions/dataset_associations_spec.rb +++ b/spec/extensions/dataset_associations_spec.rb @@ -35,7 +35,7 @@ def @Track.name; 'Track' end @Track.plugin :many_through_many @Artist.plugin :pg_array_associations @Tag.plugin :pg_array_associations - @Artist.one_to_many :albums, :class=>@Album + @Artist.one_to_many :albums, :class=>@Album, :dataset_associations_join=>true @Artist.one_to_one :first_album, :class=>@Album @Album.many_to_one :artist, :class=>@Artist @Album.many_to_many :tags, :class=>@Tag diff --git a/spec/extensions/datetime_parse_to_time_spec.rb b/spec/extensions/datetime_parse_to_time_spec.rb index 268d324c08..6f5decb82f 100644 --- a/spec/extensions/datetime_parse_to_time_spec.rb +++ b/spec/extensions/datetime_parse_to_time_spec.rb @@ -34,6 +34,10 @@ def supports_timestamp_usecs?; false end Sequel.database_timezone = :utc Sequel.database_to_application_timestamp("2017-03-26 02:30:00").getutc.hour.must_equal 2 Sequel.database_to_application_timestamp("2017-03-12 02:30:00").getutc.hour.must_equal 2 + + Sequel.application_timezone = :utc + Sequel.database_to_application_timestamp("2017-03-26 02:30:00").getutc.hour.must_equal 2 + Sequel.database_to_application_timestamp("2017-03-12 02:30:00").getutc.hour.must_equal 2 end it "should handle an database timezone of :utc when literalizing values" do diff --git a/spec/model/associations_spec.rb b/spec/model/associations_spec.rb index 0e90031873..b9703d4206 100644 --- a/spec/model/associations_spec.rb +++ b/spec/model/associations_spec.rb @@ -3547,6 +3547,12 @@ def supports_distinct_on?; true; end @Album.filter(:b_tags=>@Tag.load(:id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT albums_tags.album_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE ((name = 'B') AND (albums_tags.album_id IS NOT NULL) AND (tags.id = 3))))" end + it "should not use an eager limit strategy if the strategy is not specified and the model defaults to not using one" do + @Album.default_eager_limit_strategy = nil + @Album.one_to_many :l_tracks2, :clone=>:l_tracks + @Album.filter(:l_tracks2=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id = 5))))" + end + it "should be able to filter on one_to_many associations with :limit" do @Album.filter(:l_tracks=>@Track.load(:id=>5, :album_id=>3)).sql.must_equal "SELECT * FROM albums WHERE (albums.id IN (SELECT tracks.album_id FROM tracks WHERE ((tracks.album_id IS NOT NULL) AND (tracks.id IN (SELECT id FROM (SELECT tracks.id, row_number() OVER (PARTITION BY tracks.album_id) AS x_sequel_row_number_x FROM tracks) AS t1 WHERE (x_sequel_row_number_x <= 10))) AND (tracks.id = 5))))" end diff --git a/spec/model/plugins_spec.rb b/spec/model/plugins_spec.rb index fadfd99cc1..dd9688b124 100644 --- a/spec/model/plugins_spec.rb +++ b/spec/model/plugins_spec.rb @@ -442,6 +442,12 @@ def one; dataset.send(:cache_set, :foo, 1) end proc{@scope.send(m1, 1)}.must_raise ArgumentError end + it "should raise if an invalid arg type is used" do + o = Object.new + def o.parameters; [[:foo]] end + proc{Sequel::Plugins.send(:_define_sequel_method_arg_numbers, o)}.must_raise Sequel::Error + end + if RUBY_VERSION > '2.1' it "should raise for required keyword arguments for expected_arity 0 or 1" do proc{eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|b:| [b, 1]}", binding)}.must_raise Sequel::Error