vrana/notorm

Table Prefix, problem with left join convention structure.

Opened this issue · 4 comments

Hi,

There seems to be a problem with left joining, when using the convention structure. The prefix was not removed from the column name, which suppose to be a must.

Take a look this sample tables below:

  • user : id, name, email
  • question : id, user_id, text, html
  • answer : id, user_id, question_id, text, html

If I do this call, then it will return the left join with foreign column being referenced together with table prefix:
$db->question()->where('answer:user_id = ?', 1);

I fix this with:

protected function getColumnFromTable($name) {
    if ($this->table != '%s' && preg_match('(^' . str_replace('%s', '(.*)', preg_quote($this->table)) . '$)', $name, $match)) {
        return $match[1];
    }
    return substr($name, strlen($this->prefix)); // FIX: Remove Unnecessary Prefix
}

I haven't tested further, but I assume it might trigger abnormal behavior. Would you mind taking a look into this?

Thanks.
Wendy

I think the problem is not on the convention structure class, instead it's on the result class itself, when joining the table. Here's what I did and so far it looks ok, though I'm not sure whether it solves the root of the bug or not. Please advice!

protected function createJoins($val) {
    $return = array();
    preg_match_all('~\\b([a-z_][a-z0-9_.:]*[.:])[a-z_*]~i', $val, $matches);
    foreach ($matches[1] as $names) {
        $parent = $this->table;
        if ($names != "$parent.") { // case-sensitive
            preg_match_all('~\\b([a-z_][a-z0-9_]*)([.:])~i', $names, $matches, PREG_SET_ORDER);
            foreach ($matches as $match) {
                list(, $name, $delimiter) = $match;
                $table = $this->notORM->structure->getReferencedTable($name, $parent);
                $column = ($delimiter == ':' ? $this->notORM->structure->getPrimary($parent) : $this->notORM->structure->getReferencedColumn($name, $parent));
                $primary = ($delimiter == ':' ? $this->notORM->structure->getReferencingColumn($table, $parent) : $this->notORM->structure->getPrimary($table));
                $return[$name] = " LEFT JOIN $table" . ($table != $name ? " AS $name" : "") . " ON $parent.$column = $name.$primary"; // should use alias if the table is used on more places
                $parent = $name;
            }
        }
    }
    return $return;
}

I wonder whether this issue had been fixed yet?

$primary = ($delimiter == ':' ? $this->notORM->structure->getReferencingColumn($parent, $table) : $this->notORM->structure->getPrimary($table));

I change getReferencedColumn to getReferencingColumn.
Is the fix above actually fix the problem or not?

Please advice.

I think this is more complicated than it does.

Anybody can help out?

I tried this, but haven't actually tested it fully.

    protected function getColumnFromTable($name) {
        if ($this->table != '%s' && preg_match('(^' . str_replace('%s', '(.*)', preg_quote($this->table)) . '$)', $name, $match)) {
            return $match[1];
        }
        return substr($name, strlen($this->prefix));
    }

Basically I change return $name; into return substr($name, strlen($this->prefix));.

Please correct me if I'm wrong.