{"record":{"id":"7668688149c41c40","repo":"phalcon/cphalcon","slug":"adding-a-primary-key-after-table-has-been-created","errorCode":null,"errorMessage":"Adding a primary key after table has been created is not supported by SQLite","messagePattern":"Adding a primary key after table has been created is not supported by SQLite","errorType":"exception","errorClass":"SqliteAlterPrimaryKeyNotSupported","httpStatus":null,"severity":"error","filePath":"phalcon/Db/Dialect/Sqlite.zep","lineNumber":141,"sourceCode":"            let sql .= \"\\\"\" . index->getName() . \"\\\"\";\n        }\n\n        let sql .= \" ON \\\"\" . tableName . \"\\\" (\"\n            . this->getIndexColumnList(index, false) . \")\";\n\n        if index->getWhere() !== \"\" {\n            let sql .= \" WHERE \" . index->getWhere();\n        }\n\n        return sql;\n    }\n\n    /**\n     * Generates SQL to add the primary key to a table\n     */\n    public function addPrimaryKey( string tableName,  string schemaName, <IndexInterface> index) -> string\n    {\n        throw new SqliteAlterPrimaryKeyNotSupported();\n    }\n\n    /**\n     * Generates SQL to create a table\n     */\n    public function createTable( string tableName,  string schemaName,  array definition) -> string\n    {\n        var columns, table, temporary, options, createLines, columnLine,\n            column, indexes, index, indexName, indexType, references, reference,\n            defaultValue, referenceSql, onDelete, onUpdate, checks, check;\n        bool hasPrimary;\n        string sql;\n\n        let table = this->prepareTable(tableName, schemaName);\n\n        let temporary = false;\n        if fetch options, definition[\"options\"] {\n            fetch temporary, options[\"temporary\"];","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Db/Dialect/Sqlite.zep#L123-L159","documentation":"The SQLite dialect's addPrimaryKey() always throws SqliteAlterPrimaryKeyNotSupported. SQLite's ALTER TABLE cannot add a PRIMARY KEY after a table exists; the key must be declared in the original CREATE TABLE column/table definition. The dialect throws immediately instead of producing SQL the engine would reject.","triggerScenarios":"Calling $sqliteAdapter->addPrimaryKey('robots', null, $index) — typically from generated migrations that create the table first and add its primary key in a later step; running those migrations against SQLite in tests or local dev.","commonSituations":"Migration generators that split primary-key creation into a separate ALTER step (valid on MySQL/PostgreSQL); adapting production migrations to SQLite-backed test environments.","solutions":["Declare the primary key at creation: new Column('id', ['type' => Column::TYPE_INTEGER, 'primary' => true]) or the 'primary' key in the table definition's indexes","For an existing table use the SQLite table-rebuild procedure (new table with PK, copy data, drop, rename)","Skip the call on SQLite: if (!($adapter->getDialect() instanceof Sqlite)) { $adapter->addPrimaryKey(...); }"],"exampleFix":"// before\n$connection->addPrimaryKey('robots', null, new Index('PRIMARY', ['id']));\n\n// after — PK at CREATE TABLE time on SQLite\n$connection->createTable('robots', null, [\n    'columns' => [\n        new Column('id', ['type' => Column::TYPE_INTEGER, 'primary' => true]),\n    ],\n]);","handlingStrategy":"type-guard","validationCode":"if ($adapter->getDialect() instanceof \\Phalcon\\Db\\Dialect\\Sqlite) {\n    throw new RuntimeException('SQLite: declare the primary key in createTable(), not addPrimaryKey()');\n}\n$adapter->addPrimaryKey($table, $schema, $index);","typeGuard":"function supportsAddPrimaryKey(\\Phalcon\\Db\\Adapter\\AdapterInterface $adapter): bool\n{\n    return !($adapter->getDialect() instanceof \\Phalcon\\Db\\Dialect\\Sqlite);\n}","tryCatchPattern":"try {\n    $adapter->addPrimaryKey($table, $schema, $index);\n} catch (\\Phalcon\\Db\\Exceptions\\SqliteAlterPrimaryKeyNotSupported $e) {\n    rebuildSqliteTableWithPrimaryKey($adapter, $table, $index);\n}","preventionTips":["Mark the primary key on the Column ('primary' => true) at CREATE TABLE time for SQLite","Avoid migration generators that split primary-key creation into a later ALTER step","Test the full migration chain on every adapter you support"],"tags":["phalcon","sqlite","ddl","primary-key","alter-table"],"backgroundTag":"alter-table-unsupported","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}