top-think / top-think/think-orm

分页功能--buildSql生成的SQL语句不准确导致mysql存在隐式转换的字段查询失效

Open
#216 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PHP
Stars
437
Forks
188
PR merge metrics
No merged PRs in 30d

Description

我们mysql中有个status字段类型是enum,即字符串对象,在查询的时候如果传入int类型会触发mysql的隐私转换。(解决办法在TP各种入口将status字段值强制转换为string即可)

但是我们在使用TP6的时候发现使用框架不做强制转换竟然也能查询出来,但是打印出来的SQL语句直接去执行是查不到的:
image
image

带着好奇心看了think-orm的底层代码发现实际上打印出来的SQL并非真正执行的SQL,真正执行的是通过PDO的prepare以及bindValue,而bindValue中会指定字段对应类型, 这个类型TP6在逻辑里面就会去获取mysql对应表的字段(仅限单表)
image
image

所以我们判断 TP的打印SQL日志方法【getLastsql()】是有问题的
原本以为不需要在所有入口做强制转换,TP底层就帮我们做了, 但我们发现列表做了分页后, 列表的数据和分页中的total统计结果不一致。

由于通过PDO的bindValue占坑的形式TP6是获取不到mysql最终执行的语句的,我们通过打开mysql打印log, 在真正打印出来的SQL发现 COUNT和select的语句中, COUNT查询竟然没有做转换
image

通过追溯源码, 发现了问题点:
TP的分页count和select调用方式不同,而恰好count方法是使用buildSql生成SQL语句再去做查询,而我们上面说到getLastSql这个方法有问题, 查找代码发现buildSql()方法底层最终和getLastsql方法一样是调用了PDOConnection中的getRealSql()方法。这个方法是有问题的,生成出来的语句中隐式转换没有做对
image

image

当然按前面说的,我们通过入口传入的参数全部转为字符串可以解决,但是既然TP底层提供了这个自动转换功能,也希望能把count方法也改一下,不然列表查询是做了转换,但是count又没做转换,导致列表和count查找结果不一致。

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing PDOConnection.getRealSql(), then compare the buildSql() path used by pagination count with the select path and the getLastsql() output. Reproduce the enum status query against MySQL and inspect the generated SQL and bound values. Done means count and select apply equivalent type handling and return consistent results, with regression coverage if the existing tests expose a suitable location.

Written by the indexing model from the issue text.

Assessment

Tech stack
mysql, php
Domain
database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.