MCPcopy Index your code
hub / github.com/simstudioai/sim / checkColumns

Function checkColumns

apps/sim/lib/table/validation.ts:585–648  ·  view source on GitHub ↗
(ex: UniqueCheckExecutor)

Source from the content-addressed store, hash-verified

583 // LOCAL dies at its commit; it only penalizes plan shape, and the statements
584 // that follow in those transactions are tenant-scoped writes).
585 const checkColumns = async (ex: UniqueCheckExecutor) => {
586 for (const [columnId, { values, column }] of valuesByColumn) {
587 if (values.size === 0) continue
588
589 if (!NAME_PATTERN.test(columnId)) {
590 throw new Error(`Invalid column id: ${columnId}`)
591 }
592
593 const valueArray = Array.from(values)
594 const valueConditions = valueArray.map((normalizedValue) => {
595 // Check if the original values are strings (normalized values for strings are lowercase)
596 // We need to determine the type from the column definition or the first row that has this value
597 const isStringColumn = column.type === 'string'
598
599 if (isStringColumn) {
600 return sql`lower(${userTableRows.data}->>${sql.raw(`'${columnId}'`)}) = ${normalizedValue}`
601 }
602 return sql`(${userTableRows.data}->${sql.raw(`'${columnId}'`)})::jsonb = ${normalizedValue}::jsonb`
603 })
604
605 const conflictingRows = await ex
606 .select({
607 id: userTableRows.id,
608 data: userTableRows.data,
609 position: userTableRows.position,
610 })
611 .from(userTableRows)
612 .where(and(eq(userTableRows.tableId, tableId), or(...valueConditions)))
613 .limit(valueArray.length) // We only need up to one conflict per value
614
615 // Map conflicts back to batch rows
616 for (const conflict of conflictingRows) {
617 const conflictData = conflict.data as RowData
618 const conflictValue = conflictData[columnId]
619 const normalizedConflictValue =
620 typeof conflictValue === 'string'
621 ? conflictValue.toLowerCase()
622 : JSON.stringify(conflictValue)
623
624 // Find which batch rows have this conflicting value
625 for (let i = 0; i < rows.length; i++) {
626 const rowValue = rows[i][columnId]
627 if (rowValue === null || rowValue === undefined) continue
628
629 const normalizedRowValue =
630 typeof rowValue === 'string' ? rowValue.toLowerCase() : JSON.stringify(rowValue)
631
632 if (normalizedRowValue === normalizedConflictValue) {
633 // Check if this row already has errors for this column
634 let rowError = rowErrors.find((e) => e.row === i)
635 if (!rowError) {
636 rowError = { row: i, errors: [] }
637 rowErrors.push(rowError)
638 }
639
640 const errorMsg = `Column "${column.name}" must be unique. Value "${rowValue}" already exists in row ${conflict.position + 1}`
641 if (!rowError.errors.includes(errorMsg)) {
642 rowError.errors.push(errorMsg)

Callers 1

Calls 3

testMethod · 0.80
eqFunction · 0.50
pushMethod · 0.45

Tested by

no test coverage detected