0

私のクエリには位置パラメータがないため、このエラーはバグのようです。メソッドは次のとおりです。

public function getAll(User $user, DateTime $start = null, DateTime $end = null)
{
    $params = array('user_id' => $user->getId());

    $rsm = new \Doctrine\ORM\Query\ResultSetMapping(); // Result set mapping
    $rsm->addScalarResult('subtype', 'subtype');
    $rsm->addScalarResult('count',   'count');

    $sms_sql =
    "SELECT CONCAT('sms_', IF(is_auto = 0, 'user' , 'auto')) AS subtype, " .
    "SUM(messages_count * (customers_count + recipients_count)) AS count " .
    "FROM outgoing_message AS m INNER JOIN small_text_message AS s ON " . 
    "m.id = s.id WHERE status <> 'pending' AND user_id = :user_id";

    $news_sql =
    "SELECT CONCAT('news_', IF(is_auto = 0, 'user' , 'auto')) AS subtype, " .
    "SUM(customers_count + recipients_count) AS count " .
    "FROM outgoing_message AS m JOIN newsletter AS n ON m.id = n.id " .
    "WHERE status <> 'pending' AND user_id = :user_id";

    if($start) :
        $sms_sql        .= " AND sent_at >= :start";
        $news_sql       .= " AND sent_at >= :start";
        $params['start'] = $start->format('Y-m-d');
    endif;

    $sms_sql  .= ' GROUP BY type, is_auto';
    $news_sql .= ' GROUP BY type, is_auto';

    return $this->_em->createNativeQuery("$sms_sql UNION ALL $news_sql", $rsm)
        >setParameters($params)->getResult();
}

そして、これは例外をスローします:

SQLSTATE[HY093]: 無効なパラメーター番号: 名前付きパラメーターと位置パラメーターが混在しています

配列$paramsはOKなので、生成されたSQL

var_dump($params);

array (size=2)
  'user_id' => int 1
  'start' => string '2012-01-01' (length=10)

最も奇妙なことは、それが"$sms_sql"のみで動作することです!

アップデート

また変なもの発見。名前だけを(のstart_date代わりにstart)変更した場合:

    if($start) :
        $sms_sql             .= " AND sent_at >= :start_date";
        $news_sql            .= " AND sent_at >= :start_date";
        $params['start_date'] = $start->format('Y-m-d');
    endif;

何が起こるかというと、Doctrine/PDO は次のように言っています:

SQLSTATE [42S22]: 列が見つかりません: 1054 不明な列 'sent1rt_date' が 'where 句' にあります

...1rt列名の途中に文字列が追加されたので!

4

1 に答える 1

2

問題は、NativeSQL の Doctrine ORM サポートにあると思います。

setParameters名前付きパラメーターに使用されているメソッドのドキュメントに例が見つかりません。そのメソッドが使用されている例はすべて、名前ではなく位置に関するものです。

名前付きパラメーターのすべての例では、setParameter("s" を使用しない) メソッドを使用しています。また、SQL 内で一致するプレースホルダーが 1 回だけ出現することを示しています。

テストとして (および考えられる回避策として)、SQL テキスト内の各プレースホルダーを一意にしてから、それぞれを個別に設定してみてください。

「名前付きパラメーター」のサポートは、(Oracle や他の ORM フレームワークで慣れているものと比較して) やや不完全なようです。Doctrine の方が位置表記をより適切にサポートしているようです。(これは単純なステートメントには最適ですが、多くのパラメーターがあり、SQL ステートメントに変更を加える必要がある場合は、実際に問題になる可能性があります。名前付きパラメーターの利点が本当に輝き始めるのは、そのような場合です...右をサポートしています。)

Doctrine ORM ドキュメントへのリンクは次のとおりですhttp://doctrine-orm.readthedocs.org/en/latest/reference/query-builder.html?highlight=setParameterssetParameters (そのページで例を 検索してください)。

(あなたの質問に対する私のコメントを参照してください。)

それはあなたの質問に本当に答えないかもしれませんが、正しい方向に進むかもしれません. そこに注意してください。

于 2012-07-06T21:11:27.903 に答える