mirror of
https://github.com/silverstripe/silverstripe-mssql
synced 2024-10-22 08:05:53 +02:00
MINOR: MSSQL stub function created for Postgres-specific functionality
This commit is contained in:
parent
c104222019
commit
7ea6652e56
@ -1,69 +1,69 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Microsoft SQL Server 2008+ connector class.
|
* Microsoft SQL Server 2008+ connector class.
|
||||||
*
|
*
|
||||||
* <h2>Connecting using Windows</h2>
|
* <h2>Connecting using Windows</h2>
|
||||||
*
|
*
|
||||||
* If you've got your website running on Windows, it's highly recommended you
|
* If you've got your website running on Windows, it's highly recommended you
|
||||||
* use Microsoft SQL Server Driver for PHP "sqlsrv".
|
* use Microsoft SQL Server Driver for PHP "sqlsrv".
|
||||||
*
|
*
|
||||||
* A complete guide to installing a Windows IIS + PHP + SQL Server web stack can be
|
* A complete guide to installing a Windows IIS + PHP + SQL Server web stack can be
|
||||||
* found here: http://doc.silverstripe.org/installation-on-windows-server-manual-iis
|
* found here: http://doc.silverstripe.org/installation-on-windows-server-manual-iis
|
||||||
*
|
*
|
||||||
* @see http://sqlsrvphp.codeplex.com/
|
* @see http://sqlsrvphp.codeplex.com/
|
||||||
*
|
*
|
||||||
* <h2>Connecting using Linux or Mac OS X</h2>
|
* <h2>Connecting using Linux or Mac OS X</h2>
|
||||||
*
|
*
|
||||||
* The following commands assume you used the default package manager
|
* The following commands assume you used the default package manager
|
||||||
* to install PHP with the operating system.
|
* to install PHP with the operating system.
|
||||||
*
|
*
|
||||||
* Debian, and Ubuntu:
|
* Debian, and Ubuntu:
|
||||||
* <code>apt-get install php5-sybase</code>
|
* <code>apt-get install php5-sybase</code>
|
||||||
*
|
*
|
||||||
* Fedora, CentOS and RedHat:
|
* Fedora, CentOS and RedHat:
|
||||||
* <code>yum install php-mssql</code>
|
* <code>yum install php-mssql</code>
|
||||||
*
|
*
|
||||||
* Mac OS X (MacPorts):
|
* Mac OS X (MacPorts):
|
||||||
* <code>port install php5-mssql</code>
|
* <code>port install php5-mssql</code>
|
||||||
*
|
*
|
||||||
* These packages will install the mssql extension for PHP, as well
|
* These packages will install the mssql extension for PHP, as well
|
||||||
* as FreeTDS, which will let you connect to SQL Server.
|
* as FreeTDS, which will let you connect to SQL Server.
|
||||||
*
|
*
|
||||||
* More information available in the SilverStripe developer wiki:
|
* More information available in the SilverStripe developer wiki:
|
||||||
* @see http://doc.silverstripe.org/modules:mssql
|
* @see http://doc.silverstripe.org/modules:mssql
|
||||||
* @see http://doc.silverstripe.org/installation-on-windows-server-manual-iis
|
* @see http://doc.silverstripe.org/installation-on-windows-server-manual-iis
|
||||||
*
|
*
|
||||||
* References:
|
* References:
|
||||||
* @see http://freetds.org
|
* @see http://freetds.org
|
||||||
*
|
*
|
||||||
* @package mssql
|
* @package mssql
|
||||||
*/
|
*/
|
||||||
class MSSQLDatabase extends SS_Database {
|
class MSSQLDatabase extends SS_Database {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection to the DBMS.
|
* Connection to the DBMS.
|
||||||
* @var resource
|
* @var resource
|
||||||
*/
|
*/
|
||||||
protected $dbConn;
|
protected $dbConn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if we are connected to a database.
|
* True if we are connected to a database.
|
||||||
* @var boolean
|
* @var boolean
|
||||||
*/
|
*/
|
||||||
protected $active;
|
protected $active;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the database.
|
* The name of the database.
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $database;
|
protected $database;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true, use the mssql_... functions.
|
* If true, use the mssql_... functions.
|
||||||
* If false use the sqlsrv_... functions
|
* If false use the sqlsrv_... functions
|
||||||
*/
|
*/
|
||||||
protected $mssql = null;
|
protected $mssql = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the affected rows of the last query.
|
* Stores the affected rows of the last query.
|
||||||
* Used by sqlsrv functions only, as sqlsrv_rows_affected
|
* Used by sqlsrv functions only, as sqlsrv_rows_affected
|
||||||
@ -79,17 +79,17 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
/**
|
/**
|
||||||
* Transactions will work with FreeTDS, but not entirely with sqlsrv driver on Windows with MARS enabled.
|
* Transactions will work with FreeTDS, but not entirely with sqlsrv driver on Windows with MARS enabled.
|
||||||
* TODO:
|
* TODO:
|
||||||
* - after the test fails with open transaction, the transaction should be rolled back,
|
* - after the test fails with open transaction, the transaction should be rolled back,
|
||||||
* otherwise other tests will break claiming that transaction is still open.
|
* otherwise other tests will break claiming that transaction is still open.
|
||||||
* - figure out SAVEPOINTS
|
* - figure out SAVEPOINTS
|
||||||
* - READ ONLY transactions
|
* - READ ONLY transactions
|
||||||
*/
|
*/
|
||||||
protected $supportsTransactions = true;
|
protected $supportsTransactions = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cached flag to determine if full-text is enabled. This is set by
|
* Cached flag to determine if full-text is enabled. This is set by
|
||||||
* {@link MSSQLDatabase::fullTextEnabled()}
|
* {@link MSSQLDatabase::fullTextEnabled()}
|
||||||
*
|
*
|
||||||
* @var boolean
|
* @var boolean
|
||||||
*/
|
*/
|
||||||
protected $fullTextEnabled = null;
|
protected $fullTextEnabled = null;
|
||||||
@ -112,7 +112,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
public static function set_collation($collation) {
|
public static function set_collation($collation) {
|
||||||
self::$collation = $collation;
|
self::$collation = $collation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to a MS SQL database.
|
* Connect to a MS SQL database.
|
||||||
* @param array $parameters An map of parameters, which should include:
|
* @param array $parameters An map of parameters, which should include:
|
||||||
@ -163,7 +163,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$this->query('SET TEXTSIZE 2147483647');
|
$this->query('SET TEXTSIZE 2147483647');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct() {
|
public function __destruct() {
|
||||||
if(is_resource($this->dbConn)) {
|
if(is_resource($this->dbConn)) {
|
||||||
if($this->mssql) {
|
if($this->mssql) {
|
||||||
@ -173,11 +173,11 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the current SQL Server version has full-text
|
* Checks whether the current SQL Server version has full-text
|
||||||
* support installed and full-text is enabled for this database.
|
* support installed and full-text is enabled for this database.
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function fullTextEnabled() {
|
public function fullTextEnabled() {
|
||||||
@ -192,7 +192,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
}
|
}
|
||||||
return $this->fullTextEnabled;
|
return $this->fullTextEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw a database error
|
* Throw a database error
|
||||||
*/
|
*/
|
||||||
@ -205,18 +205,18 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
}
|
}
|
||||||
$message .= ": \n" . implode("; ",$errorMessages);
|
$message .= ": \n" . implode("; ",$errorMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::databaseError($message, $errorLevel);
|
return parent::databaseError($message, $errorLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will set up the full text search capabilities.
|
* This will set up the full text search capabilities.
|
||||||
*/
|
*/
|
||||||
function createFullTextCatalog() {
|
function createFullTextCatalog() {
|
||||||
$result = $this->query("SELECT name FROM sys.fulltext_catalogs WHERE name = 'ftCatalog';")->value();
|
$result = $this->query("SELECT name FROM sys.fulltext_catalogs WHERE name = 'ftCatalog';")->value();
|
||||||
if(!$result) $this->query("CREATE FULLTEXT CATALOG ftCatalog AS DEFAULT;");
|
if(!$result) $this->query("CREATE FULLTEXT CATALOG ftCatalog AS DEFAULT;");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sleep until the catalog has been fully rebuilt. This is a busy wait designed for situations
|
* Sleep until the catalog has been fully rebuilt. This is a busy wait designed for situations
|
||||||
* when you need to be sure the index is up to date - for example in unit tests.
|
* when you need to be sure the index is up to date - for example in unit tests.
|
||||||
@ -229,12 +229,12 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
function waitUntilIndexingFinished($maxWaitingTime = 15) {
|
function waitUntilIndexingFinished($maxWaitingTime = 15) {
|
||||||
if($this->fullTextEnabled()) {
|
if($this->fullTextEnabled()) {
|
||||||
$this->query("EXEC sp_fulltext_catalog 'ftCatalog', 'Rebuild';");
|
$this->query("EXEC sp_fulltext_catalog 'ftCatalog', 'Rebuild';");
|
||||||
|
|
||||||
// Busy wait until it's done updating, but no longer than 15 seconds.
|
// Busy wait until it's done updating, but no longer than 15 seconds.
|
||||||
$start = time();
|
$start = time();
|
||||||
while(time()-$start<$maxWaitingTime) {
|
while(time()-$start<$maxWaitingTime) {
|
||||||
$status = $this->query("EXEC sp_help_fulltext_catalogs 'ftCatalog';")->first();
|
$status = $this->query("EXEC sp_help_fulltext_catalogs 'ftCatalog';")->first();
|
||||||
|
|
||||||
if (isset($status['STATUS']) && $status['STATUS']==0) {
|
if (isset($status['STATUS']) && $status['STATUS']==0) {
|
||||||
// Idle!
|
// Idle!
|
||||||
break;
|
break;
|
||||||
@ -243,14 +243,14 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Not implemented, needed for PDO
|
* Not implemented, needed for PDO
|
||||||
*/
|
*/
|
||||||
public function getConnect($parameters) {
|
public function getConnect($parameters) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this database supports collations
|
* Returns true if this database supports collations
|
||||||
* @return boolean
|
* @return boolean
|
||||||
@ -258,7 +258,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
public function supportsCollations() {
|
public function supportsCollations() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the version of MSSQL.
|
* Get the version of MSSQL.
|
||||||
* @return string
|
* @return string
|
||||||
@ -266,7 +266,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
public function getVersion() {
|
public function getVersion() {
|
||||||
return trim($this->query("SELECT CONVERT(char(15), SERVERPROPERTY('ProductVersion'))")->value());
|
return trim($this->query("SELECT CONVERT(char(15), SERVERPROPERTY('ProductVersion'))")->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the database server, namely mssql.
|
* Get the database server, namely mssql.
|
||||||
* @return string
|
* @return string
|
||||||
@ -274,14 +274,14 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
public function getDatabaseServer() {
|
public function getDatabaseServer() {
|
||||||
return "mssql";
|
return "mssql";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function query($sql, $errorLevel = E_USER_ERROR) {
|
public function query($sql, $errorLevel = E_USER_ERROR) {
|
||||||
if(isset($_REQUEST['previewwrite']) && in_array(strtolower(substr($sql,0,strpos($sql,' '))), array('insert','update','delete','replace'))) {
|
if(isset($_REQUEST['previewwrite']) && in_array(strtolower(substr($sql,0,strpos($sql,' '))), array('insert','update','delete','replace'))) {
|
||||||
Debug::message("Will execute: $sql");
|
Debug::message("Will execute: $sql");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isset($_REQUEST['showqueries'])) {
|
if(isset($_REQUEST['showqueries'])) {
|
||||||
$starttime = microtime(true);
|
$starttime = microtime(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
if(!$handle && $errorLevel) $this->databaseError("Couldn't run query ($error): $sql", $errorLevel);
|
if(!$handle && $errorLevel) $this->databaseError("Couldn't run query ($error): $sql", $errorLevel);
|
||||||
return new MSSQLQuery($this, $handle, $this->mssql);
|
return new MSSQLQuery($this, $handle, $this->mssql);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getGeneratedID($table) {
|
public function getGeneratedID($table) {
|
||||||
return $this->query("SELECT IDENT_CURRENT('$table')")->value();
|
return $this->query("SELECT IDENT_CURRENT('$table')")->value();
|
||||||
}
|
}
|
||||||
@ -322,8 +322,8 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
* @param string $tableName Name of table with primary key column "ID"
|
* @param string $tableName Name of table with primary key column "ID"
|
||||||
* @return string Internal identifier for primary key
|
* @return string Internal identifier for primary key
|
||||||
*/
|
*/
|
||||||
function getPrimaryKey($tableName) {
|
function getPrimaryKey($tableName){
|
||||||
$indexes = DB::query("EXEC sp_helpindex '$tableName';");
|
$indexes=DB::query("EXEC sp_helpindex '$tableName';");
|
||||||
$indexName = '';
|
$indexName = '';
|
||||||
foreach($indexes as $index) {
|
foreach($indexes as $index) {
|
||||||
if($index['index_keys'] == 'ID') {
|
if($index['index_keys'] == 'ID') {
|
||||||
@ -348,11 +348,11 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
TABLE_NAME = '$tableName'
|
TABLE_NAME = '$tableName'
|
||||||
")->value();
|
")->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isActive() {
|
public function isActive() {
|
||||||
return $this->active ? true : false;
|
return $this->active ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the database that is currently selected.
|
* Create the database that is currently selected.
|
||||||
*/
|
*/
|
||||||
@ -387,18 +387,18 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
public function currentDatabase() {
|
public function currentDatabase() {
|
||||||
return $this->database;
|
return $this->database;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switches to the given database.
|
* Switches to the given database.
|
||||||
*
|
*
|
||||||
* If the database doesn't exist, you should call
|
* If the database doesn't exist, you should call
|
||||||
* createDatabase() after calling selectDatabase()
|
* createDatabase() after calling selectDatabase()
|
||||||
*
|
*
|
||||||
* @param string $dbname The database name to switch to
|
* @param string $dbname The database name to switch to
|
||||||
*/
|
*/
|
||||||
public function selectDatabase($dbname) {
|
public function selectDatabase($dbname) {
|
||||||
$this->database = $dbname;
|
$this->database = $dbname;
|
||||||
|
|
||||||
if($this->databaseExists($this->database)) {
|
if($this->databaseExists($this->database)) {
|
||||||
if($this->mssql) {
|
if($this->mssql) {
|
||||||
if(mssql_select_db($this->database, $this->dbConn)) {
|
if(mssql_select_db($this->database, $this->dbConn)) {
|
||||||
@ -409,7 +409,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$this->active = true;
|
$this->active = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->tableList = $this->fieldList = $this->indexList = $this->fullTextEnabled = null;
|
$this->tableList = $this->fieldList = $this->indexList = $this->fullTextEnabled = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,9 +422,9 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$databases = $this->allDatabaseNames();
|
$databases = $this->allDatabaseNames();
|
||||||
foreach($databases as $dbname) {
|
foreach($databases as $dbname) {
|
||||||
if($dbname == $name) return true;
|
if($dbname == $name) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return all databases names from the server.
|
* Return all databases names from the server.
|
||||||
@ -447,26 +447,26 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
public function createTable($tableName, $fields = null, $indexes = null, $options = null, $advancedOptions = null) {
|
public function createTable($tableName, $fields = null, $indexes = null, $options = null, $advancedOptions = null) {
|
||||||
$fieldSchemas = $indexSchemas = "";
|
$fieldSchemas = $indexSchemas = "";
|
||||||
if($fields) foreach($fields as $k => $v) $fieldSchemas .= "\"$k\" $v,\n";
|
if($fields) foreach($fields as $k => $v) $fieldSchemas .= "\"$k\" $v,\n";
|
||||||
|
|
||||||
// Temporary tables start with "#" in MSSQL-land
|
// Temporary tables start with "#" in MSSQL-land
|
||||||
if(!empty($options['temporary'])) {
|
if(!empty($options['temporary'])) {
|
||||||
// Randomize the temp table name to avoid conflicts in the tempdb table which derived databases share
|
// Randomize the temp table name to avoid conflicts in the tempdb table which derived databases share
|
||||||
$tableName = "#$tableName" . '-' . rand(1000000, 9999999);
|
$tableName = "#$tableName" . '-' . rand(1000000, 9999999);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->query("CREATE TABLE \"$tableName\" (
|
$this->query("CREATE TABLE \"$tableName\" (
|
||||||
$fieldSchemas
|
$fieldSchemas
|
||||||
primary key (\"ID\")
|
primary key (\"ID\")
|
||||||
);");
|
);");
|
||||||
|
|
||||||
//we need to generate indexes like this: CREATE INDEX IX_vault_to_export ON vault (to_export);
|
//we need to generate indexes like this: CREATE INDEX IX_vault_to_export ON vault (to_export);
|
||||||
//This needs to be done AFTER the table creation, so we can set up the fulltext indexes correctly
|
//This needs to be done AFTER the table creation, so we can set up the fulltext indexes correctly
|
||||||
if($indexes) foreach($indexes as $k => $v) {
|
if($indexes) foreach($indexes as $k => $v) {
|
||||||
$indexSchemas .= $this->getIndexSqlDefinition($tableName, $k, $v) . "\n";
|
$indexSchemas .= $this->getIndexSqlDefinition($tableName, $k, $v) . "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if($indexSchemas) $this->query($indexSchemas);
|
if($indexSchemas) $this->query($indexSchemas);
|
||||||
|
|
||||||
return $tableName;
|
return $tableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,7 +482,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$fieldSchemas = $indexSchemas = "";
|
$fieldSchemas = $indexSchemas = "";
|
||||||
$alterList = array();
|
$alterList = array();
|
||||||
$indexList = $this->indexList($tableName);
|
$indexList = $this->indexList($tableName);
|
||||||
|
|
||||||
if($newFields) foreach($newFields as $k => $v) $alterList[] .= "ALTER TABLE \"$tableName\" ADD \"$k\" $v";
|
if($newFields) foreach($newFields as $k => $v) $alterList[] .= "ALTER TABLE \"$tableName\" ADD \"$k\" $v";
|
||||||
|
|
||||||
if($alteredFields) {
|
if($alteredFields) {
|
||||||
@ -496,7 +496,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
if($val != '') $alterList[] .= $val;
|
if($val != '') $alterList[] .= $val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($alteredIndexes) foreach($alteredIndexes as $k => $v) $alterList[] .= $this->getIndexSqlDefinition($tableName, $k, $v);
|
if($alteredIndexes) foreach($alteredIndexes as $k => $v) $alterList[] .= $this->getIndexSqlDefinition($tableName, $k, $v);
|
||||||
if($newIndexes) foreach($newIndexes as $k =>$v) $alterList[] .= $this->getIndexSqlDefinition($tableName, $k, $v);
|
if($newIndexes) foreach($newIndexes as $k =>$v) $alterList[] .= $this->getIndexSqlDefinition($tableName, $k, $v);
|
||||||
|
|
||||||
@ -568,7 +568,8 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
and parent_obj= OBJECT_ID('$tableName')
|
and parent_obj= OBJECT_ID('$tableName')
|
||||||
and c.name = '$colName'")->value();
|
and c.name = '$colName'")->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get enum values from a constraint check clause.
|
* Get enum values from a constraint check clause.
|
||||||
* @param string $clause Check clause to parse values from
|
* @param string $clause Check clause to parse values from
|
||||||
@ -581,14 +582,15 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$bits = preg_split('/ *= */', $segment);
|
$bits = preg_split('/ *= */', $segment);
|
||||||
for($i = 1; $i < sizeof($bits); $i += 2) {
|
for($i = 1; $i < sizeof($bits); $i += 2) {
|
||||||
array_unshift($constraints, substr(rtrim($bits[$i], ')'), 1, -1));
|
array_unshift($constraints, substr(rtrim($bits[$i], ')'), 1, -1));
|
||||||
}
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $constraints;
|
return $constraints;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates an ALTER expression for a column in MS SQL
|
* Creates an ALTER expression for a column in MS SQL
|
||||||
*
|
*
|
||||||
* @param $tableName Name of the table to be altered
|
* @param $tableName Name of the table to be altered
|
||||||
* @param $colName Name of the column to be altered
|
* @param $colName Name of the column to be altered
|
||||||
* @param $colSpec String which contains conditions for a column
|
* @param $colSpec String which contains conditions for a column
|
||||||
@ -602,32 +604,32 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$pattern = '/^([\w()]+)\s?((?:not\s)?null)?\s?(default\s[\w\']+)?\s?(check\s?[\w()\'",\s]+)?$/i';
|
$pattern = '/^([\w()]+)\s?((?:not\s)?null)?\s?(default\s[\w\']+)?\s?(check\s?[\w()\'",\s]+)?$/i';
|
||||||
$matches=Array();
|
$matches=Array();
|
||||||
preg_match($pattern, $colSpec, $matches);
|
preg_match($pattern, $colSpec, $matches);
|
||||||
|
|
||||||
// drop the index if it exists
|
// drop the index if it exists
|
||||||
$alterCol='';
|
$alterCol='';
|
||||||
$indexName = isset($indexList[$colName]['indexname']) ? $indexList[$colName]['indexname'] : null;
|
$indexName = isset($indexList[$colName]['indexname']) ? $indexList[$colName]['indexname'] : null;
|
||||||
if($indexName && $colName != 'ID') {
|
if($indexName && $colName != 'ID') {
|
||||||
$alterCol = "\nDROP INDEX \"$indexName\" ON \"$tableName\";";
|
$alterCol = "\nDROP INDEX \"$indexName\" ON \"$tableName\";";
|
||||||
}
|
}
|
||||||
|
|
||||||
$prefix="ALTER TABLE \"" . $tableName . "\" ";
|
$prefix="ALTER TABLE \"" . $tableName . "\" ";
|
||||||
|
|
||||||
// Remove the old default prior to adjusting the column.
|
// Remove the old default prior to adjusting the column.
|
||||||
if($defaultConstraintName = $this->defaultConstraintName($tableName, $colName)) {
|
if($defaultConstraintName = $this->defaultConstraintName($tableName, $colName)) {
|
||||||
$alterCol .= ";\n$prefix DROP CONSTRAINT \"$defaultConstraintName\"";
|
$alterCol .= ";\n$prefix DROP CONSTRAINT \"$defaultConstraintName\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isset($matches[1])) {
|
if(isset($matches[1])) {
|
||||||
//We will prevent any changes being made to the ID column. Primary key indexes will have a fit if we do anything here.
|
//We will prevent any changes being made to the ID column. Primary key indexes will have a fit if we do anything here.
|
||||||
if($colName!='ID'){
|
if($colName!='ID'){
|
||||||
$alterCol .= ";\n$prefix ALTER COLUMN \"$colName\" $matches[1]";
|
$alterCol .= ";\n$prefix ALTER COLUMN \"$colName\" $matches[1]";
|
||||||
|
|
||||||
// SET null / not null
|
// SET null / not null
|
||||||
if(!empty($matches[2])) $alterCol .= ";\n$prefix ALTER COLUMN \"$colName\" $matches[1] $matches[2]";
|
if(!empty($matches[2])) $alterCol .= ";\n$prefix ALTER COLUMN \"$colName\" $matches[1] $matches[2]";
|
||||||
|
|
||||||
// Add a default back
|
// Add a default back
|
||||||
if(!empty($matches[3])) $alterCol .= ";\n$prefix ADD $matches[3] FOR \"$colName\"";
|
if(!empty($matches[3])) $alterCol .= ";\n$prefix ADD $matches[3] FOR \"$colName\"";
|
||||||
|
|
||||||
// SET check constraint (The constraint HAS to be dropped)
|
// SET check constraint (The constraint HAS to be dropped)
|
||||||
if(!empty($matches[4])) {
|
if(!empty($matches[4])) {
|
||||||
$constraint = $this->getConstraintName($tableName, $colName);
|
$constraint = $this->getConstraintName($tableName, $colName);
|
||||||
@ -637,31 +639,33 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
|
|
||||||
//NOTE: 'with nocheck' seems to solve a few problems I've been having for modifying existing tables.
|
//NOTE: 'with nocheck' seems to solve a few problems I've been having for modifying existing tables.
|
||||||
$alterCol .= ";\n$prefix WITH NOCHECK ADD CONSTRAINT \"{$tableName}_{$colName}_check\" $matches[4]";
|
$alterCol .= ";\n$prefix WITH NOCHECK ADD CONSTRAINT \"{$tableName}_{$colName}_check\" $matches[4]";
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return isset($alterCol) ? $alterCol : '';
|
return isset($alterCol) ? $alterCol : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renameTable($oldTableName, $newTableName) {
|
public function renameTable($oldTableName, $newTableName) {
|
||||||
$this->query("EXEC sp_rename \"$oldTableName\", \"$newTableName\"");
|
$this->query("EXEC sp_rename \"$oldTableName\", \"$newTableName\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks a table's integrity and repairs it if necessary.
|
* Checks a table's integrity and repairs it if necessary.
|
||||||
* NOTE: MSSQL does not appear to support any vacuum or optimise commands
|
* NOTE: MSSQL does not appear to support any vacuum or optimise commands
|
||||||
*
|
*
|
||||||
* @var string $tableName The name of the table.
|
* @var string $tableName The name of the table.
|
||||||
* @return boolean Return true if the table has integrity after the method is complete.
|
* @return boolean Return true if the table has integrity after the method is complete.
|
||||||
*/
|
*/
|
||||||
public function checkAndRepairTable($tableName) {
|
public function checkAndRepairTable($tableName) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createField($tableName, $fieldName, $fieldSpec) {
|
public function createField($tableName, $fieldName, $fieldSpec) {
|
||||||
$this->query("ALTER TABLE \"$tableName\" ADD \"$fieldName\" $fieldSpec");
|
$this->query("ALTER TABLE \"$tableName\" ADD \"$fieldName\" $fieldSpec");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the database type of the given field.
|
* Change the database type of the given field.
|
||||||
* @param string $tableName The name of the tbale the field is in.
|
* @param string $tableName The name of the tbale the field is in.
|
||||||
@ -674,14 +678,14 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the database column name of the given field.
|
* Change the database column name of the given field.
|
||||||
*
|
*
|
||||||
* @param string $tableName The name of the tbale the field is in.
|
* @param string $tableName The name of the tbale the field is in.
|
||||||
* @param string $oldName The name of the field to change.
|
* @param string $oldName The name of the field to change.
|
||||||
* @param string $newName The new name of the field
|
* @param string $newName The new name of the field
|
||||||
*/
|
*/
|
||||||
public function renameField($tableName, $oldName, $newName) {
|
public function renameField($tableName, $oldName, $newName) {
|
||||||
$this->query("EXEC sp_rename @objname = '$tableName.$oldName', @newname = '$newName', @objtype = 'COLUMN'");
|
$this->query("EXEC sp_rename @objname = '$tableName.$oldName', @newname = '$newName', @objtype = 'COLUMN'");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fieldList($table) {
|
public function fieldList($table) {
|
||||||
//This gets us more information than we need, but I've included it all for the moment....
|
//This gets us more information than we need, but I've included it all for the moment....
|
||||||
@ -697,7 +701,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
foreach($fieldRecords as $record) {
|
foreach($fieldRecords as $record) {
|
||||||
$fields[] = $record;
|
$fields[] = $record;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($fields as $field) {
|
foreach($fields as $field) {
|
||||||
// Update the data_type field to be a complete column definition string for use by
|
// Update the data_type field to be a complete column definition string for use by
|
||||||
// SS_Database::requireField()
|
// SS_Database::requireField()
|
||||||
@ -737,14 +741,14 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$field['data_type'] .= " default $default";
|
$field['data_type'] .= " default $default";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'nvarchar':
|
case 'nvarchar':
|
||||||
case 'varchar':
|
case 'varchar':
|
||||||
//Check to see if there's a constraint attached to this column:
|
//Check to see if there's a constraint attached to this column:
|
||||||
$clause = $this->getConstraintCheckClause($table, $field['column_name']);
|
$clause = $this->getConstraintCheckClause($table, $field['column_name']);
|
||||||
if($clause) {
|
if($clause) {
|
||||||
$constraints = $this->enumValuesFromCheckClause($clause);
|
$constraints = $this->enumValuesFromCheckClause($clause);
|
||||||
$default = substr($field['column_default'], 2, -2);
|
$default=substr($field['column_default'], 2, -2);
|
||||||
$field['data_type'] = $this->enum(array(
|
$field['data_type'] = $this->enum(array(
|
||||||
'default' => $default,
|
'default' => $default,
|
||||||
'name' => $field['column_name'],
|
'name' => $field['column_name'],
|
||||||
@ -772,12 +776,24 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$output[$field['column_name']]=$field;
|
$output[$field['column_name']]=$field;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This is a stub function. Postgres caches the fieldlist results.
|
||||||
|
*
|
||||||
|
* @param string $tableName
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
function clear_cached_fieldlist($tableName=false){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an index on a table.
|
* Create an index on a table.
|
||||||
* @param string $tableName The name of the table.
|
* @param string $tableName The name of the table.
|
||||||
@ -787,7 +803,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
public function createIndex($tableName, $indexName, $indexSpec) {
|
public function createIndex($tableName, $indexName, $indexSpec) {
|
||||||
$this->query($this->getIndexSqlDefinition($tableName, $indexName, $indexSpec));
|
$this->query($this->getIndexSqlDefinition($tableName, $indexName, $indexSpec));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This takes the index spec which has been provided by a class (ie static $indexes = blah blah)
|
* This takes the index spec which has been provided by a class (ie static $indexes = blah blah)
|
||||||
* and turns it into a proper string.
|
* and turns it into a proper string.
|
||||||
@ -806,10 +822,10 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $indexSpec;
|
return $indexSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return SQL for dropping and recreating an index
|
* Return SQL for dropping and recreating an index
|
||||||
*/
|
*/
|
||||||
@ -821,7 +837,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$indexSpec=trim($indexSpec, '()');
|
$indexSpec=trim($indexSpec, '()');
|
||||||
$bits=explode(',', $indexSpec);
|
$bits=explode(',', $indexSpec);
|
||||||
$indexes="\"" . implode("\",\"", $bits) . "\"";
|
$indexes="\"" . implode("\",\"", $bits) . "\"";
|
||||||
|
|
||||||
return "$drop CREATE INDEX $index ON \"" . $tableName . "\" (" . $indexes . ");";
|
return "$drop CREATE INDEX $index ON \"" . $tableName . "\" (" . $indexes . ");";
|
||||||
} else {
|
} else {
|
||||||
//create a type-specific index
|
//create a type-specific index
|
||||||
@ -830,7 +846,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
//Enable full text search.
|
//Enable full text search.
|
||||||
$this->createFullTextCatalog();
|
$this->createFullTextCatalog();
|
||||||
$primary_key = $this->getPrimaryKey($tableName);
|
$primary_key = $this->getPrimaryKey($tableName);
|
||||||
|
|
||||||
$query = '';
|
$query = '';
|
||||||
if($this->fullTextIndexExists($tableName)) {
|
if($this->fullTextIndexExists($tableName)) {
|
||||||
$query .= "\nDROP FULLTEXT INDEX ON \"$tableName\";";
|
$query .= "\nDROP FULLTEXT INDEX ON \"$tableName\";";
|
||||||
@ -839,21 +855,21 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($indexSpec['type'] == 'unique') {
|
if($indexSpec['type'] == 'unique') {
|
||||||
if(!is_array($indexSpec['value'])) $columns = preg_split('/ *, */', trim($indexSpec['value']));
|
if(!is_array($indexSpec['value'])) $columns = preg_split('/ *, */', trim($indexSpec['value']));
|
||||||
else $columns = $indexSpec['value'];
|
else $columns = $indexSpec['value'];
|
||||||
$SQL_columnList = '"' . implode('", "', $columns) . '"';
|
$SQL_columnList = '"' . implode('", "', $columns) . '"';
|
||||||
|
|
||||||
return "$drop CREATE UNIQUE INDEX $index ON \"" . $tableName . "\" ($SQL_columnList);";
|
return "$drop CREATE UNIQUE INDEX $index ON \"" . $tableName . "\" ($SQL_columnList);";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDbSqlDefinition($tableName, $indexName, $indexSpec){
|
function getDbSqlDefinition($tableName, $indexName, $indexSpec){
|
||||||
return $indexName;
|
return $indexName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alter an index on a table.
|
* Alter an index on a table.
|
||||||
* @param string $tableName The name of the table.
|
* @param string $tableName The name of the table.
|
||||||
@ -861,21 +877,21 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
* @param string $indexSpec The specification of the index, see SS_Database::requireIndex() for more details.
|
* @param string $indexSpec The specification of the index, see SS_Database::requireIndex() for more details.
|
||||||
*/
|
*/
|
||||||
public function alterIndex($tableName, $indexName, $indexSpec) {
|
public function alterIndex($tableName, $indexName, $indexSpec) {
|
||||||
$indexSpec = trim($indexSpec);
|
$indexSpec = trim($indexSpec);
|
||||||
if($indexSpec[0] != '(') {
|
if($indexSpec[0] != '(') {
|
||||||
list($indexType, $indexFields) = explode(' ', $indexSpec, 2);
|
list($indexType, $indexFields) = explode(' ',$indexSpec,2);
|
||||||
} else {
|
} else {
|
||||||
$indexFields = $indexSpec;
|
$indexFields = $indexSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$indexType) {
|
if(!$indexType) {
|
||||||
$indexType = "index";
|
$indexType = "index";
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->query("DROP INDEX $indexName ON $tableName;");
|
$this->query("DROP INDEX $indexName ON $tableName;");
|
||||||
$this->query("ALTER TABLE \"$tableName\" ADD $indexType \"$indexName\" $indexFields");
|
$this->query("ALTER TABLE \"$tableName\" ADD $indexType \"$indexName\" $indexFields");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the list of indexes in a table.
|
* Return the list of indexes in a table.
|
||||||
* @param string $table The table name.
|
* @param string $table The table name.
|
||||||
@ -928,14 +944,14 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
}
|
}
|
||||||
return $tables;
|
return $tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty the given table of all contents.
|
* Empty the given table of all contents.
|
||||||
*/
|
*/
|
||||||
public function clearTable($table) {
|
public function clearTable($table) {
|
||||||
$this->query("TRUNCATE TABLE \"$table\"");
|
$this->query("TRUNCATE TABLE \"$table\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the number of rows affected by the previous operation.
|
* Return the number of rows affected by the previous operation.
|
||||||
* @return int
|
* @return int
|
||||||
@ -951,7 +967,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
/**
|
/**
|
||||||
* Return a boolean type-formatted string
|
* Return a boolean type-formatted string
|
||||||
* We use 'bit' so that we can do numeric-based comparisons
|
* We use 'bit' so that we can do numeric-based comparisons
|
||||||
*
|
*
|
||||||
* @params array $values Contains a tokenised list of info about this data type
|
* @params array $values Contains a tokenised list of info about this data type
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -959,20 +975,20 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$default = ($values['default']) ? '1' : '0';
|
$default = ($values['default']) ? '1' : '0';
|
||||||
return 'bit not null default ' . $default;
|
return 'bit not null default ' . $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a date type-formatted string.
|
* Return a date type-formatted string.
|
||||||
*
|
*
|
||||||
* @params array $values Contains a tokenised list of info about this data type
|
* @params array $values Contains a tokenised list of info about this data type
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function date($values) {
|
public function date($values) {
|
||||||
return 'datetime null';
|
return 'datetime null';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a decimal type-formatted string
|
* Return a decimal type-formatted string
|
||||||
*
|
*
|
||||||
* @params array $values Contains a tokenised list of info about this data type
|
* @params array $values Contains a tokenised list of info about this data type
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -983,18 +999,18 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
} else {
|
} else {
|
||||||
$precision = $values['precision'];
|
$precision = $values['precision'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$defaultValue = '0';
|
$defaultValue = '0';
|
||||||
if(isset($values['default']) && is_numeric($values['default'])) {
|
if(isset($values['default']) && is_numeric($values['default'])) {
|
||||||
$defaultValue = $values['default'];
|
$defaultValue = $values['default'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'decimal(' . $precision . ') not null default ' . $defaultValue;
|
return 'decimal(' . $precision . ') not null default ' . $defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a enum type-formatted string
|
* Return a enum type-formatted string
|
||||||
*
|
*
|
||||||
* @params array $values Contains a tokenised list of info about this data type
|
* @params array $values Contains a tokenised list of info about this data type
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -1005,31 +1021,31 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
|
|
||||||
$maxLength = max(array_map('strlen', $values['enums']));
|
$maxLength = max(array_map('strlen', $values['enums']));
|
||||||
|
|
||||||
return "varchar($maxLength) not null default '" . $values['default']
|
return "varchar($maxLength) not null default '" . $values['default']
|
||||||
. "' check(\"" . $values['name'] . "\" in ('" . implode("','", $values['enums'])
|
. "' check(\"" . $values['name'] . "\" in ('" . implode("','", $values['enums'])
|
||||||
. "'))";
|
. "'))";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo Make this work like {@link MySQLDatabase::set()}
|
* @todo Make this work like {@link MySQLDatabase::set()}
|
||||||
*/
|
*/
|
||||||
public function set($values) {
|
public function set($values) {
|
||||||
return $this->enum($values);
|
return $this->enum($values);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a float type-formatted string.
|
* Return a float type-formatted string.
|
||||||
*
|
*
|
||||||
* @params array $values Contains a tokenised list of info about this data type
|
* @params array $values Contains a tokenised list of info about this data type
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function float($values) {
|
public function float($values) {
|
||||||
return 'float not null default ' . $values['default'];
|
return 'float not null default ' . $values['default'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a int type-formatted string
|
* Return a int type-formatted string
|
||||||
*
|
*
|
||||||
* @params array $values Contains a tokenised list of info about this data type
|
* @params array $values Contains a tokenised list of info about this data type
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -1037,21 +1053,21 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
//We'll be using an 8 digit precision to keep it in line with the serial8 datatype for ID columns
|
//We'll be using an 8 digit precision to keep it in line with the serial8 datatype for ID columns
|
||||||
return 'numeric(8) not null default ' . (int) $values['default'];
|
return 'numeric(8) not null default ' . (int) $values['default'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a datetime type-formatted string
|
* Return a datetime type-formatted string
|
||||||
* For MS SQL, we simply return the word 'timestamp', no other parameters are necessary
|
* For MS SQL, we simply return the word 'timestamp', no other parameters are necessary
|
||||||
*
|
*
|
||||||
* @params array $values Contains a tokenised list of info about this data type
|
* @params array $values Contains a tokenised list of info about this data type
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function ss_datetime($values) {
|
public function ss_datetime($values) {
|
||||||
return 'datetime null';
|
return 'datetime null';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a text type-formatted string
|
* Return a text type-formatted string
|
||||||
*
|
*
|
||||||
* @params array $values Contains a tokenised list of info about this data type
|
* @params array $values Contains a tokenised list of info about this data type
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -1059,20 +1075,20 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$collation = self::$collation ? " COLLATE " . self::$collation : "";
|
$collation = self::$collation ? " COLLATE " . self::$collation : "";
|
||||||
return "nvarchar(max)$collation null";
|
return "nvarchar(max)$collation null";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a time type-formatted string.
|
* Return a time type-formatted string.
|
||||||
*
|
*
|
||||||
* @params array $values Contains a tokenised list of info about this data type
|
* @params array $values Contains a tokenised list of info about this data type
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function time($values){
|
public function time($values){
|
||||||
return 'time null';
|
return 'time null';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a varchar type-formatted string
|
* Return a varchar type-formatted string
|
||||||
*
|
*
|
||||||
* @params array $values Contains a tokenised list of info about this data type
|
* @params array $values Contains a tokenised list of info about this data type
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -1080,13 +1096,13 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$collation = self::$collation ? " COLLATE " . self::$collation : "";
|
$collation = self::$collation ? " COLLATE " . self::$collation : "";
|
||||||
return "nvarchar(" . $values['precision'] . ")$collation null";
|
return "nvarchar(" . $values['precision'] . ")$collation null";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a 4 digit numeric type.
|
* Return a 4 digit numeric type.
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function year($values) {
|
public function year($values) {
|
||||||
return 'numeric(4)';
|
return 'numeric(4)';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1104,14 +1120,14 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
else return 'bigint not null';
|
else return 'bigint not null';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the SQL command to get all the tables in this database
|
* Returns the SQL command to get all the tables in this database
|
||||||
*/
|
*/
|
||||||
function allTablesSQL(){
|
function allTablesSQL(){
|
||||||
return "SELECT \"name\" FROM \"sys\".\"tables\";";
|
return "SELECT \"name\" FROM \"sys\".\"tables\";";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this table exists
|
* Returns true if this table exists
|
||||||
* @todo Make a proper implementation
|
* @todo Make a proper implementation
|
||||||
@ -1121,7 +1137,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$value = DB::query("SELECT table_name FROM information_schema.tables WHERE table_name = '$SQL_tableName'")->value();
|
$value = DB::query("SELECT table_name FROM information_schema.tables WHERE table_name = '$SQL_tableName'")->value();
|
||||||
return (bool)$value;
|
return (bool)$value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the values of the given enum field
|
* Returns the values of the given enum field
|
||||||
* NOTE: Experimental; introduced for db-abstraction and may changed before 2.4 is released.
|
* NOTE: Experimental; introduced for db-abstraction and may changed before 2.4 is released.
|
||||||
@ -1144,17 +1160,17 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
function now() {
|
function now() {
|
||||||
return 'CURRENT_TIMESTAMP';
|
return 'CURRENT_TIMESTAMP';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the database-specific version of the random() function
|
* Returns the database-specific version of the random() function
|
||||||
*/
|
*/
|
||||||
function random() {
|
function random(){
|
||||||
return 'RAND()';
|
return 'RAND()';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a lookup table for data types.
|
* This is a lookup table for data types.
|
||||||
*
|
*
|
||||||
* For instance, MSSQL uses 'BIGINT', while MySQL uses 'UNSIGNED'
|
* For instance, MSSQL uses 'BIGINT', while MySQL uses 'UNSIGNED'
|
||||||
* and PostgreSQL uses 'INT'.
|
* and PostgreSQL uses 'INT'.
|
||||||
*/
|
*/
|
||||||
@ -1165,15 +1181,15 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
if(isset($values[$type])) return $values[$type];
|
if(isset($values[$type])) return $values[$type];
|
||||||
else return '';
|
else return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a SQLQuery object into a SQL statement.
|
* Convert a SQLQuery object into a SQL statement.
|
||||||
*/
|
*/
|
||||||
public function sqlQueryToString(SQLQuery $sqlQuery) {
|
public function sqlQueryToString(SQLQuery $sqlQuery) {
|
||||||
if (!$sqlQuery->from) return '';
|
if (!$sqlQuery->from) return '';
|
||||||
|
|
||||||
if($sqlQuery->orderby && strtoupper(trim($sqlQuery->orderby)) == 'RAND()') $sqlQuery->orderby = "NEWID()";
|
if($sqlQuery->orderby && strtoupper(trim($sqlQuery->orderby)) == 'RAND()') $sqlQuery->orderby = "NEWID()";
|
||||||
|
|
||||||
//Get the limit and offset
|
//Get the limit and offset
|
||||||
$limit='';
|
$limit='';
|
||||||
$offset='0';
|
$offset='0';
|
||||||
@ -1181,7 +1197,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$limit=$sqlQuery->limit['limit'];
|
$limit=$sqlQuery->limit['limit'];
|
||||||
if(isset($sqlQuery->limit['start']))
|
if(isset($sqlQuery->limit['start']))
|
||||||
$offset=$sqlQuery->limit['start'];
|
$offset=$sqlQuery->limit['start'];
|
||||||
|
|
||||||
} else if(preg_match('/^([0-9]+) offset ([0-9]+)$/i', trim($sqlQuery->limit), $matches)) {
|
} else if(preg_match('/^([0-9]+) offset ([0-9]+)$/i', trim($sqlQuery->limit), $matches)) {
|
||||||
$limit = $matches[1];
|
$limit = $matches[1];
|
||||||
$offset = $matches[2];
|
$offset = $matches[2];
|
||||||
@ -1194,7 +1210,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$limit = $bits[0];
|
$limit = $bits[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$text = '';
|
$text = '';
|
||||||
$suffixText = '';
|
$suffixText = '';
|
||||||
$nestedQuery = false;
|
$nestedQuery = false;
|
||||||
@ -1202,16 +1218,16 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
// DELETE queries
|
// DELETE queries
|
||||||
if($sqlQuery->delete) {
|
if($sqlQuery->delete) {
|
||||||
$text = 'DELETE ';
|
$text = 'DELETE ';
|
||||||
|
|
||||||
// SELECT queries
|
// SELECT queries
|
||||||
} else {
|
} else {
|
||||||
$distinct = $sqlQuery->distinct ? "DISTINCT " : "";
|
$distinct = $sqlQuery->distinct ? "DISTINCT " : "";
|
||||||
|
|
||||||
// If there's a limit but no offset, just use 'TOP X'
|
// If there's a limit but no offset, just use 'TOP X'
|
||||||
// rather than the more complex sub-select method
|
// rather than the more complex sub-select method
|
||||||
if ($limit != 0 && $offset == 0) {
|
if ($limit != 0 && $offset == 0) {
|
||||||
$text = "SELECT $distinct TOP $limit";
|
$text = "SELECT $distinct TOP $limit";
|
||||||
|
|
||||||
// If there's a limit and an offset, then we need to do a subselect
|
// If there's a limit and an offset, then we need to do a subselect
|
||||||
} else if($limit && $offset) {
|
} else if($limit && $offset) {
|
||||||
if($sqlQuery->orderby) {
|
if($sqlQuery->orderby) {
|
||||||
@ -1229,7 +1245,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
} else {
|
} else {
|
||||||
$text = "SELECT $distinct";
|
$text = "SELECT $distinct";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now add the columns to be selected
|
// Now add the columns to be selected
|
||||||
$text .= implode(", ", $sqlQuery->select);
|
$text .= implode(", ", $sqlQuery->select);
|
||||||
}
|
}
|
||||||
@ -1239,10 +1255,10 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
if($sqlQuery->groupby) $text .= " GROUP BY " . implode(", ", $sqlQuery->groupby);
|
if($sqlQuery->groupby) $text .= " GROUP BY " . implode(", ", $sqlQuery->groupby);
|
||||||
if($sqlQuery->having) $text .= " HAVING ( " . implode(" ) AND ( ", $sqlQuery->having) . " )";
|
if($sqlQuery->having) $text .= " HAVING ( " . implode(" ) AND ( ", $sqlQuery->having) . " )";
|
||||||
if(!$nestedQuery && $sqlQuery->orderby) $text .= " ORDER BY " . $sqlQuery->orderby;
|
if(!$nestedQuery && $sqlQuery->orderby) $text .= " ORDER BY " . $sqlQuery->orderby;
|
||||||
|
|
||||||
// $suffixText is used by the nested queries to create an offset limit
|
// $suffixText is used by the nested queries to create an offset limit
|
||||||
if($suffixText) $text .= $suffixText;
|
if($suffixText) $text .= $suffixText;
|
||||||
|
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1251,10 +1267,11 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
* @param string $value String to escape
|
* @param string $value String to escape
|
||||||
* @return string Escaped string
|
* @return string Escaped string
|
||||||
*/
|
*/
|
||||||
function addslashes($value) {
|
function addslashes($value){
|
||||||
$value = str_replace("'", "''", $value);
|
$value=str_replace("'","''",$value);
|
||||||
$value = str_replace("\0", "[NULL]", $value);
|
$value=str_replace("\0","[NULL]",$value);
|
||||||
return $value;
|
|
||||||
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1269,7 +1286,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
* The core search engine configuration.
|
* The core search engine configuration.
|
||||||
* Picks up the fulltext-indexed tables from the database and executes search on all of them.
|
* Picks up the fulltext-indexed tables from the database and executes search on all of them.
|
||||||
* Results are obtained as ID-ClassName pairs which is later used to reconstruct the DataObjectSet.
|
* Results are obtained as ID-ClassName pairs which is later used to reconstruct the DataObjectSet.
|
||||||
*
|
*
|
||||||
* @param array classesToSearch computes all descendants and includes them. Check is done via WHERE clause.
|
* @param array classesToSearch computes all descendants and includes them. Check is done via WHERE clause.
|
||||||
* @param string $keywords Keywords as a space separated string
|
* @param string $keywords Keywords as a space separated string
|
||||||
* @return object DataObjectSet of result pages
|
* @return object DataObjectSet of result pages
|
||||||
@ -1284,7 +1301,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
$allClassesToSearch = array_merge($allClassesToSearch, ClassInfo::dataClassesFor($class));
|
$allClassesToSearch = array_merge($allClassesToSearch, ClassInfo::dataClassesFor($class));
|
||||||
}
|
}
|
||||||
$allClassesToSearch = array_unique($allClassesToSearch);
|
$allClassesToSearch = array_unique($allClassesToSearch);
|
||||||
|
|
||||||
//Get a list of all the tables and columns we'll be searching on:
|
//Get a list of all the tables and columns we'll be searching on:
|
||||||
$fulltextColumns = DB::query('EXEC sp_help_fulltext_columns');
|
$fulltextColumns = DB::query('EXEC sp_help_fulltext_columns');
|
||||||
$queries = array();
|
$queries = array();
|
||||||
@ -1406,7 +1423,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
else {
|
else {
|
||||||
$keywords = Convert::raw2sql(str_replace(array('&','|','!','"','\''), '', trim($keywords)));
|
$keywords = Convert::raw2sql(str_replace(array('&','|','!','"','\''), '', trim($keywords)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove stopwords, concat with ANDs
|
// Remove stopwords, concat with ANDs
|
||||||
$keywords = explode(' ', $keywords);
|
$keywords = explode(' ', $keywords);
|
||||||
$keywords = self::removeStopwords($keywords);
|
$keywords = self::removeStopwords($keywords);
|
||||||
@ -1419,11 +1436,11 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
|
|
||||||
return "FREETEXTTABLE(\"$tableName\", ($fieldNames), '$keywords')";
|
return "FREETEXTTABLE(\"$tableName\", ($fieldNames), '$keywords')";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove stopwords that would kill a MSSQL full-text query
|
* Remove stopwords that would kill a MSSQL full-text query
|
||||||
*
|
*
|
||||||
* @param array $keywords
|
* @param array $keywords
|
||||||
*
|
*
|
||||||
* @return array $keywords with stopwords removed
|
* @return array $keywords with stopwords removed
|
||||||
*/
|
*/
|
||||||
@ -1435,14 +1452,14 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
}
|
}
|
||||||
return $goodKeywords;
|
return $goodKeywords;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does this database support transactions?
|
* Does this database support transactions?
|
||||||
*/
|
*/
|
||||||
public function supportsTransactions(){
|
public function supportsTransactions(){
|
||||||
return $this->supportsTransactions;
|
return $this->supportsTransactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a quick lookup to discover if the database supports particular extensions
|
* This is a quick lookup to discover if the database supports particular extensions
|
||||||
* Currently, MSSQL supports no extensions
|
* Currently, MSSQL supports no extensions
|
||||||
@ -1457,7 +1474,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start transaction. READ ONLY not supported.
|
* Start transaction. READ ONLY not supported.
|
||||||
*/
|
*/
|
||||||
@ -1469,14 +1486,14 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
if (!$result) $this->databaseError("Couldn't start the transaction.", E_USER_ERROR);
|
if (!$result) $this->databaseError("Couldn't start the transaction.", E_USER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a savepoint that you can jump back to if you encounter problems
|
* Create a savepoint that you can jump back to if you encounter problems
|
||||||
*/
|
*/
|
||||||
public function transactionSavepoint($savepoint){
|
public function transactionSavepoint($savepoint){
|
||||||
DB::query("SAVE TRANSACTION \"$savepoint\"");
|
DB::query("SAVE TRANSACTION \"$savepoint\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollback or revert to a savepoint if your queries encounter problems
|
* Rollback or revert to a savepoint if your queries encounter problems
|
||||||
* If you encounter a problem at any point during a transaction, you may
|
* If you encounter a problem at any point during a transaction, you may
|
||||||
@ -1494,7 +1511,7 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commit everything inside this transaction so far
|
* Commit everything inside this transaction so far
|
||||||
*/
|
*/
|
||||||
@ -1565,9 +1582,9 @@ class MSSQLDatabase extends SS_Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return '(' . implode(' + ', $strings) . ')';
|
return '(' . implode(' + ', $strings) . ')';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to return an SQL datetime expression for MSSQL.
|
* Function to return an SQL datetime expression for MSSQL.
|
||||||
* used for querying a datetime addition
|
* used for querying a datetime addition
|
||||||
@ -1672,13 +1689,13 @@ class MSSQLQuery extends SS_Query {
|
|||||||
|
|
||||||
public function __destruct() {
|
public function __destruct() {
|
||||||
if(is_resource($this->handle)) {
|
if(is_resource($this->handle)) {
|
||||||
if($this->mssql) {
|
if($this->mssql) {
|
||||||
mssql_free_result($this->handle);
|
mssql_free_result($this->handle);
|
||||||
} else {
|
} else {
|
||||||
sqlsrv_free_stmt($this->handle);
|
sqlsrv_free_stmt($this->handle);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function seek($row) {
|
public function seek($row) {
|
||||||
if(!is_resource($this->handle)) return false;
|
if(!is_resource($this->handle)) return false;
|
||||||
@ -1692,7 +1709,6 @@ class MSSQLQuery extends SS_Query {
|
|||||||
|
|
||||||
public function numRecords() {
|
public function numRecords() {
|
||||||
if(!is_resource($this->handle)) return false;
|
if(!is_resource($this->handle)) return false;
|
||||||
|
|
||||||
if($this->mssql) {
|
if($this->mssql) {
|
||||||
return mssql_num_rows($this->handle);
|
return mssql_num_rows($this->handle);
|
||||||
} else {
|
} else {
|
||||||
@ -1706,12 +1722,13 @@ class MSSQLQuery extends SS_Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function nextRecord() {
|
public function nextRecord() {
|
||||||
|
|
||||||
if(!is_resource($this->handle)) return false;
|
if(!is_resource($this->handle)) return false;
|
||||||
|
|
||||||
// Coalesce rather than replace common fields.
|
// Coalesce rather than replace common fields.
|
||||||
$output = array();
|
$output = array();
|
||||||
|
|
||||||
if($this->mssql) {
|
if($this->mssql) {
|
||||||
if($data = mssql_fetch_row($this->handle)) {
|
if($data = mssql_fetch_row($this->handle)) {
|
||||||
foreach($data as $columnIdx => $value) {
|
foreach($data as $columnIdx => $value) {
|
||||||
$columnName = mssql_field_name($this->handle, $columnIdx);
|
$columnName = mssql_field_name($this->handle, $columnIdx);
|
||||||
@ -1733,7 +1750,7 @@ class MSSQLQuery extends SS_Query {
|
|||||||
foreach($fields as $columnIdx => $field) {
|
foreach($fields as $columnIdx => $field) {
|
||||||
$value = $data[$columnIdx];
|
$value = $data[$columnIdx];
|
||||||
if($value instanceof DateTime) $value = $value->format('Y-m-d H:i:s');
|
if($value instanceof DateTime) $value = $value->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
// $value || !$ouput[$columnName] means that the *last* occurring value is shown
|
// $value || !$ouput[$columnName] means that the *last* occurring value is shown
|
||||||
// !$ouput[$columnName] means that the *first* occurring value is shown
|
// !$ouput[$columnName] means that the *first* occurring value is shown
|
||||||
if(isset($value) || !isset($output[$field['Name']])) {
|
if(isset($value) || !isset($output[$field['Name']])) {
|
||||||
|
Loading…
Reference in New Issue
Block a user