vrana/notorm

error with translated tables

Opened this issue · 3 comments

Hi Jakub, commit 3419027 broke my code. I use NotORM with language extension inspired by (http://php.vrana.cz/co-je-noveho-v-notorm.php). I have text fields translated in second table (e.g. article and article_translation(article_id, lang, title,....)). After I applied "git pull" this commit on this code:

foreach ($notorm->article() as $article) {
    echo "$article[id], $article[title]\n";
}

I got this error:

SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

File: /home/marek/www/new/libs/notorm/NotORM/Result.php   Line: 157

155:            }
156:            $return = $this->notORM->connection->prepare($query);
157:            if (!$return || !$return->execute(array_map(array($this, 'formatValue'), $parameters))) {
158:                return false;
159:            }
160:            return $return;
161:        }

Do you know where the problem is?
thanks
Marek.

Please enable debug ($notorm->debug = true from command line) and send me the executed queries.

correct queries before commit are:

SELECT * FROM category;

with params:

array(0) 

and second query

SELECT * 
FROM category_strings 
WHERE (category_strings.category_id IN (1, 2, 3, 4, 5, 6, 7, 12, 13, 14, 64, 60, 61, 65)) 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1)

with params:

array(2) [
     0 => "sk" (2)
     1 => "cz" (2)
]

bad queries after commit are (with same params):

SELECT * FROM category;

and second:

(
SELECT * 
FROM category_strings 
WHERE (category_id = '1') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '2') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '3') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '4') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '5') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '6') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '7') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '12') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '13') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '14') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '64') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '60') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '61') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0) UNION (
SELECT * 
FROM category_strings 
WHERE (category_id = '65') 
ORDER BY category_strings.category_id, IF(language = ?, 0, 1), IF(language = ?, 0, 1) 
LIMIT 1 OFFSET 0)

I realize where the problem is. My Implementation of NotORM_Row is:

function offsetExists($offset) {
    if (!isset($this->row[$offset])) {
        $table = $this->result->table . "_translation";
        $result = $this->$table()
                    ->order(new NotORM_Literal('IF(language = ?, 0, 1)', 'cz'))
                    ->order(new NotORM_Literal('IF(language = ?, 0, 1)', 'en'))->limit(1);
        foreach ($result as $row) {
            foreach ($row as $key => $val) {
                $this->row[$key] = $val;
            }
        }
    }
    return parent::offsetExists($offset);
}

I use this because I need specify primary, secondary and also ternary language if primary and secondary don't exists.
and in this commit you change implementation for using UNION but params are only two array('cz','en').

whne I change my code, without NotORM_Literal, result is ok

        $result = $this->$table()
                    ->order("IF(language = '{$this->primaryLang}', 0, 1)")
                    ->order("IF(language = '{$this->secondaryLang}', 0, 1)")->limit(1);

may be this problem (UNION with less params) is bug, I am not sure, but you can close this issue.