Skip to content

. - #265

Closed
MrIbrahem wants to merge 4 commits into
zfrom
z2
Closed

.#265
MrIbrahem wants to merge 4 commits into
zfrom
z2

Conversation

@MrIbrahem

Copy link
Copy Markdown
Collaborator

No description provided.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9e73207b-21ca-4687-88db-4334b01cf842

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch z2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the database access layer from legacy pymysql-based raw SQL helpers to SQLAlchemy, refactoring to_sql.py to use table reflection and updating various scripts to use SQLAlchemy sessions. The code review identified several critical issues with this migration: a potential accidental full-table update in update_table_2 if columns_where is empty, runtime crashes in add_to_pages_users_db.py due to passing flat lists of scalars to session.execute(text(...)) with %s placeholders, and a crash in fixcat.py because SQLAlchemy's text() does not automatically expand list parameters in IN clauses without expanding=True. Additionally, the reviewer recommended defaulting missing values to None instead of "" to avoid type conversion errors on non-string columns, and passing dictionaries directly to .values() instead of unpacking them.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/db/utils/to_sql.py
Comment on lines 201 to 202
columns_to_set = columns_to_set or []
columns_where = columns_where or []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

If columns_where is empty or evaluates to False, where_clause will be empty, causing the generated UPDATE statement to execute without a WHERE clause. This will accidentally update all rows in the table. Adding a guard clause prevents catastrophic full-table updates.

Suggested change
columns_to_set = columns_to_set or []
columns_where = columns_where or []
columns_to_set = columns_to_set or []
if not columns_where:
raise ValueError("columns_where must be provided and non-empty to prevent accidental full-table updates.")

Comment on lines +69 to 72
with get_session() as session:
session.execute(text(insert_qua), values)
session.commit()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Passing a flat list of scalars (values) to session.execute() with text() will crash at runtime with an ArgumentError because SQLAlchemy interprets lists of parameters as multiple parameter sets (for executemany). Additionally, text() does not natively support positional %s placeholders. Since the raw SQL query uses %s placeholders, using exec_driver_sql on the connection allows sending the query and positional parameters directly to the underlying PyMySQL driver without rewriting the query.

Suggested change
with get_session() as session:
session.execute(text(insert_qua), values)
session.commit()
with get_session() as session:
session.connection().exec_driver_sql(insert_qua, tuple(values))

Comment on lines +91 to 94
with get_session() as session:
session.execute(text(update_qua), values)
session.commit()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Passing a flat list of scalars (values) to session.execute() with text() will crash at runtime with an ArgumentError because SQLAlchemy interprets lists of parameters as multiple parameter sets (for executemany). Additionally, text() does not natively support positional %s placeholders. Since the raw SQL query uses %s placeholders, using exec_driver_sql on the connection allows sending the query and positional parameters directly to the underlying PyMySQL driver without rewriting the query.

Suggested change
with get_session() as session:
session.execute(text(update_qua), values)
session.commit()
with get_session() as session:
session.connection().exec_driver_sql(update_qua, tuple(values))

Comment on lines +119 to +124
with get_session() as session:
session.execute(
text("UPDATE pages SET cat = :cat WHERE title IN :titles"),
{"cat": cat, "titles": list(values)},
)
session.commit()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

SQLAlchemy's text() construct does not automatically expand list/tuple parameters for IN clauses. Passing a list directly to :titles will cause a runtime crash or DBAPI error. To support list expansion, you must explicitly configure the parameter as expanding=True using bindparam.

Suggested change
with get_session() as session:
session.execute(
text("UPDATE pages SET cat = :cat WHERE title IN :titles"),
{"cat": cat, "titles": list(values)},
)
session.commit()
from sqlalchemy import bindparam
with get_session() as session:
stmt = text("UPDATE pages SET cat = :cat WHERE title IN :titles").bindparams(
bindparam("titles", expanding=True)
)
session.execute(stmt, {"cat": cat, "titles": list(values)})

Comment thread src/db/utils/to_sql.py
# ---
logger.info(f"to_sql.py insert_dict({table_name}) {done} done, from {len(list_of_lines)} | batch: {lento}.")
batch = list_of_lines[i : i + lento]
values_list = [{col: row.get(col, "") for col in columns} for row in batch]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using row.get(col, "") defaults missing values to an empty string "". For non-string columns (such as integers, floats, or datetimes), this can cause type conversion errors or insert incorrect default values in MySQL. Using row.get(col) (which defaults to None / NULL) is much safer and database-idiomatic.

Suggested change
values_list = [{col: row.get(col, "") for col in columns} for row in batch]
values_list = [{col: row.get(col) for col in columns} for row in batch]

Comment thread src/db/utils/to_sql.py
for row in batch:
where_clause = [tbl.c[col] == row.get(col, "") for col in columns_where]
values = {col: row.get(col, "") for col in columns_to_set}
stmt = update(tbl).where(*where_clause).values(**values) # type: ignore[arg-type]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Unpacking the values dictionary as keyword arguments via **values can fail if any column name is not a valid Python identifier (e.g., contains spaces, hyphens, or is a reserved keyword). Passing the dictionary directly to .values(values) is safer and standard in SQLAlchemy.

Suggested change
stmt = update(tbl).where(*where_clause).values(**values) # type: ignore[arg-type]
stmt = update(tbl).where(*where_clause).values(values)

@MrIbrahem
MrIbrahem deleted the branch z July 17, 2026 01:04
@MrIbrahem MrIbrahem closed this Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant