381 lines
8.5 KiB
PHP
381 lines
8.5 KiB
PHP
<?php
|
|
/**
|
|
* @package FrameworkOnFramework
|
|
* @subpackage database
|
|
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
|
|
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
|
*
|
|
* This file is adapted from the Joomla! Platform. It is used to iterate a database cursor returning F0FTable objects
|
|
* instead of plain stdClass objects
|
|
*/
|
|
|
|
// Protect from unauthorized access
|
|
defined('F0F_INCLUDED') or die;
|
|
|
|
/**
|
|
* Query Building Class.
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
class F0FDatabaseQuerySqlsrv extends F0FDatabaseQuery implements F0FDatabaseQueryLimitable
|
|
{
|
|
/**
|
|
* The character(s) used to quote SQL statement names such as table names or field names,
|
|
* etc. The child classes should define this as necessary. If a single character string the
|
|
* same character is used for both sides of the quoted name, else the first character will be
|
|
* used for the opening quote and the second for the closing quote.
|
|
*
|
|
* @var string
|
|
* @since 11.1
|
|
*/
|
|
protected $name_quotes = '`';
|
|
|
|
/**
|
|
* The null or zero representation of a timestamp for the database driver. This should be
|
|
* defined in child classes to hold the appropriate value for the engine.
|
|
*
|
|
* @var string
|
|
* @since 11.1
|
|
*/
|
|
protected $null_date = '1900-01-01 00:00:00';
|
|
|
|
/**
|
|
* @var integer The affected row limit for the current SQL statement.
|
|
* @since 3.2
|
|
*/
|
|
protected $limit = 0;
|
|
|
|
/**
|
|
* @var integer The affected row offset to apply for the current SQL statement.
|
|
* @since 3.2
|
|
*/
|
|
protected $offset = 0;
|
|
|
|
/**
|
|
* Magic function to convert the query to a string.
|
|
*
|
|
* @return string The completed query.
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function __toString()
|
|
{
|
|
$query = '';
|
|
|
|
switch ($this->type)
|
|
{
|
|
case 'select':
|
|
$query .= (string) $this->select;
|
|
$query .= (string) $this->from;
|
|
|
|
if ($this->join)
|
|
{
|
|
// Special case for joins
|
|
foreach ($this->join as $join)
|
|
{
|
|
$query .= (string) $join;
|
|
}
|
|
}
|
|
|
|
if ($this->where)
|
|
{
|
|
$query .= (string) $this->where;
|
|
}
|
|
|
|
if ($this->group)
|
|
{
|
|
$query .= (string) $this->group;
|
|
}
|
|
|
|
if ($this->order)
|
|
{
|
|
$query .= (string) $this->order;
|
|
}
|
|
|
|
if ($this->having)
|
|
{
|
|
$query .= (string) $this->having;
|
|
}
|
|
|
|
if ($this instanceof F0FDatabaseQueryLimitable && ($this->limit > 0 || $this->offset > 0))
|
|
{
|
|
$query = $this->processLimit($query, $this->limit, $this->offset);
|
|
}
|
|
|
|
break;
|
|
|
|
case 'insert':
|
|
$query .= (string) $this->insert;
|
|
|
|
// Set method
|
|
if ($this->set)
|
|
{
|
|
$query .= (string) $this->set;
|
|
}
|
|
// Columns-Values method
|
|
elseif ($this->values)
|
|
{
|
|
if ($this->columns)
|
|
{
|
|
$query .= (string) $this->columns;
|
|
}
|
|
|
|
$elements = $this->insert->getElements();
|
|
$tableName = array_shift($elements);
|
|
|
|
$query .= 'VALUES ';
|
|
$query .= (string) $this->values;
|
|
|
|
if ($this->autoIncrementField)
|
|
{
|
|
$query = 'SET IDENTITY_INSERT ' . $tableName . ' ON;' . $query . 'SET IDENTITY_INSERT ' . $tableName . ' OFF;';
|
|
}
|
|
|
|
if ($this->where)
|
|
{
|
|
$query .= (string) $this->where;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case 'delete':
|
|
$query .= (string) $this->delete;
|
|
$query .= (string) $this->from;
|
|
|
|
if ($this->join)
|
|
{
|
|
// Special case for joins
|
|
foreach ($this->join as $join)
|
|
{
|
|
$query .= (string) $join;
|
|
}
|
|
}
|
|
|
|
if ($this->where)
|
|
{
|
|
$query .= (string) $this->where;
|
|
}
|
|
|
|
if ($this->order)
|
|
{
|
|
$query .= (string) $this->order;
|
|
}
|
|
|
|
break;
|
|
|
|
case 'update':
|
|
$query .= (string) $this->update;
|
|
|
|
if ($this->join)
|
|
{
|
|
// Special case for joins
|
|
foreach ($this->join as $join)
|
|
{
|
|
$query .= (string) $join;
|
|
}
|
|
}
|
|
|
|
$query .= (string) $this->set;
|
|
|
|
if ($this->where)
|
|
{
|
|
$query .= (string) $this->where;
|
|
}
|
|
|
|
if ($this->order)
|
|
{
|
|
$query .= (string) $this->order;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
$query = parent::__toString();
|
|
break;
|
|
}
|
|
|
|
return $query;
|
|
}
|
|
|
|
/**
|
|
* Casts a value to a char.
|
|
*
|
|
* Ensure that the value is properly quoted before passing to the method.
|
|
*
|
|
* @param string $value The value to cast as a char.
|
|
*
|
|
* @return string Returns the cast value.
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function castAsChar($value)
|
|
{
|
|
return 'CAST(' . $value . ' as NVARCHAR(10))';
|
|
}
|
|
|
|
/**
|
|
* Gets the function to determine the length of a character string.
|
|
*
|
|
* @param string $field A value.
|
|
* @param string $operator Comparison operator between charLength integer value and $condition
|
|
* @param string $condition Integer value to compare charLength with.
|
|
*
|
|
* @return string The required char length call.
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function charLength($field, $operator = null, $condition = null)
|
|
{
|
|
return 'DATALENGTH(' . $field . ')' . (isset($operator) && isset($condition) ? ' ' . $operator . ' ' . $condition : '');
|
|
}
|
|
|
|
/**
|
|
* Concatenates an array of column names or values.
|
|
*
|
|
* @param array $values An array of values to concatenate.
|
|
* @param string $separator As separator to place between each value.
|
|
*
|
|
* @return string The concatenated values.
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function concatenate($values, $separator = null)
|
|
{
|
|
if ($separator)
|
|
{
|
|
return '(' . implode('+' . $this->quote($separator) . '+', $values) . ')';
|
|
}
|
|
else
|
|
{
|
|
return '(' . implode('+', $values) . ')';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the current date and time.
|
|
*
|
|
* @return string
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function currentTimestamp()
|
|
{
|
|
return 'GETDATE()';
|
|
}
|
|
|
|
/**
|
|
* Get the length of a string in bytes.
|
|
*
|
|
* @param string $value The string to measure.
|
|
*
|
|
* @return integer
|
|
*
|
|
* @since 11.1
|
|
*/
|
|
public function length($value)
|
|
{
|
|
return 'LEN(' . $value . ')';
|
|
}
|
|
|
|
/**
|
|
* Add to the current date and time.
|
|
* Usage:
|
|
* $query->select($query->dateAdd());
|
|
* Prefixing the interval with a - (negative sign) will cause subtraction to be used.
|
|
*
|
|
* @param datetime $date The date to add to; type may be time or datetime.
|
|
* @param string $interval The string representation of the appropriate number of units
|
|
* @param string $datePart The part of the date to perform the addition on
|
|
*
|
|
* @return string The string with the appropriate sql for addition of dates
|
|
*
|
|
* @since 13.1
|
|
* @note Not all drivers support all units.
|
|
* @link http://msdn.microsoft.com/en-us/library/ms186819.aspx for more information
|
|
*/
|
|
public function dateAdd($date, $interval, $datePart)
|
|
{
|
|
return "DATEADD('" . $datePart . "', '" . $interval . "', '" . $date . "'" . ')';
|
|
}
|
|
|
|
/**
|
|
* Method to modify a query already in string format with the needed
|
|
* additions to make the query limited to a particular number of
|
|
* results, or start at a particular offset.
|
|
*
|
|
* @param string $query The query in string format
|
|
* @param integer $limit The limit for the result set
|
|
* @param integer $offset The offset for the result set
|
|
*
|
|
* @return string
|
|
*
|
|
* @since 12.1
|
|
*/
|
|
public function processLimit($query, $limit, $offset = 0)
|
|
{
|
|
if ($limit == 0 && $offset == 0)
|
|
{
|
|
return $query;
|
|
}
|
|
|
|
$start = $offset + 1;
|
|
$end = $offset + $limit;
|
|
|
|
$orderBy = stristr($query, 'ORDER BY');
|
|
|
|
if (is_null($orderBy) || empty($orderBy))
|
|
{
|
|
$orderBy = 'ORDER BY (select 0)';
|
|
}
|
|
|
|
$query = str_ireplace($orderBy, '', $query);
|
|
|
|
$rowNumberText = ', ROW_NUMBER() OVER (' . $orderBy . ') AS RowNumber FROM ';
|
|
|
|
$query = preg_replace('/\sFROM\s/i', $rowNumberText, $query, 1);
|
|
$query = 'SELECT * FROM (' . $query . ') A WHERE A.RowNumber BETWEEN ' . $start . ' AND ' . $end;
|
|
|
|
return $query;
|
|
}
|
|
|
|
/**
|
|
* Sets the offset and limit for the result set, if the database driver supports it.
|
|
*
|
|
* Usage:
|
|
* $query->setLimit(100, 0); (retrieve 100 rows, starting at first record)
|
|
* $query->setLimit(50, 50); (retrieve 50 rows, starting at 50th record)
|
|
*
|
|
* @param integer $limit The limit for the result set
|
|
* @param integer $offset The offset for the result set
|
|
*
|
|
* @return F0FDatabaseQuery Returns this object to allow chaining.
|
|
*
|
|
* @since 12.1
|
|
*/
|
|
public function setLimit($limit = 0, $offset = 0)
|
|
{
|
|
$this->limit = (int) $limit;
|
|
$this->offset = (int) $offset;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Return correct rand() function for MSSQL.
|
|
*
|
|
* Ensure that the rand() function is MSSQL compatible.
|
|
*
|
|
* Usage:
|
|
* $query->Rand();
|
|
*
|
|
* @return string The correct rand function.
|
|
*
|
|
* @since 3.5
|
|
*/
|
|
public function Rand()
|
|
{
|
|
return ' NEWID() ';
|
|
}
|
|
}
|