diff --git a/backend/open_webui/migrations/versions/4ace53fd72c8_update_folder_table_datetime.py b/backend/open_webui/migrations/versions/4ace53fd72c8_update_folder_table_datetime.py index 9088cb3772..ac0d45016d 100644 --- a/backend/open_webui/migrations/versions/4ace53fd72c8_update_folder_table_datetime.py +++ b/backend/open_webui/migrations/versions/4ace53fd72c8_update_folder_table_datetime.py @@ -16,6 +16,18 @@ depends_on = None def upgrade(): + conn = op.get_bind() + inspector = sa.inspect(conn) + columns = {c['name']: c for c in inspector.get_columns('folder')} + + created_at_col = columns.get('created_at') + if not created_at_col: + return + + # Only convert if still DateTime — skip if already BigInteger + if isinstance(created_at_col['type'], sa.BigInteger): + return + # Perform safe alterations using batch operation with op.batch_alter_table('folder', schema=None) as batch_op: # Step 1: Remove server defaults for created_at and updated_at diff --git a/backend/open_webui/migrations/versions/6a39f3d8e55c_add_knowledge_table.py b/backend/open_webui/migrations/versions/6a39f3d8e55c_add_knowledge_table.py index 470d8bf399..b1fd2ab40a 100644 --- a/backend/open_webui/migrations/versions/6a39f3d8e55c_add_knowledge_table.py +++ b/backend/open_webui/migrations/versions/6a39f3d8e55c_add_knowledge_table.py @@ -19,62 +19,67 @@ depends_on = None def upgrade(): - # Creating the 'knowledge' table - print('Creating knowledge table') - knowledge_table = op.create_table( - 'knowledge', - sa.Column('id', sa.Text(), primary_key=True), - sa.Column('user_id', sa.Text(), nullable=False), - sa.Column('name', sa.Text(), nullable=False), - sa.Column('description', sa.Text(), nullable=True), - sa.Column('data', sa.JSON(), nullable=True), - sa.Column('meta', sa.JSON(), nullable=True), - sa.Column('created_at', sa.BigInteger(), nullable=False), - sa.Column('updated_at', sa.BigInteger(), nullable=True), - ) + conn = op.get_bind() + inspector = sa.inspect(conn) + existing_tables = set(inspector.get_table_names()) - print('Migrating data from document table to knowledge table') - # Representation of the existing 'document' table - document_table = table( - 'document', - column('collection_name', sa.String()), - column('user_id', sa.String()), - column('name', sa.String()), - column('title', sa.Text()), - column('content', sa.Text()), - column('timestamp', sa.BigInteger()), - ) - - # Select all from existing document table - documents = op.get_bind().execute( - select( - document_table.c.collection_name, - document_table.c.user_id, - document_table.c.name, - document_table.c.title, - document_table.c.content, - document_table.c.timestamp, + if 'knowledge' not in existing_tables: + # Creating the 'knowledge' table + print('Creating knowledge table') + knowledge_table = op.create_table( + 'knowledge', + sa.Column('id', sa.Text(), primary_key=True), + sa.Column('user_id', sa.Text(), nullable=False), + sa.Column('name', sa.Text(), nullable=False), + sa.Column('description', sa.Text(), nullable=True), + sa.Column('data', sa.JSON(), nullable=True), + sa.Column('meta', sa.JSON(), nullable=True), + sa.Column('created_at', sa.BigInteger(), nullable=False), + sa.Column('updated_at', sa.BigInteger(), nullable=True), ) - ) - # Insert data into knowledge table from document table - for doc in documents: - op.get_bind().execute( - knowledge_table.insert().values( - id=doc.collection_name, - user_id=doc.user_id, - description=doc.name, - meta={ - 'legacy': True, - 'document': True, - 'tags': json.loads(doc.content or '{}').get('tags', []), - }, - name=doc.title, - created_at=doc.timestamp, - updated_at=doc.timestamp, # using created_at for both created_at and updated_at in project + print('Migrating data from document table to knowledge table') + # Representation of the existing 'document' table + document_table = table( + 'document', + column('collection_name', sa.String()), + column('user_id', sa.String()), + column('name', sa.String()), + column('title', sa.Text()), + column('content', sa.Text()), + column('timestamp', sa.BigInteger()), + ) + + # Select all from existing document table + documents = conn.execute( + select( + document_table.c.collection_name, + document_table.c.user_id, + document_table.c.name, + document_table.c.title, + document_table.c.content, + document_table.c.timestamp, ) ) + # Insert data into knowledge table from document table + for doc in documents: + conn.execute( + knowledge_table.insert().values( + id=doc.collection_name, + user_id=doc.user_id, + description=doc.name, + meta={ + 'legacy': True, + 'document': True, + 'tags': json.loads(doc.content or '{}').get('tags', []), + }, + name=doc.title, + created_at=doc.timestamp, + updated_at=doc.timestamp, + ) + ) + def downgrade(): op.drop_table('knowledge') diff --git a/backend/open_webui/migrations/versions/f1e2d3c4b5a6_add_access_grant_table.py b/backend/open_webui/migrations/versions/f1e2d3c4b5a6_add_access_grant_table.py index 5ed0b543e4..6a33d087b5 100644 --- a/backend/open_webui/migrations/versions/f1e2d3c4b5a6_add_access_grant_table.py +++ b/backend/open_webui/migrations/versions/f1e2d3c4b5a6_add_access_grant_table.py @@ -80,13 +80,18 @@ def upgrade() -> None: if table_name not in existing_tables: continue - # Query all rows - try: - result = conn.execute(sa.text(f'SELECT id, access_control FROM "{table_name}"')) - rows = result.fetchall() - except Exception: + # Check if access_control and id columns exist (may already be dropped on re-run, + # or table may have been rebuilt without id during intermediate migration states) + insp = sa.inspect(conn) + insp.clear_cache() # Ensure fresh metadata after prior migrations that rebuild tables + table_cols = {c['name'] for c in insp.get_columns(table_name)} + if 'access_control' not in table_cols or 'id' not in table_cols: continue + # Query all rows + result = conn.execute(sa.text(f'SELECT id, access_control FROM "{table_name}"')) + rows = result.fetchall() + for row in rows: resource_id = row[0] access_control_json = row[1] @@ -207,15 +212,15 @@ def upgrade() -> None: except Exception: pass - # Drop access_control columns from resource tables + # Drop access_control columns from resource tables (only if column still exists) + inspector = sa.inspect(conn) for table_name, _ in resource_tables: if table_name not in existing_tables: continue - try: + cols = {c['name'] for c in inspector.get_columns(table_name)} + if 'access_control' in cols: with op.batch_alter_table(table_name) as batch: batch.drop_column('access_control') - except Exception: - pass def downgrade() -> None: