yii2 icon indicating copy to clipboard operation
yii2 copied to clipboard

yii2/db/Schema uses getSlavePdo() to quote a value - which errors when fallbackToMaster is set to false

Open developedsoftware opened this issue 2 years ago • 6 comments

I believe

($value = $this->db->getSlavePdo()->quote($str))

should simply be

($value = $this->db->quote($str))

Why do we have to use the slave to quote a value?

What steps will reproduce the problem?

set $fallbackToMaster to false

public function getSlavePdo($fallbackToMaster = false)

public function quoteValue($str)
    {
        if (!is_string($str)) {
            return $str;
        }

        if (mb_stripos($this->db->dsn, 'odbc:') === false && ($value = $this->db->getSlavePdo()->quote($str)) !== false) {
            return $value;
        }

        // the driver doesn't support quote (e.g. oci)
        return "'" . addcslashes(str_replace("'", "''", $str), "\000\n\r\\\032") . "'";
    }

What is the expected result?

quoteValue should return the quotedValue

What do you get instead?

Call to a member function quote() on null Screenshot 2023-04-19 at 13 21 15

Additional info

Q A
Yii version 2.0.47
PHP version 8.1
Operating system RHEL

developedsoftware avatar Apr 19 '23 12:04 developedsoftware

I can open the merge request to fix this, but I wanted to check why we call $this->db->getSlavePdo()->quote($str) when not using odbc?

if (mb_stripos($this->db->dsn, 'odbc:') === false && ($value = $this->db->getSlavePdo()->quote($str)) !== false) {
     return $value;
}

developedsoftware avatar Apr 19 '23 12:04 developedsoftware

@developedsoftware the logic here is:

  1. Always try to use replica database for quoting since using primary for that isn't great for performance.
  2. If it is ODBC, do not try quoting since the driver doesn't support that.

samdark avatar Apr 21 '23 19:04 samdark

That works fine, but if you have fallbackToMaster set to false (we have overridden it in db/Connection) you get a database exception.

So I think whenever you call getSlavePdo for the purpose of quoting we should pass in fallBackToMaster as true?

We have overridden db/Connection because we want to explicitly connect to a slave and "not" fallback to the master. But as soon as we do that the framework falls over.

Have created a merge request.

developedsoftware avatar Apr 21 '23 21:04 developedsoftware

The pull request looks weird to me.

  1. $fallbackToMaster is true by default for connection.
  2. You pass true explicitly which matches the default so technically exactly the same value is passed.

How does that fix anything?

samdark avatar Apr 22 '23 09:04 samdark

$fallbackToMaster is true by default, and when its true everything works fine.

However, if you set this to false (we do this so we can try to connec to a slave and issue a notifcation if all the slaves are offline) then you get the error above if the slave is offline.

So I thought it was best to change getSlavePdo() to pass in true when doing quoting so that we can change it in our connection class without any knock on effect.

You are right though, this should not change ANYTHING until somebody overrides the getSlavePdo method in db/Connection

developedsoftware avatar Apr 24 '23 08:04 developedsoftware

Alright. That's rare case but I see now how it could be possible. Thanks for explaining.

samdark avatar Apr 24 '23 11:04 samdark