Skip to main content

autoincrement

This is the equivalent of Prisma's autoincrement(). It automatically assigns unique, monotonically increasing values during create operations.

Schema vs. Constructor​

When using the CLI, this setting is written in schema.prisma. When using the GAS editor alone, you pass it to the GassmaClient constructor (the examples on the rest of this page use the constructor form).

How to write it
Schema (CLI)id Int @id @default(autoincrement())
Constructor (GAS editor)autoincrement: { Users: "id" }
model Users {
id Int @id @default(autoincrement())
name String
}

For how to write schemas, see Schema.

Basic Usage​

const gassma = new Gassma.GassmaClient({
autoincrement: {
Users: "id",
},
});

// id is automatically assigned during create
gassma.Users.create({
data: { name: "Alice" },
});
// => \{ id: 1, name: "Alice" \}

gassma.Users.create({
data: { name: "Bob" },
});
// => \{ id: 2, name: "Bob" \}

Multiple Columns​

You can specify multiple columns using an array.

autoincrement: {
Users: ["id", "seq"],
}

Behavior with createMany​

With createMany, counters for all rows are reserved at once before being assigned to each row.

gassma.Users.createMany({
data: [{ name: "Alice" }, { name: "Bob" }],
});
// => id: 1, 2 are assigned respectively

How It Works​

  1. Exclusive control by acquiring the GassmaClient's lock with waitLock(10000)
  2. Read the counter from PropertiesService.getScriptProperties()
  3. Increment by +1 (+N for createMany) and write back
  4. Release the lock

The client generated by npx gassma generate fills lock with LockService.getScriptLock() by default. On a client that has no lock (for example one constructed in the GAS editor without passing lock), numbers are assigned without taking a lock (this is not an error).

note

This feature only works in the GAS environment because it uses GAS's LockService and PropertiesService.

Behavior with Explicit Values​

If a value is explicitly specified for a field, auto-increment is skipped.

gassma.Users.create({
data: { id: 100, name: "Alice" },
});
// => id is 100 (auto-increment is not applied)

Adopting GASsma on a Sheet That Already Has Data​

The counter starts at 0 and does not look at the values already in the sheet. So if you adopt GASsma on a sheet whose id values run from 1 to 500, the first create assigns id: 1 and collides with an existing row.

Calling $syncAutoincrement() restarts the counter just after the largest value in that column. Call it once when you adopt GASsma.

// When the existing ids run from 1 to 500
gassma.Users.$syncAutoincrement("id");
// => 501

gassma.Users.create({
data: { name: "Alice" },
});
// => { id: 501, name: "Alice" }

If rows are added by editing the spreadsheet by hand and the counter falls out of sync, calling $syncAutoincrement() again brings it back in the same way.

Operating the Counter​

In Prisma, autoincrement() takes no arguments, and the counter is adjusted with SQL such as ALTER SEQUENCE ... RESTART WITH. The GASsma counter lives in PropertiesService and can be reached neither from the schema nor from SQL, so it is exposed as methods on the model instead.

All three methods speak in terms of the value that will be issued next. This is the same meaning as ALTER SEQUENCE ... RESTART WITH 1000.

MethodReturn valueDescription
$getAutoincrement(field)numberReturns the value that will be issued next (1 if nothing has been issued yet)
$setAutoincrement(field, next)voidMakes next the value that will be issued next
$syncAutoincrement(field)numberSets the counter to the largest value in the column + 1 and returns it
gassma.Users.$getAutoincrement("id");
// => 1

gassma.Users.$setAutoincrement("id", 501);

gassma.Users.$getAutoincrement("id");
// => 501

Use $setAutoincrement when you want to decide the value yourself. If you only want to match the existing data, use $syncAutoincrement.

note

With the CLI, the type of field on all three methods is narrowed to the fields of that model that have autoincrement configured. Writing a field name that is not configured is a type error, and on a model with no autoincrement field at all the type of field is never, so the methods cannot be called.

What $syncAutoincrement Looks At​

  • It reads only the column of the target field (not the whole sheet)
  • It takes the maximum of numeric values only. Empty cells and non-numeric values are ignored
  • Decimals are truncated (if 3.7 is present, the next value is 4)
  • If there are no numeric values at all, or only negative numbers, the next value is 1
ErrorTrigger condition
GassmaAutoincrementNotConfiguredErrorA field that is not configured with autoincrement is passed as field
GassmaAutoincrementInTransactionError$setAutoincrement / $syncAutoincrement is called inside $transaction
GassmaInvalidValueErrorThe next of $setAutoincrement is not an integer of 1 or greater (NaN / Infinity / a decimal / 0 or less / a non-number)
GassmaInvalidValueError$syncAutoincrement is called when the column of the field configured with autoincrement does not exist on the sheet (for example after the column was renamed)

For details, see the Error List.

caution

$setAutoincrement / $syncAutoincrement cannot be called inside $transaction. The counter lives in PropertiesService and never enters the sheet buffer, so it is not rolled back when the transaction fails. $getAutoincrement only reads, so it can be called inside a transaction.