diff --git a/lib/MetamodelX/Red/Model.pm6 b/lib/MetamodelX/Red/Model.pm6 index 115af567..6617baa3 100644 --- a/lib/MetamodelX/Red/Model.pm6 +++ b/lib/MetamodelX/Red/Model.pm6 @@ -82,6 +82,10 @@ method columns(|) is rw { @!columns } +method column-values (\model --> Hash) { + %(@!columns.map: { %!attr-to-column{.name} => .get_value(model) }); +} + #| Returns a hash with the migration hash method migration-hash(\model --> Hash()) { columns => @!columns>>.column>>.migration-hash, @@ -447,7 +451,12 @@ multi method create(\model, *%orig-pars, :$with where not .defined) is rw { my $filter = model.^id-filter: |do if $data.defined and not $data.elems { $*RED-DB.execute(Red::AST::LastInsertedRow.new: model).row{|@ids}:kv } else { - $data{|@ids}:kv + my %data-copy = model.^id>>.column.map({ + $data{.name}:exists + ?? (.attr-name => $data{.name}) + !! (.attr-name => $data{.attr-name}) + }); + %data-copy{|@ids}:kv }.Hash if @ids; for %positionals.kv -> $name, @val { diff --git a/lib/Red/Driver/CommonSQL.pm6 b/lib/Red/Driver/CommonSQL.pm6 index 24b5b3cc..6d57468b 100644 --- a/lib/Red/Driver/CommonSQL.pm6 +++ b/lib/Red/Driver/CommonSQL.pm6 @@ -523,7 +523,7 @@ multi method translate(Red::AST::Value $_ where .type ~~ Red::AST::Select, $cont } multi method translate(Red::AST::Value $_ where .type ~~ Positional, $context?) { - '( ' ~ .get-value.map( -> $v { '?' } ).join(', ') ~ ' )' => .get-value; + '( ' ~ .get-value.map( -> $v { self.wildcard } ).join(', ') ~ ' )' => .get-value; } multi method translate(Red::AST::Value $_ where .type.HOW ~~ Metamodel::EnumHOW, $context?) { @@ -738,4 +738,4 @@ multi method prepare-json-path-item(@items) { } multi method prepare-json-path-item(Red::AST::Value $_) { self.prepare-json-path-item: .value } multi method prepare-json-path-item(Int $_) { "[{ $_ }]" } -multi method prepare-json-path-item(Str $_) { ".{ $_ }" } \ No newline at end of file +multi method prepare-json-path-item(Str $_) { ".{ $_ }" } diff --git a/lib/Red/Driver/Pg.pm6 b/lib/Red/Driver/Pg.pm6 index 12d53ec3..2145069c 100644 --- a/lib/Red/Driver/Pg.pm6 +++ b/lib/Red/Driver/Pg.pm6 @@ -115,6 +115,10 @@ multi method default-type-for(Red::Column $ where .attr.type ~~ Bool multi method default-type-for(Red::Column $ where .attr.type ~~ UUID --> Str:D) {"uuid"} multi method default-type-for(Red::Column $ --> Str:D) {"varchar(255)"} +multi method type-by-name("text" --> "text") {} +multi method type-by-name("json" --> "json") {} +multi method type-by-name("jsonb" --> "jsonb") {} + multi method inflate(Str $value, DateTime :$to!) { DateTime.new: $value } multi method map-exception(DB::Pg::Error::FatalError $x where .?message ~~ /"duplicate key value violates unique constraint " \"$=(\w+)\"/) { diff --git a/t/20-in-pg.t b/t/20-in-pg.t new file mode 100644 index 00000000..564cc97c --- /dev/null +++ b/t/20-in-pg.t @@ -0,0 +1,48 @@ +use Red; +use Test; + +my $*RED-PG-TEST-DB = $_ with %*ENV; + +my $*RED-DEBUG = $_ with %*ENV; +my $*RED-DEBUG-AST = $_ with %*ENV; + +plan 2; +unless $*RED-PG-TEST-DB { + "No RED_PG_TEST_DB initialized.".say; + skip-rest 2; +} + +model Category is table { + has Int $.id is serial; + has Int $.parent_id is column{ :references{ Category.id }, :nullable, }; + has Str $.name is column; + + has Category $.parent is relationship{ .parent_id }; + has Category @.children is relationship{ .parent_id }; +} + +$GLOBAL::RED-DB = database "Pg", :dbname($*RED-PG-TEST-DB); + +Category.^create-table; + +my $parent = Category.^create: :name('xx'); + +for [1 .. 5] -> $x { + Category.^create: :parent_id($parent.id), :name("child-$x"); +} + +# # This worked. +# (Category.^rs.grep: { .id (<) Category.^all.grep({ .id == 3 }).map({ .id }) } ).Seq.perl.say; + +# # This doesn't. +# (Category.^rs.grep: { .id (<) $parent.children.map({ .id }) } ).Seq.perl.say; + + + +# This worked in SQLite (But doesn't work with Pg driver.) +# my $*RED-DEBUG-AST = True; +my @seq = $parent.children.map({ .id }).Seq.sort; + +is-deeply @seq, [Category.^rs.grep({ .id in @seq }).map(*.id).Seq.sort], "in with literal list for pg"; +is-deeply @seq, [Category.^rs.grep({ .id (<) @seq }).map(*.id).Seq.sort], "in with literal list for pg (<) operator"; +