Search code examples
phpsqlzend-frameworklaminas-api-toolslaminas

Build SQL Select object in Laminas that cotains subquery as FROM table


I'm trying to put that query:

SELECT 
*
FROM (
  (SELECT * FROM table1)
  UNION 
  (SELECT * FROM table2)
) AS t;

into \Laminas\Db\Sql\Select object. Something like this:

$select1 = new \Laminas\Db\Sql\Select($table1); // this is select for table1
$select2 = new \Laminas\Db\Sql\Select($table2); // this is select for table2

$select1->combine($select2);

So far everything looks good, and query is fine, but while I'm trying to use that query as a table, like this:

$selectUnion = new \Laminas\Db\Sql\Select();
$selectUnion->from($select1->getSqlString());

I'm getting very strange, and wrong query, result of

echo $selectUnion->getSqlString();

is:

SELECT "((SELECT * FROM table1) UNION (SELECT * FROM table2))";

which is wrong, because FROM part is missing and also " are unnecessary.


Solution

  • I've fixed the issue by editing \Laminas\Db\Sql\Select class from line 199:

    if (! is_string($table) && ! is_array($table) && ! $table instanceof TableIdentifier) {
            throw new Exception\InvalidArgumentException(
                '$table must be a string, array, or an instance of TableIdentifier'
            );
        }
    

    by adding possibility to object of $from can be of type Select, which is natively supported by Laminas:

    if (! is_string($table) && ! is_array($table) && ! ($table instanceof TableIdentifier || $table instanceof Select)) {
            throw new Exception\InvalidArgumentException(
                '$table must be a string, array, or an instance of TableIdentifier or Select'
            );
        }
    

    Now to build SELECT from another SELECT we have two possibilities:

    $selectUnion = new \Laminas\Db\Sql\Select();
    $selectUnion->from(['t' => $select1->getSqlString()]);
    

    or

    $selectUnion = new \Laminas\Db\Sql\Select();
    $selectUnion->columns(['*'], false);
    $selectUnion->from($select1->getSqlString());
    

    Because our Select needs to have either alias name for subselect or disabled auto prefixation of table columns.