Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: inconsistent behavior of Query Builder limit 0 #6253

Open
kenjis opened this issue Dec 2, 2023 · 8 comments
Open

Bug: inconsistent behavior of Query Builder limit 0 #6253

kenjis opened this issue Dec 2, 2023 · 8 comments

Comments

@kenjis
Copy link
Contributor

kenjis commented Dec 2, 2023

$this->db->limit(0)->get('table') returns no records.
But $this->db->get('table', 0) returns all records.

Steps to reproduce:

		$config['database'] = './test.db';
		$config['dbdriver'] = 'sqlite3';
		$this->load->database($config);

		$this->load->dbforge();
		$fields = array(
			'name' => array(
				'type' => 'VARCHAR',
				'constraint' => '100',
			),
		);
		$this->dbforge->add_field('id');
		$this->dbforge->add_field($fields);
		$this->dbforge->create_table('test', TRUE);

		$data = array(
			array(
				'name' => 'My Name',
			),
			array(
				'name' => 'Another Name',
			),
			array(
				'name' => 'Other Name',
			),
		);
		$this->db->insert_batch('test', $data);

		echo '$this->db->limit(0)->get(\'test\')' . PHP_EOL;
		$query = $this->db->limit(0)->get('test');
		foreach ($query->result() as $row)
		{
			echo $row->name . PHP_EOL;
		}

		echo '$this->db->get(\'test\', 0)' . PHP_EOL;
		$query = $this->db->get('test', 0);
		foreach ($query->result() as $row)
		{
			echo $row->name . PHP_EOL;
		}

Result:

$this->db->limit(0)->get('test')
$this->db->get('test', 0)
My Name
Another Name
Other Name
@poodle123
Copy link

This is no a bug but design. $this->db->get('table', 0) means no limit not zero records.

@kenjis
Copy link
Contributor Author

kenjis commented Dec 6, 2023

No, it is not documented like that.

$query = $this->db->get('mytable', 10, 20);
// Executes: SELECT * FROM mytable LIMIT 20, 10
https://www.codeigniter.com/userguide3/database/query_builder.html#selecting-data

* @param string the table
* @param string the limit clause
* @param string the offset clause
* @return CI_DB_result
*/
public function get($table = '', $limit = NULL, $offset = NULL)

@poodle123
Copy link

interesting. seems i misunderstood it then. I looked into DB_query_builder.php and it seems you are right. 0 should indeed be passed as a limit. Do you have the generated SQL query from your code? Just to be sure if the code is generated correctly or not?

@kenjis
Copy link
Contributor Author

kenjis commented Dec 6, 2023

$this->db->limit(0)->get('test')
SELECT *
FROM "test"
 LIMIT 0
$this->db->get('test', 0)
SELECT *
FROM "test"

@poodle123
Copy link

poodle123 commented Dec 6, 2023

This is what I mentioned originally: 0 is not passed along due to this in the DB_query_builder.php:

	public function limit($value, $offset = 0)
	{
		is_null($value) OR $this->qb_limit = (int) $value;
		empty($offset) OR $this->qb_offset = (int) $offset;

		return $this;
	}

giving you all records when you set limit to zero.

If you change it to

public function limit($value, $offset = 0)
{
    $this->qb_limit = ($value === 0) ? 0 : (int) $value;
    empty($offset) OR $this->qb_offset = (int) $offset;

    return $this;
}

It should return what you expect. But again my understanding was that 0 was supposed to be interpreted als "do not set a limit" but I might be wrong.

@kenjis
Copy link
Contributor Author

kenjis commented Dec 6, 2023

No, no. limit(0) returns 0 records. It is a correct behavior.
The issue is that $this->db->get('table', 0) returns all records.

php > $value = 0;
php > is_null($value) OR $qb_limit = (int) $value;
php > var_dump($qb_limit);
php shell code:1:
int(0)

But again my understanding was that 0 was supposed to be interpreted als "do not set a limit" but I might be wrong.

LIMIT 0 returns 0 records. Try MySQL or SQLite3 or PostgreSQL.

@poodle123
Copy link

I know that limit 0 returns 0 records in MySQL. But I understood the CI way differently: namely limit 0 = no limit,

I have no other ideas why limit is dropped. Sorry.

@kenjis
Copy link
Contributor Author

kenjis commented Dec 7, 2023

It seems CI3 distinguishes between $limit = 0 and $limit = NULL.
So it is natural to interpret $limit = NULL means no limit, $limit = 0 means zero records.
In fact, limit() behaves like that.
Therefore I think the behavior of get() is a bug.

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

No branches or pull requests

2 participants