protected function processExpression(ExpressionInterface $expression, PlatformInterface $platform, DriverInterface $driver = null, $namedParameterPrefix = null) { // static counter for the number of times this method was invoked across the PHP runtime static $runtimeExpressionPrefix = 0; if ($driver && ((!is_string($namedParameterPrefix) || $namedParameterPrefix == ''))) { $namedParameterPrefix = sprintf('expr%04dParam', ++$runtimeExpressionPrefix); } $return = array( 'sql' => '', 'parameters' => array() ); // initialize variables $parts = $expression->getExpressionData(); $expressionParamIndex = 1; foreach ($parts as $part) { // if it is a string, simply tack it onto the return sql "specification" string if (is_string($part)) { $return['sql'] .= $part; continue; } if (!is_array($part)) { throw new Exception\RuntimeException('Elements returned from getExpressionData() array must be a string or array.'); } // process values and types (the middle and last position of the expression data) $values = $part[1]; $types = (isset($part[2])) ? $part[2] : array(); foreach ($values as $vIndex => $value) { if (isset($types[$vIndex]) && $types[$vIndex] == ExpressionInterface::TYPE_IDENTIFIER) { $values[$vIndex] = $platform->quoteIdentifierInFragment($value); } elseif (isset($types[$vIndex]) && $types[$vIndex] == ExpressionInterface::TYPE_VALUE) { // if prepareType is set, it means that this particular value must be // passed back to the statement in a way it can be used as a placeholder value if ($driver) { $name = $namedParameterPrefix . $expressionParamIndex++; $return['parameters'][$name] = $value; $values[$vIndex] = $driver->formatParameterName($name); continue; } // if not a preparable statement, simply quote the value and move on $values[$vIndex] = $platform->quoteValue($value); } elseif (isset($types[$vIndex]) && $types[$vIndex] == ExpressionInterface::TYPE_LITERAL) { $values[$vIndex] = $value; } } // after looping the values, interpolate them into the sql string (they might be placeholder names, or values) $return['sql'] .= vsprintf($part[0], $values); } return $return; }
/** * @param PlatformInterface $platform * @param DriverInterface $driver * @param ParameterContainer $parameterContainer * @param array $sqls * @param array $parameters */ protected function processLimitOffset(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null, &$sqls, &$parameters) { if ($this->limit === null && $this->offset === null) { return; } $selectParameters = $parameters[self::SELECT]; $starSuffix = $platform->getIdentifierSeparator() . self::SQL_STAR; foreach ($selectParameters[0] as $i => $columnParameters) { if ($columnParameters[0] == self::SQL_STAR || isset($columnParameters[1]) && $columnParameters[1] == self::SQL_STAR || strpos($columnParameters[0], $starSuffix)) { $selectParameters[0] = [[self::SQL_STAR]]; break; } if (isset($columnParameters[1])) { array_shift($columnParameters); $selectParameters[0][$i] = $columnParameters; } } // first, produce column list without compound names (using the AS portion only) array_unshift($sqls, $this->createSqlFromSpecificationAndParameters(['SELECT %1$s FROM (' => current($this->specifications[self::SELECT])], $selectParameters)); if (preg_match('/DISTINCT/i', $sqls[0])) { $this->setIsSelectContainDistinct(true); } if ($parameterContainer) { // create bottom part of query, with offset and limit using row_number $limitParamName = $driver->formatParameterName('limit'); $offsetParamName = $driver->formatParameterName('offset'); array_push($sqls, sprintf(") AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN %s AND %s", $offsetParamName, $limitParamName)); if ((int) $this->offset > 0) { $parameterContainer->offsetSet('offset', (int) $this->offset + 1); } else { $parameterContainer->offsetSet('offset', (int) $this->offset); } $parameterContainer->offsetSet('limit', (int) $this->limit + (int) $this->offset); } else { if ((int) $this->offset > 0) { $offset = (int) $this->offset + 1; } else { $offset = (int) $this->offset; } array_push($sqls, sprintf(") AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN %d AND %d", $offset, (int) $this->limit + (int) $this->offset)); } if (isset($sqls[self::ORDER])) { $orderBy = $sqls[self::ORDER]; unset($sqls[self::ORDER]); } else { $orderBy = ''; } // add a column for row_number() using the order specification //dense_rank() if ($this->getIsSelectContainDistinct()) { $parameters[self::SELECT][0][] = ['DENSE_RANK() OVER (' . $orderBy . ')', 'ZEND_DB_ROWNUM']; } else { $parameters[self::SELECT][0][] = ['ROW_NUMBER() OVER (' . $orderBy . ')', 'ZEND_DB_ROWNUM']; } $sqls[self::SELECT] = $this->createSqlFromSpecificationAndParameters($this->specifications[self::SELECT], $parameters[self::SELECT]); }
/** * @param PlatformInterface $adapterPlatform * @return array */ protected function processTable(PlatformInterface $adapterPlatform = null) { $ret = array(''); if ($this->isTemporary) { $table = '#'; } else { $table = ''; } $ret[] = $adapterPlatform->quoteIdentifier($table . ltrim($this->table, '#')); return $ret; }
/** * */ public function setUpMockedAdapter() { $this->mockedDbAdapterDriver = $this->getMock('Zend\\Db\\Adapter\\Driver\\DriverInterface'); $this->mockedDbAdapterPlatform = $this->getMock('\\Zend\\Db\\Adapter\\Platform\\PlatformInterface', array()); $this->mockedDbAdapterStatement = $this->getMock('\\Zend\\Db\\Adapter\\Driver\\StatementInterface', array()); $this->mockedDbAdapterPlatform->expects($this->any())->method('getName')->will($this->returnValue('null')); $this->mockedDbAdapter = $this->getMockBuilder('\\Zend\\Db\\Adapter\\Adapter')->setConstructorArgs(array($this->mockedDbAdapterDriver, $this->mockedDbAdapterPlatform))->getMock(array('getPlatform')); $this->mockedDbAdapter->expects($this->any())->method('getPlatform')->will($this->returnValue($this->mockedDbAdapterPlatform)); $this->mockedDbSql = $this->getMockBuilder('\\Zend\\Db\\Sql\\Sql')->setConstructorArgs(array($this->mockedDbAdapter))->setMethods(array('prepareStatementForSqlObject'))->getMock(); $this->mockedDbSql->expects($this->any())->method('prepareStatementForSqlObject')->will($this->returnValue($this->mockedDbAdapterStatement)); $this->mockedDbSqlPlatform = $this->getMockBuilder('\\Zend\\Db\\Sql\\Platform\\Platform')->setConstructorArgs(array($this->mockedDbAdapter))->getMock(); }
/** * @param PlatformInterface $platform * @param DriverInterface $driver * @param ParameterContainer $parameterContainer * @param $sqls * @param $parameters * @return null */ protected function processLimitOffset(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null, &$sqls, &$parameters) { if ($this->limit === null && $this->offset === null) { return; } $selectParameters = $parameters[self::SELECT]; /** if this is a DISTINCT query then real SELECT part goes to second element in array **/ $parameterIndex = 0; if ($selectParameters[0] === 'DISTINCT') { unset($selectParameters[0]); $selectParameters = array_values($selectParameters); $parameterIndex = 1; } $starSuffix = $platform->getIdentifierSeparator() . self::SQL_STAR; foreach ($selectParameters[0] as $i => $columnParameters) { if ($columnParameters[0] == self::SQL_STAR || isset($columnParameters[1]) && $columnParameters[1] == self::SQL_STAR || strpos($columnParameters[0], $starSuffix)) { $selectParameters[0] = [[self::SQL_STAR]]; break; } if (isset($columnParameters[1])) { array_shift($columnParameters); $selectParameters[0][$i] = $columnParameters; } } // first, produce column list without compound names (using the AS portion only) array_unshift($sqls, $this->createSqlFromSpecificationAndParameters(['SELECT %1$s FROM (' => current($this->specifications[self::SELECT])], $selectParameters)); if ($parameterContainer) { // create bottom part of query, with offset and limit using row_number $limitParamName = $driver->formatParameterName('limit'); $offsetParamName = $driver->formatParameterName('offset'); $offsetForSumParamName = $driver->formatParameterName('offsetForSum'); array_push($sqls, ') AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ' . $offsetParamName . '+1 AND ' . $limitParamName . '+' . $offsetForSumParamName); $parameterContainer->offsetSet('offset', $this->offset); $parameterContainer->offsetSet('limit', $this->limit); $parameterContainer->offsetSetReference('offsetForSum', 'offset'); } else { array_push($sqls, ') AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ' . (int) $this->offset . '+1 AND ' . (int) $this->limit . '+' . (int) $this->offset); } if (isset($sqls[self::ORDER])) { $orderBy = $sqls[self::ORDER]; unset($sqls[self::ORDER]); } else { $orderBy = 'ORDER BY (SELECT 1)'; } // add a column for row_number() using the order specification $parameters[self::SELECT][$parameterIndex][] = ['ROW_NUMBER() OVER (' . $orderBy . ')', '[__ZEND_ROW_NUMBER]']; $sqls[self::SELECT] = $this->createSqlFromSpecificationAndParameters($this->specifications[self::SELECT], $parameters[self::SELECT]); }
protected function processChangeColumns(PlatformInterface $adapterPlatform = null) { /* @var Column\Column $column */ $sqls = []; foreach ($this->changeColumns as $name => $column) { if ($name !== $column->getName()) { trigger_error('One statement must rename a column, other separate statements must change table definition.', E_USER_DEPRECATED); } $default = $column->getDefault(); $columnClass = get_class($column); $emptyColumn = new $columnClass(null, true); $emptyColumn->setOptions($column->getOptions()); $sqls[] = [$adapterPlatform->quoteIdentifier($name), ' SET DATA TYPE' . $this->processExpression($emptyColumn, $adapterPlatform)]; $sqls[] = [$adapterPlatform->quoteIdentifier($name), null !== $default ? ' SET ' . $this->processExpression(new DefaultValue($default), $adapterPlatform) : ' DROP DEFAULT']; $sqls[] = [$adapterPlatform->quoteIdentifier($name), $column->isNullable() ? ' DROP NOT NULL' : ' SET NOT NULL']; } return [$sqls]; }
/** * @param PlatformInterface $platform * @param DriverInterface $driver * @param ParameterContainer $parameterContainer * @param array $sqls * @param array $parameters * @return null */ protected function processLimitOffset(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null, &$sqls = [], &$parameters = []) { if ($this->limit === null && $this->offset === null) { return; } $selectParameters = $parameters[self::SELECT]; $starSuffix = $platform->getIdentifierSeparator() . self::SQL_STAR; foreach ($selectParameters[0] as $i => $columnParameters) { if ($columnParameters[0] == self::SQL_STAR || isset($columnParameters[1]) && $columnParameters[1] == self::SQL_STAR || strpos($columnParameters[0], $starSuffix)) { $selectParameters[0] = [[self::SQL_STAR]]; break; } if (isset($columnParameters[1])) { array_shift($columnParameters); $selectParameters[0][$i] = $columnParameters; } } if ($this->offset === null) { $this->offset = 0; } // first, produce column list without compound names (using the AS portion only) array_unshift($sqls, $this->createSqlFromSpecificationAndParameters(['SELECT %1$s FROM (SELECT b.%1$s, rownum b_rownum FROM (' => current($this->specifications[self::SELECT])], $selectParameters)); if ($parameterContainer) { $number = $this->processInfo['subselectCount'] ? $this->processInfo['subselectCount'] : ''; if ($this->limit === null) { array_push($sqls, ') b ) WHERE b_rownum > (:offset' . $number . ')'); $parameterContainer->offsetSet('offset' . $number, $this->offset, $parameterContainer::TYPE_INTEGER); } else { // create bottom part of query, with offset and limit using row_number array_push($sqls, ') b WHERE rownum <= (:offset' . $number . '+:limit' . $number . ')) WHERE b_rownum >= (:offset' . $number . ' + 1)'); $parameterContainer->offsetSet('offset' . $number, $this->offset, $parameterContainer::TYPE_INTEGER); $parameterContainer->offsetSet('limit' . $number, $this->limit, $parameterContainer::TYPE_INTEGER); } $this->processInfo['subselectCount']++; } else { if ($this->limit === null) { array_push($sqls, ') b ) WHERE b_rownum > (' . (int) $this->offset . ')'); } else { array_push($sqls, ') b WHERE rownum <= (' . (int) $this->offset . '+' . (int) $this->limit . ')) WHERE b_rownum >= (' . (int) $this->offset . ' + 1)'); } } $sqls[self::SELECT] = $this->createSqlFromSpecificationAndParameters($this->specifications[self::SELECT], $parameters[self::SELECT]); }
/** * @param PlatformInterface $platform * @param Adapter $adapter * @param ParameterContainer $parameterContainer * @param $sqls * @param $parameters * @return null */ protected function processLimitOffset(PlatformInterface $platform, Adapter $adapter = null, ParameterContainer $parameterContainer = null, &$sqls, &$parameters) { if ($this->limit === null && $this->offset === null) { return null; } $selectParameters = $parameters[self::SPECIFICATION_SELECT]; $starSuffix = $platform->getIdentifierSeparator() . self::SQL_STAR; foreach ($selectParameters[0] as $i => $columnParameters) { if ($columnParameters[0] == self::SQL_STAR || (isset($columnParameters[1]) && $columnParameters[1] == self::SQL_STAR) || strpos($columnParameters[0], $starSuffix)) { $selectParameters[0] = array(array(self::SQL_STAR)); break; } if (isset($columnParameters[1])) { array_shift($columnParameters); $selectParameters[0][$i] = $columnParameters; } } // first, produce column list without compound names (using the AS portion only) array_unshift($sqls, $this->createSqlFromSpecificationAndParameters( array('SELECT %1$s FROM (' => current($this->specifications[self::SPECIFICATION_SELECT])), $selectParameters )); if ($parameterContainer) { // create bottom part of query, with offset and limit using row_number array_push($sqls, ') AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?'); $parameterContainer->offsetSet('offset', $this->offset); $parameterContainer->offsetSet('limit', $this->limit); $parameterContainer->offsetSetReference('offsetForSum', 'offset'); } else { array_push($sqls, ') AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ' . (int) $this->offset . '+1 AND ' . (int) $this->limit . '+' . (int) $this->offset ); } if (isset($sqls[self::SPECIFICATION_ORDER])) { $orderBy = $sqls[self::SPECIFICATION_ORDER]; unset($sqls[self::SPECIFICATION_ORDER]); } else { $orderBy = 'SELECT 1'; } // add a column for row_number() using the order specification $parameters[self::SPECIFICATION_SELECT][0][] = array('ROW_NUMBER() OVER (' . $orderBy . ')', '[__ZEND_ROW_NUMBER]'); $sqls[self::SPECIFICATION_SELECT] = $this->createSqlFromSpecificationAndParameters( $this->specifications[self::SPECIFICATION_SELECT], $parameters[self::SPECIFICATION_SELECT] ); }
protected function processInsert(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) { if ($this->select) { return; } if (!$this->columns) { throw new InvalidArgumentException('values or select should be present'); } $columns = []; $values = []; foreach ($this->columns as $column => $value) { $columns[] = $platform->quoteIdentifier($column); foreach ($value as $key => $item) { /* if (is_scalar($item) && $parameterContainer) { $values[$key][] = $driver->formatParameterName($column); $parameterContainer->offsetSet($column, $item); } else {*/ $values[$key][] = $this->resolveColumnValue($item, $platform, $driver, $parameterContainer); /* }*/ } } $strValues = ''; foreach ($values as $value) { $strValues .= '(' . implode(', ', $value) . '),'; } $strValues = rtrim($strValues, ','); $sql = sprintf($this->specifications[static::SPECIFICATION_INSERT], $this->resolveTable($this->table, $platform, $driver, $parameterContainer), implode(', ', $columns), $strValues); return $sql; }
protected function processOffset(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) { if ($this->offset === null) { return; } if ($parameterContainer) { $parameterContainer->offsetSet('offset', $this->offset, ParameterContainer::TYPE_INTEGER); return [$driver->formatParameterName('offset')]; } return [$platform->quoteValue($this->offset)]; }
/** * @param PlatformInterface $adapterPlatform * * @return string[] */ protected function processTable(PlatformInterface $adapterPlatform = null) { return array($this->isTemporary ? 'TEMPORARY ' : '', $adapterPlatform->quoteIdentifier($this->table)); }
/** * @param PlatformInterface $platform * @param DriverInterface $driver * @param ParameterContainer $pContainer * @return array|null */ protected function processLike(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $pContainer = null) { if (!$this->like) { return null; } $like = (string) $this->like; if ($driver && $pContainer) { $pContainer->offsetSet('like', $like, ParameterContainer::TYPE_STRING); return array($driver->formatParameterName('like')); } return array($platform->quoteValue($like)); }
/** * @param PlatformInterface $adapterPlatform * @return array */ protected function processTable(PlatformInterface $adapterPlatform = null) { $table = ($this->isTemporary ? '#' : '') . ltrim($this->table, '#'); return ['', $adapterPlatform->quoteIdentifier($table)]; }
protected function processTable(PlatformInterface $adapterPlatform = null) { return array($adapterPlatform->quoteIdentifier($this->table)); }
protected function processDropConstraints(PlatformInterface $adapterPlatform = null) { $sqls = array(); foreach ($this->dropConstraints as $constraint) { $sqls[] = $adapterPlatform->quoteIdentifier($constraint); } return array($sqls); }
protected function processRenameColumn(PlatformInterface $adapterPlatform = null) { $sqls = []; foreach ($this->renameColumn as $name => $column) { $sqls[] = [$adapterPlatform->quoteIdentifier($name), $this->processExpression($column, $adapterPlatform)]; } return [$sqls]; }
protected function processInsert(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) { if ($this->select) { return; } if (!$this->columns) { throw new Exception\InvalidArgumentException('values or select should be present'); } $columns = []; $values = []; foreach ($this->columns as $column => $value) { $columns[] = $platform->quoteIdentifier($column); if (is_scalar($value) && $parameterContainer) { $values[] = $driver->formatParameterName($column); $parameterContainer->offsetSet($column, $value); } else { $values[] = $this->resolveColumnValue($value, $platform, $driver, $parameterContainer); } } return sprintf($this->specifications[static::SPECIFICATION_INSERT], $this->resolveTable($this->table, $platform, $driver, $parameterContainer), implode(', ', $columns), implode(', ', $values)); }
protected function processTable(PlatformInterface $adapterPlatform = null) { $ret = array(); if ($this->isTemporary) { $ret[] = 'TEMPORARY'; } $ret[] = $adapterPlatform->quoteIdentifier($this->table); return $ret; }
/** * @param Join[] $joins * @param PlatformInterface $platform * @param null|DriverInterface $driver * @param null|ParameterContainer $parameterContainer * @return null|string[] Null if no joins present, array of JOIN statements * otherwise * @throws Exception\InvalidArgumentException for invalid JOIN table names. */ protected function processJoin(Join $joins, PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) { if (!$joins->count()) { return; } // process joins $joinSpecArgArray = []; foreach ($joins->getJoins() as $j => $join) { $joinName = null; $joinAs = null; // table name if (is_array($join['name'])) { $joinName = current($join['name']); $joinAs = $platform->quoteIdentifier(key($join['name'])); } else { $joinName = $join['name']; } if ($joinName instanceof Expression) { $joinName = $joinName->getExpression(); } elseif ($joinName instanceof TableIdentifier) { $joinName = $joinName->getTableAndSchema(); $joinName = ($joinName[1] ? $platform->quoteIdentifier($joinName[1]) . $platform->getIdentifierSeparator() : '') . $platform->quoteIdentifier($joinName[0]); } elseif ($joinName instanceof Select) { $joinName = '(' . $this->processSubSelect($joinName, $platform, $driver, $parameterContainer) . ')'; } elseif (is_string($joinName) || is_object($joinName) && is_callable([$joinName, '__toString'])) { $joinName = $platform->quoteIdentifier($joinName); } else { throw new Exception\InvalidArgumentException(sprintf('Join name expected to be Expression|TableIdentifier|Select|string, "%s" given', gettype($joinName))); } $joinSpecArgArray[$j] = [strtoupper($join['type']), $this->renderTable($joinName, $joinAs)]; // on expression // note: for Expression objects, pass them to processExpression with a prefix specific to each join (used for named parameters) $joinSpecArgArray[$j][] = $join['on'] instanceof ExpressionInterface ? $this->processExpression($join['on'], $platform, $driver, $parameterContainer, 'join' . ($j + 1) . 'part') : $platform->quoteIdentifierInFragment($join['on'], ['=', 'AND', 'OR', '(', ')', 'BETWEEN', '<', '>']); // on } return [$joinSpecArgArray]; }
protected function processOffset(PlatformInterface $platform, Adapter $adapter = null, ParameterContainer $parameterContainer = null) { if ($this->offset === null) { return null; } if ($adapter) { $parameterContainer->offsetSet('offset', $this->offset, ParameterContainer::TYPE_INTEGER); return array($adapter->getDriver()->formatParameterName('offset')); } else { return array($platform->quoteValue($this->offset)); } }
protected function processUpdate(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) { $setSql = []; foreach ($this->set as $column => $value) { $prefix = $platform->quoteIdentifier($column) . ' = '; if (is_scalar($value) && $parameterContainer) { $setSql[] = $prefix . $driver->formatParameterName($column); $parameterContainer->offsetSet($column, $value); } else { $setSql[] = $prefix . $this->resolveColumnValue($value, $platform, $driver, $parameterContainer); } } return sprintf($this->specifications[static::SPECIFICATION_UPDATE], $this->resolveTable($this->table, $platform, $driver, $parameterContainer), implode(', ', $setSql)); }
/** * @param null|PlatformInterface|AdapterInterface $adapterOrPlatform * * @return PlatformInterface * * @throws Exception\InvalidArgumentException */ protected function resolvePlatform($adapterOrPlatform) { if (!$adapterOrPlatform) { return $this->getDefaultPlatform(); } if ($adapterOrPlatform instanceof AdapterInterface) { return $adapterOrPlatform->getPlatform(); } if ($adapterOrPlatform instanceof PlatformInterface) { return $adapterOrPlatform; } throw new Exception\InvalidArgumentException(sprintf('$adapterOrPlatform should be null, %s, or %s', 'Zend\\Db\\Adapter\\AdapterInterface', 'Zend\\Db\\Adapter\\Platform\\PlatformInterface')); }
protected function processJoins(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) { if (!$this->joins) { return null; } // process joins $joinSpecArgArray = array(); foreach ($this->joins as $j => $join) { $joinSpecArgArray[$j] = array(); // type $joinSpecArgArray[$j][] = strtoupper($join['type']); // table name $joinSpecArgArray[$j][] = is_array($join['name']) ? $platform->quoteIdentifier(current($join['name'])) . ' ' . $platform->quoteIdentifier(key($join['name'])) : $platform->quoteIdentifier($join['name']); // on expression $joinSpecArgArray[$j][] = $join['on'] instanceof ExpressionInterface ? $this->processExpression($join['on'], $platform, $driver, $this->processInfo['paramPrefix'] . 'join') : $platform->quoteIdentifierInFragment($join['on'], array('=', 'AND', 'OR', '(', ')', 'BETWEEN')); // on if ($joinSpecArgArray[$j][2] instanceof StatementContainerInterface) { if ($parameterContainer) { $parameterContainer->merge($joinSpecArgArray[$j][2]->getParameterContainer()); } $joinSpecArgArray[$j][2] = $joinSpecArgArray[$j][2]->getSql(); } } return array($joinSpecArgArray); }
protected function processExpression(ExpressionInterface $expression, PlatformInterface $platform, DriverInterface $driver = null, $namedParameterPrefix = null) { // static counter for the number of times this method was invoked across the PHP runtime static $runtimeExpressionPrefix = 0; if ($driver && (!is_string($namedParameterPrefix) || $namedParameterPrefix == '')) { $namedParameterPrefix = sprintf('expr%04dParam', ++$runtimeExpressionPrefix); } $sql = ''; $statementContainer = new StatementContainer(); $parameterContainer = $statementContainer->getParameterContainer(); // initialize variables $parts = $expression->getExpressionData(); if (!isset($this->instanceParameterIndex[$namedParameterPrefix])) { $this->instanceParameterIndex[$namedParameterPrefix] = 1; } $expressionParamIndex =& $this->instanceParameterIndex[$namedParameterPrefix]; foreach ($parts as $part) { // if it is a string, simply tack it onto the return sql "specification" string if (is_string($part)) { $sql .= $part; continue; } if (!is_array($part)) { throw new Exception\RuntimeException('Elements returned from getExpressionData() array must be a string or array.'); } // process values and types (the middle and last position of the expression data) $values = $part[1]; $types = isset($part[2]) ? $part[2] : array(); foreach ($values as $vIndex => $value) { if (isset($types[$vIndex]) && $types[$vIndex] == ExpressionInterface::TYPE_IDENTIFIER) { $values[$vIndex] = $platform->quoteIdentifierInFragment($value); } elseif (isset($types[$vIndex]) && $types[$vIndex] == ExpressionInterface::TYPE_VALUE && $value instanceof Select) { // process sub-select if ($driver) { $values[$vIndex] = '(' . $this->processSubSelect($value, $platform, $driver, $parameterContainer) . ')'; } else { $values[$vIndex] = '(' . $this->processSubSelect($value, $platform) . ')'; } } elseif (isset($types[$vIndex]) && $types[$vIndex] == ExpressionInterface::TYPE_VALUE && $value instanceof ExpressionInterface) { // recursive call to satisfy nested expressions $innerStatementContainer = $this->processExpression($value, $platform, $driver, $namedParameterPrefix . $vIndex . 'subpart'); $values[$vIndex] = $innerStatementContainer->getSql(); if ($driver) { $parameterContainer->merge($innerStatementContainer->getParameterContainer()); } } elseif (isset($types[$vIndex]) && $types[$vIndex] == ExpressionInterface::TYPE_VALUE) { // if prepareType is set, it means that this particular value must be // passed back to the statement in a way it can be used as a placeholder value if ($driver) { $name = $namedParameterPrefix . $expressionParamIndex++; $parameterContainer->offsetSet($name, $value); $values[$vIndex] = $driver->formatParameterName($name); continue; } // if not a preparable statement, simply quote the value and move on $values[$vIndex] = $platform->quoteValue($value); } elseif (isset($types[$vIndex]) && $types[$vIndex] == ExpressionInterface::TYPE_LITERAL) { $values[$vIndex] = $value; } } // after looping the values, interpolate them into the sql string (they might be placeholder names, or values) $sql .= vsprintf($part[0], $values); } $statementContainer->setSql($sql); return $statementContainer; }
protected function processInsert(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) { if ($this->select) { return; } if (!$this->columns) { throw new \Zend\Db\Exception\InvalidArgumentException('values or select should be present'); } $columns = array(); $values = array(); if (empty($this->valueRows)) { return ''; //TODO Test that } $prepareColumns = true; foreach ($this->valueRows as $row) { if (!is_array($row)) { throw new \Zend\Db\Exception\InvalidArgumentException('values must be arrays for multi-insertion'); } $subValues = array(); ksort($row); // Make sure columns always appear in the same order foreach ($row as $col => $subValue) { if ($prepareColumns) { $columns[] = $platform->quoteIdentifier($col); } if (is_scalar($subValue) && $parameterContainer) { $subValues[] = $driver->formatParameterName($col); $parameterContainer->offsetSet($col, $subValue); } else { $subValues[] = $this->resolveColumnValue($subValue, $platform, $driver, $parameterContainer); } } $values[] = implode(', ', $subValues); $prepareColumns = false; } return sprintf($this->specifications[static::SPECIFICATION_INSERT], $this->resolveTable($this->table, $platform, $driver, $parameterContainer), implode(', ', $columns), implode('), (', $values)); }