Propel: selecting columns from aliased join tables

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-21 20:44:53

问题


I have the following two tables:

  table_a:
    id_table_a: { type: integer, primaryKey: true, autoIncrement: true, required: true }
    name:       { type: varchar(255) }
    id_table_b: { type: integer, foreignTable: table_b, foreignReference: id_table_b }

  table_b: 
    id_table_b: { type: integer, primaryKey: true, autoIncrement: true, required: true }
    value_1:    { type: varchar(255) }
    value_2:    { type: integer }

and I would like to build SQL query using select method to skip hydration, also using aliases on joined tables:

 TableAQuery::create()
            ->useTableBQuery('a')
                // some filters methods
            ->endUse()
            ->useTableBQuery('b')
                // some filters methods
            ->endUse()
            ->select(array('a.value_1', 'b.value_2'))
            ->find();

Now here is the problem. Propel consantly keep changing a and b aliases to table_b generating incorrect SQL like this:

SELECT table_b.value_1 AS "a.value_1", table_b.value_2 AS "b.value_2" FROM `table_a`
LEFT JOIN `table_b` `a` ON (table_a.id_table_b=a.id_table_b) 
LEFT JOIN `table_b` `b` ON (table_a.id_table_b=b.id_table_b)

instead of

SELECT a.value_1 AS value_1, b.value_2 AS value_2 FROM `table_a` 
LEFT JOIN `table_b` `a` ON (table_a.id_table_b=a.id_table_b) 
LEFT JOIN `table_b` `b` ON (table_a.id_table_b=b.id_table_b)

How can I deal with that? I use Propel 1.6.9

UPDATE

I also checked propel 1.7.1, no difference.


回答1:


Could you change it to this?

TableAQuery::create()
        ->useTableBQuery('a')
            // some filters methods
        ->endUse()
        ->useTableBQuery('b')
            // some filters methods
        ->endUse()
        //->select(array('a.value_1', 'b.value_2'))
        ->addAsColumn('a.value_1', 'a.value_1')
        ->addAsColumn('b.value_2', 'b.value_2')
        ->find();

Caveat: I'm not a Propel user. I'm just wondering if the auto-generated useXXXQuery() is setting the table alias on the same relation both times, or something like that.

As in the query above, replace your select() with the two addAsColumn() statements. It's a bit of a hack, but I think it achieves your desired result.

I just spent a while reading the Propel source code, and I've concluded that Propel 1 is not built to use different aliases on the same table joined multiple times, as you attempt. In ModelCriteria.php, the use of $column->getFullyQualifiedName ensures that the full name (table.column) is used in the select for joined tables, regardless of alias. (See https://github.com/propelorm/Propel/blob/7ddb0956b699343d33ce0c94043fa5970cc719c1/runtime/lib/query/ModelCriteria.php#L2082.) I expect this is indeed a bug.

If the addAsColumn() method is used instead of select(), Propel will use your literal SQL expression, whether it's an alias and column or anything else. That said, I'm not sure that's its intended use.




回答2:


I do a little reserch after I read jchamberlain's comment about where caluse under his answer and I came to conclusion that

  • you should always use UpperCamelCase style when you type column names in propel functions, even though it sometimes works fine if you don't use this style
  • solution depends on Propel version

Probably there is no solution for Propel <= 1.6.7 (or maybe raw SQL query is the only solution), because no matter how much I try I always ends up with Cannot fetch ColumnMap for undefined column: ID_TABLE_B Propel exception.

For Propel >= 1.6.8 this will work:

If you need array with aliased columns as result

TableAQuery::create()
  ->useTableBQuery('a')
      // some filters methods
  ->endUse()
  ->useTableBQuery('b')
      // some filters methods
  ->endUse()
  ->select(array('a.Value1', 'b.Value2')) // notice a.value_1 or b.value_2 won't work
  ->find();

If you need objects with virtual columns from aliased columns

TableAQuery::create()
  ->useTableBQuery('a')
      // some filters methods
  ->endUse()
  ->useTableBQuery('b')
      // some filters methods
  ->endUse()
  ->withColumn('a.Value1') // notice a.value_1 won't work
  ->withColumn('b.Value2') // notice b.value_2 won't work
  ->find();


来源:https://stackoverflow.com/questions/19524589/propel-selecting-columns-from-aliased-join-tables

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!