diff --git a/Changes b/Changes index ae84e2b4..ddfcd8f0 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,8 @@ Revision history for Red {{$NEXT}} + - Fix create child with no ids + - Fix double as on computation + column value 0.1.72 2024-04-15T19:34:47+01:00 - Fix select for on SQLite diff --git a/lib/MetamodelX/Red/Dirtable.rakumod b/lib/MetamodelX/Red/Dirtable.rakumod index aad2fc9d..b8fc9cda 100644 --- a/lib/MetamodelX/Red/Dirtable.rakumod +++ b/lib/MetamodelX/Red/Dirtable.rakumod @@ -136,7 +136,7 @@ method compose-dirtable(Mu \type) { my %new = |@columns.map: { my Mu $built := .build; - $built := $built.(self.WHAT, Mu) if $built ~~ Method; + $built := $built.(self, Mu) if $built ~~ Method; next if $built =:= Mu; if instance.^is-id: $_ { instance.^set-id: .name => $built diff --git a/lib/MetamodelX/Red/Model.rakumod b/lib/MetamodelX/Red/Model.rakumod index 22a864eb..4729989c 100644 --- a/lib/MetamodelX/Red/Model.rakumod +++ b/lib/MetamodelX/Red/Model.rakumod @@ -581,6 +581,8 @@ multi method create(\model where *.DEFINITE, *%orig-pars, :$with where not .defi }.Hash } else { %pars.kv.map(-> $key, $value { + next without $value; + next without %cols{$key}; Red::AST::Eq.new: %cols{$key}, ast-value $value }) .reduce: { Red::AST::AND.new: $^a, $^b } diff --git a/lib/Red/ColumnMethods.rakumod b/lib/Red/ColumnMethods.rakumod index 800b5e3b..ba6b01e4 100644 --- a/lib/Red/ColumnMethods.rakumod +++ b/lib/Red/ColumnMethods.rakumod @@ -64,17 +64,17 @@ multi method index($base: $needle) { #| Return the year from the date column method year($base where { .returns ~~ (Date|DateTime|Instant) }:) { - Red::AST::DateTimePart.new(:$base, :part(Red::AST::DateTime::Part::year)) but Red::ColumnMethods + Red::AST::Mul.new(ast-value(1), Red::AST::DateTimePart.new(:$base, :part(Red::AST::DateTime::Part::year))) but Red::ColumnMethods } #| Return the month from the date column method month($base where { .returns ~~ (Date|DateTime|Instant) }:) { - Red::AST::DateTimePart.new(:$base, :part(Red::AST::DateTime::Part::month)) but Red::ColumnMethods + Red::AST::Mul.new(ast-value(1), Red::AST::DateTimePart.new(:$base, :part(Red::AST::DateTime::Part::month))) but Red::ColumnMethods } #| Return the day from the date column method day($base where { .returns ~~ (Date|DateTime|Instant) }:) { - Red::AST::DateTimePart.new(:$base, :part(Red::AST::DateTime::Part::day)) but Red::ColumnMethods + Red::AST::Mul.new(ast-value(1), Red::AST::DateTimePart.new(:$base, :part(Red::AST::DateTime::Part::day))) but Red::ColumnMethods } #| Return the date from a datetime, timestamp etc diff --git a/lib/Red/Driver/CommonSQL.rakumod b/lib/Red/Driver/CommonSQL.rakumod index dd84e2ed..d4ff89b2 100644 --- a/lib/Red/Driver/CommonSQL.rakumod +++ b/lib/Red/Driver/CommonSQL.rakumod @@ -649,11 +649,12 @@ multi method translate(Red::AST::Select $sel, "select") { multi method translate(Red::Column $col, "select", Str :$RED-OVERRIDE-COLUMN-AS-PREFIX) { my ($str, @bind) := do with $col.computation { + my $*RED-INSIDE-COMPUTATION = True; do given self.translate: $_, "select" { .key, .value } } else { "{ self.table-name-wrapper: $col.model.^as }.{ $col.name }", [] } - my $as = do if $col.computation.?type !~~ Positional { + my $as = do if $col.computation.?type !~~ Positional and not $*RED-INSIDE-COMPUTATION { qq; } qq[$str { $as if @@ -725,6 +726,7 @@ multi method translate(Red::AST::Value $_ where .type ~~ Red::AST::Select, $cont multi method translate(Red::AST::Value $_ where .type ~~ Positional, "select") { my @sql; my @bind; + my $RED-INSIDE-COMPUTATION = True; .get-value.map: { my ( :$key, :@value) = self.translate: $_, "select"; @sql.push: $key; diff --git a/t/82-emakei.rakutest b/t/82-emakei.rakutest new file mode 100644 index 00000000..4fa30a79 --- /dev/null +++ b/t/82-emakei.rakutest @@ -0,0 +1,63 @@ +use Test; +use Red:api<2>; +#use RedX::HashedPassword; +use UUID; + +model User { ... }; + +model Company is rw is export { + has Str $.id is column = ~UUID.new; + has Str $.name is column is required; + has Str $.official-name is column = ""; + has Str $.reg-number is column = ""; + has Str $.official-addr is column = ""; + has Str $.email-addr is column = ""; + has Str $.main-addr is column = ""; + has Str $.skype-nick is column = ""; + has Str $.telegram-nick is column = ""; + has Str $.phone-number is column = ""; + has User @.users is relationship{ .company-id }; +} + +model User is rw is export { + has Str $.id is column = ~UUID.new; + has Str $!company-id is referencing( *.id, :model(Company)); + has Str $.login-name is column( :unique ); + #has Str $.password is password handles ; + has Bool $.is-admin is column = False; + has Str $.full-name is column = ""; + has Str $.email-addr is column = ""; + has Str $.skype-nick is column = ""; + has Str $.telegram-nick is column = ""; + has Str $.phone-number is column = ""; + has Str $.home-addr is column = ""; + has Company $.company is relationship{ .company-id }; +} + + +my $*RED-DEBUG = $_ with %*ENV; +my $*RED-DEBUG-RESPONSE = $_ with %*ENV; +my @conf = (%*ENV // "SQLite").split(" "); +my $driver = @conf.shift; +my $*RED-DB = database $driver, |%( @conf.map: { do given .split: "=" { .[0] => val .[1] } } ); + +schema(Company, User).drop; + +Company.^create-table: :unless-exists; + +my $company = Company.^create(name => 'abc'); + +is Company.^all.head.name, "abc"; + +User.^create-table: :unless-exists; + +my $admin = $company.users.create(login-name => 'admin', password => 'nimda', full-name => "Administrator", is-admin => True); + +$company.users.create(login-name => "fox", password => "xof", full-name => "Jon"); + +my @users = User.^all.sort(*.login-name).map: { "{ .company.name } - { .login-name }" } + +is @users[0], "abc - admin"; +is @users[1], "abc - fox"; + +done-testing;