codeigniter4 / CodeIgniter4

Open Source PHP Framework (originally from EllisLab)
https://codeigniter.com/
MIT License
5.4k stars 1.9k forks source link

Bug: RawSql() triggers an error when used in combination with like() and countAllResults() #7268

Closed skycyclone closed 1 year ago

skycyclone commented 1 year ago

PHP Version

8.1

CodeIgniter4 Version

4.3.1

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Windows

Which server did you use?

apache

Database

No response

What happened?

$builder = $this->db->table('users');
$builder->select('id');
$builder->like(new RawSql("CONCAT(username, email)"), 'sky');
$count = $builder->countAllResults(FALSE);
$tableList = $builder->get()->getResultArray();

In Query Builder Class, if you use new RawSql() in $builder ->like(), and then use $builder ->countAllResults (FALSE); An error will be triggered when the total number of query results is obtained and then the query results are obtained.

Error prompt:

code: 500
file:"G:\\Code\\website\\ci4_cms\\vendor\\codeigniter4\\framework\\system\\Database\\BaseBuilder.php"
line: 3071
message: "Cannot use object of type CodeIgniter\\Database\\RawSql as array"

After debugging, it is found that if the countAllResults parameter is not set to FALSE, no error will be reported, but the subsequent get() cannot obtain the correct query results;

In addition, the third parameter of get() can also reset the query object. After setting, $builder ->countAllResults(); The same error is reported!

Problem conclusion: New RawSql() cannot be used in the link() before resetting values for SELECT; Or if you want to use new RawSql(), you cannot reset values for SELECTs??

Steps to Reproduce

$builder = $this->db->table('users');
$builder->select('id');
$builder->like(new RawSql("CONCAT(username, email)"), 'sky');
$count = $builder->countAllResults(FALSE);
$tableList = $builder->get(25, 0)->getResultArray();

or

$builder = $this->db->table('users');
$builder->select('id');
$builder->like(new RawSql("CONCAT(username, email)"), 'sky');
$tableList = $builder->get(25, 0, FALSE)->getResultArray();
$count = $builder->countAllResults();

Expected Output

Get the total number of query results and query result array normally

Anything else?

No response

skycyclone commented 1 year ago

What's more, I don't understand what the role of new RawSql() is. Even though I have roughly looked at the source file of RawSql, I still don't understand whether it is for security protection or to generate objects for the next reuse to improve efficiency??

kenjis commented 1 year ago

Thank you for reporting.

RawSql expresses raw SQL strings. That's all. Normally, values passed to QueryBuilder are escaped, protected, DBPrefix-added, or otherwise manipulated. RawSql ensures that no such processing occurs.

It does not provide any security protection. You must ensure it is safe by yourself.

kenjis commented 1 year ago

I sent a PR to fix this: #7277