Giter VIP home page Giter VIP logo

Comments (9)

hernangonzalez avatar hernangonzalez commented on May 9, 2024 15

Hi, is this still planned for inclusion?

from fluent-kit.

gwynne avatar gwynne commented on May 9, 2024 3

This was implemented at the SQLKit layer in vapor/sql-kit#90, but support in the FluentKit layer has yet to be added.

from fluent-kit.

rnantes avatar rnantes commented on May 9, 2024 1

+1 on this useful feature. The Rust Diesel ORM has a upsert functionality when inserting/updating multiple rows. If there is a conflict on row it allows custom functionality on for that specific row using the on_conflict() function. This is similar to how a raw postgres query works. Here is are postgreSQL and Diesel examples. Might be a good starting point.

from fluent-kit.

marc-medley avatar marc-medley commented on May 9, 2024

Related fluent-sqlite-driver issue 23: 'save(on:)' with given UUID fails to save to database

The Vapor document seemed to indicate that save(on:) would behave something like an classic UPDATE OR INSERT SQL command. However, save(on:) is not an UPSERT and could fail (at that time) without any error notification.

Saves the model, calling either create(...) or update(...) …

Once the upsert is implemented in fluent-kit and the associated drivers (e.g. fluent-sqlite-driver), then perhaps then it would be time to deprecate save(on:) … as mentioned by @tanner0101 ?

from fluent-kit.

tanner0101 avatar tanner0101 commented on May 9, 2024

save simply calls either create or update depending on whether the model was fetched from the database. There's no upsert support yet. It would be a nice feature to have, though.

from fluent-kit.

marc-medley avatar marc-medley commented on May 9, 2024

Hmmm..., UPSERT (or MERGE) would be "simply a call to either create or update depending on whether" the id key exists in the SQL database:

IF EXISTS (key …) /* ** e.g. ID in the SQL database ** */
  UPDATE command  /* update */
ELSE
  INSERT command  /* create */

... seems that a variant of save which checks for key exists in database instead of model fetch source might provide an upsert capability.

And BTW, a MERGE (aka UPSERT) capabitility seems to be more than a "would be a nice feature " ... MERGE "was officially introduced in the SQL:2003 standard, and expanded in the SQL:2008 standard." ... it's a standard SQL capability which is missing in fluent-kit.

from fluent-kit.

tanner0101 avatar tanner0101 commented on May 9, 2024

The SQL you pasted checks the db and decides whether to update or insert in a single query. save() is simply checking whether your code fetched this model in from the database or initialized it manually. It assumes if you fetched from the db, then save should be an update. If this is a new model you just initialized, then save should be a create.

The fact that this is an old SQL capability is not very helpful support for inclusion in Fluent. If you have specific examples of what problems you're trying to solve, ideas about how this could relate to the Model API (as @calebkleveter has done), or references to other ORMs similar to Fluent that include support (as @rnantes has done), that is much more helpful. Building this feature in a meaningful, easy-to-use way that is consistent with how the rest of Fluent works takes more effort than just adding in the SQL keywords.

from fluent-kit.

tanner0101 avatar tanner0101 commented on May 9, 2024

Here's an initial idea for API based on what @calebkleveter and @rnantes shared:

let uuid = UUID()

// Insert user with name Foo
User(id: uuid, name: "Foo")
    .create(on: db)

// Updates name to Bar
// Automatically uses same input values for the update
User(id: uuid, name: "Bar")
    .create(orUpdate: .conflict(\.$id), on: db)

// Updates name to Qux
// User decides the input values in case of conflict
User(id: uuid, name: "Baz")
    .create(orUpdate: .conflict(\.$id), on: db) {
        $0.set(\.$name, to: "Qux")
    }

// Updates name to Quuz
// The model API will use this query builder API internally
User.query(on: db)
    .set(\.$id, to: uuid)
    .set(\.$name, to: "Quuz")
    .create(orUpdate: .conflict(\.$id), on: db)

I also tried with .on(conflict:) but then the method uses "on" twice which might be a little confusing.

user.create(orUpdate: .on(conflict: \.$id), on: db)

from fluent-kit.

tanner0101 avatar tanner0101 commented on May 9, 2024

Note from vapor/fluent-mysql-driver#153 that timestamps should be updated correctly during upsert.

from fluent-kit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.