1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
|
require_relative "spec_helper"
describe "constraint_validations extension" do
def parse_insert(s)
m = /\AINSERT INTO "?sequel_constraint_validations"? \("?(.*)"?\) VALUES \((.*)\)\z/.match(s)
Hash[*m[1].split(/"?, "?/).map{|v| v.to_sym}.zip(m[2].split(/"?, "?/).map{|v| parse_insert_value(v)}).reject{|k, v| v.nil?}.flatten]
end
def parse_insert_value(s)
case s
when 'NULL'
nil
when /\A'(.*)'\z/
$1
else
raise Sequel::Error, "unhandled insert value: #{s.inspect}"
end
end
before do
@db = Sequel.mock
@db.extend(Module.new{attr_writer :schema; def schema(table, *) execute("parse schema for #{table}"); @schema; end})
def @db.table_exists?(_) true; end
@db.singleton_class.send(:alias_method, :table_exists?, :table_exists?)
@db.extension(:constraint_validations)
end
it "should allow creating the sequel_constraint_validations table" do
@db.create_constraint_validations_table
@db.sqls.must_equal ["CREATE TABLE sequel_constraint_validations (table varchar(255) NOT NULL, constraint_name varchar(255), validation_type varchar(255) NOT NULL, column varchar(255) NOT NULL, argument varchar(255), message varchar(255), allow_nil boolean)"]
end
it "should allow creating the sequel_constraint_validations table with a non-default table name" do
@db.constraint_validations_table = :foo
@db.create_constraint_validations_table
@db.sqls.must_equal ["CREATE TABLE foo (table varchar(255) NOT NULL, constraint_name varchar(255), validation_type varchar(255) NOT NULL, column varchar(255) NOT NULL, argument varchar(255), message varchar(255), allow_nil boolean)"]
end
it "should allow dropping the sequel_constraint_validations table" do
@db.drop_constraint_validations_table
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'sequel_constraint_validations')", "DROP TABLE sequel_constraint_validations"]
end
it "should allow dropping the sequel_constraint_validations table with a non-default table name" do
@db.constraint_validations_table = :foo
@db.drop_constraint_validations_table
@db.sqls.must_equal ["DELETE FROM foo WHERE (table = 'foo')", "DROP TABLE foo"]
end
it "should allow dropping validations for a given table" do
@db.drop_constraint_validations_for(:table=>:foo)
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')"]
end
it "should drop validations for a given table when dropping the table" do
@db.drop_table(:foo)
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')", "DROP TABLE foo"]
@db.drop_table(:foo, :if_exists => true)
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')", "DROP TABLE IF EXISTS foo"]
@db.drop_table?(:foo)
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE (table = 'foo')", "DROP TABLE foo"]
end
it "should not drop validations for a given table if the constraint validations table does not exist" do
def @db.table_exists?(_) false; end
@db.drop_table(:foo)
@db.sqls.must_equal ["DROP TABLE foo"]
end
it "should allow dropping validations for a given table and column" do
@db.drop_constraint_validations_for(:table=>:foo, :column=>:bar)
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table = 'foo') AND (column = 'bar'))"]
end
it "should allow dropping validations for a given table and constraint" do
@db.drop_constraint_validations_for(:table=>:foo, :constraint=>:bar)
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table = 'foo') AND (constraint_name = 'bar'))"]
end
it "should allow dropping validations for a non-default constraint_validations table" do
@db.constraint_validations_table = :cv
@db.drop_constraint_validations_for(:table=>:foo)
@db.sqls.must_equal ["DELETE FROM cv WHERE (table = 'foo')"]
end
it "should raise an error without deleting if attempting to drop validations without table, column, or constraint" do
proc{@db.drop_constraint_validations_for({})}.must_raise(Sequel::Error)
@db.sqls.must_equal []
end
it "should allow adding constraint validations via create_table validate" do
@db.create_table(:foo){String :name; validate{presence :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
end
it "should allow adding constraint validations using generator directly" do
gen = @db.create_table_generator
gen.String :name
gen.validate{presence :name}
@db.create_table(:foo, :generator=>gen)
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
end
it "should allow adding constraint validations via alter_table validate" do
@db.schema = [[:name, {:type=>:string}]]
@db.alter_table(:foo){validate{presence :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(2)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
sqls.must_equal ["parse schema for foo", "BEGIN", "COMMIT", "ALTER TABLE foo ADD CHECK ((name IS NOT NULL) AND (trim(name) != ''))"]
end
it "should allow altering the table without validation" do
@db.schema = [[:name, {:type=>:string}]]
@db.alter_table(:foo){rename_column :a, :b}
@db.sqls.must_equal ["ALTER TABLE foo RENAME COLUMN a TO b"]
end
it "should handle :message option when adding validations" do
@db.create_table(:foo){String :name; validate{presence :name, :message=>'not there'}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :message=>'not there')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
end
it "should handle :allow_nil option when adding validations" do
@db.create_table(:foo){String :name; validate{presence :name, :allow_nil=>true}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :allow_nil=>'t')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NULL) OR (trim(name) != '')))"]
end
it "should handle :name option when adding validations" do
@db.create_table(:foo){String :name; validate{presence :name, :name=>'cons'}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :constraint_name=>'cons')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CONSTRAINT cons CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
end
it "should handle multiple string columns when adding presence validations" do
@db.create_table(:foo){String :name; String :bar; validate{presence [:name, :bar]}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo")
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), bar varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '') AND (bar IS NOT NULL) AND (trim(bar) != '')))"]
end
it "should handle multiple string columns when adding presence validations with :allow_nil" do
@db.create_table(:foo){String :name; String :bar; validate{presence [:name, :bar], :allow_nil=>true}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :allow_nil=>'t')
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo", :allow_nil=>'t')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), bar varchar(255), CHECK (((name IS NULL) OR (trim(name) != '')) AND ((bar IS NULL) OR (trim(bar) != ''))))"]
end
it "should handle multiple string columns when adding presence validations" do
@db.create_table(:foo){String :name; Integer :x; String :bar; validate{presence [:name, :x, :bar]}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"x", :table=>"foo")
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo")
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), x integer, bar varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '') AND (bar IS NOT NULL) AND (trim(bar) != '') AND (x IS NOT NULL)))"]
end
it "should handle multiple string columns when adding presence validations with :allow_nil" do
@db.create_table(:foo){String :name; Integer :x; String :bar; validate{presence [:name, :x, :bar], :allow_nil=>true}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :allow_nil=>'t')
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"x", :table=>"foo", :allow_nil=>'t')
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo", :allow_nil=>'t')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), x integer, bar varchar(255), CHECK (((name IS NULL) OR (trim(name) != '')) AND ((bar IS NULL) OR (trim(bar) != ''))))"]
end
it "should handle presence validation on non-String columns" do
@db.create_table(:foo){Integer :name; validate{presence :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK (name IS NOT NULL))"]
@db.schema = [[:name, {:type=>:integer}]]
@db.alter_table(:foo){validate{presence :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(2)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
sqls.must_equal ["parse schema for foo", "BEGIN", "COMMIT", "ALTER TABLE foo ADD CHECK (name IS NOT NULL)"]
end
it "should handle presence validation on Oracle with IS NOT NULL instead of != ''" do
@db = Sequel.mock(:host=>'oracle')
@db.extend_datasets do
def quote_identifiers?; false end
private
def input_identifier(v) v.to_s end
end
@db.extension(:constraint_validations)
@db.create_table(:foo){String :name; validate{presence :name}}
sqls = @db.sqls
s = sqls.slice!(1).upcase
m = /\AINSERT INTO sequel_constraint_validations \((.*)\) SELECT (.*) FROM DUAL\z/i.match(s)
Hash[*m[1].split(', ').map{|v| v.downcase.to_sym}.zip(m[2].split(', ').map{|v| parse_insert_value(v.downcase.gsub('null', 'NULL'))}).reject{|k, v| v.nil?}.flatten].must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo")
sqls.must_equal ["BEGIN", "COMMIT", 'CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) IS NOT NULL)))']
end
it "should assume column is not a String if it can't determine the type" do
@db.create_table(:foo){Integer :name; validate{presence :bar}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo")
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK (bar IS NOT NULL))"]
@db.schema = [[:name, {:type=>:integer}]]
@db.alter_table(:foo){validate{presence :bar}}
sqls = @db.sqls
parse_insert(sqls.slice!(2)).must_equal(:validation_type=>"presence", :column=>"bar", :table=>"foo")
sqls.must_equal ["parse schema for foo", "BEGIN", "COMMIT", "ALTER TABLE foo ADD CHECK (bar IS NOT NULL)"]
end
it "should handle presence validation on non-String columns with :allow_nil option" do
@db.create_table(:foo){Integer :name; validate{presence :name, :allow_nil=>true}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"foo", :allow_nil=>'t')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer)"]
end
it "should support :exact_length constraint validation" do
@db.create_table(:foo){String :name; validate{exact_length 5, :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"exact_length", :column=>"name", :table=>"foo", :argument=>'5')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) = 5)))"]
end
it "should support :min_length constraint validation" do
@db.create_table(:foo){String :name; validate{min_length 5, :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"min_length", :column=>"name", :table=>"foo", :argument=>'5')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) >= 5)))"]
end
it "should support :max_length constraint validation" do
@db.create_table(:foo){String :name; validate{max_length 5, :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"max_length", :column=>"name", :table=>"foo", :argument=>'5')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) <= 5)))"]
end
it "should support :length_range constraint validation" do
@db.create_table(:foo){String :name; validate{length_range 3..5, :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"length_range", :column=>"name", :table=>"foo", :argument=>'3..5')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) >= 3) AND (char_length(name) <= 5)))"]
@db.create_table(:foo){String :name; validate{length_range 3...5, :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"length_range", :column=>"name", :table=>"foo", :argument=>'3...5')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (char_length(name) >= 3) AND (char_length(name) < 5)))"]
end
it "should support :format constraint validation" do
@db = Sequel.mock(:host=>'postgres')
@db.extend_datasets{def quote_identifiers?; false end}
@db.extension(:constraint_validations)
@db.create_table(:foo){String :name; validate{format(/^foo.*/, :name)}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"format", :column=>"name", :table=>"foo", :argument=>'^foo.*')
sqls.must_equal ["BEGIN", "COMMIT", %[CREATE TABLE foo (name text, CHECK ((name IS NOT NULL) AND (name ~ '^foo.*')))]]
end
it "should support :format constraint validation with case insensitive format" do
@db = Sequel.mock(:host=>'postgres')
@db.extend_datasets{def quote_identifiers?; false end}
@db.extension(:constraint_validations)
@db.create_table(:foo){String :name; validate{format(/^foo.*/i, :name)}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"iformat", :column=>"name", :table=>"foo", :argument=>'^foo.*')
sqls.must_equal ["BEGIN", "COMMIT", %[CREATE TABLE foo (name text, CHECK ((name IS NOT NULL) AND (name ~* '^foo.*')))]]
end
it "should support :includes constraint validation with an array of strings" do
@db.create_table(:foo){String :name; validate{includes %w'a b c', :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"includes_str_array", :column=>"name", :table=>"foo", :argument=>'a,b,c')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name IN ('a', 'b', 'c'))))"]
end
it "should support :includes constraint validation with an array of integers" do
@db.create_table(:foo){String :name; validate{includes [1, 2, 3], :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"includes_int_array", :column=>"name", :table=>"foo", :argument=>'1,2,3')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name IN (1, 2, 3))))"]
end
it "should support :includes constraint validation with a inclusive range of integers" do
@db.create_table(:foo){String :name; validate{includes 3..5, :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"includes_int_range", :column=>"name", :table=>"foo", :argument=>'3..5')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name >= 3) AND (name <= 5)))"]
end
it "should support :includes constraint validation with a exclusive range of integers" do
@db.create_table(:foo){String :name; validate{includes 3...5, :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"includes_int_range", :column=>"name", :table=>"foo", :argument=>'3...5')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name >= 3) AND (name < 5)))"]
end
it "should support :like constraint validation" do
@db.create_table(:foo){String :name; validate{like 'foo%', :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"like", :column=>"name", :table=>"foo", :argument=>'foo%')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name LIKE 'foo%' ESCAPE '\\')))"]
end
it "should support :ilike constraint validation" do
@db.create_table(:foo){String :name; validate{ilike 'foo%', :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"ilike", :column=>"name", :table=>"foo", :argument=>'foo%')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (UPPER(name) LIKE UPPER('foo%') ESCAPE '\\')))"]
end
it "should support :operator :< constraint validation with string" do
@db.create_table(:foo){String :name; validate{operator :<, 'a', :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"str_lt", :column=>"name", :table=>"foo", :argument=>'a')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name < 'a')))"]
end
it "should support :operator :<= constraint validation with string" do
@db.create_table(:foo){String :name; validate{operator :<=, 'a', :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"str_lte", :column=>"name", :table=>"foo", :argument=>'a')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name <= 'a')))"]
end
it "should support :operator :> constraint validation with string" do
@db.create_table(:foo){String :name; validate{operator :>, 'a', :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"str_gt", :column=>"name", :table=>"foo", :argument=>'a')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name > 'a')))"]
end
it "should support :operator :>= constraint validation with string" do
@db.create_table(:foo){String :name; validate{operator :>=, 'a', :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"str_gte", :column=>"name", :table=>"foo", :argument=>'a')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), CHECK ((name IS NOT NULL) AND (name >= 'a')))"]
end
it "should support :operator :< constraint validation with integer" do
@db.create_table(:foo){Integer :name; validate{operator :<, 2, :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"int_lt", :column=>"name", :table=>"foo", :argument=>'2')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK ((name IS NOT NULL) AND (name < 2)))"]
end
it "should support :operator :<= constraint validation with integer" do
@db.create_table(:foo){Integer :name; validate{operator :<=, 2, :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"int_lte", :column=>"name", :table=>"foo", :argument=>'2')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK ((name IS NOT NULL) AND (name <= 2)))"]
end
it "should support :operator :> constraint validation with integer" do
@db.create_table(:foo){Integer :name; validate{operator :>, 2, :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"int_gt", :column=>"name", :table=>"foo", :argument=>'2')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK ((name IS NOT NULL) AND (name > 2)))"]
end
it "should support :operator :>= constraint validation with integer" do
@db.create_table(:foo){Integer :name; validate{operator :>=, 2, :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"int_gte", :column=>"name", :table=>"foo", :argument=>'2')
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name integer, CHECK ((name IS NOT NULL) AND (name >= 2)))"]
end
it "should support :unique constraint validation" do
@db.create_table(:foo){String :name; validate{unique :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"unique", :column=>"name", :table=>"foo")
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), UNIQUE (name))"]
end
it "should support :unique constraint validation with multiple columns" do
@db.create_table(:foo){String :name; Integer :id; validate{unique [:name, :id]}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"unique", :column=>"name,id", :table=>"foo")
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE foo (name varchar(255), id integer, UNIQUE (name, id))"]
end
it "should support :unique constraint validation in alter_table" do
@db.alter_table(:foo){validate{unique :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"unique", :column=>"name", :table=>"foo")
sqls.must_equal ["BEGIN", "COMMIT", "ALTER TABLE foo ADD UNIQUE (name)"]
end
it "should drop constraints and validations when dropping a constraint validation" do
@db.alter_table(:foo){String :name; validate{drop :bar}}
@db.sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table, constraint_name) IN (('foo', 'bar')))", "ALTER TABLE foo DROP CONSTRAINT bar"]
end
it "should drop constraints and validations before adding new ones" do
@db.alter_table(:foo){String :name; validate{unique :name; drop :bar}}
sqls = @db.sqls
parse_insert(sqls.slice!(2)).must_equal(:validation_type=>"unique", :column=>"name", :table=>"foo")
sqls.must_equal ["DELETE FROM sequel_constraint_validations WHERE ((table, constraint_name) IN (('foo', 'bar')))", "BEGIN", "COMMIT", "ALTER TABLE foo ADD UNIQUE (name)", "ALTER TABLE foo DROP CONSTRAINT bar"]
end
it "should raise an error if attempting to validate inclusion with a range of non-integers" do
proc{@db.create_table(:foo){String :name; validate{includes 'a'..'z', :name}}}.must_raise(Sequel::Error)
end
it "should raise an error if attempting to validate inclusion with a range of non-integers or strings" do
proc{@db.create_table(:foo){String :name; validate{includes [1.0, 2.0], :name}}}.must_raise(Sequel::Error)
end
it "should raise an error if attempting to validate inclusion with a unsupported object" do
proc{@db.create_table(:foo){String :name; validate{includes 'a', :name}}}.must_raise(Sequel::Error)
end
it "should raise an error if attempting attempting to process an operator validation with an unsupported operator" do
proc{@db.alter_table(:foo){String :name; validate{operator :===, 'a', :name}}}.must_raise(Sequel::Error)
end
it "should raise an error if attempting attempting to process an operator validation with an unsupported argument" do
proc{@db.alter_table(:foo){String :name; validate{operator :>, [], :name}}}.must_raise(Sequel::Error)
end
it "should raise an error if attempting to drop a constraint validation in a create_table generator" do
proc{@db.create_table(:foo){String :name; validate{drop :foo}}}.must_raise(Sequel::Error)
end
it "should raise an error if attempting to drop a constraint validation without a name" do
proc{@db.alter_table(:foo){String :name; validate{drop nil}}}.must_raise(Sequel::Error)
end
it "should raise an error if attempting attempting to process a constraint validation with an unsupported type" do
proc{@db.alter_table(:foo){String :name; validations << {:type=>:foo}}}.must_raise(Sequel::Error)
end
it "should allow adding constraint validations for tables specified as a SQL::Identifier" do
@db.create_table(Sequel.identifier(:sch__foo)){String :name; validate{presence :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"sch__foo")
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE sch__foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
end
it "should allow adding constraint validations for tables specified as a SQL::QualifiedIdentifier" do
@db.create_table(Sequel.qualify(:sch, :foo)){String :name; validate{presence :name}}
sqls = @db.sqls
parse_insert(sqls.slice!(1)).must_equal(:validation_type=>"presence", :column=>"name", :table=>"sch.foo")
sqls.must_equal ["BEGIN", "COMMIT", "CREATE TABLE sch.foo (name varchar(255), CHECK ((name IS NOT NULL) AND (trim(name) != '')))"]
end
end
|