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: [Postgres] QueryBuilder::updateBatch() pg_affected_rows(): Argument #1 ($result) must be of type PgSql\Result, bool given #7387

Closed
Onerosolutions opened this issue Mar 27, 2023 · 13 comments · Fixed by #8439
Labels
bug Verified issues on the current code behavior or pull requests that will fix them database Issues or pull requests that affect the database layer

Comments

@Onerosolutions
Copy link

Onerosolutions commented Mar 27, 2023

PHP Version

8.1

CodeIgniter4 Version

4.3.3

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Windows

Which server did you use?

apache

Database

PostgeSQL 15

What happened?

Error after run $this->modelName->updateBatch($updatedData, 'id');

{
    "title": "TypeError",
    "type": "TypeError",
    "code": 500,
    "message": "pg_affected_rows(): Argument #1 ($result) must be of type PgSql\\Result, bool given",
    "file": "D:\\onero\\onero-crm-ci4-api\\vendor\\codeigniter4\\framework\\system\\Database\\Postgre\\Connection.php",
    "line": 172,
    "trace": [
        {
            "file": "D:\\onero\\onero-crm-ci4-api\\vendor\\codeigniter4\\framework\\system\\Database\\Postgre\\Connection.php",
            "line": 172,
            "function": "pg_affected_rows",
            "args": [
                false
            ]
        },
        {
            "file": "D:\\onero\\onero-crm-ci4-api\\vendor\\codeigniter4\\framework\\system\\Database\\BaseBuilder.php",
            "line": 1802,
            "function": "affectedRows",
            "class": "CodeIgniter\\Database\\Postgre\\Connection",
            "type": "->",
            "args": []
        },
        {
            "file": "D:\\onero\\onero-crm-ci4-api\\vendor\\codeigniter4\\framework\\system\\Database\\BaseBuilder.php",
            "line": 2562,
            "function": "batchExecute",
            "class": "CodeIgniter\\Database\\BaseBuilder",
            "type": "->",
            "args": [
                "_updateBatch",
                100
            ]
        },
        {
            "file": "D:\\onero\\onero-crm-ci4-api\\vendor\\codeigniter4\\framework\\system\\Model.php",
            "line": 414,
            "function": "updateBatch",
            "class": "CodeIgniter\\Database\\BaseBuilder",
            "type": "->",
            "args": [
                [
                    {
                        "package_plan_id": "PP63aa9a4a1f221",
                        "package_plan_name": "Basic",
                        "package_plan_description": "The ideal solution for small businesses with an affordable price, easy to use, even for beginners.",
                        "updated_at": "2023-03-27 05:08:21"
                    },
                    {
                        "package_plan_id": "PP63aa9a4a1f252",
                        "package_plan_name": "Business",
                        "package_plan_description": "The perfect package for mid-size companies, various additional features to market, sell & support your business.",
                        "updated_at": "2023-03-27 05:08:21"
                    },
                    {
                        "package_plan_id": "PP63aa9a4a1f26d",
                        "package_plan_name": "Professional",
                        "package_plan_description": "Complete features for complex needs, bring value to customers and create the best user experience.",
                        "updated_at": "2023-03-27 05:08:21"
                    }
                ],
                "package_plan_id",
                100
            ]
        },

Steps to Reproduce

Run updateBatch method
$this->modelName->updateBatch($updatedData, 'id');

Expected Output

No error.

Anything else?

No response

@Onerosolutions Onerosolutions added the bug Verified issues on the current code behavior or pull requests that will fix them label Mar 27, 2023
@Onerosolutions Onerosolutions changed the title Error: pg_affected_rows(): Argument #1 ($result) must be of type PgSql\\Result, bool given Bug: pg_affected_rows(): Argument #1 ($result) must be of type PgSql\\Result, bool given Mar 27, 2023
@kenjis
Copy link
Member

kenjis commented Mar 27, 2023

It seems there is no id in $updatedData.

@kenjis
Copy link
Member

kenjis commented Mar 27, 2023

This test passes:

public function testUpdateBatchEvent(): void

Can you write a failed test case?

@Onerosolutions
Copy link
Author

Onerosolutions commented Mar 28, 2023

It seems there is no id in $updatedData.

i mean $this->packagePlanModel->updateBatch($updatedData, 'package_plan_id');

id is using package_plan_id

$updatedData =   [
                    [
                        "package_plan_id" => "PP63aa9a4a1f221",
                        "package_plan_name" =>  "Basic",
                        "package_plan_description" => "The ideal solution for small businesses with an affordable price, easy to use, even for beginners.",
                    ],
                    {
                        "package_plan_id"=>"PP63aa9a4a1f252",
                        "package_plan_name"=>"Business",
                        "package_plan_description"=>"The perfect package for mid-size companies, various additional features to market, sell & support your business.",
                    ],
                    [
                        "package_plan_id"=>"PP63aa9a4a1f26d",
                        "package_plan_name"=>"Professional",
                        "package_plan_description"=>"Complete features for complex needs, bring value to customers and create the best user experience.",
                    ]
                ]

@Onerosolutions
Copy link
Author

Onerosolutions commented Mar 28, 2023

Same issue when im running insertBatch:

            $modules = [
                [
                    'module_uuid' => $uuidGenerator::uuid4()->toString(),
                    'module_name' => 'Contact',
                    'module_description' => 'Module for contact',
                    'created_at' => date('Y-m-d H:i:s'),
                ],
                [
                    'module_uuid' => $uuidGenerator::uuid4()->toString(),
                    'module_name' => 'Deal',
                    'module_description' => 'Module for Sales Funnel',
                    'created_at' => date('Y-m-d H:i:s'),
                ],
                [
                    'module_uuid' => $uuidGenerator::uuid4()->toString(),
                    'module_name' => 'Product',
                    'module_description' => 'Module for Product',
                    'created_at' => date('Y-m-d H:i:s'),
                ]
            ];

            $moduleModel->insertBatch($modules);

it's throw error:

$ php spark db:seed CustomFieldInitialSeeder

CodeIgniter v4.3.3 Command Line Tool - Server Time: 2023-03-28 03:57:43 UTC+00:00


[TypeError]

pg_affected_rows(): Argument #1 ($result) must be of type PgSql\Result, bool given

at SYSTEMPATH\Database\Postgre\Connection.php:172

Backtrace:
  1    SYSTEMPATH\Database\Postgre\Connection.php:172
       pg_affected_rows(false)

  2    SYSTEMPATH\Database\BaseBuilder.php:1802
       CodeIgniter\Database\Postgre\Connection()->affectedRows()

  3    SYSTEMPATH\Database\BaseBuilder.php:2192
       CodeIgniter\Database\BaseBuilder()->batchExecute('_insertBatch', 100)

  4    APPPATH\Database\Seeds\CustomFieldInitialSeeder.php:43
       CodeIgniter\Database\BaseBuilder()->insertBatch([...])

  5    SYSTEMPATH\Database\Seeder.php:146
       App\Database\Seeds\CustomFieldInitialSeeder()->run()

  6    SYSTEMPATH\Commands\Database\Seed.php:77
       CodeIgniter\Database\Seeder()->call('App\\Database\\Seeds\\CustomFieldInitialSeeder')

  7    SYSTEMPATH\CLI\Commands.php:65
       CodeIgniter\Commands\Database\Seed()->run([])

  8    SYSTEMPATH\CLI\Console.php:37
       CodeIgniter\CLI\Commands()->run('db:seed', [...])

  9    ROOTPATH\spark:87
       CodeIgniter\CLI\Console()->run()

@kenjis
Copy link
Member

kenjis commented Mar 28, 2023

We cannot reproduce.
Please show us minimum working code that reproduces the error.

@kenjis kenjis added the waiting for info Issues or pull requests that need further clarification from the author label Mar 28, 2023
@iRedds
Copy link
Collaborator

iRedds commented Mar 28, 2023

As I can see from the code, such an error can be caused by a broken SQL query.
Therefore, as @kenjis wrote, we need more information.

I'm not sure, but try wrapping your code in a try...catch

try {
    $moduleModel->insertBatch($modules);
} catch (Exception $e) {
    dd($moduleModel->error());
}

@kenjis
Copy link
Member

kenjis commented Apr 9, 2023

@Onerosolutions Can you provide minimum code that reproduces the error?
Or we will close this because we cannot reproduce it.

@kenjis kenjis removed the bug Verified issues on the current code behavior or pull requests that will fix them label Apr 9, 2023
@kenjis kenjis changed the title Bug: pg_affected_rows(): Argument #1 ($result) must be of type PgSql\\Result, bool given Bug: pg_affected_rows(): Argument #1 ($result) must be of type PgSql\Result, bool given Apr 9, 2023
@kenjis kenjis closed this as completed Apr 19, 2023
@Onerosolutions
Copy link
Author

Onerosolutions commented Jun 13, 2023

Hello, sorry for the late reply. @kenjis @iRedds

The possible cause of the error may be that I added updated_at to the $allowedFields attribute as shown below:

class PackagePlanModel extends BaseModel
{
  protected $table = 'package_plan_ms';
  protected $primaryKey = 'package_plan_id';
  protected $returnType = 'App\Entities\PackageBuilder\PackagePlan';
  protected $useSoftDeletes = true;

  protected $allowedFields = [
    'package_plan_id',
    'package_id',
    'package_plan_name',
    'package_plan_description',
    'created_at',
    'updated_at',
  ];

....

I tried to run updateBatch with the returnSQL parameter set to true to get the raw SQL, and running it manually in PostgreSQL using DBbeaver:

 $packagePlanModel = new PackagePlanModel();
    try {
      $sql = $packagePlanModel->updateBatch($packagePlanUpdateBatchData, 'package_plan_id', 100, true);
      print_r($sql); die;

....
Array
(
[0] => UPDATE "package_plan_ms"
SET
"package_plan_description" = _u."package_plan_description",
"package_plan_name" = _u."package_plan_name",
"updated_at" = _u."updated_at"
FROM (
SELECT 'The ideal solution for small businesses with an affordable price, easy to use, even for beginners.' "package_plan_description", 'PP63aa9a4a1f221' "package_plan_id", 'Basic' "package_plan_name", '2023-06-13 04:11:37' "updated_at" UNION ALL
SELECT 'The perfect package for mid-size companies, various additional features to market, sell & support your business.' "package_plan_description", 'PP63aa9a4a1f252' "package_plan_id", 'Business' "package_plan_name", '2023-06-13 04:11:37' "updated_at" UNION ALL
SELECT 'Complete features for complex needs, bring value to customers and create the best user experience.' "package_plan_description", 'PP63aa9a4a1f26d' "package_plan_id", 'Professional' "package_plan_name", '2023-06-13 04:11:37' "updated_at"
) _u
WHERE "package_plan_ms"."package_plan_id" = _u."package_plan_id"
)

but it resulted in an error like this:

"SQL Error [42804]: ERROR: column "updated_at" is of type timestamp without time zone but expression is of type text
Hint: You will need to rewrite or cast the expression.
Position: 155"

So the issue could be due to the failure when updating the data, where the updated_at column and the value to be updated have different types.
My question is, how can I cast the updated_at column when running updateBatch to become:

UPDATE "package_plan_ms"
SET
"package_plan_description" = _u."package_plan_description",
"package_plan_name" = _u."package_plan_name",
"updated_at" = CAST(_u."updated_at" AS timestamp without time zone)
FROM (
SELECT 'The ideal solution for small businesses with an affordable price, easy to use, even for beginners.' "package_plan_description", 'PP63aa9a4a1f221' "package_plan_id", 'Basic' "package_plan_name", '2023-06-13 04:00:57'::timestamp without time zone "updated_at" UNION ALL
SELECT 'The perfect package for mid-size companies, various additional features to market, sell & support your business.' "package_plan_description", 'PP63aa9a4a1f252' "package_plan_id", 'Business' "package_plan_name", '2023-06-13 04:00:57'::timestamp without time zone "updated_at" UNION ALL
SELECT 'Complete features for complex needs, bring value to customers and create the best user experience.' "package_plan_description", 'PP63aa9a4a1f26d' "package_plan_id", 'Professional' "package_plan_name", '2023-06-13 04:00:57'::timestamp without time zone "updated_at"
) _u
WHERE "package_plan_ms"."package_plan_id" = _u."package_plan_id";

@kenjis kenjis reopened this Jun 13, 2023
@kenjis kenjis removed the waiting for info Issues or pull requests that need further clarification from the author label Jun 13, 2023
@rdconsolo
Copy link

PHP Version
8.1

CodeIgniter4 Version
4.4.3

CodeIgniter4 Installation Method
Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?
Windows

Which server did you use?
php spark

Database
PostgeSQL 13

What happened?
Error after $db->table('pr_ordens')->updateBatch($op_ins, 'id_pr_ordens');

Data

op_ins =
	Array
	(
		[0] => Array
			(
				[id_pr_ordens] => 1
				[id_pr_programas] => 11
				[posicao] => 1
				[updated_at] => 2023-12-02 18:47:52
			)

		[1] => Array
			(
				[id_pr_ordens] => 2
				[id_pr_programas] => 11
				[posicao] => 1
				[updated_at] => 2023-12-02 18:47:52
			)

)

Code

$db = \Config\Database::connect();
$db->table('pr_ordens')->updateBatch($op_ins, 'id_pr_ordens');

Error message when in database trasaction:

pg_affected_rows(): Argument #1 ($result) must be of type PgSql\Result, bool given

Error message when not in trasaction:

pg_query(): Query failed: ERROR: operator does not exist: integer = text
LINE 10: WHERE "pr_ordens"."id_pr_ordens" = _u."id_pr_ordens"
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.

@kenjis kenjis changed the title Bug: pg_affected_rows(): Argument #1 ($result) must be of type PgSql\Result, bool given Bug: [QueryBuilder] updateBatch() pg_affected_rows(): Argument #1 ($result) must be of type PgSql\Result, bool given Dec 2, 2023
@kenjis
Copy link
Member

kenjis commented Dec 2, 2023

The same issue as this?
https://forum.codeigniter.com/showthread.php?tid=88871

@kenjis
Copy link
Member

kenjis commented Dec 2, 2023

My question is, how can I cast the updated_at column when running updateBatch to become:

There is no way to do that now.
So we need to add a way to specify column types.

See also #8282 (comment)

@kenjis kenjis changed the title Bug: [QueryBuilder] updateBatch() pg_affected_rows(): Argument #1 ($result) must be of type PgSql\Result, bool given Bug: [Postgres] QueryBuilder::updateBatch() pg_affected_rows(): Argument #1 ($result) must be of type PgSql\Result, bool given Dec 2, 2023
@kenjis kenjis added bug Verified issues on the current code behavior or pull requests that will fix them database Issues or pull requests that affect the database layer labels Dec 2, 2023
@kenjis
Copy link
Member

kenjis commented Jan 17, 2024

I sent a PR: #8426

@kenjis
Copy link
Member

kenjis commented Jan 24, 2024

Please try #8439

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Verified issues on the current code behavior or pull requests that will fix them database Issues or pull requests that affect the database layer
Projects
None yet
4 participants