drizzle-team / drizzle-orm

Headless TypeScript ORM with a head. Runs on Node, Bun and Deno. Lives on the Edge and yes, it's a JavaScript ORM too 😅
https://orm.drizzle.team
Apache License 2.0
23.68k stars 587 forks source link

Feedback for “SQL Insert - .onConflictDoUpdate()” #1205

Open JS-GitRepo opened 1 year ago

JS-GitRepo commented 1 year ago

Is there a way to provide the conflicting object to the "set" parameter for .onConflictDoUpdate()? i.e.

let processedCards: processedCards[] = [{data},{data},{data}]
const processedCardsResult = await db2
      .insert(cards_temp)
      .values(processedCards)
      .onConflictDoUpdate({
          target: cards_temp.card_id,
          set: ***current conflicting card***
      });

My thought for this, similar to Kysely's approach, would be something like a callback with values or an index relative to the value

let processedCards: processedCards[] = [{data},{data},{data}]
const processedCardsResult = await db2
      .insert(cards_temp)
      .values(processedCards)
      .onConflictDoUpdate((conflictingItem)=>{
          target: cards_temp.card_id,
          set: conflictingItem
      });

Or

let processedCards: processedCards[] = [{data},{data},{data}]
const processedCardsResult = await db2
      .insert(cards_temp)
      .values(processedCards)
      .onConflictDoUpdate((conflictingItem, i)=>{
          target: cards_temp.card_id,
          set: processedCards[i]
      });

Or x2

let processedCards: processedCards[] = [{data},{data},{data}]
const processedCardsResult = await db2
      .insert(cards_temp)
      .values(processedCards)
      .onConflictDoUpdate({
          target: cards_temp.card_id,
          set: set
      });

(In this last case, leaving "set" undefined or defined as itself would refer to updating the current conflicting insert object).

Overall, my goal is to insert a card to the DB and update it if it already exists. If there is a better way to go about this as an alternative please let me know!

Lastly, Kysely's approach for comparison:

  const processedCardsResult = await db
      .insertInto("cards_temp")
      .values(processedCards)
      .onConflict((onConflictBuilder) =>
          onConflictBuilder
              .column("card_id")
              .doUpdateSet((expressionBuilder) =>
                  generateUpdateSetObject_ProcessedCard(
                      expressionBuilder,
                  ),
              ),
      )
      .execute();

  function generateUpdateSetObject_ProcessedCard(
      eb: ExpressionBuilder<
          OnConflictDatabase<DB, "cards_temp">,
          OnConflictTables<"cards_temp">
      >,
  ): object {
      return {
          name: eb.ref("excluded.name"),
          ...<more data>
      };
  }
bernatfortet commented 10 months ago

Did you figure it out @JS-GitRepo ?