adonisjs / lucid

AdonisJS SQL ORM. Supports PostgreSQL, MySQL, MSSQL, Redshift, SQLite and many more
https://lucid.adonisjs.com/
MIT License
1.02k stars 189 forks source link

Default values does not return in create #992

Closed AlexcastroDev closed 5 months ago

AlexcastroDev commented 5 months ago

Package version

9.x.x

Describe the bug

I started a new project and notice that when i create a new row, and a column with default value, it does not return.

migration example:

async up() {
    this.schema.createTable(this.tableName, (table) => {
      table.increments("id");
      table.string("language").notNullable();
      table.text("message").notNullable();
      table.string("group").notNullable().defaultTo("global");
      table.string("key").notNullable();
    });
  }

in database column is created correctly and data is correct also:

image

The following image shows that after creation, the translation has a property group as undefined:

image

Am i missing something? i can investigate this if you want.

full code: https://github.com/I18nOrbit/cms/blob/main/api/app/controllers/me/translations_controller.ts

Reproduction repo

No response

RomainLanz commented 5 months ago

Hey @AlexcastroDev! 👋🏻

Your screen shows that the block variable group is undefined, not the value of translation.group.

AlexcastroDev commented 5 months ago

Hey @AlexcastroDev! 👋🏻

Your screen shows that the block variable group is undefined, not the value of translation.group.

in debugger console, translation.group is undefined

AlexcastroDev commented 5 months ago

@RomainLanz I suspected that it probably should create the line in the table based on my payload, and insert returning the id, and then perform a merge. Because this would avoid having to do an insert and then an unnecessary select query.

Upon running the tests and seeing the postgres log, that was really the case

2024-01-27 23:28:20.674 UTC [35] LOG:  duration: 0.039 ms  bind <unnamed>: insert into "translations" ("group", "key", "language", "message") values (DEFAULT, $1, $2, $3) returning "id"
2024-01-27 23:28:20.674 UTC [35] DETAIL:  parameters: $1 = 'hello_world', $2 = 'en_US', $3 = 'Hello World'
2024-01-27 23:28:20.674 UTC [35] LOG:  execute <unnamed>: insert into "translations" ("group", "key", "language", "message") values (DEFAULT, $1, $2, $3) returning "id"
2024-01-27 23:28:20.674 UTC [35] DETAIL:  parameters: $1 = 'hello_world', $2 = 'en_US', $3 = 'Hello World'
2024-01-27 23:28:20.674 UTC [35] LOG:  duration: 0.203 ms
2024-01-27 23:28:24.371 UTC [1] LOG:  received fast shutdown request
2024-01-27 23:28:24.373 UTC [1] LOG:  aborting any active transactions
2024-01-27 23:28:24.377 UTC [1] LOG:  background worker "logical replication launcher" (PID 34) exited with exit code 1
2024-01-27 23:28:24.377 UTC [29] LOG:  shutting down
2024-01-27 23:28:24.378 UTC [29] LOG:  checkpoint starting: shutdown immediate
2024-01-27 23:28:24.389 UTC [29] LOG:  checkpoint complete: wrote 13 buffers (0.1%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.004 s, sync=0.004 s, total=0.012 s; sync files=12, longest=0.002 s, average=0.001 s; distance=16 kB, estimate=16 kB; lsn=0/1A5A4B8, redo lsn=0/1A5A4B8
2024-01-27 23:28:24.393 UTC [1] LOG:  database system is shut down
thetutlage commented 5 months ago

Isn't this how SQL works? When you insert something to the database, you do not get back the inserted row in the result.

AlexcastroDev commented 5 months ago

Isn't this how SQL works? When you insert something to the database, you do not get back the inserted row in the result.

It's not about how SQL works, but the model implementation.

Tbh, the problem here is the model, based on this issue, i should put a default value in model also.

Look the active_record gem:

class CreateTranslations < ActiveRecord::Migration[7.1]
  def change
    create_table :translations do |t|
      t.string :key
      t.string :value
      t.string :group, null: false, default: 'hello'
    end
  end
end

Now, perform a creation:

3.1.4 :002 > t = Translation.new(key: 'some', value: 'thing')
 => #<Translation:0x00000001132af490 id: nil, key: "some", value: "thing", group: "hello", created_at: nil, updated_at: nil> 
3.1.4 :003 > t.save
  TRANSACTION (0.1ms)  begin transaction
  Translation Create (1.0ms)  INSERT INTO "translations" ("key", "value", "group", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) RETURNING "id"  [["key", "some"], ["value", "thing"], ["group", "hello"], ["created_at", "2024-01-29 10:15:24.064165"], ["updated_at", "2024-01-29 10:15:24.064165"]]
  TRANSACTION (0.5ms)  commit transaction
 => true

In the end, i need declare the default value in migration and model.

i will close this issue too, thanks.

RomainLanz commented 5 months ago

You can also refresh your model: await translation.refresh()

AlexcastroDev commented 5 months ago

You can also refresh your model: await translation.refresh()

Yeah, but it need to do it in my specs also, and others places. So in this case, a default value in model is better.

thetutlage commented 5 months ago

I think it works for Rails because they scan the database schema on app load and that is the time when they are reading the default values from the database as well.

This is something we do not do and have no plans to do.

But as you said, duplicating the default value in the model does the trick for this use case.