{"record":{"id":"8f95e2de468ef5be","repo":"OtterMind/Chat2DB","slug":"copy-table-error","errorCode":"copy table error","errorMessage":"copy table error","messagePattern":"copy table error","errorType":"exception","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/db/DbTableServiceImpl.java","lineNumber":334,"sourceCode":"    @Override\n    public void copyTable(DbTableCopyRequest param) {\n        try {\n            IDbMetaData metaData = Chat2DBContext.getDbMetaData();\n            String newName = param.getNewName();\n            if (StringUtils.isBlank(newName)) {\n                newName = param.getTableName() + \"_copy_\" + DateUtil.format(new Date(), \"MMddHHmmss\");\n                if (newName.length() > 32) {\n                    newName = newName.substring(0, 32);\n                }\n            }\n            String tableName = metaData.getMetaDataName(param.getTableName());\n            String newTableName = metaData.getMetaDataName(newName);\n            Chat2DBContext.getDbManager().copyTable(\n                    Chat2DBContext.getConnection(),\n                    param.getDatabaseName(), param.getSchemaName(), tableName, newTableName, param.isCopyData());\n        } catch (Exception e) {\n            log.error(\"copy table error\", e);\n            throw new BusinessException(\"copy table error\", new Object[]{e.getMessage()}, e);\n        }\n    }\n\n    private void setPrimaryKey(Table table) {\n        if (table == null) {\n            return;\n        }\n        List<TableIndex> tableIndices = table.getIndexList();\n        if (CollectionUtils.isEmpty(tableIndices)) {\n            return;\n        }\n        List<TableColumn> columns = table.getColumnList();\n        if (CollectionUtils.isEmpty(columns)) {\n            return;\n        }\n        Map<String, TableColumn> columnMap = columns.stream()\n                .collect(Collectors.toMap(TableColumn::getName, Function.identity()));\n        List<TableIndex> indexes = new ArrayList<>();","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/db/DbTableServiceImpl.java#L316-L352","documentation":"Thrown by DbTableServiceImpl.copyTable when the underlying IDbManager.copyTable call fails. The service first builds a new table name (defaulting to '<table>_copy_<MMddHHmmss>', truncated to 32 chars), resolves both names through the dialect's metadata name, then delegates to the plugin's copyTable implementation. Any exception there is wrapped and rethrown as a generic 'copy table error'.","triggerScenarios":"POST copyTable with a name that already exists, exceeds the dialect identifier length limit, contains illegal characters, or when the source table cannot be found. Also triggered when the connected DB user lacks CREATE/INSERT privileges, the connection is dropped mid-copy, or the dialect plugin throws on copyData=true for a table with unsupported column types.","commonSituations":"Auto-generated '_copy_' name collides after the 32-char truncation (e.g. long table name makes the timestamp suffix ambiguous); copying into a schema with existing objects; driver version that does not implement copyTable for the selected DB type.","solutions":["Provide an explicit, unique param.newName that fits the target dialect's identifier rules and length limit instead of relying on the auto-generated truncated name.","Verify the connected user has CREATE TABLE and (if copyData) INSERT privileges on the target schema.","Check the server log line 'copy table error' — the wrapped e.getMessage() names the underlying SQL/plugin cause; address that first.","Confirm the dialect plugin (chat2db-community-plugins) supports copyTable for the selected DB type."],"exampleFix":"// before\nDbTableCopyRequest param = new DbTableCopyRequest();\n// newName left null -> '_copy_<ts>' may truncate past 32 chars\n// after\nString safe = param.getTableName();\nif (safe.length() > 26) safe = safe.substring(0, 26);\nparam.setNewName(safe + \"_copy\"); // explicit, within limits\n","handlingStrategy":"validation","validationCode":"// before delegating to copyTable\nString name = param.getNewName() != null ? param.getNewName()\n    : param.getTableName() + \"_copy_\" + DateUtil.format(new Date(), \"MMddHHmmss\");\nif (name.length() > 32) name = name.substring(0, 32);\nif (!name.matches(\"[A-Za-z_][A-Za-z0-9_]*\")) throw new IllegalArgumentException(\"bad table name: \" + name);\n// existence/uniqueness check via dbManager before copyTable\n","typeGuard":null,"tryCatchPattern":"try { dbTableService.copyTable(param); }\ncatch (BusinessException e) {\n    // e.getArgs()[0] holds the wrapped SQL message\n    throw new CopyFailedException(\"copy table failed: \" + e.getArgs()[0], e);\n}","preventionTips":["Always pass an explicit, validated newName rather than relying on the auto-generated truncated suffix.","Confirm target schema CREATE/INSERT privileges before initiating the copy.","Log the wrapped e.getMessage() to surface the real dialect-level cause."],"tags":["database","ddl","table-copy","plugin"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}