Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add have any criteria #1042

Merged
merged 10 commits into from
May 17, 2024
31 changes: 31 additions & 0 deletions spec/avram/array_column_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,35 @@ describe "Array Columns" do
bucket = SaveBucket.update!(bucket, enums: [Bucket::Size::Small])
bucket.enums.should eq([Bucket::Size::Small])
end

describe "the #have_any method" do
it "returns the records with have at least one element of the provided ones" do
BucketFactory.new.numbers([1, 2]).create
BucketFactory.new.numbers([1, 3]).create

bucket = BucketQuery.new.numbers.have_any([1, 2, 3]).select_count
bucket.should eq 2

bucket = BucketQuery.new.numbers.have_any([1, 3]).select_count
bucket.should eq 2

bucket = BucketQuery.new.numbers.have_any([3, 4]).select_count
bucket.should eq 1

bucket = BucketQuery.new.numbers.have_any([4]).select_count
bucket.should eq 0
end

it "returns nothing with an empty array" do
BucketFactory.new.numbers([1, 2]).create
bucket = BucketQuery.new.numbers.have_any([] of Int64).select_count
bucket.should eq 0
end

it "negates with not" do
BucketFactory.new.numbers([1, 2]).create
bucket = BucketQuery.new.numbers.not.have_any([3]).select_count
bucket.should eq 1
end
end
end
21 changes: 21 additions & 0 deletions spec/avram/migrator/alter_table_statement_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,27 @@ describe Avram::Migrator::AlterTableStatement do
built.statements[2].should eq "ALTER TABLE ONLY test_defaults ALTER COLUMN money SET DEFAULT '29.99';"
end

it "changes defaults after changing the type" do
built = Avram::Migrator::AlterTableStatement.new(:users).build do
change_type id : Int64
change_default id : Int64, default: 54
end
built.statements.size.should eq 2
built.statements[0].should eq "ALTER TABLE users ALTER COLUMN id SET DATA TYPE bigint;"
built.statements[1].should eq "ALTER TABLE ONLY users ALTER COLUMN id SET DEFAULT '54';"
end

it "can change column nullability" do
built = Avram::Migrator::AlterTableStatement.new(:users).build do
forbid_nulls_for :id
allow_nulls_for :age
end

built.statements.size.should eq 2
built.statements[0].should eq "ALTER TABLE users ALTER COLUMN id SET NOT NULL;"
built.statements[1].should eq "ALTER TABLE users ALTER COLUMN age DROP NOT NULL;"
end

Comment on lines +92 to +112
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops! Looks like this snuck in here 😂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤕 did the checkout from the wrong branch 😢

describe "fill_existing_with" do
it "fills existing with value and sets column to be non-null for non-null types" do
built = Avram::Migrator::AlterTableStatement.new(:users).build do
Expand Down
2 changes: 2 additions & 0 deletions spec/avram/where_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,7 @@ describe Avram::Where do
should_negate(Avram::Where::In, Avram::Where::NotIn)
should_negate(Avram::Where::NotIn, Avram::Where::In)
should_negate(Avram::Where::Null, Avram::Where::NotNull)
should_negate(Avram::Where::Any, Avram::Where::NotAny)
should_negate(Avram::Where::NotAny, Avram::Where::Any)
end
end
5 changes: 5 additions & 0 deletions src/avram/criteria.cr
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ class Avram::Criteria(T, V)
add_clause(Avram::Where::In.new(column, values))
end

def have_any(values) : T
values = values.map { |value| V.adapter.to_db!(value) }
add_clause(Avram::Where::Any.new(column, values))
end

# :nodoc:
def private_distinct_on : T
rows.tap &.query.distinct_on(column)
Expand Down
27 changes: 26 additions & 1 deletion src/avram/migrator/alter_table_statement.cr
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Avram::Migrator::AlterTableStatement
getter fill_existing_with_statements = [] of String
getter change_type_statements = [] of String
getter change_default_statements = [] of String
getter change_nullability_statements = [] of String
private getter? if_exists : Bool = false

def initialize(@table_name : TableName, *, @if_exists : Bool = false)
Expand Down Expand Up @@ -80,6 +81,30 @@ class Avram::Migrator::AlterTableStatement
add_change_default_statement %column
end

# Change the column's nullability from whatever it is currently to true.
# ```
# alter table_for(User) do
# allow_nulls_for :email
# end
# ```
macro allow_nulls_for(column_name)
change_nullability_statements << build_nullability_statement({{column_name.id.stringify}}, true)
end

# Change the column's nullability from whatever it is currently to false.
# ```
# alter table_for(User) do
# forbid_nulls_for :email
# end
# ```
macro forbid_nulls_for(column_name)
change_nullability_statements << build_nullability_statement({{column_name.id.stringify}}, false)
end

def build_nullability_statement(column_name, nullability)
"ALTER TABLE #{@table_name} ALTER COLUMN #{column_name} #{nullability ? "DROP" : "SET"} NOT NULL;"
end

def add_change_type_statement(column : ::Avram::Migrator::Columns::Base)
change_type_statements << column.build_change_type_statement(@table_name)
end
Expand Down Expand Up @@ -114,7 +139,7 @@ class Avram::Migrator::AlterTableStatement
end

def statements
alter_statements + change_default_statements + change_type_statements + index_statements + fill_existing_with_statements
alter_statements + change_type_statements + change_default_statements + change_nullability_statements + index_statements + fill_existing_with_statements
end

def if_exists_statement
Expand Down
28 changes: 28 additions & 0 deletions src/avram/where.cr
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,34 @@ module Avram::Where
end
end

class Any < ValueHoldingSqlClause
def operator : String
"&&"
end

def negated : NotAny
NotAny.new(column, value)
end

def prepare(placeholder_supplier : Proc(String)) : String
"#{column} #{operator} (#{placeholder_supplier.call})"
end
end

class NotAny < ValueHoldingSqlClause
def operator : String
"&&"
end

def negated : Any
Any.new(column, value)
end

def prepare(placeholder_supplier : Proc(String)) : String
"NOT(#{column} #{operator} (#{placeholder_supplier.call}))"
end
end

class Includes < ValueHoldingSqlClause
def operator : String
"= ANY"
Expand Down
Loading