MCPcopy
hub / github.com/simstudioai/sim / updateColumnConstraints

Function updateColumnConstraints

apps/sim/lib/table/columns/service.ts:549–629  ·  view source on GitHub ↗
(
  data: UpdateColumnConstraintsData,
  requestId: string
)

Source from the content-addressed store, hash-verified

547 * @throws Error if table not found, column not found, or existing data violates the constraint
548 */
549export async function updateColumnConstraints(
550 data: UpdateColumnConstraintsData,
551 requestId: string
552): Promise<TableDefinition> {
553 return withLockedTable(data.tableId, async (table, trx) => {
554 // Scale both statement and idle timeouts to row count: the required/unique
555 // validation runs between separate queries inside this transaction, leaving
556 // it briefly idle. Match `updateColumnType` so the default 5s
557 // `idle_in_transaction_session_timeout` can't abort a valid change on a
558 // large table.
559 const timeoutMs = scaledStatementTimeoutMs(table.rowCount ?? 0, {
560 baseMs: 60_000,
561 perRowMs: 2,
562 })
563 await setTableTxTimeouts(trx, { statementMs: timeoutMs, idleMs: timeoutMs })
564
565 const schema = table.schema
566 const columnIndex = schema.columns.findIndex((c) => columnMatchesRef(c, data.columnName))
567 if (columnIndex === -1) {
568 throw new Error(`Column "${data.columnName}" not found`)
569 }
570
571 const column = schema.columns[columnIndex]
572 const columnKey = getColumnId(column)
573 if (column.workflowGroupId) {
574 throw new Error(
575 `Cannot change constraints on workflow-output column "${column.name}". Constraints aren't applicable to columns whose values come from workflow execution.`
576 )
577 }
578 if (data.required === true && !column.required) {
579 const [result] = await trx
580 .select({ count: count() })
581 .from(userTableRows)
582 .where(
583 and(
584 eq(userTableRows.tableId, data.tableId),
585 sql`(NOT (${userTableRows.data} ? ${columnKey}) OR ${userTableRows.data}->>${columnKey}::text IS NULL)`
586 )
587 )
588
589 if (result.count > 0) {
590 throw new Error(
591 `Cannot set column "${column.name}" as required: ${result.count} row(s) have null or missing values`
592 )
593 }
594 }
595
596 if (data.unique === true && !column.unique) {
597 const duplicates = (await trx.execute(
598 sql`SELECT ${userTableRows.data}->>${columnKey}::text AS val, count(*) AS cnt FROM ${userTableRows} WHERE table_id = ${data.tableId} AND ${userTableRows.data} ? ${columnKey} AND ${userTableRows.data}->>${columnKey}::text IS NOT NULL GROUP BY val HAVING count(*) > 1 LIMIT 1`
599 )) as { val: string; cnt: number }[]
600
601 if (duplicates.length > 0) {
602 throw new Error(`Cannot set column "${column.name}" as unique: duplicate values exist`)
603 }
604 }
605
606 const updatedColumns = schema.columns.map((c, i) =>

Callers 3

executeFunction · 0.90
route.tsFile · 0.90
route.tsFile · 0.90

Calls 9

withLockedTableFunction · 0.90
scaledStatementTimeoutMsFunction · 0.90
setTableTxTimeoutsFunction · 0.90
columnMatchesRefFunction · 0.90
getColumnIdFunction · 0.90
infoMethod · 0.80
executeMethod · 0.65
setMethod · 0.65
eqFunction · 0.50

Tested by

no test coverage detected