mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
API CHANGE: Updated DB::manipulate() to be more db-agnostic.
API CHANGE: Moved the meat of SQLQuery's SQL generation into Database::sqlQueryToString(), to be overloaded by different database implementations. API CHANGE: Moved the implementation of ClassInfo::hasTable() and ClassInfo::getValidSubClasses() into Database::hasTable() and Database::enumValuesForField(), to be overloaded by different database implementations. git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@66422 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
c7330dd231
commit
5a98e83f7a
@ -29,8 +29,7 @@ class ClassInfo {
|
||||
*/
|
||||
static function hasTable($class) {
|
||||
if(DB::isActive()) {
|
||||
$SQL_table = Convert::raw2sql($class);
|
||||
return (bool)(DB::query("SHOW TABLES LIKE '$SQL_table'")->value());
|
||||
return DB::getConn()->hasTable($class);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@ -40,14 +39,7 @@ class ClassInfo {
|
||||
* Returns the manifest of all classes which are present in the database.
|
||||
*/
|
||||
static function getValidSubClasses(){
|
||||
// Get the enum of all page types from the SiteTree table
|
||||
$classnameinfo = DB::query("DESCRIBE SiteTree ClassName")->first();
|
||||
preg_match_all("/'[^,]+'/", $classnameinfo["Type"], $matches);
|
||||
|
||||
foreach($matches[0] as $value) {
|
||||
$classes[] = trim($value, "'");
|
||||
}
|
||||
return $classes;
|
||||
return DB::getConn()->enumValuesForField("SiteTree", "ClassName");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,6 +111,22 @@ abstract class Database extends Object {
|
||||
*/
|
||||
protected abstract function tableList();
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the given table exists in the database
|
||||
*/
|
||||
abstract function hasTable($tableName);
|
||||
|
||||
/**
|
||||
* Returns the enum values available on the given field
|
||||
*/
|
||||
abstract function enumValuesForField($tableName, $fieldName);
|
||||
|
||||
/**
|
||||
* Convert a SQLQuery object into a SQL statement
|
||||
*/
|
||||
abstract function sqlQueryToString(SQLQuery $sqlQuery);
|
||||
|
||||
/**
|
||||
* The table list, generated by the tableList() function.
|
||||
* Used by the requireTable() function.
|
||||
@ -297,6 +313,8 @@ abstract class Database extends Object {
|
||||
|
||||
Profiler::mark('requireField');
|
||||
|
||||
// TODO: This is tempororary
|
||||
$spec['parts']['name'] = $field;
|
||||
//Convert the $spec array into a database-specific string
|
||||
$spec=DB::getConn()->$spec['type']($spec['parts']);
|
||||
|
||||
@ -386,37 +404,37 @@ abstract class Database extends Object {
|
||||
function manipulate($manipulation) {
|
||||
foreach($manipulation as $table => $writeInfo) {
|
||||
if(isset($writeInfo['fields']) && $writeInfo['fields']) {
|
||||
$fieldList = array();
|
||||
$fieldList = $columnList = $valueList = array();
|
||||
foreach($writeInfo['fields'] as $fieldName => $fieldVal) {
|
||||
$fieldList[] = "\"$fieldName\" = $fieldVal";
|
||||
$columnList[] = "\"$fieldName\"";
|
||||
|
||||
// Empty strings inserted as null in INSERTs. Replacement of Database::replace_with_null().
|
||||
if($fieldVal === "''") $valueList[] = "null";
|
||||
else $valueList[] = $fieldVal;
|
||||
}
|
||||
$fieldList = implode(", ", $fieldList);
|
||||
|
||||
if(!isset($writeInfo['where']) && isset($writeInfo['id'])) {
|
||||
$writeInfo['where'] = "ID = $writeInfo[id]";
|
||||
$writeInfo['where'] = "\"ID\" = " . (int)$writeInfo['id'];
|
||||
}
|
||||
|
||||
switch($writeInfo['command']) {
|
||||
case "update":
|
||||
$fieldList = implode(", ", $fieldList);
|
||||
$sql = "update \"$table\" SET $fieldList where $writeInfo[where]";
|
||||
$this->query($sql);
|
||||
|
||||
// If numAffectedRecord = 0, then we want to run instert instead
|
||||
if(!$this->affectedRows()) {
|
||||
if(!isset($writeInfo['fields']['ID']) && isset($writeInfo['id'])) {
|
||||
$fieldList .= ", ID = $writeInfo[id]";
|
||||
}
|
||||
$sql = "insert into \"$table\" SET $fieldList";
|
||||
$this->query($sql, null);
|
||||
}
|
||||
break;
|
||||
|
||||
// If affectedRows = 0, then don't break, meaning the insert query below gets called
|
||||
if($this->affectedRows()) break;
|
||||
|
||||
case "insert":
|
||||
if(!isset($writeInfo['fields']['ID']) && isset($writeInfo['id'])) {
|
||||
$fieldList .= ", ID = $writeInfo[id]";
|
||||
$columnList[] = "\"$ID\"";
|
||||
$valueList[] = (int)$writeInfo['id'];
|
||||
}
|
||||
$fieldList = Database::replace_with_null($fieldList);
|
||||
$sql = "insert into \"$table\" SET $fieldList";
|
||||
$columnList = implode(", ", $columnList);
|
||||
$valueList = implode(", ", $valueList);
|
||||
$sql = "insert into \"$table\" ($columnList) VALUES ($valueList)";
|
||||
$this->query($sql);
|
||||
break;
|
||||
|
||||
|
@ -539,6 +539,74 @@ class MySQLDatabase extends Database {
|
||||
|
||||
return 'varchar(' . $values['precision'] . ') character set utf8 collate utf8_general_ci';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given table is exists in the current database
|
||||
* NOTE: Experimental; introduced for db-abstraction and may changed before 2.4 is released.
|
||||
*/
|
||||
public function hasTable($table) {
|
||||
$SQL_table = Convert::raw2sql($table);
|
||||
return (bool)($this->query("SHOW TABLES LIKE '$SQL_table'")->value());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the values of the given enum field
|
||||
* NOTE: Experimental; introduced for db-abstraction and may changed before 2.4 is released.
|
||||
*/
|
||||
public function enumValuesForField($tableName, $fieldName) {
|
||||
// Get the enum of all page types from the SiteTree table
|
||||
$classnameinfo = DB::query("DESCRIBE \"$tableName\" \"$fieldName\"")->first();
|
||||
preg_match_all("/'[^,]+'/", $classnameinfo["Type"], $matches);
|
||||
|
||||
foreach($matches[0] as $value) {
|
||||
$classes[] = trim($value, "'");
|
||||
}
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a SQLQuery object into a SQL statement
|
||||
*/
|
||||
public function sqlQueryToString(SQLQuery $sqlQuery) {
|
||||
if (!$sqlQuery->from) return '';
|
||||
$distinct = $sqlQuery->distinct ? "DISTINCT " : "";
|
||||
if($sqlQuery->delete) {
|
||||
$text = "DELETE ";
|
||||
} else if($sqlQuery->select) {
|
||||
$text = "SELECT $distinct" . implode(", ", $sqlQuery->select);
|
||||
}
|
||||
$text .= " FROM " . implode(" ", $sqlQuery->from);
|
||||
|
||||
if($sqlQuery->where) $text .= " WHERE (" . $sqlQuery->getFilter(). ")";
|
||||
if($sqlQuery->groupby) $text .= " GROUP BY " . implode(", ", $sqlQuery->groupby);
|
||||
if($sqlQuery->having) $text .= " HAVING ( " . implode(" ) AND ( ", $sqlQuery->having) . " )";
|
||||
if($sqlQuery->orderby) $text .= " ORDER BY " . $sqlQuery->orderby;
|
||||
|
||||
if($sqlQuery->limit) {
|
||||
$limit = $sqlQuery->limit;
|
||||
// Pass limit as array or SQL string value
|
||||
if(is_array($limit)) {
|
||||
if(!array_key_exists('limit',$limit)) user_error('SQLQuery::limit(): Wrong format for $limit', E_USER_ERROR);
|
||||
|
||||
if(isset($limit['start']) && is_numeric($limit['start']) && isset($limit['limit']) && is_numeric($limit['limit'])) {
|
||||
// @todo MySQL specific LIMIT syntax
|
||||
//$combinedLimit = (int)$limit['start'] . ',' . (int)$limit['limit'];
|
||||
$combinedLimit = "$limit[limit] OFFSET $limit[start]";
|
||||
} elseif(isset($limit['limit']) && is_numeric($limit['limit'])) {
|
||||
$combinedLimit = (int)$limit['limit'];
|
||||
} else {
|
||||
$combinedLimit = false;
|
||||
}
|
||||
if(!empty($combinedLimit)) $this->limit = $combinedLimit;
|
||||
|
||||
} else {
|
||||
$text .= " LIMIT " . $sqlQuery->limit;
|
||||
}
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,23 +169,7 @@ class SQLQuery extends Object {
|
||||
* @return SQLQuery This instance
|
||||
*/
|
||||
public function limit($limit) {
|
||||
// Pass limit as array or SQL string value
|
||||
if(is_array($limit)) {
|
||||
if(!array_key_exists('limit',$limit)) user_error('SQLQuery::limit(): Wrong format for $limit', E_USER_ERROR);
|
||||
|
||||
if(isset($limit['start']) && is_numeric($limit['start']) && isset($limit['limit']) && is_numeric($limit['limit'])) {
|
||||
// @todo MySQL specific LIMIT syntax
|
||||
$combinedLimit = (int)$limit['start'] . ',' . (int)$limit['limit'];
|
||||
} elseif(isset($limit['limit']) && is_numeric($limit['limit'])) {
|
||||
$combinedLimit = (int)$limit['limit'];
|
||||
} else {
|
||||
$combinedLimit = false;
|
||||
}
|
||||
} else {
|
||||
$combinedLimit = $limit;
|
||||
}
|
||||
|
||||
if(!empty($combinedLimit)) $this->limit = $combinedLimit;
|
||||
$this->limit = $limit;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -392,22 +376,7 @@ class SQLQuery extends Object {
|
||||
* @return string
|
||||
*/
|
||||
function sql() {
|
||||
if (!$this->from) return '';
|
||||
$distinct = $this->distinct ? "DISTINCT " : "";
|
||||
if($this->delete) {
|
||||
$text = "DELETE ";
|
||||
} else if($this->select) {
|
||||
$text = "SELECT $distinct" . implode(", ", $this->select);
|
||||
}
|
||||
$text .= " FROM " . implode(" ", $this->from);
|
||||
|
||||
if($this->where) $text .= " WHERE (" . $this->getFilter(). ")";
|
||||
if($this->groupby) $text .= " GROUP BY " . implode(", ", $this->groupby);
|
||||
if($this->having) $text .= " HAVING ( " . implode(" ) AND ( ", $this->having) . " )";
|
||||
if($this->orderby) $text .= " ORDER BY " . $this->orderby;
|
||||
if($this->limit) $text .= " LIMIT " . $this->limit;
|
||||
|
||||
return $text;
|
||||
return DB::getConn()->sqlQueryToString($this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user