diff --git a/packages/nc-gui/components/dlg/QuickImport.vue b/packages/nc-gui/components/dlg/QuickImport.vue index 6d98a74341..d49f72f209 100644 --- a/packages/nc-gui/components/dlg/QuickImport.vue +++ b/packages/nc-gui/components/dlg/QuickImport.vue @@ -653,7 +653,7 @@ const onChange = () => { - Auto-Select Field Types + {{ $t('labels.autoSelectFieldTypes') }} diff --git a/packages/nc-gui/components/template/Editor.vue b/packages/nc-gui/components/template/Editor.vue index 1c59e4218e..f621f79b37 100644 --- a/packages/nc-gui/components/template/Editor.vue +++ b/packages/nc-gui/components/template/Editor.vue @@ -535,6 +535,15 @@ async function importTemplate() { title: '', columns: table.columns || [], }) + + if (process.env.NC_SANITIZE_COLUMN_NAME !== 'false') { + // column_name could have been updated in tableCreate + // e.g. sanitize column name to something like field_1, field_2, and etc + createdTable.columns.forEach((column, i) => { + table.columns[i].column_name = column.column_name + }) + } + table.id = createdTable.id table.title = createdTable.title diff --git a/packages/nc-gui/lang/en.json b/packages/nc-gui/lang/en.json index 837f801730..03dab6da39 100644 --- a/packages/nc-gui/lang/en.json +++ b/packages/nc-gui/lang/en.json @@ -591,6 +591,7 @@ "goToDashboard": "Go to Dashboard", "importing": "Importing", "formatJson": "Format JSON", + "autoSelectFieldTypes": "Auto-Select Field Types", "firstRowAsHeaders": "Use First Record as Headers", "flattenNested": "Flatten Nested", "downloadAllowed": "Download allowed", diff --git a/packages/noco-docs/docs/020.getting-started/050.self-hosted/020.environment-variables.md b/packages/noco-docs/docs/020.getting-started/050.self-hosted/020.environment-variables.md index a22ba523a1..01a5779b20 100644 --- a/packages/noco-docs/docs/020.getting-started/050.self-hosted/020.environment-variables.md +++ b/packages/noco-docs/docs/020.getting-started/050.self-hosted/020.environment-variables.md @@ -68,4 +68,5 @@ For production use-cases, it is **recommended** to configure | NC_AUTOMATION_LOG_LEVEL | Possible Values: `OFF`, `ERROR`, `ALL`. See [Webhooks](/automation/webhook/create-webhook#call-log) for details. | `OFF` | | NC_SECURE_ATTACHMENTS | Allow accessing attachments only through presigned urls. To enable set value as `true` any other value treated as false. (⚠ this will make existing links inaccessible ⚠) | `false` | | NC_ATTACHMENT_EXPIRE_SECONDS | How many seconds before expiring presigned attachment urls. (Attachments will expire in at least set seconds and at most 10mins after set time) | 7200 (2 hours) | -| NC_ALLOW_LOCAL_HOOKS | To enable set value as `true` any other value treated as false. (⚠ this will allow webhooks to call local links which can raise security issues ⚠) | `false` | \ No newline at end of file +| NC_ALLOW_LOCAL_HOOKS | To enable set value as `true` any other value treated as false. (⚠ this will allow webhooks to call local links which can raise security issues ⚠) | `false` | +| NC_SANITIZE_COLUMN_NAME | Sanitize the column name during column creation. To enable set value as `true` any other value treated as false. | `true` | \ No newline at end of file diff --git a/packages/nocodb/src/helpers/columnHelpers.ts b/packages/nocodb/src/helpers/columnHelpers.ts index 898ffa1f88..6a14089d53 100644 --- a/packages/nocodb/src/helpers/columnHelpers.ts +++ b/packages/nocodb/src/helpers/columnHelpers.ts @@ -267,6 +267,7 @@ export async function populateRollupForLTAR({ } export const sanitizeColumnName = (name: string) => { + if (process.env.NC_SANITIZE_COLUMN_NAME === 'false') return name; const columnName = name.replace(/\W/g, '_'); // if column name only contains _ then return as 'field' diff --git a/packages/nocodb/src/services/tables.service.ts b/packages/nocodb/src/services/tables.service.ts index 1546f2f460..cf765556be 100644 --- a/packages/nocodb/src/services/tables.service.ts +++ b/packages/nocodb/src/services/tables.service.ts @@ -455,9 +455,21 @@ export class TablesService { const mxColumnLength = Column.getMaxColumnNameLength(sqlClientType); + const uniqueColumnNameCount = {}; + for (const column of param.table.columns) { if (!isVirtualCol(column)) { column.column_name = sanitizeColumnName(column.column_name); + + if (uniqueColumnNameCount[column.column_name]) { + let suffix = 1; + let targetColumnName = `${column.column_name}_${suffix++}`; + while (uniqueColumnNameCount[targetColumnName]) { + targetColumnName = `${column.column_name}_${suffix++}`; + } + column.column_name = targetColumnName; + } + uniqueColumnNameCount[column.column_name] = 1; } if (column.column_name.length > mxColumnLength) {