Source code for neosqlite.collection.schema_utils
"""
Schema inspection and modification utilities for NeoSQLite.
This module provides common functionality for inspecting and modifying
database schemas, avoiding code duplication across multiple modules.
"""
import logging
from typing import Any
logger = logging.getLogger(__name__)
[docs]
def get_table_columns(db_connection: Any, table_name: str) -> set[str]:
"""
Get set of column names for a table.
Args:
db_connection: SQLite database connection
table_name: Name of the table to inspect
Returns:
Set of column names
"""
from ..sql_utils import quote_table_name
cursor = db_connection.execute(
f"PRAGMA table_info({quote_table_name(table_name)})"
)
return {row[1] for row in cursor.fetchall()}
[docs]
def column_exists(
db_connection: Any,
table_name: str,
column_name: str,
) -> bool:
"""
Check if column exists in table.
Args:
db_connection: SQLite database connection
table_name: Name of the table
column_name: Name of the column to check
Returns:
True if column exists, False otherwise
"""
columns = get_table_columns(db_connection, table_name)
return column_name in columns
[docs]
def add_column_if_not_exists(
db_connection: Any,
table_name: str,
column_name: str,
column_type: str = "TEXT",
) -> bool:
"""
Add column if it doesn't exist.
Args:
db_connection: SQLite database connection
table_name: Name of the table
column_name: Name of the column to add
column_type: SQL type for the new column (default: TEXT)
Returns:
True if column was added, False if it already existed
"""
if column_exists(db_connection, table_name, column_name):
return False
from ..sql_utils import quote_table_name
db_connection.execute(
f"ALTER TABLE {quote_table_name(table_name)} "
f"ADD COLUMN {column_name} {column_type}"
)
return True
[docs]
def create_unique_index_on_id(
db_connection: Any,
table_name: str,
) -> bool:
"""
Create a unique index on the _id column if it doesn't exist.
Args:
db_connection: SQLite database connection
table_name: Name of the table
Returns:
True if index was created successfully, False otherwise
"""
from ..sql_utils import quote_identifier, quote_table_name
try:
db_connection.execute(
f"CREATE UNIQUE INDEX IF NOT EXISTS "
f"idx_{quote_identifier(table_name)}_id "
f"ON {quote_table_name(table_name)}(_id)"
)
return True
except Exception as e:
# If we can't create the index (e.g., due to duplicate values),
# continue without it
logger.debug(
f"Failed to create unique index on _id for {table_name}: {e}"
)
return False
[docs]
def get_table_info(db_connection: Any, table_name: str) -> dict[str, Any]:
"""
Get detailed information about a table.
Args:
db_connection: SQLite database connection
table_name: Name of the table to inspect
Returns:
Dictionary with table information including columns and indexes
"""
from ..sql_utils import quote_table_name
# Get column information
table_info = db_connection.execute(
f"PRAGMA table_info({quote_table_name(table_name)})"
).fetchall()
columns = [
{
"name": str(col[1]),
"type": str(col[2]),
"notnull": bool(col[3]),
"default": col[4] if len(col) > 4 else None,
"pk": bool(col[5]),
}
for col in table_info
]
# Get index information
indexes = db_connection.execute(
"SELECT name, sql FROM sqlite_master "
"WHERE type='index' AND tbl_name=?",
(table_name,),
).fetchall()
index_info = [
{
"name": str(idx[0]),
"definition": str(idx[1]) if idx[1] is not None else "",
}
for idx in indexes
]
return {
"columns": columns,
"indexes": index_info,
}
__all__ = [
"get_table_columns",
"column_exists",
"add_column_if_not_exists",
"create_unique_index_on_id",
"get_table_info",
]