forge-sql-orm 2.0.20 → 2.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -465,6 +465,20 @@ await forgeSQL.crud().insert(Users, [
465
465
  ],
466
466
  true
467
467
  );
468
+
469
+ // Insert with sequence (nextVal)
470
+ import { nextVal } from "forge-sql-orm";
471
+
472
+ const user = {
473
+ id: nextVal('user_id_seq'),
474
+ name: "user test",
475
+ organization_id: 1
476
+ };
477
+ const id = await forgeSQL.modify().insert(appUser, [user]);
478
+
479
+ // The generated SQL will be:
480
+ // INSERT INTO app_user (id, name, organization_id)
481
+ // VALUES (NEXTVAL(user_id_seq), ?, ?) -- params: ["user test", 1]
468
482
  ```
469
483
 
470
484
  ### Update Operations
@@ -494,6 +508,41 @@ await forgeSQL.crud().updateFields(
494
508
  await forgeSQL.crud().deleteById(1, Users);
495
509
  ```
496
510
 
511
+ ## SQL Utilities
512
+
513
+ ### formatLimitOffset
514
+
515
+ The `formatLimitOffset` utility function is used to safely insert numeric values directly into SQL queries for LIMIT and OFFSET clauses. This is necessary because Atlassian Forge SQL doesn't support parameterized queries for these clauses.
516
+
517
+ ```typescript
518
+ import { formatLimitOffset } from "forge-sql-orm";
519
+
520
+ // Example usage in a query
521
+ const result = await forgeSQL
522
+ .select()
523
+ .from(orderItem)
524
+ .orderBy(asc(orderItem.createdAt))
525
+ .limit(formatLimitOffset(10))
526
+ .offset(formatLimitOffset(350000));
527
+
528
+ // The generated SQL will be:
529
+ // SELECT * FROM order_item
530
+ // ORDER BY created_at ASC
531
+ // LIMIT 10
532
+ // OFFSET 350000
533
+ ```
534
+
535
+ **Important Notes:**
536
+ - The function performs type checking to prevent SQL injection
537
+ - It throws an error if the input is not a valid number
538
+ - Use this function instead of direct parameter binding for LIMIT and OFFSET clauses
539
+ - The function is specifically designed to work with Atlassian Forge SQL's limitations
540
+
541
+ **Security Considerations:**
542
+ - The function includes validation to ensure the input is a valid number
543
+ - This prevents SQL injection by ensuring only numeric values are inserted
544
+ - Always use this function instead of string concatenation for LIMIT and OFFSET values
545
+
497
546
  ## Optimistic Locking
498
547
 
499
548
  Optimistic locking is a concurrency control mechanism that prevents data conflicts when multiple transactions attempt to update the same record concurrently. Instead of using locks, this technique relies on a version field in your entity models.
@@ -131,6 +131,7 @@ function generateDropTableStatements(tables) {
131
131
  const dropStatements = [];
132
132
  tables.forEach((tableName) => {
133
133
  dropStatements.push(`DROP TABLE IF EXISTS \`${tableName}\`;`);
134
+ dropStatements.push(`DROP SEQUENCE IF EXISTS \`${tableName}\`;`);
134
135
  });
135
136
  return dropStatements;
136
137
  }
@@ -269,6 +270,15 @@ function processNullBranches(obj) {
269
270
  }
270
271
  return allNull ? null : result;
271
272
  }
273
+ function formatLimitOffset(limitOrOffset) {
274
+ if (typeof limitOrOffset !== "number" || isNaN(limitOrOffset)) {
275
+ throw new Error("limitOrOffset must be a valid number");
276
+ }
277
+ return drizzleOrm.sql.raw(`${limitOrOffset}`);
278
+ }
279
+ function nextVal(sequenceName) {
280
+ return drizzleOrm.sql.raw(`NEXTVAL(${sequenceName})`);
281
+ }
272
282
  class ForgeSQLCrudOperations {
273
283
  forgeOperations;
274
284
  options;
@@ -1338,6 +1348,7 @@ exports.forgeDriver = forgeDriver;
1338
1348
  exports.forgeSystemTables = forgeSystemTables;
1339
1349
  exports.forgeTimeString = forgeTimeString;
1340
1350
  exports.forgeTimestampString = forgeTimestampString;
1351
+ exports.formatLimitOffset = formatLimitOffset;
1341
1352
  exports.generateDropTableStatements = generateDropTableStatements;
1342
1353
  exports.getHttpResponse = getHttpResponse;
1343
1354
  exports.getPrimaryKeys = getPrimaryKeys;
@@ -1346,6 +1357,7 @@ exports.getTables = getTables;
1346
1357
  exports.mapSelectAllFieldsToAlias = mapSelectAllFieldsToAlias;
1347
1358
  exports.mapSelectFieldsWithAlias = mapSelectFieldsWithAlias;
1348
1359
  exports.migrations = migrations;
1360
+ exports.nextVal = nextVal;
1349
1361
  exports.parseDateTime = parseDateTime;
1350
1362
  exports.patchDbWithSelectAliased = patchDbWithSelectAliased;
1351
1363
  //# sourceMappingURL=ForgeSQLORM.js.map