new pisilinux web sites
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Datatype;
|
||||
|
||||
trait CallableTalkingQueries
|
||||
{
|
||||
/**
|
||||
* Magic call
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
$method = strtolower($originMethodName = $method);
|
||||
$split = Datatype::splitUpperCase($originMethodName);
|
||||
|
||||
# Is Function Elements
|
||||
if( in_array($method, $this->functionElements) )
|
||||
{
|
||||
$functionMethod = $method; // @codeCoverageIgnore
|
||||
}
|
||||
else
|
||||
{
|
||||
$functionMethod = $this->functionElements[$method] ?? NULL;
|
||||
}
|
||||
|
||||
# Is Vartype Elements
|
||||
if( in_array($method, $this->vartypeElements) )
|
||||
{
|
||||
$vartypeMethod = $method;
|
||||
}
|
||||
else
|
||||
{
|
||||
$vartypeMethod = $this->vartypeElements[$method] ?? NULL;
|
||||
}
|
||||
|
||||
# Math Functions
|
||||
if( $functionMethod !== NULL )
|
||||
{
|
||||
return $this->callMathMethod($functionMethod, $parameters); // @codeCoverageIgnore
|
||||
}
|
||||
# Variable Types
|
||||
elseif( $vartypeMethod !== NULL )
|
||||
{
|
||||
return $this->db->variableTypes($vartypeMethod, ...$parameters);
|
||||
}
|
||||
# Statements
|
||||
# 5.7.4[edited]
|
||||
elseif( in_array($method, $this->statementElements) )
|
||||
{
|
||||
# 5.7.4[added]
|
||||
if( $method === 'constraint' )
|
||||
{
|
||||
$parameters[1] = false;
|
||||
}
|
||||
|
||||
return $this->db->statements($method, ...$parameters);
|
||||
}
|
||||
# Join
|
||||
elseif( ($split[1] ?? NULL) === 'Join')
|
||||
{
|
||||
return $this->callJoinTalkingQuery($split, $parameters);
|
||||
}
|
||||
# Order By - Group By
|
||||
elseif( $split[0] === 'order' || $split[0] === 'group')
|
||||
{
|
||||
return $this->callOrderGroupByTalkingQuery($split);
|
||||
}
|
||||
# Where - Having
|
||||
elseif( $split[0] === 'where' || $split[0] === 'having' )
|
||||
{
|
||||
return $this->callWhereHavingTalkingQuery($split, $parameters);
|
||||
}
|
||||
# Insert - Update - Delete
|
||||
elseif( in_array($split[1] ?? NULL, ['Delete', 'Update', 'Insert']) )
|
||||
{
|
||||
return $this->callCrudTalkingQuery($split, $parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->callResultMethodsTalkingQuery($originMethodName, $split, $parameters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected call join talkin query
|
||||
*/
|
||||
protected function callJoinTalkingQuery($split, $parameters)
|
||||
{
|
||||
$type = $split[0] ?? 'left';
|
||||
$table1 = $split[2] ?? '';
|
||||
$column1 = strtolower($table1 . '.' . $split[3]);
|
||||
$table2 = $split[4] ?? '';
|
||||
$column2 = strtolower($table2 . '.' . $split[5]);
|
||||
$met = $type . $split[1];
|
||||
|
||||
return $this->$met($column1, $column2, $parameters[0] ?? '=');
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected call order group by talking query
|
||||
*/
|
||||
protected function callOrderGroupByTalkingQuery($split)
|
||||
{
|
||||
$column = strtolower($split[2] ?? '');
|
||||
$type = $split[0] === 'order' ? $split[3] ?? 'asc' : '';
|
||||
$met = $split[0] . 'By';
|
||||
|
||||
return $this->$met($column, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected call crud talking query
|
||||
*/
|
||||
protected function callCrudTalkingQuery($split, $parameters)
|
||||
{
|
||||
$table = $split[0];
|
||||
$method = $split[1];
|
||||
|
||||
if( is_string($parameters[0]) )
|
||||
{
|
||||
$prefix = $parameters[0] . ':';
|
||||
$data = [];
|
||||
}
|
||||
else
|
||||
{
|
||||
$prefix = '';
|
||||
$data = $parameters[0];
|
||||
}
|
||||
|
||||
# [5.6.5] In case of using 3rd section, it is accepted as a condition.
|
||||
if( isset($split[2]) )
|
||||
{
|
||||
# For delete: tableDeleteColumn($value)
|
||||
if( $method === 'Delete' && isset($parameters[0]) )
|
||||
{
|
||||
$prefix = '';
|
||||
|
||||
$this->where($split[2], $parameters[0]);
|
||||
}
|
||||
# For update: tableUpdateColumn($data, $value)
|
||||
elseif( $method === 'Update' && isset($parameters[1]) )
|
||||
{
|
||||
$this->where($split[2], $parameters[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->$method($prefix . $table, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected call where having talking query
|
||||
*/
|
||||
protected function callWhereHavingTalkingQuery($split, $parameters)
|
||||
{
|
||||
$met = $split[0];
|
||||
$column = strtolower($split[1] ?? '');
|
||||
$condition = $split[2] ?? '';
|
||||
$operator = isset($parameters[1]) ? ' ' . $parameters[1] : '';
|
||||
|
||||
return $this->$met($column . $operator, $parameters[0], $condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* updated[5.7.0.1]
|
||||
* Protected call result methods talking query
|
||||
*/
|
||||
protected function callResultMethodsTalkingQuery($method, $split, $parameters)
|
||||
{
|
||||
$func = $split[1] ?? NULL;
|
||||
|
||||
$result = NULL;
|
||||
|
||||
# Row & Result
|
||||
if( $func === 'Row' || $func === 'Result' )
|
||||
{
|
||||
$method = $split[0];
|
||||
$result = strtolower($func);
|
||||
}
|
||||
|
||||
$whereClause = $parameters[0] ?? ($result === 'row' ? 0 : 'object');
|
||||
|
||||
# Value
|
||||
if( $select = ($split[2] ?? NULL) )
|
||||
{
|
||||
if( isset($parameters[0]) )
|
||||
{
|
||||
$this->where(strtolower($split[2] ?? ''), $parameters[0]);
|
||||
|
||||
$whereClause = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = 'value';
|
||||
|
||||
$this->select($select);
|
||||
|
||||
$whereClause = true;
|
||||
}
|
||||
}
|
||||
|
||||
$return = $this->get($method);
|
||||
|
||||
# Return ->get()
|
||||
if( ! isset($result) )
|
||||
{
|
||||
return $return;
|
||||
}
|
||||
|
||||
# Return ->row(0) || result('object')
|
||||
return $return->$result($whereClause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected call math method
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function callMathMethod($functionMethod, $parameters)
|
||||
{
|
||||
$math = $this->setMathFunction($functionMethod, $parameters);
|
||||
|
||||
if( $math->return === true )
|
||||
{
|
||||
return $math->args;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->selectFunctions[] = $math->args;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,793 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Base;
|
||||
use ZN\Config;
|
||||
use ZN\Support;
|
||||
use ZN\Helpers\Logger;
|
||||
use ZN\DataTypes\Arrays;
|
||||
use ZN\Database\Exception\InvalidArgumentException;
|
||||
|
||||
class Connection
|
||||
{
|
||||
/**
|
||||
* Keeps database drivers
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $drivers =
|
||||
[
|
||||
'odbc' => 'ODBC',
|
||||
'mysqli' => 'MySQLi',
|
||||
'oracle' => 'Oracle',
|
||||
'postgres' => 'Postgres',
|
||||
'sqlite' => 'SQLite',
|
||||
'sqlserver' => 'SQLServer'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keeps database driver
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* Keeps database config
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Keeps database default config
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $defaultConfig;
|
||||
|
||||
/**
|
||||
* Keeps table prefix
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* Keeps secure data
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $secure = [];
|
||||
|
||||
/**
|
||||
* Keeps aliases data
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aliases = [];
|
||||
|
||||
/**
|
||||
* Select table name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* Keeps table name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $tableName;
|
||||
|
||||
/**
|
||||
* Get string query
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $stringQuery;
|
||||
|
||||
/**
|
||||
* Get string queries
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $stringQueries;
|
||||
|
||||
/**
|
||||
* Keeps select functions
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $selectFunctions;
|
||||
|
||||
/**
|
||||
* Keeps column
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $column;
|
||||
|
||||
/**
|
||||
* Keep database driver
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $driver;
|
||||
|
||||
/**
|
||||
* Keeps string query
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $string;
|
||||
|
||||
/**
|
||||
* Transaction queries
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $transaction;
|
||||
|
||||
/**
|
||||
* Keeps transaction queries
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $transactionQueries;
|
||||
|
||||
/**
|
||||
* Magic construtor
|
||||
*
|
||||
* @param array $config
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
$this->defaultConfig = Config::default('ZN\Database\DatabaseDefaultConfiguration')
|
||||
::get('Database', 'database');
|
||||
$this->config = array_merge($this->defaultConfig, $config);
|
||||
$this->db = $this->runDriver();
|
||||
$this->prefix = $this->config['prefix'];
|
||||
Properties::$prefix = $this->prefix;
|
||||
|
||||
$this->db->connect($this->config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Debug Info
|
||||
*/
|
||||
public function __debugInfo()
|
||||
{
|
||||
return ['return' => $this->stringQuery ?: 'This is a general object, please call the sub method!'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Restructure
|
||||
*
|
||||
* @param array $config
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function restruct(array $config = [])
|
||||
{
|
||||
$this->__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias different connection
|
||||
*
|
||||
* @param mixed $connectName = NULL
|
||||
*
|
||||
* @return Connection
|
||||
*/
|
||||
public function new($connectName = NULL) : Connection
|
||||
{
|
||||
return $this->differentConnection($connectName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates different connection
|
||||
*
|
||||
* @param mixed $connectName = NULL
|
||||
*
|
||||
* @return Connection
|
||||
*/
|
||||
public function differentConnection($connectName = NULL) : Connection
|
||||
{
|
||||
$getCalledClass = get_called_class();
|
||||
|
||||
if( empty($connectName) )
|
||||
{
|
||||
return new $getCalledClass;
|
||||
}
|
||||
|
||||
$config = $this->defaultConfig;
|
||||
$configDifferent = $config['differentConnection'];
|
||||
|
||||
if( is_string($connectName) && isset($configDifferent[$connectName]) )
|
||||
{
|
||||
$connection = $configDifferent[$connectName];
|
||||
}
|
||||
elseif( is_array($connectName) )
|
||||
{
|
||||
$connection = $connectName;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException('Error', 'invalidInput', 'Mixed $connectName');
|
||||
}
|
||||
|
||||
foreach( $config as $key => $val )
|
||||
{
|
||||
if( $key !== 'differentConnection' )
|
||||
{
|
||||
if( ! isset($connection[$key]) )
|
||||
{
|
||||
$connection[$key] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new $getCalledClass($connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get var types
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function vartypes() : array
|
||||
{
|
||||
return $this->db->vartypes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets table name
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return Connection
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function table(string $table) : Connection
|
||||
{
|
||||
$this->table = ' '.$this->prefix.$table.' ';
|
||||
$this->tableName = $this->prefix.$table;
|
||||
Properties::$table = $this->tableName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets column
|
||||
*
|
||||
* @param string $col
|
||||
* @param mixed $val = NULL
|
||||
*
|
||||
* @return Connection
|
||||
*/
|
||||
public function column(string $col, $val = NULL) : Connection
|
||||
{
|
||||
$this->column[$col] = $val;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts string query
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return Connection
|
||||
*/
|
||||
public function string() : Connection
|
||||
{
|
||||
$this->string = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string query
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function stringQuery() : string
|
||||
{
|
||||
if( ! empty($this->stringQuery) )
|
||||
{
|
||||
return $this->stringQuery;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string queries
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
public function stringQueries()
|
||||
{
|
||||
if( ! empty($this->stringQueries) )
|
||||
{
|
||||
return $this->stringQueries;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets query security
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return Connection
|
||||
*/
|
||||
public function secure(array $data) : Connection
|
||||
{
|
||||
$this->secure = $data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines function
|
||||
*
|
||||
* @param string ...$args
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function func(...$args)
|
||||
{
|
||||
$array = $args;
|
||||
|
||||
array_shift($array);
|
||||
|
||||
$math = $this->setMathFunction(isset($args[0]) ? strtoupper($args[0] ?? '') : false, $array);
|
||||
|
||||
if( $math->return === true )
|
||||
{
|
||||
return $math->args;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->selectFunctions[] = $math->args;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get database query error
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function error()
|
||||
{
|
||||
return $this->db->error();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close database connection
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return $this->db->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get database version
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function version()
|
||||
{
|
||||
return $this->db->version();
|
||||
}
|
||||
|
||||
/**
|
||||
* protected escape string add nail
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param mixed $numeric = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function escapeStringAddNail($value, $numeric = false)
|
||||
{
|
||||
if( $numeric === true && is_numeric($value) )
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
return Base::presuffix($this->nailEncode($value), "'");
|
||||
}
|
||||
|
||||
/**
|
||||
* protected exp
|
||||
*
|
||||
* @param string $column = ''
|
||||
* @param string $exp = 'exp'
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function isExpressionExists($column = '', $exp = 'exp')
|
||||
{
|
||||
return stristr($column, $exp . ':');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param string $ext = 'exp'
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function clearExpression($column, $exp = 'exp')
|
||||
{
|
||||
return str_ireplace($exp . ':', '', $column ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
* protected clear nail
|
||||
*
|
||||
* @param string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function clearNail($value)
|
||||
{
|
||||
return trim((string) $value, '\'');
|
||||
}
|
||||
|
||||
/**
|
||||
* protected convert type
|
||||
*
|
||||
* @param string &$column
|
||||
* @param string &$value
|
||||
*
|
||||
* @param void
|
||||
*/
|
||||
protected function convertVartype(&$column = '', &$value = '')
|
||||
{
|
||||
$clearValue = $this->clearNail($value);
|
||||
|
||||
if( $this->isExpressionExists($column, $type = 'int') )
|
||||
{
|
||||
$value = (int) $clearValue;
|
||||
}
|
||||
elseif( $this->isExpressionExists($column, $type = 'float') )
|
||||
{
|
||||
$value = (float) $clearValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
$type = 'exp';
|
||||
}
|
||||
|
||||
$column = $this->clearExpression($column, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* protected query security
|
||||
*
|
||||
* @param string $query
|
||||
* @param string $isString = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function querySecurity($query, $isString = false)
|
||||
{
|
||||
if( ! empty($this->secure) )
|
||||
{
|
||||
$query = $this->applySecure($query);
|
||||
}
|
||||
|
||||
if( ! empty($this->aliases) )
|
||||
{
|
||||
$query = $this->applyAliases($query);
|
||||
}
|
||||
|
||||
$this->applyNullable($query);
|
||||
|
||||
if( $isString === false && ($this->config['queryLog'] ?? NULL) === true )
|
||||
{
|
||||
Logger::report('DatabaseQueries', $query, 'DatabaseQueries'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$this->stringQueries[] = $this->stringQuery = $query;
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected apply nullable
|
||||
*/
|
||||
protected function applyNullable(&$query)
|
||||
{
|
||||
$query = str_ireplace('\'null\'', 'null', $query ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
* protected apply secure
|
||||
*/
|
||||
protected function applySecure($query)
|
||||
{
|
||||
$query = $query ?? '';
|
||||
|
||||
$secure = $this->secure; $this->secure = []; $secureParams = [];
|
||||
|
||||
if( is_numeric(key($secure)) )
|
||||
{
|
||||
$strex = explode('?', $query);
|
||||
$newstr = '';
|
||||
|
||||
if( ! empty($strex) ) for( $i = 0; $i < count($strex) - 1; $i++ )
|
||||
{
|
||||
$sec = $secure[$i] ?? NULL;
|
||||
|
||||
$newstr .= $strex[$i].$this->escapeStringAddNail($sec);
|
||||
}
|
||||
|
||||
$query = $newstr . end($strex);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach( $secure as $k => $v )
|
||||
{
|
||||
$this->convertVartype($k, $v);
|
||||
|
||||
$secureParams[$k] = $this->escapeStringAddNail($v);
|
||||
}
|
||||
}
|
||||
|
||||
return str_replace(array_keys($secureParams), array_values($secureParams), $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* protected apply aliases
|
||||
*/
|
||||
protected function applyAliases($query)
|
||||
{
|
||||
$aliases = $this->aliases; $this->aliases = [];
|
||||
|
||||
foreach( $aliases as $alias => $origin )
|
||||
{
|
||||
$query = preg_replace
|
||||
(
|
||||
[
|
||||
'/(^|\s)' . $this->prefix . $alias . '($|\s)/i',
|
||||
'/(^|\W)' . $this->prefix . $alias . '($|\W)/i'
|
||||
],
|
||||
[
|
||||
'$1' . $this->prefix . $origin . ' ' . $alias . '$2',
|
||||
'$1' . $alias . '$2'
|
||||
],
|
||||
$query
|
||||
);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets math functions
|
||||
*
|
||||
* @param string $type
|
||||
* @param array $args
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
protected function setMathFunction($type, $args)
|
||||
{
|
||||
$type = strtoupper($type ?? '');
|
||||
$getLast = Arrays\GetElement::last($args) ?? '';
|
||||
$asparam = ' ';
|
||||
|
||||
if( $getLast === true )
|
||||
{
|
||||
array_pop($args);
|
||||
|
||||
$return = true;
|
||||
$as = Arrays\GetElement::last($args) ?? '';
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
if( stripos(trim($as), 'as') === 0 )
|
||||
{
|
||||
$asparam .= $as;
|
||||
array_pop($args);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
else
|
||||
{
|
||||
$return = false;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
if( stripos(trim($getLast), 'as') === 0 )
|
||||
{
|
||||
$asparam .= $getLast;
|
||||
array_pop($args);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
$args = $type.'('.rtrim(implode(',', $args), ',').')'.$asparam;
|
||||
|
||||
return (object)
|
||||
[
|
||||
'args' => $args,
|
||||
'return' => $return
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Run driver
|
||||
*
|
||||
* @param array $settings = []
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
protected function runDriver($settings = [])
|
||||
{
|
||||
$this->driver = preg_replace('/(\w+)(\:\w+)*/', '$1', $this->config['driver']);
|
||||
|
||||
return $this->getDriver(NULL, $settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* protected get driver library
|
||||
*
|
||||
* @param string $suffix = 'Driver'
|
||||
* @param array $settings = []
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
protected function getDriver($suffix = NULL, $settings = [])
|
||||
{
|
||||
Support::driver(array_keys($this->drivers), $this->driver);
|
||||
|
||||
$class = 'ZN\Database\\' . $this->drivers[$this->driver] . '\\DB' . $suffix;
|
||||
|
||||
return new $class($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* protected encode nail
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function nailEncode($data)
|
||||
{
|
||||
if( $data === NULL )
|
||||
{
|
||||
return 'NULL';
|
||||
}
|
||||
|
||||
return str_replace(["'", "\'", "\\'"], "'", $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* protected run exec query
|
||||
*
|
||||
* @param string $query
|
||||
* @param string $type = 'query'
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function runQuery($query, $type = 'query')
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
if( $this->string === true )
|
||||
{
|
||||
$this->string = NULL;
|
||||
|
||||
return $query;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
if( $this->transaction === true )
|
||||
{
|
||||
$this->transactionQueries[] = $query;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
if( empty($query) )
|
||||
{
|
||||
$this->stringQuery = NULL;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->db->$type($this->querySecurity($query), $this->secure);
|
||||
|
||||
return ! (bool) $this->db->error();
|
||||
}
|
||||
|
||||
/**
|
||||
* protected run exec query
|
||||
*
|
||||
* @param string $query
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function runExecQuery($query)
|
||||
{
|
||||
return $this->runQuery($query, 'exec');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets table name
|
||||
*
|
||||
* @param mixed $p = NULL
|
||||
* @param string $name = 'table'
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function addPrefixForTableAndColumn($p = NULL, $name = 'table')
|
||||
{
|
||||
if( $name === 'prefix' )
|
||||
{
|
||||
return $this->$name.$p;
|
||||
}
|
||||
|
||||
if( $name === 'table' )
|
||||
{
|
||||
$p = $this->prefix.$p;
|
||||
}
|
||||
|
||||
if( ! empty($this->$name) )
|
||||
{
|
||||
$data = $this->$name;
|
||||
|
||||
$this->$name = NULL;
|
||||
|
||||
return $data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic destructor
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->db->close();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,491 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Support;
|
||||
use ZN\Datatype;
|
||||
use ZN\Singleton;
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
|
||||
class DBForge extends Connection
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $extras;
|
||||
|
||||
/**
|
||||
* Keeps Forge Driver
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $forge;
|
||||
|
||||
/**
|
||||
* Magic Call
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
*
|
||||
* @param mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
$split = Datatype::splitUpperCase($originMethodName = $method);
|
||||
$table = $split[0];
|
||||
$method = $split[1] ?? NULL;
|
||||
|
||||
switch($method)
|
||||
{
|
||||
case 'Create' : $method = 'createTable'; break;
|
||||
case 'Drop' : $method = 'dropTable' ; break;
|
||||
case 'Alter' : $method = 'alterTable' ; break;
|
||||
case 'Rename' : $method = 'renameTable'; break;
|
||||
case 'Truncate': $method = 'truncate' ; break;
|
||||
default : Support::classMethod(get_called_class(), $originMethodName); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $this->$method($table, ...$parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Constructor
|
||||
*
|
||||
* @param array $settings
|
||||
*/
|
||||
public function __construct($settings = [])
|
||||
{
|
||||
parent::__construct($settings);
|
||||
|
||||
$this->forge = $this->getDriver('Forge', $settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Table & Database Extras
|
||||
*
|
||||
* @param mixed $extras
|
||||
*
|
||||
* @return DBForge
|
||||
*/
|
||||
public function extras($extras) : DBForge
|
||||
{
|
||||
$this->extras = $this->forge->extras($extras);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Database
|
||||
*
|
||||
* @param string $dbname
|
||||
* @param string $extras
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createDatabase(string $dbname, $extras = NULL)
|
||||
{
|
||||
$query = $this->forge->createDatabase($dbname, $this->addPrefixForTableAndColumn($extras, 'extras'));
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Database
|
||||
*
|
||||
* @param string $dbname
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dropDatabase(string $dbname)
|
||||
{
|
||||
$query = $this->forge->dropDatabase($dbname);
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Table
|
||||
*
|
||||
* @param string $tabşe
|
||||
* @param array $columns
|
||||
* @param string $extras
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createTable(?string $table = NULL, ?array $columns = NULL, $extras = NULL)
|
||||
{
|
||||
$query = $this->forge->createTable($this->addPrefixForTableAndColumn($table), $this->addPrefixForTableAndColumn($columns, 'column'), $this->addPrefixForTableAndColumn($extras, 'extras'));
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Temporary Table
|
||||
*
|
||||
* @param string $tabşe
|
||||
* @param array $columns
|
||||
* @param string $extras
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function createTempTable(?string $table = NULL, ?array $columns = NULL, $extras = NULL)
|
||||
{
|
||||
$query = $this->forge->createTempTable($this->addPrefixForTableAndColumn($table), $this->addPrefixForTableAndColumn($columns, 'column'), $this->addPrefixForTableAndColumn($extras, 'extras'));
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Table
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dropTable(?string $table = NULL)
|
||||
{
|
||||
$query = $this->forge->dropTable($this->addPrefixForTableAndColumn($table));
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter Table
|
||||
*
|
||||
* @param string $table
|
||||
* @param mixed $condition
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function alterTable(?string $table = NULL, ?array $condition = NULL)
|
||||
{
|
||||
$table = $this->addPrefixForTableAndColumn($table);
|
||||
$key = key($condition);
|
||||
|
||||
return $this->$key($table, $condition[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename Table
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $newname
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function renameTable(string $name, string $newName)
|
||||
{
|
||||
$query = $this->forge->renameTable($this->addPrefixForTableAndColumn($name, 'prefix'), $this->addPrefixForTableAndColumn($newName, 'prefix'));
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function truncate(?string $table = NULL)
|
||||
{
|
||||
$query = $this->forge->truncate($this->addPrefixForTableAndColumn($table));
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function addColumn(?string $table = NULL, ?array $columns = NULL)
|
||||
{
|
||||
$query = $this->forge->addColumn($this->addPrefixForTableAndColumn($table), $this->addPrefixForTableAndColumn($columns, 'column'));
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Auto Increment
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param int $start = 0
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function startAutoIncrement(string $table, int $start = 0)
|
||||
{
|
||||
$query = $this->forge->startAutoIncrement($this->addPrefixForTableAndColumn($table), $start);
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Auto Increment
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param int $start = 0
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function addAutoIncrement(string $table, string $column = 'id', ?int $start = NULL)
|
||||
{
|
||||
if( $start !== NULL )
|
||||
{
|
||||
$this->startAutoIncrement($table, $start);
|
||||
}
|
||||
|
||||
return $this->modifyColumn($table, [$column => [($db = Singleton::class('ZN\Database\DB'))->int(), $db->autoIncrement()]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Primary Key
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
* @param string $constraint = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function addPrimaryKey(string $table, string $columns, ?string $constraint = NULL)
|
||||
{
|
||||
$query = $this->forge->addPrimaryKey($this->addPrefixForTableAndColumn($table), $columns, $constraint);
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Foreign Key
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
* @param string $reftable
|
||||
* @param string $refcolumn
|
||||
* @param string $constraint = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function addForeignKey(string $table, string $columns, string $reftable, string $refcolumn, ?string $constraint = NULL)
|
||||
{
|
||||
$query = $this->forge->addForeignKey($this->addPrefixForTableAndColumn($table), $columns, $reftable, $refcolumn, $constraint);
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Primary Key
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $constraint = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dropPrimaryKey(?string $table = NULL, ?string $constraint = NULL)
|
||||
{
|
||||
$query = $this->forge->dropPrimaryKey($this->addPrefixForTableAndColumn($table), $constraint);
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Foreign Key
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $constraint = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dropForeignKey(?string $table = NULL, ?string $constraint = NULL)
|
||||
{
|
||||
$query = $this->forge->dropForeignKey($this->addPrefixForTableAndColumn($table), $constraint);
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createIndex(string $indexName, string $table, string $columns)
|
||||
{
|
||||
$query = $this->forge->createIndex($indexName, $this->addPrefixForTableAndColumn($table), $columns);
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Unique index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createUniqueIndex(string $indexName, string $table, string $columns)
|
||||
{
|
||||
$query = $this->forge->createUniqueIndex($indexName, $this->addPrefixForTableAndColumn($table), $columns);
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Fulltext index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createFulltextIndex(string $indexName, string $table, string $columns)
|
||||
{
|
||||
$query = $this->forge->createFulltextIndex($indexName, $this->addPrefixForTableAndColumn($table), $columns);
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Spatial index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createSpatialIndex(string $indexName, string $table, string $columns)
|
||||
{
|
||||
$query = $this->forge->createSpatialIndex($indexName, $this->addPrefixForTableAndColumn($table), $columns);
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropIndex(string $indexName, ?string $table = NULL)
|
||||
{
|
||||
$query = $this->forge->dropIndex($indexName, $this->addPrefixForTableAndColumn($table));
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dropColumn(?string $table = NULL, $columns = NULL)
|
||||
{
|
||||
$columns = $this->addPrefixForTableAndColumn($columns, 'column');
|
||||
|
||||
if( ! is_array($columns) )
|
||||
{
|
||||
$query = $this->forge->dropColumn($this->addPrefixForTableAndColumn($table), $columns);
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach( $columns as $key => $col )
|
||||
{
|
||||
if( ! is_numeric($key) )
|
||||
{
|
||||
$col = $key; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$query = $this->forge->dropColumn($this->addPrefixForTableAndColumn($table), $col);
|
||||
|
||||
$this->runExecQuery($query);
|
||||
}
|
||||
|
||||
return ! (bool) $this->error();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MOdify Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function modifyColumn(?string $table = NULL, ?array $columns = NULL)
|
||||
{
|
||||
$query = $this->forge->modifyColumn($this->addPrefixForTableAndColumn($table), $this->addPrefixForTableAndColumn($columns, 'column'));
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function renameColumn(?string $table = NULL , ?array $columns = NULL)
|
||||
{
|
||||
$query = $this->forge->renameColumn($this->addPrefixForTableAndColumn($table), $this->addPrefixForTableAndColumn($columns, 'column'));
|
||||
|
||||
return $this->runExecQuery($query);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
|
||||
class DBTool extends Connection
|
||||
{
|
||||
/**
|
||||
* Database Tool Driver
|
||||
*
|
||||
* @param object
|
||||
*/
|
||||
protected $tool;
|
||||
|
||||
/**
|
||||
* Magic Constructor
|
||||
*
|
||||
* @param array $settings
|
||||
*/
|
||||
public function __construct($settings = [])
|
||||
{
|
||||
parent::__construct($settings);
|
||||
|
||||
$this->tool = $this->getDriver('Tool', $settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* List Databases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listDatabases()
|
||||
{
|
||||
return $this->tool->listDatabases();
|
||||
}
|
||||
|
||||
/**
|
||||
* List Tables
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listTables()
|
||||
{
|
||||
return $this->tool->listTables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Status Tabkes
|
||||
*
|
||||
* @param mixed $table
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function statusTables($table = '*')
|
||||
{
|
||||
return $this->tool->statusTables($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize Tabkes
|
||||
*
|
||||
* @param mixed $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function optimizeTables($table = '*')
|
||||
{
|
||||
return $this->tool->optimizeTables($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repair Tables
|
||||
*
|
||||
* @param mixed $table
|
||||
* @param string $query = 'REPAIR TABLE'
|
||||
* @param string $message = 'repairTablesSuccess'
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function repairTables($table = '*')
|
||||
{
|
||||
return $this->tool->repairTables($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Backup Table
|
||||
*
|
||||
* @param mixed $tables
|
||||
* @param string $fileName
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function backup($tables = '*', ?string $fileName = NULL, string $path = STORAGE_DIR)
|
||||
{
|
||||
return $this->tool->backup($tables, $fileName, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import File
|
||||
*
|
||||
* @param string $file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function import(string $file)
|
||||
{
|
||||
return $this->tool->import($file);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default Configuration
|
||||
*
|
||||
* Enabled when the configuration file can not be accessed.
|
||||
*/
|
||||
class DatabaseDefaultConfiguration
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Database
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Database connection settings are made.
|
||||
|
|
||||
| driver : The database platform to be used is set.
|
||||
| Options: mysqli, pdo(Only MySQL), oracle, postgres, sqlite,
|
||||
| sqlserver, odbc
|
||||
| host : Database server address.
|
||||
| database : Sets the database name.
|
||||
| user : Sets the database user name.
|
||||
| password : Sets the database user password.
|
||||
| dns : DSN connection settings.
|
||||
| Using Database: Oracle, ODBC, Postgres, PDO
|
||||
| server : Sets the server.
|
||||
| Using Database: ODBC, SQLServer
|
||||
| port : Sets the port.
|
||||
| Using Database: Postgres, SQLServer, PDO:MySQL
|
||||
| ssl : SSL connection.
|
||||
| Using Database: PDO, MySQLi
|
||||
| cacheDriver: Sets the cache driver.
|
||||
| Options: get, apcu, apc, memcache, wincache, file, redis
|
||||
| queryLog : Sets the loging of queries.
|
||||
| pconnect : Sets the persistent connection status.
|
||||
| Using Database: Oracle, ODBC, Postgres, SQLite
|
||||
| encode : It only uses the SQLServer driver.
|
||||
| prefix : Defines a prefix for prefixed tables.
|
||||
| charset : Character encoding of constructions.
|
||||
| collation : Character group definition.
|
||||
| Using Database: MySQLi, PDO:MySQL
|
||||
| differentConnection: It creates different connections at the same time.
|
||||
| Used with DB/Forge/Tool::differentConnection() method.
|
||||
| ['x' => ['driver' => 'postgres', ...], ...]
|
||||
|
|
||||
*/
|
||||
|
||||
public $driver = 'mysqli';
|
||||
public $host = 'localhost';
|
||||
public $database = 'test';
|
||||
public $user = 'root';
|
||||
public $password = '';
|
||||
public $dsn = '';
|
||||
public $server = '';
|
||||
public $port = '';
|
||||
public $ssl =
|
||||
[
|
||||
'key' => NULL,
|
||||
'cert' => NULL,
|
||||
'ca' => NULL,
|
||||
'capath' => NULL,
|
||||
'cipher' => NULL
|
||||
];
|
||||
public $cacheDriver = 'file';
|
||||
public $queryLog = false;
|
||||
public $pconnect = false;
|
||||
public $encode = false;
|
||||
public $prefix = '';
|
||||
public $charset = 'utf8';
|
||||
public $collation = 'utf8_general_ci';
|
||||
public $differentConnection = [];
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default Configuration
|
||||
*
|
||||
* Enabled when the language file can not be accessed.
|
||||
*/
|
||||
class DatabaseDefaultLanguage
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Database
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The language of the Database library.
|
||||
|
|
||||
*/
|
||||
|
||||
public $en =
|
||||
[
|
||||
'tableNotExistsError' => '`%` table is not exists!',
|
||||
'updateError' => 'Update not performed!',
|
||||
'connectError' => 'ERROR: Database connection error! Please check your connection settings.',
|
||||
'duplicateCheckError' => '`%` Column or Columns could not be added because it has the same value as before!',
|
||||
'optimizeTablesSuccess' => 'The optimization process was completed successfully.',
|
||||
'backupTablesSuccess' => 'The backup process was completed successfully.',
|
||||
'repairTablesSuccess' => 'The repair process was completed successfully.'
|
||||
];
|
||||
|
||||
public $tr =
|
||||
[
|
||||
'tableNotExistsError' => '`%` tablosu bulunamadı!',
|
||||
'updateError' => 'Güncelleme işlemi gerçekleştirilemedi!',
|
||||
'connectError' => 'HATA: Veritabanı bağlantısı sağlanamadı! Lütfen bağlantı ayarlarınızı kontrol edin.',
|
||||
'duplicateCheckError' => '`%` sütun veya sütunları daha önce aynı değere sahip olduğu için eklenemedi!',
|
||||
'optimizeTablesSuccess' => 'Optimizasyon işlemi başarı ile tamamlandı.',
|
||||
'backupTablesSuccess' => 'Yedekleme işlemi başarı ile tamamlandı.',
|
||||
'repairTablesSuccess' => 'Onarma işlemi başarı ile tamamlandı.'
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Lang;
|
||||
use ZN\Singleton;
|
||||
|
||||
class DriverExtends
|
||||
{
|
||||
protected $differentConnection;
|
||||
protected $settings;
|
||||
protected $getLang;
|
||||
|
||||
public function __construct($settings = [])
|
||||
{
|
||||
$this->settings = $settings;
|
||||
$this->differentConnection = Singleton::class('ZN\Database\DB')->differentConnection($settings);
|
||||
$this->getLang = Lang::default('ZN\Database\DatabaseDefaultLanguage')::select('Database');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,458 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Singleton;
|
||||
|
||||
class DriverForge
|
||||
{
|
||||
/**
|
||||
* Create Table & Database Extras
|
||||
*
|
||||
* @param mixed $extras
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function extras($extras)
|
||||
{
|
||||
return $extras;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Database
|
||||
*
|
||||
* @param string $dbname
|
||||
* @param string $extras
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createDatabase($dbname, $extras)
|
||||
{
|
||||
return 'CREATE DATABASE ' . $dbname . $this->addExtrasForCreateProcess($extras);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Database
|
||||
*
|
||||
* @param string $dbname
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropDatabase($dbname)
|
||||
{
|
||||
return 'DROP DATABASE ' . $dbname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Table
|
||||
*
|
||||
* @param string $tabşe
|
||||
* @param array $columns
|
||||
* @param string $extras
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createTable($table, $columns, $extras)
|
||||
{
|
||||
return 'CREATE TABLE ' . $this->createTableColumnsSyntax($table, $columns, $extras);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Temporary Table
|
||||
*
|
||||
* @param string $tabşe
|
||||
* @param array $columns
|
||||
* @param string $extras
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function createTempTable($table, $columns, $extras)
|
||||
{
|
||||
return 'CREATE TEMPORARY TABLE ' . $this->createTableColumnsSyntax($table, $columns, $extras);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected create table columns syntax
|
||||
*/
|
||||
protected function createTableColumnsSyntax($table, $columns, $extras)
|
||||
{
|
||||
$column = '';
|
||||
|
||||
foreach( $columns as $key => $value )
|
||||
{
|
||||
$values = '';
|
||||
|
||||
if( is_array($value) ) foreach( $value as $val )
|
||||
{
|
||||
$values .= ' ' . rtrim($val);
|
||||
}
|
||||
else
|
||||
{
|
||||
$values = $value;
|
||||
}
|
||||
|
||||
$this->commonConversion($key, $values);
|
||||
|
||||
$column .= $key . ' ' . rtrim($values) . ', ';
|
||||
}
|
||||
|
||||
return $table . '(' .rtrim(trim($column), ', ') . ')' . $this->addExtrasForCreateProcess($extras);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Table
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropTable($table)
|
||||
{
|
||||
return 'DROP TABLE ' . $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter Table
|
||||
*
|
||||
* @param string $table
|
||||
* @param mixed $condition
|
||||
*/
|
||||
public function alterTable($table, $condition){}
|
||||
|
||||
/**
|
||||
* Rename Table
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $newname
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renameTable($name, $newName)
|
||||
{
|
||||
return 'ALTER TABLE ' . $name . ' RENAME TO ' . $newName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function truncate($table)
|
||||
{
|
||||
return 'TRUNCATE TABLE ' . $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function addColumn($table, $columns)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' ADD (' . $this->buildForgeColumnsQuery($columns) . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropColumn($table, $column)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' DROP ' . $column . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Auto Increment
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param int $start = 0
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function startAutoIncrement($table, $start = 0)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' ' . $this->db()->autoIncrement() . '=' . $start . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Primary Key
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
* @param string $constraint = NULL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function addPrimaryKey($table, $columns, $constraint = NULL)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' ADD ' . $this->addedConstraint($constraint) . $this->db()->primaryKey() . '(' . $columns . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Foreign Key
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
* @param string $reftable
|
||||
* @param string $refcolumn
|
||||
* @param string $constraint = NULL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function addForeignKey($table, $columns, $reftable, $refcolumn, $constraint = NULL)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' ADD ' . $this->addedConstraint($constraint) . $this->db()->foreignKey() . '(' . $columns . ') REFERENCES '.$reftable.'('.$refcolumn.');';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createIndex($indexName, $table, $columns, $uniq = NULL)
|
||||
{
|
||||
return 'CREATE ' . $uniq . ' INDEX ' . $indexName . ' ON ' . $table . ' (' . $columns . ');';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Unique index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createUniqueIndex($indexName, $table, $columns)
|
||||
{
|
||||
return $this->createIndex($indexName, $table, $columns, 'UNIQUE');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Fulltext index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createFulltextIndex($indexName, $table, $columns)
|
||||
{
|
||||
return $this->createIndex($indexName, $table, $columns, 'FULLTEXT');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Spatial index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createSpatialIndex($indexName, $table, $columns)
|
||||
{
|
||||
return $this->createIndex($indexName, $table, $columns, 'SPATIAL');
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropIndex($indexName, $table)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' DROP INDEX ' . $indexName . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Primary Key
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $constraint = NULL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropPrimaryKey($table, $constraint = NULL)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' DROP ' . $this->db()->constraint() . ' ' . $constraint . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Foreign Key
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $constraint = NULL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropForeignKey($table, $constraint = NULL)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' DROP ' . $this->db()->constraint() . $constraint . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* MOdify Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function modifyColumn($table, $columns)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' MODIFY ' . $this->buildForgeColumnsQuery($columns) . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renameColumn($table, $columns)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' CHANGE COLUMN ' . $this->buildForgeColumnsQuery($columns) . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected added constraint
|
||||
*/
|
||||
protected function addedConstraint($string = NULL)
|
||||
{
|
||||
if( $string !== NULL )
|
||||
{
|
||||
return $this->db()->constraint() . ' ' . $string . ' ';
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected DB class
|
||||
*
|
||||
* @return ZN\Database\DB
|
||||
*/
|
||||
protected function db()
|
||||
{
|
||||
return Singleton::class('ZN\Database\DB');
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected common conversion
|
||||
*/
|
||||
protected function commonConversion($key, &$value)
|
||||
{
|
||||
$value = preg_replace('/('.$this->db()->constraint().'.*?)*('.(rtrim($this->db()->foreignKey())).')/', ', $1 $2 ('.$key.')', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* protected Syntax
|
||||
*/
|
||||
protected function buildForgeColumnsSyntax($column, $sep = NULL)
|
||||
{
|
||||
return key($column) . ' ' . $sep . ' ' . (is_array($cols = current($column)) ? implode(' ', $cols) : $cols);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Extract Column
|
||||
*/
|
||||
protected function buildForgeColumnsQuery($columns)
|
||||
{
|
||||
$con = '';
|
||||
|
||||
foreach( $columns as $column => $values )
|
||||
{
|
||||
$colvals = '';
|
||||
|
||||
if( is_array($values) )
|
||||
{
|
||||
foreach( $values as $val )
|
||||
{
|
||||
$colvals .= ' ' . $val;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$colvals .= ' ' . $values;
|
||||
}
|
||||
|
||||
$con .= $column . $colvals . ',';
|
||||
}
|
||||
|
||||
return rtrim($con, ',');
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Extras
|
||||
*/
|
||||
protected function addExtrasForCreateProcess($extras)
|
||||
{
|
||||
if( is_array($extras) )
|
||||
{
|
||||
$extraCodes = ' ' . implode(' ', $extras) . ';'; // @codeCoverageIgnore
|
||||
}
|
||||
elseif( is_string($extras) )
|
||||
{
|
||||
$extraCodes = ' ' . $extras . ';';
|
||||
}
|
||||
else
|
||||
{
|
||||
$extraCodes = '';
|
||||
}
|
||||
|
||||
return $extraCodes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Protection\Json;
|
||||
|
||||
abstract class DriverMappingAbstract
|
||||
{
|
||||
/**
|
||||
* Variables
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $config, $connect, $query;
|
||||
|
||||
/**
|
||||
* Abstract Methods
|
||||
*/
|
||||
abstract public function connect($config);
|
||||
abstract public function exec($query, $security);
|
||||
abstract public function query($query, $security);
|
||||
|
||||
/**
|
||||
* Standart Methods
|
||||
*/
|
||||
public function multiQuery($query, $security){}
|
||||
public function transStart(){}
|
||||
public function transRollback(){}
|
||||
public function transCommit(){}
|
||||
public function insertID(){}
|
||||
public function columnData($column){}
|
||||
public function numRows(){}
|
||||
public function columns(){}
|
||||
public function numFields(){}
|
||||
public function realEscapeString($data){}
|
||||
public function error(){}
|
||||
public function fetchArray(){}
|
||||
public function fetchAssoc(){}
|
||||
public function fetchRow(){}
|
||||
public function affectedRows(){}
|
||||
public function version(){}
|
||||
|
||||
/**
|
||||
* Protected Clean Limit
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function cleanLimit($data)
|
||||
{
|
||||
return preg_replace('/limit\s+[0-9]+(\s*OFFSET\s*[0-9]+)*/xi', '', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Get Limit Values
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLimitValues($data)
|
||||
{
|
||||
preg_match('/limit\s+(?<limit>[0-9]+)(\s*OFFSET\s*(?<start>[0-9]+))*/xi', $data ?? '', $match);
|
||||
|
||||
return $match;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit
|
||||
*
|
||||
* @param int $start = NULL
|
||||
* @param int $limit = 0
|
||||
*
|
||||
* @return DB
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function limit($start = NULL, int $limit = 0)
|
||||
{
|
||||
return ' LIMIT '. ( ! empty($limit) ? $limit . ' OFFSET ' . $start. ' ' : $start );
|
||||
}
|
||||
|
||||
/**
|
||||
* protected get insert extras by drvier
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getInsertExtrasByDriver()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Result
|
||||
*
|
||||
* @param string $type = 'object'
|
||||
*
|
||||
* @return object|array|string
|
||||
*/
|
||||
public function result($type = 'object', $jsonColumns = NULL, $usageRow = false)
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
$rows = [];
|
||||
|
||||
while( $data = $this->fetchAssoc() )
|
||||
{
|
||||
if( $jsonColumns )
|
||||
{
|
||||
$data = $this->jsonDecode($jsonColumns, $data, $type, $usageRow);
|
||||
}
|
||||
|
||||
if( $type === 'object' )
|
||||
{
|
||||
$data = (object) $data;
|
||||
}
|
||||
|
||||
$rows[] = $data;
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Result Array
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function resultArray()
|
||||
{
|
||||
return $this->result('array');
|
||||
}
|
||||
|
||||
/**
|
||||
* Row
|
||||
*
|
||||
* @return object|false
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function row()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
$data = $this->fetchAssoc();
|
||||
|
||||
return (object) $data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* References
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $column
|
||||
*/
|
||||
public function references($table, $column)
|
||||
{
|
||||
return 'REFERENCES '.$table.'('.$column.')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Foreign Key
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $references
|
||||
*/
|
||||
public function foreignKey($column = NULL, $references = NULL)
|
||||
{
|
||||
if( $references === NULL )
|
||||
{
|
||||
return $this->statements('foreignkey', $column);
|
||||
}
|
||||
// @codeCoverageIgnoreStart
|
||||
elseif( $column === NULL )
|
||||
{
|
||||
return $this->statements('foreignkey');
|
||||
}
|
||||
|
||||
return $this->statements('foreignkey') . ' ' . $this->references($column, $references);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Full Text
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $value
|
||||
* @param string $type = NULL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function fullText($column, $value, $type = NULL)
|
||||
{
|
||||
$against = '';
|
||||
|
||||
switch( $type )
|
||||
{
|
||||
case 'boolean' : $against = ' IN BOOLEAN MODE' ; break;
|
||||
case 'booleanExpansion' : $against = ' IN BOOLEAN MODE WITH QUERY EXPANSION' ; break;
|
||||
case 'language' : $against = ' IN NATURAL LANGUAGE MODE' ; break;
|
||||
case 'expansion' : $against = ' WITH QUERY EXPANSION' ; break;
|
||||
case 'languageExpansion': $against = ' IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION'; break;
|
||||
}
|
||||
|
||||
return 'MATCH(' . $column . ') AGAINST(' . $value . $against . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Where Json
|
||||
*
|
||||
* @string $column
|
||||
* @string $value
|
||||
*/
|
||||
public function whereJson($column, $value, $type = 'IS NOT NULL')
|
||||
{
|
||||
return 'JSON_SEARCH('.$column.', \'one\', '.$value.') ' . $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Where Not Json
|
||||
*
|
||||
* @string $column
|
||||
* @string $value
|
||||
*/
|
||||
public function whereNotJson($column, $value)
|
||||
{
|
||||
return $this->whereJson($column, $value, 'IS NULL');
|
||||
}
|
||||
|
||||
/**
|
||||
* Vartypes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function vartypes()
|
||||
{
|
||||
return $this->variableTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cvartype
|
||||
*
|
||||
* @param string $type = NULL
|
||||
* @param int $len = NULL
|
||||
* @param bool $output = true
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function cvartype($type = NULL, $len = NULL, $output = true)
|
||||
{
|
||||
if( empty($len) )
|
||||
{
|
||||
return " $type ";
|
||||
}
|
||||
elseif( $output === true )
|
||||
{
|
||||
return " $type($len) ";
|
||||
}
|
||||
else
|
||||
{
|
||||
return " $type $len ";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Operator
|
||||
*
|
||||
* @param string $operator = 'like'
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function operator($operator = 'like')
|
||||
{
|
||||
$operator = strtolower($operator);
|
||||
|
||||
return $this->operators[$operator] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Statements
|
||||
*
|
||||
* @param string $state = NULL
|
||||
* @param int $len = NULL
|
||||
* @param bool $type = true
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function statements($state = NULL, $len = NULL, $type = true)
|
||||
{
|
||||
$state = strtolower($state ?? '');
|
||||
|
||||
if( $isstate = ($this->statements[$state] ?? NULL) )
|
||||
{
|
||||
if( strstr($isstate, '%') )
|
||||
{
|
||||
$vartype = str_replace('%', $len ?? '', $isstate); // @codeCoverageIgnore
|
||||
|
||||
return $this->cvartype($vartype); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $this->cvartype($isstate, $len, $type);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes a previously opened database connection
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
if( ! empty($this->connect) )
|
||||
{
|
||||
$this->query = NULL;
|
||||
$this->connect = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Variable Types
|
||||
*
|
||||
* @param string $vartype = NULL
|
||||
* @param int $len = NULL
|
||||
* @param bool $type = true
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function variableTypes($vartype = NULL, $len = NULL, $type = true)
|
||||
{
|
||||
$vartype = strtolower($vartype ?? '');
|
||||
|
||||
if( $isvartype = ($this->variableTypes[$vartype] ?? NULL) )
|
||||
{
|
||||
if( strpos($isvartype, ':') === 0 )
|
||||
{
|
||||
$len = NULL;
|
||||
$isvartype = substr($isvartype, 1);
|
||||
}
|
||||
|
||||
return $this->cvartype($isvartype, $len, $type);
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* protected json decode
|
||||
*/
|
||||
protected function jsonDecode($columns, $row, $type, $usageRow)
|
||||
{
|
||||
$columns = $columns === '*' ? array_keys(preg_grep('/^(\{|\[).*(\]|\})$/s', $row)) : $columns;
|
||||
|
||||
if( is_array($columns) )
|
||||
{
|
||||
foreach( $columns as $column )
|
||||
{
|
||||
$value = $row[$column] ?? '';
|
||||
|
||||
if( Json::check($value) )
|
||||
{
|
||||
$row[$column] = ( $type === 'object' || $usageRow === true ) ? Json::decodeObject($value) : Json::decodeArray($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
return $row; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use stdClass;
|
||||
use ZN\Base;
|
||||
|
||||
class DriverTool extends DriverExtends
|
||||
{
|
||||
/**
|
||||
* List Databases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listDatabases($query = 'SHOW DATABASES')
|
||||
{
|
||||
return $this->runListQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* List Tables
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listTables($query = 'SHOW TABLES')
|
||||
{
|
||||
return $this->runListQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected List
|
||||
*/
|
||||
protected function runListQuery($query)
|
||||
{
|
||||
$result = $this->differentConnection->query($query)->result();
|
||||
|
||||
if( empty($result) )
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
$newTables = [];
|
||||
|
||||
foreach( $result as $tables )
|
||||
{
|
||||
foreach( $tables as $tb => $table )
|
||||
{
|
||||
$newTables[] = $table;
|
||||
}
|
||||
}
|
||||
|
||||
return $newTables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Status Tabkes
|
||||
*
|
||||
* @param mixed $table
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function statusTables($table)
|
||||
{
|
||||
$infos = new stdClass;
|
||||
|
||||
if( $table === '*' )
|
||||
{
|
||||
$listTables = $this->listTables();
|
||||
|
||||
foreach( $listTables as $table )
|
||||
{
|
||||
$infos->$table = $this->differentConnection->status($table)->row(); // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
elseif( is_array($table) )
|
||||
{
|
||||
foreach( $table as $tbl )
|
||||
{
|
||||
$infos->$tbl = $this->differentConnection->status($tbl)->row();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$infos = $this->differentConnection->status($table)->row();
|
||||
}
|
||||
|
||||
return $infos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize Tabkes
|
||||
*
|
||||
* @param mixed $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function optimizeTables($table)
|
||||
{
|
||||
return $this->repairTables($table, 'OPTIMIZE TABLE', 'optimizeTablesSuccess');
|
||||
}
|
||||
|
||||
/**
|
||||
* Repair Tables
|
||||
*
|
||||
* @param mixed $table
|
||||
* @param string $query = 'REPAIR TABLE'
|
||||
* @param string $message = 'repairTablesSuccess'
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function repairTables($table, $query = 'REPAIR TABLE', $message = 'repairTablesSuccess')
|
||||
{
|
||||
$result = $this->differentConnection->query("SHOW TABLES")->result();
|
||||
$status = NULL;
|
||||
|
||||
if( $table === '*' )
|
||||
{
|
||||
foreach( $result as $tables )
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
foreach( $tables as $db => $tableName )
|
||||
{
|
||||
$status = $this->differentConnection->query($query . ' ' . $tableName);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$tables = is_array($table)
|
||||
? $table
|
||||
: explode(',',$table);
|
||||
|
||||
foreach( $tables as $tableName )
|
||||
{
|
||||
$status = $this->differentConnection->query($query . ' ' . Properties::$prefix . $tableName);
|
||||
}
|
||||
}
|
||||
|
||||
if( $status !== NULL )
|
||||
{
|
||||
return $this->getLang[$message];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backup Table
|
||||
*
|
||||
* @param mixed $tables
|
||||
* @param string $fileName
|
||||
* @param string $path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function backup($tables, $fileName, $path)
|
||||
{
|
||||
if( $path === STORAGE_DIR )
|
||||
{
|
||||
$path .= 'DatabaseBackup'; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$eol = EOL;
|
||||
|
||||
if( $tables === '*' )
|
||||
{
|
||||
$tables = [];
|
||||
|
||||
$resultArray = $this->differentConnection->query('SHOW TABLES')->resultArray();
|
||||
|
||||
foreach( $resultArray as $key => $val )
|
||||
{
|
||||
$tables[] = current($val); // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$tables = ( is_array($tables) )
|
||||
? $tables
|
||||
: explode(',',$tables);
|
||||
}
|
||||
|
||||
$return = '';
|
||||
|
||||
foreach( $tables as $table )
|
||||
{
|
||||
if( ! empty(Properties::$prefix) && ! strstr($table, Properties::$prefix) )
|
||||
{
|
||||
$table = Properties::$prefix.$table; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$return .= 'DROP TABLE IF EXISTS '.$table.';';
|
||||
|
||||
$fetchRow = $this->differentConnection->query('SHOW CREATE TABLE '.$table)->fetchRow();
|
||||
|
||||
if( ! $fetchRow )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
$fetchResult = $this->differentConnection->query('SELECT * FROM '.$table)->result();
|
||||
|
||||
$return .= $eol.$eol.$fetchRow[1].";".$eol.$eol;
|
||||
|
||||
if( ! empty($fetchResult) ) foreach( $fetchResult as $row )
|
||||
{
|
||||
$return.= 'INSERT INTO '.$table.' VALUES(';
|
||||
|
||||
foreach( $row as $k => $v )
|
||||
{
|
||||
$v = preg_replace("/\n/","\\n", $v ?? '');
|
||||
|
||||
if( is_numeric($v) )
|
||||
{
|
||||
$return.= $v;
|
||||
}
|
||||
else if( empty($v) )
|
||||
{
|
||||
$return.= 'NULL';
|
||||
}
|
||||
else
|
||||
{
|
||||
$return.= '"' . addslashes(stripslashes($v)) .'"' ;
|
||||
}
|
||||
|
||||
$return.= ', ';
|
||||
}
|
||||
|
||||
$return = rtrim(trim($return), ', ');
|
||||
|
||||
$return .= ");".$eol;
|
||||
}
|
||||
|
||||
$return .= $eol.$eol.$eol;
|
||||
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
if( ! trim($return) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( empty($fileName) )
|
||||
{
|
||||
$fileName = 'db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql';
|
||||
}
|
||||
|
||||
if( ! is_dir($path) )
|
||||
{
|
||||
mkdir($path); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
file_put_contents(Base::suffix($path) . $fileName, $return);
|
||||
|
||||
return $this->getLang['backupTablesSuccess'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Import File
|
||||
*
|
||||
* @param string $file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function import(string $file)
|
||||
{
|
||||
if( is_file($file) )
|
||||
{
|
||||
return $this->differentConnection->multiQuery(file_get_contents($file));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php namespace ZN\Database\Exception;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Exception;
|
||||
|
||||
class ConnectionErrorException extends Exception
|
||||
{
|
||||
const lang =
|
||||
[
|
||||
'tr' => 'Veritabanı bağlantısı sağlanamadı! Lütfen bağlantı ayarlarınızı kontrol edin! [%]',
|
||||
'en' => 'Database connection error! Please check your connection settings! [%]'
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php namespace ZN\Database\Exception;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Exception;
|
||||
|
||||
class DatabaseErrorException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php namespace ZN\Database\Exception;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Exception;
|
||||
|
||||
class DuplicateCheckException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php namespace ZN\Database\Exception;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Exception;
|
||||
|
||||
class InvalidArgumentException extends Exception
|
||||
{
|
||||
const lang =
|
||||
[
|
||||
'tr' => '[%] yöntemini parametresiz kullanamazsınız!',
|
||||
'en' => 'You cannot use the [%] method without parameters!'
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php namespace ZN\Database\Exception;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Exception;
|
||||
|
||||
class NoSearchException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php namespace ZN\Database\Exception;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Exception;
|
||||
|
||||
class NoTableException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php namespace ZN\Database\Exception;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Exception;
|
||||
|
||||
class OrderByInvalidSecondArgumentException extends Exception
|
||||
{
|
||||
const lang =
|
||||
[
|
||||
'tr' => 'string $type parametresi "asc" veya "desc" değerlerini alabilir!',
|
||||
'en' => 'string $type parameter can take "asc" or "desc" values!'
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php namespace ZN\Database\Exception;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Exception;
|
||||
|
||||
class UnconditionalException extends Exception
|
||||
{
|
||||
const lang =
|
||||
[
|
||||
'placement' =>
|
||||
[
|
||||
'#' => '[DB::where(mixed $column, string $value [, string $condition = "and"])]'
|
||||
],
|
||||
'tr' => 'Koşulsuz silme işlemi gerçekleştiremezsiniz! Lütfen # ile koşul tanımlayın.',
|
||||
'en' => 'You can not perform unconditional deletion! Please define the condition with #.'
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,724 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Base;
|
||||
use ZN\Config;
|
||||
use ZN\Support;
|
||||
use ZN\Datatype;
|
||||
use ZN\Singleton;
|
||||
|
||||
class GrandModel
|
||||
{
|
||||
/**
|
||||
* Table name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $grandTable = '';
|
||||
|
||||
/**
|
||||
* Keep connection
|
||||
*
|
||||
* @var resource
|
||||
*/
|
||||
protected $connect;
|
||||
|
||||
/**
|
||||
* Keep connection for DBTool library
|
||||
*
|
||||
* @var resource
|
||||
*/
|
||||
protected $connectTool;
|
||||
|
||||
/**
|
||||
* Keep connection for DBForge library
|
||||
*
|
||||
* @var resource
|
||||
*/
|
||||
protected $connectForge;
|
||||
|
||||
/**
|
||||
* Get list tables
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $tables;
|
||||
|
||||
/**
|
||||
* Process status
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $status;
|
||||
|
||||
/**
|
||||
* Get query result
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $get;
|
||||
|
||||
/**
|
||||
* Keep options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
/**
|
||||
* Table prefix
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* String query
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $stringQuery;
|
||||
|
||||
/**
|
||||
* Error
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $error;
|
||||
|
||||
/**
|
||||
* Magic constructor
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
# Get database connections
|
||||
$this->getDatabaseConnections();
|
||||
|
||||
# Get active table name
|
||||
$this->setGrandTableName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic call
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
*
|
||||
* @param mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
# If it is a valid transaction type.
|
||||
if( $this->isCallColumnTransaction($method, $transaction) )
|
||||
{
|
||||
return $this->callColumnProcess($method, $parameters, $transaction);
|
||||
}
|
||||
else if( $this->isDatabaseCallMethod($method, $parameters) !== false )
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->callColumnForge($method, $parameters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data insert
|
||||
*
|
||||
* @param mixed $data = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function insert($data = NULL) : bool
|
||||
{
|
||||
$this->postGetExpression($table, $data);
|
||||
|
||||
return $this->returnQuery($this->connect->insert($table, $data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert csv
|
||||
*
|
||||
* @param string $file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function insertCSV(string $file) : bool
|
||||
{
|
||||
return $this->connect->insertCSV($this->grandTable, $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Last insert id
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function insertID() : int
|
||||
{
|
||||
return $this->connect->insertID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Last hash id
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function hashId()
|
||||
{
|
||||
return $this->connect->hashId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is exists value into table
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isExists(string $column, string $value) : bool
|
||||
{
|
||||
return $this->connect->isExists($this->grandTable, $column, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update data
|
||||
*
|
||||
* @param mixed $data = NULL
|
||||
* @param string $column = NULL
|
||||
* @param string $value = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function update($data = NULL, ?string $column = NULL, ?string $value = NULL) : bool
|
||||
{
|
||||
$this->postGetExpression($table, $data);
|
||||
|
||||
if( $column !== NULL )
|
||||
{
|
||||
$this->connect->where($column, $value);
|
||||
}
|
||||
|
||||
return $this->returnQuery($this->connect->update($table, $data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete data
|
||||
*
|
||||
* @param string $column = NULL
|
||||
* @param string $value = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete(?string $column = NULL, ?string $value = NULL) : bool
|
||||
{
|
||||
if( $column !== NULL )
|
||||
{
|
||||
$this->connect->where($column, $value);
|
||||
}
|
||||
|
||||
return $this->returnQuery($this->connect->delete($this->grandTable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table object. It is like using DB::get($table)
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return $this->connect->get($this->grandTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* protected db get
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
protected function getInstance()
|
||||
{
|
||||
return $this->get = $this->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get columns
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function columns() : array
|
||||
{
|
||||
return $this->returnQuery($this->getInstance()->columns());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total columns
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function totalColumns() : int
|
||||
{
|
||||
return $this->returnQuery($this->getInstance()->totalColumns());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get row
|
||||
*
|
||||
* @param mixed $printable = false - options[bool|index]
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function row($printable = false)
|
||||
{
|
||||
return $this->returnQuery($this->getInstance()->row($printable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get result
|
||||
*
|
||||
* @param string $type = 'object' - options[object|array|json]
|
||||
*/
|
||||
public function result(string $type = 'object')
|
||||
{
|
||||
return $this->returnQuery($this->getInstance()->result($type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment columns value
|
||||
*
|
||||
* @param mixed $columns
|
||||
* @param int $increment = 1
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function increment($columns, int $increment = 1) : bool
|
||||
{
|
||||
return $this->returnQuery($this->connect->increment($this->grandTable, $columns, $increment));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement columns value
|
||||
*
|
||||
* @param mixed $columns
|
||||
* @param int $decrement = 1
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function decrement($columns, int $decrement = 1) : bool
|
||||
{
|
||||
return $this->returnQuery($this->connect->decrement($this->grandTable, $columns, $decrement));
|
||||
}
|
||||
|
||||
/**
|
||||
* Status table
|
||||
*
|
||||
* @param string $type = 'row' - options[row|result]
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function status(string $type = 'row')
|
||||
{
|
||||
return $this->returnQuery($this->connect->status($this->grandTable)->$type());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total rows
|
||||
*
|
||||
* @param bool $status = false
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function totalRows(bool $status = false) : int
|
||||
{
|
||||
return $this->returnQuery($this->getCurrent()->totalRows($status));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pagination
|
||||
*
|
||||
* @param string $url = NULL
|
||||
* @param array $settings = []
|
||||
* @param bool $output = true
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function pagination(?string $url = NULL, array $settings = [], bool $output = true)
|
||||
{
|
||||
return $this->getCurrent()->pagination($url, $settings, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create table
|
||||
*
|
||||
* @param mixed $data
|
||||
* @param mxeid $extra = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function create($data = NULL, $extra = NULL) : bool
|
||||
{
|
||||
$this->status = 'create';
|
||||
|
||||
if( ! empty($this->options) )
|
||||
{
|
||||
$extra = $data;
|
||||
$data = $this->options;
|
||||
|
||||
$this->options = [];
|
||||
}
|
||||
|
||||
return $this->returnQuery($this->connectForge->createTable($this->grandTable, $data, $extra), 'forge');
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate table
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function truncate() : bool
|
||||
{
|
||||
return $this->returnQuery($this->connectForge->truncate($this->grandTable), 'forge');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add column
|
||||
*
|
||||
* @param array $columns
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function add() : bool
|
||||
{
|
||||
$columns = $this->options;
|
||||
|
||||
$this->options = [];
|
||||
|
||||
return $this->returnQuery($this->connectForge->addColumn($this->grandTable, $columns), 'forge');
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop column
|
||||
*
|
||||
* @param array $column
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function drop() : bool
|
||||
{
|
||||
$columns = $this->options;
|
||||
|
||||
$this->options = [];
|
||||
|
||||
return $this->returnQuery($this->connectForge->dropColumn($this->grandTable, array_keys($columns)), 'forge');
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify column
|
||||
*
|
||||
* @param array $columns
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function modify() : bool
|
||||
{
|
||||
$columns = $this->options;
|
||||
|
||||
$this->options = [];
|
||||
|
||||
return $this->returnQuery($this->connectForge->modifyColumn($this->grandTable, $columns), 'forge');
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename column
|
||||
*
|
||||
* @param array $column
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function rename() : bool
|
||||
{
|
||||
$columns = $this->options;
|
||||
|
||||
$this->options = [];
|
||||
|
||||
return $this->returnQuery($this->connectForge->renameColumn($this->grandTable, $columns), 'forge');
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize table
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function optimize() : string
|
||||
{
|
||||
return $this->returnQuery($this->connectTool->optimizeTables($this->grandTable), 'tool');
|
||||
}
|
||||
|
||||
/**
|
||||
* Repair table
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function repair() : string
|
||||
{
|
||||
return $this->returnQuery($this->connectTool->repairTables($this->grandTable), 'tool');
|
||||
}
|
||||
|
||||
/**
|
||||
* Backup table
|
||||
*
|
||||
* @param string $fileName = NULL
|
||||
* @param string $path = STORAGE_DIR
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function backup(?string $fileName = NULL, string $path = STORAGE_DIR) : string
|
||||
{
|
||||
return $this->returnQuery($this->connectTool->backup($this->grandTable, $fileName, $path), 'tool');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function error()
|
||||
{
|
||||
$error = $this->error ?: false;
|
||||
|
||||
$this->error = NULL;
|
||||
|
||||
return $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string query
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function stringQuery()
|
||||
{
|
||||
$query = $this->stringQuery ?: false;
|
||||
|
||||
$this->stringQuery = NULL;
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected get database connections
|
||||
*/
|
||||
protected function getDatabaseConnections()
|
||||
{
|
||||
$staticConnection = defined('static::connection') ? static::connection : NULL;
|
||||
|
||||
$this->connect = Singleton::class('ZN\Database\DB')->differentConnection($staticConnection);
|
||||
$this->connectTool = Singleton::class('ZN\Database\DBTool')->differentConnection($staticConnection);
|
||||
$this->connectForge = Singleton::class('ZN\Database\DBForge')->differentConnection($staticConnection);
|
||||
$this->tables = $this->connectTool->listTables();
|
||||
$this->prefix = $staticConnection['prefix'] ?? Config::database('database')['prefix'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected set grand table name
|
||||
*/
|
||||
protected function setGrandTableName()
|
||||
{
|
||||
if( defined('static::table') )
|
||||
{
|
||||
$this->grandTable = static::table;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->grandTable = $this->getGrandTableName(); // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected get grand table name
|
||||
*/
|
||||
protected function getGrandTableName()
|
||||
{
|
||||
return Base::removeSuffix
|
||||
(
|
||||
Base::removeSuffix
|
||||
(
|
||||
Base::removePrefix(Datatype::divide(get_called_class(), '\\', -1), INTERNAL_ACCESS),
|
||||
'Grand'
|
||||
),
|
||||
'Vision'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* protected post get expressions
|
||||
*
|
||||
* @param string &$table
|
||||
* @param array &$data
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function postGetExpression(&$table, &$data)
|
||||
{
|
||||
$table = $this->grandTable;
|
||||
|
||||
if( is_string($data) )
|
||||
{
|
||||
$table = $data . ':' . $table;
|
||||
$data = [];
|
||||
}
|
||||
|
||||
$data = $data ?: $this->options;
|
||||
|
||||
$this->options = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* protected call column process - 5.6.2|5.7.6.6[update]
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $params
|
||||
* @param string $type
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function callColumnProcess($method, $params, $type)
|
||||
{
|
||||
$func = $type;
|
||||
$col = substr($method, strlen($type));
|
||||
|
||||
if( $func === 'update' )
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
if( ! empty($this->options) )
|
||||
{
|
||||
$params[1] = $params[0] ?? NULL;
|
||||
$params[0] = $this->options;
|
||||
|
||||
$this->options = [];
|
||||
}
|
||||
|
||||
if( ! is_array($params[0] ?? NULL) || ! is_scalar($params[1] ?? []) )
|
||||
{
|
||||
throw new Exception\InvalidArgumentException(NULL, get_called_class() . '::update(array $data, scalar $value)');
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return $this->where($col, $params[1])->$func($params[0]);
|
||||
}
|
||||
|
||||
if( ! is_scalar($params[0] ?? []) )
|
||||
{
|
||||
throw new Exception\InvalidArgumentException(NULL, get_called_class() . '::' . $method . '(scalar $value)'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $this->where($col, $params[0])->$func();
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected call column forge
|
||||
*/
|
||||
protected function callColumnForge($method, $parameters)
|
||||
{
|
||||
# 5.3.7[added]
|
||||
$param = $parameters[0] ?? NULL;
|
||||
|
||||
$this->options[$method] = $param;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected is database call method
|
||||
*/
|
||||
protected function isDatabaseCallMethod($method, $parameters)
|
||||
{
|
||||
if( method_exists($this->connect, $method) )
|
||||
{
|
||||
return $this->connect->$method(...$parameters);
|
||||
}
|
||||
else if( method_exists($this->connectForge, $method) )
|
||||
{
|
||||
return $this->connectForge->$method(...$parameters); // @codeCoverageIgnore
|
||||
}
|
||||
else if( method_exists($this->connectTool, $method) )
|
||||
{
|
||||
return $this->connectTool->$method(...$parameters); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected is call column process
|
||||
*/
|
||||
protected function isCallColumnTransaction($method, &$selectTransaction)
|
||||
{
|
||||
if( preg_match('/^(row|result|update|delete)/', $method, $match) )
|
||||
{
|
||||
$selectTransaction = $match[1];
|
||||
}
|
||||
|
||||
return $selectTransaction ?? NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected return query
|
||||
*/
|
||||
protected function returnQuery($process, $fix = '')
|
||||
{
|
||||
$this->stringQuery = $this->{'connect' . ucfirst($fix)}->stringQuery();
|
||||
$this->error = $this->{'connect' . ucfirst($fix)}->error();
|
||||
|
||||
return $process;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected get current
|
||||
*/
|
||||
protected function getCurrent()
|
||||
{
|
||||
if( ! empty($this->get) )
|
||||
{
|
||||
$get = $this->get;
|
||||
}
|
||||
else
|
||||
{
|
||||
$get = $this->getInstance(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $get;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,780 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Config;
|
||||
use MongoDB\BSON\Regex;
|
||||
use MongoDB\Driver\Query;
|
||||
use MongoDB\Driver\Session;
|
||||
use MongoDB\Driver\Manager;
|
||||
use MongoDB\Driver\Command;
|
||||
use MongoDB\Driver\BulkWrite;
|
||||
use MongoDB\Driver\ReadConcern;
|
||||
use MongoDB\Driver\WriteConcern;
|
||||
use MongoDB\Driver\ReadPreference;
|
||||
use MongoDB\Driver\Exception\RuntimeException;
|
||||
use ZN\Database\Exception\OrderByInvalidSecondArgumentException;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class MDB implements MDBInterface
|
||||
{
|
||||
/**
|
||||
* Keeps database
|
||||
*/
|
||||
protected $database;
|
||||
|
||||
/**
|
||||
* Keeps manager
|
||||
*
|
||||
* @var Manager
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* Keeps host
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $host = '127.0.0.1';
|
||||
|
||||
/**
|
||||
* Keeps options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
/**
|
||||
* Keeps executable
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $executable = [];
|
||||
|
||||
/**
|
||||
* Keeps filters
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $filters = [];
|
||||
|
||||
/**
|
||||
* Keeps config
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $config = [];
|
||||
|
||||
/**
|
||||
* Keeps result
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $result;
|
||||
|
||||
/**
|
||||
* Keeps error
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $error = '';
|
||||
|
||||
/**
|
||||
* Magic constructor method.
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct($config = [])
|
||||
{
|
||||
if( $config !== NULL )
|
||||
{
|
||||
$config = $config ?: Config::get('Database')['mongodb'] ?? [];
|
||||
|
||||
$this->manager = new Manager
|
||||
(
|
||||
'mongodb://' . $config['dns'] . '/',
|
||||
$config['options'] ?? [],
|
||||
$config['driverOptions'] ?? []
|
||||
);
|
||||
|
||||
$this->database = $config['database'] ?? 'test';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executable
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function executable($options)
|
||||
{
|
||||
$this->executable = $config;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* MongoDB\Driver\WriteConcern
|
||||
*
|
||||
* @return WriteConcern
|
||||
*/
|
||||
public static function writeConcern(...$parameters)
|
||||
{
|
||||
return new WriteConcern(...$parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* MongoDB\Driver\ReadPreference
|
||||
*
|
||||
* @return ReadPreference
|
||||
*/
|
||||
public static function readPreference(...$parameters)
|
||||
{
|
||||
return new ReadPreference(...$parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* MongoDB\Driver\ReadConcern
|
||||
*
|
||||
* @return ReadConcern
|
||||
*/
|
||||
public static function readConcern(...$parameters)
|
||||
{
|
||||
return new ReadConcern(...$parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* MongoDB\Driver\Session
|
||||
*
|
||||
* @return Session
|
||||
*/
|
||||
public static function session(...$parameters)
|
||||
{
|
||||
return new Session(...$parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* New
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public static function new(array $config)
|
||||
{
|
||||
return new self($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $datas
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function insert(string $table, array $datas) : bool
|
||||
{
|
||||
$bulk = new BulkWrite;
|
||||
|
||||
if( is_array($datas[0]) )
|
||||
{
|
||||
foreach( $datas as $data )
|
||||
{
|
||||
$this->setAutoIncrement($table, $data);
|
||||
|
||||
$bulk->insert($data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->setAutoIncrement($table, $datas);
|
||||
|
||||
$bulk->insert($datas);
|
||||
}
|
||||
|
||||
return (bool) $this->operation($table, $bulk)->getInsertedCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete(string $table) : bool
|
||||
{
|
||||
$bulk = new BulkWrite;
|
||||
|
||||
$bulk->delete($this->filters);
|
||||
|
||||
return (bool) $this->operation($table, $bulk)->getDeletedCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $datas
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function update(string $table, array $datas = []) : bool
|
||||
{
|
||||
$bulk = new BulkWrite;
|
||||
|
||||
$this->options['multi'] = true;
|
||||
|
||||
$bulk->update($this->filters, ['$set' => $datas], $this->options);
|
||||
|
||||
return (bool) $this->operation($table, $bulk)->getModifiedCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Where Regex
|
||||
*
|
||||
* @param string $key
|
||||
* @param scalar $value
|
||||
* @param string $flags = ''
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function whereRegex(string $key, $value, string $flags = '')
|
||||
{
|
||||
return $this->filter($key, new Regex($value, $flags));
|
||||
}
|
||||
|
||||
/**
|
||||
* Where
|
||||
*
|
||||
* @param string $key
|
||||
* @param scalar $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function where(string $key, $value)
|
||||
{
|
||||
return $this->filter($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upsert
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function upsert()
|
||||
{
|
||||
return $this->option('upsert', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Option
|
||||
*
|
||||
* @param string $key
|
||||
* @param scalar $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function option(string $key, $value)
|
||||
{
|
||||
$this->options[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Option
|
||||
*
|
||||
* @param string $key
|
||||
* @param scalar $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function filter(string $key, $value)
|
||||
{
|
||||
$this->filters[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Total Rows
|
||||
*
|
||||
* @param int
|
||||
*/
|
||||
public function totalRows() : int
|
||||
{
|
||||
return count($this->result());
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit
|
||||
*
|
||||
* Usage - 1
|
||||
*
|
||||
* @param int $limit
|
||||
*
|
||||
* Usage - 2
|
||||
*
|
||||
* @param int $skip
|
||||
* @param int $limit
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function limit(int $skip, ?int $limit = NULL)
|
||||
{
|
||||
if( $limit === NULL )
|
||||
{
|
||||
$this->options['limit'] = $skip;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->options['limit'] = $limit;
|
||||
$this->options['skip' ] = $skip;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Order By
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $type = 'asc'
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function orderBy(string $column, string $type = 'asc')
|
||||
{
|
||||
$type = strtolower($type);
|
||||
$types = ['asc' => 1, 'desc' => -1];
|
||||
|
||||
if( ! isset($types[$type]) )
|
||||
{
|
||||
throw new OrderByInvalidSecondArgumentException;
|
||||
}
|
||||
|
||||
$this->options['sort'] = [$column => $types[$type]];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function get(string $table)
|
||||
{
|
||||
$execute = $this->execute($table);
|
||||
|
||||
return (new self(NULL))->complete($execute->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Result
|
||||
*
|
||||
* @return array|object
|
||||
*/
|
||||
public function result()
|
||||
{
|
||||
return $this->result ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Row
|
||||
*
|
||||
* @param int|bool $printable = 0
|
||||
*
|
||||
* @return object|false
|
||||
*/
|
||||
public function row($printable = 0)
|
||||
{
|
||||
$result = $this->result();
|
||||
|
||||
if( $printable < 0 )
|
||||
{
|
||||
$index = count($result) + $printable;
|
||||
|
||||
return isset($result[$index]) ? (object) $result[$index] : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( $printable === true )
|
||||
{
|
||||
return current((array) $result[0] ?? []);
|
||||
}
|
||||
|
||||
return isset($result[$printable]) ? (object) $result[$printable] : false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Index
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $indexes
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createIndex(string $table, array $indexes) : bool
|
||||
{
|
||||
$generateIndexses = [];
|
||||
|
||||
foreach( $indexes as $key => $value )
|
||||
{
|
||||
$generateIndexses[] = ['name' => $key, 'key' => [$key => $value], 'ns' => $this->collect($table)];
|
||||
}
|
||||
|
||||
$index = $this->executeWriteCommand(['createIndexes' => $table, 'indexes' => $generateIndexses]);
|
||||
|
||||
return ! $this->error = $index->toArray()[0]->note ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Index
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $indexName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dropIndex(string $table, string $indexName) : bool
|
||||
{
|
||||
try
|
||||
{
|
||||
$this->executeWriteCommand(['dropIndexes' => $table, 'index' => $indexName]);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch( RuntimeException $e )
|
||||
{
|
||||
$this->error = $e->getMessage();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop/Truncate
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function drop(string $table) : bool
|
||||
{
|
||||
return $this->truncate($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $options = []
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function create(string $table, array $options = []) : bool
|
||||
{
|
||||
try
|
||||
{
|
||||
$command = ['create' => $table];
|
||||
|
||||
foreach( ['autoIndexId', 'capped', 'flags', 'max', 'maxTimeMS', 'size', 'validationAction', 'validationLevel'] as $option )
|
||||
{
|
||||
if( isset($options[$option]) )
|
||||
{
|
||||
$command[$option] = $options[$option];
|
||||
}
|
||||
}
|
||||
|
||||
foreach( ['collation', 'indexOptionDefaults', 'storageEngine', 'validator'] as $option )
|
||||
{
|
||||
if( isset($options[$option]) )
|
||||
{
|
||||
$command[$option] = (object) $options[$option];
|
||||
}
|
||||
}
|
||||
|
||||
$drop = $this->executeWriteCommand($command);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch( RuntimeException $e )
|
||||
{
|
||||
$this->error = $e->getMessage();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Auto Increment
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $column
|
||||
*/
|
||||
public function createAutoIncrement(string $table, string $column)
|
||||
{
|
||||
$table = $this->getIndexCollectionName($table);
|
||||
|
||||
if( ! $this->get($table)->row() )
|
||||
{
|
||||
return $this->insert($table, [$column => 1]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected index get index collection name
|
||||
*/
|
||||
protected function getIndexCollectionName(string $table)
|
||||
{
|
||||
return $table . 'Indexes';
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate/Drop
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function truncate(string $table) : bool
|
||||
{
|
||||
try
|
||||
{
|
||||
$drop = $this->executeWriteCommand(['drop' => $table]);
|
||||
|
||||
if( $this->isAutoIncrement($table) )
|
||||
{
|
||||
$this->executeWriteCommand(['drop' => $table]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch( RuntimeException $e )
|
||||
{
|
||||
$this->error = $e->getMessage();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Databases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function databases() : array
|
||||
{
|
||||
$databases = $this->executeReadCommand('admin', ['listDatabases' => 1]);
|
||||
|
||||
$databases = $databases->toArray();
|
||||
|
||||
$returnDatabases = [];
|
||||
|
||||
foreach( $databases[0]['databases'] as $database )
|
||||
{
|
||||
$returnDatabases[] = $database['name'];
|
||||
}
|
||||
|
||||
return $returnDatabases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function indexes(string $table) : array
|
||||
{
|
||||
$indexes = $this->executeReadCommand($this->database, ['listIndexes' => $table]);
|
||||
|
||||
$indexes = $indexes->toArray();
|
||||
|
||||
$returnIndexes = [];
|
||||
|
||||
foreach( $indexes as $index )
|
||||
{
|
||||
$returnIndexes[] = ['key' => key((array) $index['key']), 'name' => $index['name'], 'value' => current((array) $index['key'])];
|
||||
}
|
||||
|
||||
return $returnIndexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tables/Collections
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function tables() : array
|
||||
{
|
||||
return $this->collections();
|
||||
}
|
||||
|
||||
/**
|
||||
* Collections/Tables
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function collections() : array
|
||||
{
|
||||
$collections = $this->executeReadCommand($this->database, ['listCollections' => 1]);
|
||||
|
||||
$collections = $collections->toArray();
|
||||
|
||||
$returnCollections = [];
|
||||
|
||||
foreach( $collections as $collection )
|
||||
{
|
||||
$returnCollections[] = $collection['name'];
|
||||
}
|
||||
|
||||
return $returnCollections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Error
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function error() : string
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected is auto increment
|
||||
*/
|
||||
protected function isAutoIncrement(string &$table)
|
||||
{
|
||||
return in_array($table = $this->getIndexCollectionName($table), $this->collections());
|
||||
}
|
||||
|
||||
/**
|
||||
* protected set auto increment
|
||||
*/
|
||||
protected function setAutoIncrement(string $table, &$data)
|
||||
{
|
||||
if( $this->isAutoIncrement($table) )
|
||||
{
|
||||
$get = $this->get($table);
|
||||
|
||||
$row = $get->row();
|
||||
|
||||
$id = key(array_reverse((array) $row));
|
||||
|
||||
$data = array_merge([$id => $get->totalRows()], $data);
|
||||
|
||||
$this->insert($table, [$id => 1]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* protected complete
|
||||
*/
|
||||
protected function complete($result)
|
||||
{
|
||||
$this->result = $result;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected execute read command
|
||||
*/
|
||||
protected function executeReadCommand(string $database, array $command)
|
||||
{
|
||||
$query = $this->manager->executeReadCommand($database, new Command($command), $this->executable);
|
||||
|
||||
$query->setTypeMap(['root' => 'array', 'document' => 'array']);
|
||||
|
||||
$this->defaultExecuteReadCommand();
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected execute write command
|
||||
*/
|
||||
protected function executeWriteCommand(array $command)
|
||||
{
|
||||
$return = $this->manager->executeWriteCommand($this->database, new Command($command), $this->executable);
|
||||
|
||||
$this->defaultExecuteWriteCommand();
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected operation
|
||||
*/
|
||||
protected function operation(string $table, $bulk)
|
||||
{
|
||||
$return = $this->manager->executeBulkWrite($this->collect($table), $bulk, $this->executable);
|
||||
|
||||
$this->defaultExecute();
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected execute
|
||||
*/
|
||||
protected function execute(string $table)
|
||||
{
|
||||
$return = $this->manager->executeQuery($this->collect($table), new Query($this->filters, $this->options), $this->executable);
|
||||
|
||||
$this->defaultExecute();
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected collect
|
||||
*/
|
||||
protected function collect(string $collection)
|
||||
{
|
||||
return $this->database . '.' . $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected default execute read command
|
||||
*/
|
||||
protected function defaultExecuteReadCommand()
|
||||
{
|
||||
$this->executable = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* protected default execute write command
|
||||
*/
|
||||
protected function defaultExecuteWriteCommand()
|
||||
{
|
||||
$this->options = [];
|
||||
$this->executable = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* protected default
|
||||
*/
|
||||
protected function defaultExecute()
|
||||
{
|
||||
$this->filters = [];
|
||||
$this->options = [];
|
||||
$this->executable = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
interface MDBInterface
|
||||
{
|
||||
/**
|
||||
* Executable
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function executable($options);
|
||||
|
||||
/**
|
||||
* MongoDB\Driver\WriteConcern
|
||||
*
|
||||
* @return WriteConcern
|
||||
*/
|
||||
public static function writeConcern(...$parameters);
|
||||
|
||||
/**
|
||||
* MongoDB\Driver\ReadPreference
|
||||
*
|
||||
* @return ReadPreference
|
||||
*/
|
||||
public static function readPreference(...$parameters);
|
||||
|
||||
/**
|
||||
* MongoDB\Driver\ReadConcern
|
||||
*
|
||||
* @return ReadConcern
|
||||
*/
|
||||
public static function readConcern(...$parameters);
|
||||
|
||||
/**
|
||||
* MongoDB\Driver\Session
|
||||
*
|
||||
* @return Session
|
||||
*/
|
||||
public static function session(...$parameters);
|
||||
|
||||
/**
|
||||
* New
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public static function new(array $config);
|
||||
|
||||
/**
|
||||
* Insert
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $datas
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function insert(string $table, array $datas) : bool;
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete(string $table) : bool;
|
||||
|
||||
/**
|
||||
* Update
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $datas
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function update(string $table, array $datas = []) : bool;
|
||||
|
||||
/**
|
||||
* Where Regex
|
||||
*
|
||||
* @param string $key
|
||||
* @param scalar $value
|
||||
* @param string $flags = ''
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function whereRegex(string $key, $value, string $flags = '');
|
||||
|
||||
/**
|
||||
* Where
|
||||
*
|
||||
* @param string $key
|
||||
* @param scalar $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function where(string $key, $value);
|
||||
|
||||
/**
|
||||
* Upsert
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function upsert();
|
||||
|
||||
/**
|
||||
* Option
|
||||
*
|
||||
* @param string $key
|
||||
* @param scalar $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function option(string $key, $value);
|
||||
|
||||
/**
|
||||
* Filter
|
||||
*
|
||||
* @param string $key
|
||||
* @param scalar $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function filter(string $key, $value);
|
||||
|
||||
/**
|
||||
* Total Rows
|
||||
*
|
||||
* @param int
|
||||
*/
|
||||
public function totalRows() : int;
|
||||
|
||||
/**
|
||||
* Limit
|
||||
*
|
||||
* Usage - 1
|
||||
*
|
||||
* @param int $limit
|
||||
*
|
||||
* Usage - 2
|
||||
*
|
||||
* @param int $skip
|
||||
* @param int $limit
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function limit(int $skip, ?int $limit = NULL);
|
||||
|
||||
/**
|
||||
* Order By
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $type = 'asc'
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function orderBy(string $column, string $type = 'asc');
|
||||
|
||||
/**
|
||||
* Get
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function get(string $table);
|
||||
|
||||
/**
|
||||
* Result
|
||||
*
|
||||
* @return array|object
|
||||
*/
|
||||
public function result();
|
||||
|
||||
/**
|
||||
* Row
|
||||
*
|
||||
* @param int|bool $printable = 0
|
||||
*
|
||||
* @return object|false
|
||||
*/
|
||||
public function row($printable = 0);
|
||||
|
||||
/**
|
||||
* Create Index
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $indexes
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createIndex(string $table, array $indexes) : bool;
|
||||
|
||||
/**
|
||||
* Drop Index
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $indexName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dropIndex(string $table, string $indexName) : bool;
|
||||
|
||||
/**
|
||||
* Create
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $options = []
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function create(string $table, array $options = []) : bool;
|
||||
|
||||
/**
|
||||
* Create Auto Increment
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $column
|
||||
*/
|
||||
public function createAutoIncrement(string $table, string $column);
|
||||
|
||||
/**
|
||||
* Drop/Truncate
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function drop(string $table) : bool;
|
||||
|
||||
/**
|
||||
* Truncate/Drop
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function truncate(string $table) : bool;
|
||||
|
||||
/**
|
||||
* Databases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function databases() : array;
|
||||
|
||||
/**
|
||||
* Indexes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function indexes(string $table) : array;
|
||||
|
||||
/**
|
||||
* Tables/Collections
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function tables() : array;
|
||||
|
||||
/**
|
||||
* Collections/Tables
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function collections() : array;
|
||||
|
||||
/**
|
||||
* Error
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function error() : string;
|
||||
}
|
||||
@@ -0,0 +1,532 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Base;
|
||||
use ZN\Config;
|
||||
use ZN\Singleton;
|
||||
use ZN\Filesystem;
|
||||
|
||||
class Migration implements MigrationInterface
|
||||
{
|
||||
/**
|
||||
* Migrations path Models/Migrations/
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $path = MODELS_DIR . 'Migrations/';
|
||||
|
||||
/**
|
||||
* Keeps database config
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* Keeps class fix
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $classFix = INTERNAL_ACCESS . 'Migrate';
|
||||
|
||||
/**
|
||||
* Keeps migrate table name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $migrateTableName;
|
||||
|
||||
/**
|
||||
* Keeps version directory path
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $versionDir = 'Version/';
|
||||
|
||||
/**
|
||||
* Keeps database classeses
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
private $db, $forge;
|
||||
|
||||
/**
|
||||
* Magic constructor
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = Config::get('Database');
|
||||
|
||||
if( ! is_dir($this->path) )
|
||||
{
|
||||
mkdir($this->path, 0755);
|
||||
}
|
||||
|
||||
$this->db = Singleton::class('ZN\Database\DB');
|
||||
$this->forge = Singleton::class('ZN\Database\DBForge');
|
||||
$this->migrateTableName = defined('static::table') ? static::table : '';
|
||||
|
||||
$this->createMigrationTableIfNotExists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Up all migrations
|
||||
*
|
||||
* @param string ...$migrations
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function upAll(string ...$migrations) : bool
|
||||
{
|
||||
$this->runMigrateAll('up', $migrations);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Down all migrations
|
||||
*
|
||||
* @param string ...$migrations
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function downAll(string ...$migrations) : bool
|
||||
{
|
||||
$this->runMigrateAll('down', $migrations);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create table
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createTable(array $data) : bool
|
||||
{
|
||||
$this->forge->createTable($this->getTableName(), $data);
|
||||
|
||||
return $this->saveActionQuery(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop table
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dropTable() : bool
|
||||
{
|
||||
$this->forge->dropTable($this->getTableName());
|
||||
|
||||
return $this->saveActionQuery(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add column
|
||||
*
|
||||
* @param array $column
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function addColumn(array $column) : bool
|
||||
{
|
||||
$this->forge->addColumn($this->getTableName(), $column);
|
||||
|
||||
return $this->saveActionQuery(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop column
|
||||
*
|
||||
* @param mixed $column
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dropColumn($column) : bool
|
||||
{
|
||||
$this->forge->dropColumn($this->getTableName(), $column);
|
||||
|
||||
return $this->saveActionQuery(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify column
|
||||
*
|
||||
* @param array $column
|
||||
*
|
||||
* @param bool
|
||||
*/
|
||||
public function modifyColumn(array $column) : bool
|
||||
{
|
||||
$this->forge->modifyColumn($this->getTableName(), $column);
|
||||
|
||||
return $this->saveActionQuery(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename column
|
||||
*
|
||||
* @param array $column
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function renameColumn(array $column) : bool
|
||||
{
|
||||
$this->forge->renameColumn($this->getTableName(), $column);
|
||||
|
||||
return $this->saveActionQuery(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate table
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function truncate() : bool
|
||||
{
|
||||
$this->forge->truncate($this->getTableName());
|
||||
|
||||
return $this->saveActionQuery(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets migration path
|
||||
*
|
||||
* @param string $path = NULL
|
||||
*
|
||||
* @return Migration
|
||||
*/
|
||||
public function path(?string $path = NULL) : Migration
|
||||
{
|
||||
$this->path = Base::suffix($path);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create migration
|
||||
*
|
||||
* @param string $name
|
||||
* @param int $version = 0
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function create(string $name, int $ver = 0) : bool
|
||||
{
|
||||
if( $version = $this->getValidVersionNumber($ver) )
|
||||
{
|
||||
$this->createVersionDirectoryIfNotExists($name);
|
||||
|
||||
$file = $this->getVersionFile($name, $version);
|
||||
|
||||
$name .= $version;
|
||||
}
|
||||
else
|
||||
{
|
||||
$file = $this->getWithoutVersionFile($name);
|
||||
}
|
||||
|
||||
return $this->generateMigrateFileIfNotExists($name, $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete migration
|
||||
*
|
||||
* @param string $name
|
||||
* @param int $version = 0
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete(string $name, int $ver = 0) : bool
|
||||
{
|
||||
if( $version = $this->getValidVersionNumber($ver) )
|
||||
{
|
||||
$file = $this->getVersionFile($name, $version);
|
||||
|
||||
$this->deleteAllVersionDirectoryIfExists($name, $ver);
|
||||
}
|
||||
else
|
||||
{
|
||||
$file = $this->getWithoutVersionFile($name);
|
||||
}
|
||||
|
||||
return $this->deleteMigrateFileIfExists($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all migrations
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteAll() : bool
|
||||
{
|
||||
if( is_dir($this->path) )
|
||||
{
|
||||
return Filesystem::deleteFolder($this->path);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects migration version
|
||||
*
|
||||
* @param int $version = 0
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function version(int $version = 0)
|
||||
{
|
||||
if( empty($this->migrateTableName) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
$name = $this->classFix.$this->getTableName();
|
||||
|
||||
if( $version <= 0 )
|
||||
{
|
||||
return Singleton::class($name);
|
||||
}
|
||||
|
||||
$name .= $this->getValidVersionNumber($version);
|
||||
|
||||
return Singleton::class($name);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected delete migrate file if exists
|
||||
*/
|
||||
protected function deleteMigrateFileIfExists($file)
|
||||
{
|
||||
if( is_file($file) )
|
||||
{
|
||||
return unlink($file);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected generate migrate file if not exists
|
||||
*/
|
||||
protected function generateMigrateFileIfNotExists($name, $file)
|
||||
{
|
||||
if( ! is_file($file) )
|
||||
{
|
||||
return $this->createMigrateFile($name, $file);
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected delete all version directory if exists
|
||||
*/
|
||||
protected function deleteAllVersionDirectoryIfExists($name, $version)
|
||||
{
|
||||
$getVersionDirectory = $this->getVersionDirectory($name);
|
||||
|
||||
if( $version === 'all' && is_dir($getVersionDirectory) )
|
||||
{
|
||||
Filesystem::deleteFolder($getVersionDirectory); // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected create version directory if not exists
|
||||
*/
|
||||
protected function createVersionDirectoryIfNotExists($name)
|
||||
{
|
||||
if( ! is_dir($getVersionDirectory = $this->getVersionDirectory($name)) )
|
||||
{
|
||||
mkdir($getVersionDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected get file without version
|
||||
*/
|
||||
protected function getWithoutVersionFile($name)
|
||||
{
|
||||
return $this->path . Base::suffix($name, '.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected get version file
|
||||
*/
|
||||
protected function getVersionFile($name, $version)
|
||||
{
|
||||
return $this->getVersionDirectory($name) . Base::suffix($version, '.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected create migrate
|
||||
*/
|
||||
protected function getVersionDirectory($name)
|
||||
{
|
||||
return $this->path . $name . $this->versionDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected save action query
|
||||
*/
|
||||
protected function saveActionQuery($type)
|
||||
{
|
||||
if( ! $this->forge->error() )
|
||||
{
|
||||
return $this->db->insert($this->config['migration']['table'],
|
||||
[
|
||||
'name' => $this->getTableName(),
|
||||
'type' => $type ?: 'noAction',
|
||||
'version' => $this->getVersionNumberFromTableName(),
|
||||
'date' => date('Ymdhis')
|
||||
]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected create
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function createMigrationTableIfNotExists()
|
||||
{
|
||||
$table = $this->config['database']['prefix'] . $this->config['migration']['table'];
|
||||
|
||||
$this->forge->createTable('IF NOT EXISTS '.$table, array
|
||||
(
|
||||
'name' => [$this->db->varchar(512), $this->db->notNull()],
|
||||
'type' => [$this->db->varchar(256), $this->db->notNull()],
|
||||
'version' => [$this->db->varchar(3), $this->db->notNull()],
|
||||
'date' => [$this->db->varchar(15), $this->db->notNull()]
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table name
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getTableName()
|
||||
{
|
||||
$table = preg_replace('/[0-9][0-9][0-9]/', '', $this->migrateTableName);
|
||||
|
||||
return str_replace($this->classFix, '', $table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected get version number from table name
|
||||
*/
|
||||
protected function getVersionNumberFromTableName()
|
||||
{
|
||||
preg_match('(\w+([0-9][0-9][0-9]))', $this->migrateTableName, $match);
|
||||
|
||||
return $match[1] ?? '000';
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected get valid version number
|
||||
*/
|
||||
protected function getValidVersionNumber($numeric)
|
||||
{
|
||||
$length = strlen((string) $numeric);
|
||||
|
||||
if( (int) $numeric > 999 || (int) $numeric < 0 )
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
switch( $length )
|
||||
{
|
||||
case 1 : $numeric = '00'.$numeric; break;
|
||||
case 2 : $numeric = '0' .$numeric; break; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if( $numeric === '000' )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $numeric;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected run migrate all
|
||||
*/
|
||||
protected function runMigrateAll($type, $migrations)
|
||||
{
|
||||
foreach( $migrations as $migration )
|
||||
{
|
||||
$migration = Base::prefix($migration, 'Migrate');
|
||||
|
||||
$migration::$type();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* protected create migrate file
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function createMigrateFile(string $name, string $file) : bool
|
||||
{
|
||||
$eol = EOL;
|
||||
$str = '<?php'.$eol;
|
||||
$str .= 'class '.$this->classFix.$name.' extends '.__CLASS__.$eol;
|
||||
$str .= '{'.$eol;
|
||||
$str .= "\t".'# Class/Table Name'.$eol;
|
||||
$str .= "\t".'const table = __CLASS__;'.$eol.$eol;
|
||||
$str .= "\t".'# Up'.$eol;
|
||||
$str .= "\t".'public function up()'.$eol;
|
||||
$str .= "\t".'{'.$eol;
|
||||
$str .= "\t\t".'# Default Query'.$eol;
|
||||
$str .= "\t\t".'return $this->createTable' . $eol;
|
||||
$str .= "\t\t".'(['.$eol;
|
||||
$str .= "\t\t\t".'\'id\' => [DB::int(11), DB::primaryKey(), DB::autoIncrement()]' . $eol;
|
||||
$str .= "\t\t".']);'.$eol;
|
||||
$str .= "\t".'}'.$eol.$eol;
|
||||
$str .= "\t".'# Down'.$eol;
|
||||
$str .= "\t".'public function down()'.$eol;
|
||||
$str .= "\t".'{'.$eol;
|
||||
$str .= "\t\t".'# Default Query'.$eol;
|
||||
$str .= "\t\t".'return $this->dropTable();'.$eol;
|
||||
$str .= "\t".'}'.$eol;
|
||||
$str .= '}';
|
||||
|
||||
return file_put_contents($file, $str);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
interface MigrationInterface
|
||||
{
|
||||
/**
|
||||
* Up all migrations
|
||||
*
|
||||
* @param string ...$migrations
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function upAll(string ...$migrations) : bool;
|
||||
|
||||
/**
|
||||
* Down all migrations
|
||||
*
|
||||
* @param string ...$migrations
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function downAll(string ...$migrations) : bool;
|
||||
|
||||
/**
|
||||
* Create table
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createTable(array $data) : bool;
|
||||
|
||||
/**
|
||||
* Drop table
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dropTable() : bool;
|
||||
|
||||
/**
|
||||
* Add column
|
||||
*
|
||||
* @param array $column
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function addColumn(array $columns) : bool;
|
||||
|
||||
/**
|
||||
* Drop column
|
||||
*
|
||||
* @param mixed $column
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function dropColumn($columns) : bool;
|
||||
|
||||
/**
|
||||
* Modify column
|
||||
*
|
||||
* @param array $column
|
||||
*
|
||||
* @param bool
|
||||
*/
|
||||
public function modifyColumn(array $columns) : bool;
|
||||
|
||||
/**
|
||||
* Rename column
|
||||
*
|
||||
* @param array $column
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function renameColumn(array $column) : bool;
|
||||
|
||||
/**
|
||||
* Truncate table
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function truncate() : bool;
|
||||
|
||||
/**
|
||||
* Sets migration path
|
||||
*
|
||||
* @param string $path = NULL
|
||||
*
|
||||
* @return Migration
|
||||
*/
|
||||
public function path(string $path) : Migration;
|
||||
|
||||
/**
|
||||
* Selects migration version
|
||||
*
|
||||
* @param int $version = 0
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function version(int $version = 0);
|
||||
|
||||
/**
|
||||
* Create migration
|
||||
*
|
||||
* @param string $name
|
||||
* @param int $version = 0
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function create(string $name, int $ver = 0) : bool;
|
||||
|
||||
/**
|
||||
* Delete migration
|
||||
*
|
||||
* @param string $name
|
||||
* @param int $version = 0
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete(string $name, int $ver = 0) : bool;
|
||||
|
||||
/**
|
||||
* Delete all migrations
|
||||
*
|
||||
* @param void
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteAll() : bool;
|
||||
}
|
||||
@@ -0,0 +1,444 @@
|
||||
<?php namespace ZN\Database\MySQLi;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use MySQLi;
|
||||
use stdClass;
|
||||
use Exception;
|
||||
use ZN\Support;
|
||||
use ZN\ErrorHandling\Errors;
|
||||
use ZN\Database\DriverMappingAbstract;
|
||||
use ZN\Database\Exception\ConnectionErrorException;
|
||||
|
||||
class DB extends DriverMappingAbstract
|
||||
{
|
||||
/**
|
||||
* Keep Operators
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $operators =
|
||||
[
|
||||
'like' => '%'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keep Statements
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $statements =
|
||||
[
|
||||
'autoincrement' => 'AUTO_INCREMENT',
|
||||
'primarykey' => 'PRIMARY KEY',
|
||||
'foreignkey' => 'FOREIGN KEY',
|
||||
'unique' => 'UNIQUE',
|
||||
'null' => 'NULL',
|
||||
'notnull' => 'NOT NULL',
|
||||
'exists' => 'EXISTS',
|
||||
'notexists' => 'NOT EXISTS',
|
||||
'constraint' => 'CONSTRAINT',
|
||||
'default' => 'DEFAULT'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keep Variable Types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $variableTypes =
|
||||
[
|
||||
'int' => 'INT',
|
||||
'smallint' => 'SMALLINT',
|
||||
'tinyint' => 'TINYINT',
|
||||
'mediumint' => 'MEDIUMINT',
|
||||
'bigint' => 'BIGINT',
|
||||
'decimal' => 'DECIMAL',
|
||||
'double' => 'DOUBLE',
|
||||
'float' => 'FLOAT',
|
||||
'char' => 'CHAR',
|
||||
'varchar' => 'VARCHAR',
|
||||
'tinytext' => ':TINYTEXT',
|
||||
'text' => 'TEXT',
|
||||
'mediumtext' => ':MEDIUMTEXT',
|
||||
'longtext' => ':LONGTEXT',
|
||||
'date' => ':DATE',
|
||||
'datetime' => 'DATETIME',
|
||||
'time' => 'TIME',
|
||||
'timestamp' => 'TIMESTAMP'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keeps Types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $types =
|
||||
[
|
||||
0 => 'DECIMAL',
|
||||
1 => 'TINY',
|
||||
2 => 'SHORT',
|
||||
3 => 'LONG',
|
||||
4 => 'FLOAT',
|
||||
5 => 'DOUBLE',
|
||||
6 => 'NULL',
|
||||
7 => 'TIMESTAMP',
|
||||
8 => 'LONGLONG',
|
||||
9 => 'INT24',
|
||||
10 => 'DATE',
|
||||
11 => 'TIME',
|
||||
12 => 'DATETIME',
|
||||
13 => 'YEAR',
|
||||
14 => 'NEWDATE',
|
||||
247 => 'ENUM',
|
||||
248 => 'SET',
|
||||
249 => 'TINY_BLOB',
|
||||
250 => 'MEDIUM_BLOB',
|
||||
251 => 'LONG_BLOG',
|
||||
252 => 'BLOB',
|
||||
253 => 'VAR_STRING',
|
||||
254 => 'STRING',
|
||||
255 => 'GEOMETRY'
|
||||
];
|
||||
|
||||
/**
|
||||
* Magic Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
Support::extension('MySQLi');
|
||||
}
|
||||
|
||||
/**
|
||||
* Connection
|
||||
*
|
||||
* @param array $config = []
|
||||
*/
|
||||
public function connect($config = [])
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
$host = ($this->config['pconnect'] === true ? 'p:' : NULL) . $this->config['host'];
|
||||
$user = $this->config['user'];
|
||||
$pass = $this->config['password'];
|
||||
$db = $this->config['database'];
|
||||
$port = $this->config['port'] ?: 3306;
|
||||
$ssl = $this->config['ssl'] ?? NULL;
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
set_error_handler(function(){});
|
||||
if( ! empty($ssl['key']) || ! empty($ssl['cert']) || ! empty($ssl['ca']) || ! empty($ssl['capath']) || ! empty($ssl['cipher']) )
|
||||
{
|
||||
$this->connect = new MySQLi;
|
||||
|
||||
$this->connect->options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, true);
|
||||
$this->connect->ssl_set($ssl['key'] ?? NULL, $ssl['cert'] ?? NULL, $ssl['ca'] ?? NULL, $ssl['capath'] ?? NULL, $ssl['cipher'] ?? NULL);
|
||||
$this->connect->real_connect($host, $user, $pass, $db, $port, NULL, MYSQLI_CLIENT_SSL);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
else
|
||||
{
|
||||
$this->connect = new MySQLi($host, $user, $pass, $db, $port);
|
||||
}
|
||||
restore_error_handler();
|
||||
|
||||
if( $this->connect->connect_errno )
|
||||
{
|
||||
throw new ConnectionErrorException(NULL, $this->connect->connect_error); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
mysqli_report(MYSQLI_REPORT_OFF);
|
||||
|
||||
if( ! empty($this->config['charset'] ) ) $this->query("SET NAMES '".$this->config['charset']."'");
|
||||
if( ! empty($this->config['charset'] ) ) $this->query('SET CHARACTER SET '.$this->config['charset']);
|
||||
if( ! empty($this->config['collation']) ) $this->query('SET COLLATION_CONNECTION = "'.$this->config['collation'].'"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exec($query, $security = NULL)
|
||||
{
|
||||
if( empty($query) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->connect->query($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function query($query, $security = NULL)
|
||||
{
|
||||
return $this->query = $this->exec($query, $security);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple Queries
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function multiQuery($query, $security = NULL)
|
||||
{
|
||||
if( empty($query) )
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if( $this->query = $this->connect->multi_query($query) )
|
||||
{
|
||||
while( $this->connect->next_result() )
|
||||
{
|
||||
if( ! $this->connect->more_results() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (bool) $this->query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transStart()
|
||||
{
|
||||
$this->connect->autocommit(false);
|
||||
|
||||
return $this->connect->begin_transaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transRollback()
|
||||
{
|
||||
if( $this->connect->rollback() )
|
||||
{
|
||||
return $this->connect->autocommit(true);
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transCommit()
|
||||
{
|
||||
if( $this->connect->commit() )
|
||||
{
|
||||
return $this->connect->autocommit(true);
|
||||
}
|
||||
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert Last ID
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
public function insertID()
|
||||
{
|
||||
return $this->connect->insert_id ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns column data
|
||||
*
|
||||
* @param string $column
|
||||
*
|
||||
* @return array|object
|
||||
*/
|
||||
public function columnData($column)
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
$fieldData = $this->query->fetch_fields();
|
||||
$count = count($fieldData);
|
||||
|
||||
for( $i = 0; $i < $count; $i++ )
|
||||
{
|
||||
$fieldName = $fieldData[$i]->name;
|
||||
|
||||
$columns[$fieldName] = new stdClass();
|
||||
$columns[$fieldName]->name = $fieldName;
|
||||
$columns[$fieldName]->type = $this->types[$fieldData[$i]->type] ?? NULL;
|
||||
$columns[$fieldName]->maxLength = $fieldData[$i]->max_length;
|
||||
$columns[$fieldName]->primaryKey = (int) ($fieldData[$i]->flags & 2);
|
||||
$columns[$fieldName]->default = $fieldData[$i]->def;
|
||||
}
|
||||
|
||||
return $columns[$column] ?? $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numrows
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function numRows()
|
||||
{
|
||||
return $this->query->num_rows ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function columns()
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
$fields = $this->query->fetch_fields();
|
||||
$numFields = $this->numFields();
|
||||
|
||||
for( $i = 0; $i < $numFields; $i++ )
|
||||
{
|
||||
$columns[] = $fields[$i]->name;
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numfields
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function numFields()
|
||||
{
|
||||
return $this->query->field_count ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Real Escape String
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function realEscapeString($data)
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return $data; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $this->connect->real_escape_string($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string description of the last error.
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function error()
|
||||
{
|
||||
return $this->connect->error ?: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a result row as an associative, a numeric array, or both
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchArray()
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->query->fetch_array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a result row as an associative array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchAssoc()
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->query->fetch_assoc();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a result row as an enumerated array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchRow()
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->query->fetch_row();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows in a previous MySQL operation
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return $this->connect->affected_rows ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the MySQL server as an integer
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function version()
|
||||
{
|
||||
return (string) ($this->connect->server_version ?? 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php namespace ZN\Database\MySQLi;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Database\DriverForge;
|
||||
|
||||
class DBForge extends DriverForge
|
||||
{
|
||||
/**
|
||||
* Drop Foreign Key
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $constraint = NULL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropForeignKey($table, $constraint = NULL)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' DROP ' . $this->db()->foreignKey() . ' ' . $constraint . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Primary Key
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $constraint = NULL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropPrimaryKey($table, $constraint = NULL)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' DROP ' . $this->db()->primaryKey() . ';';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php namespace ZN\Database\MySQLi;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Database\DriverTool;
|
||||
|
||||
class DBTool extends DriverTool
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,410 @@
|
||||
<?php namespace ZN\Database\ODBC;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
|
||||
use stdClass;
|
||||
use ZN\Base;
|
||||
use ZN\Support;
|
||||
use ZN\Security;
|
||||
use ZN\ErrorHandling\Errors;
|
||||
use ZN\Database\DriverMappingAbstract;
|
||||
use ZN\Database\Exception\ConnectionErrorException;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class DB extends DriverMappingAbstract
|
||||
{
|
||||
/**
|
||||
* Keep Operators
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $operators =
|
||||
[
|
||||
'like' => '*'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keep Statements
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $statements =
|
||||
[
|
||||
'autoincrement' => 'AUTOINCREMENT',
|
||||
'primarykey' => 'PRIMARY KEY',
|
||||
'foreignkey' => 'FOREIGN KEY',
|
||||
'unique' => 'UNIQUE',
|
||||
'null' => 'NULL',
|
||||
'notnull' => 'NOT NULL',
|
||||
'exists' => 'EXISTS',
|
||||
'notexists' => 'NOT EXISTS',
|
||||
'constraint' => 'CONSTRAINT',
|
||||
'default' => 'DEFAULT'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keep Variable Types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $variableTypes =
|
||||
[
|
||||
'int' => ':INTEGER',
|
||||
'smallint' => ':SMALLINT',
|
||||
'tinyint' => ':TINYINT',
|
||||
'mediumint' => ':INTEGER',
|
||||
'bigint' => ':BIGINT',
|
||||
'decimal' => 'DECIMAL',
|
||||
'double' => 'FLOAT',
|
||||
'float' => 'FLOAT',
|
||||
'char' => 'CHAR',
|
||||
'varchar' => 'VARCHAR',
|
||||
'tinytext' => ':VARCHAR(255)',
|
||||
'text' => ':VARCHAR(65535)',
|
||||
'mediumtext' => ':VARCHAR(16277215)',
|
||||
'longtext' => ':VARCHAR(16277215)',
|
||||
'date' => ':DATE',
|
||||
'datetime' => ':DATETIME',
|
||||
'time' => ':TIME',
|
||||
'timestamp' => ':TIMESTAMP'
|
||||
];
|
||||
|
||||
/**
|
||||
* Magic Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
Support::func('odbc_connect', 'Microsoft Access(ODBC)');
|
||||
}
|
||||
|
||||
/**
|
||||
* Connection
|
||||
*
|
||||
* @param array $config = []
|
||||
*/
|
||||
public function connect($config = [])
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
$host = Base::suffix(Base::prefix($this->config['host'], '{'), '}');
|
||||
|
||||
if( ! empty($this->config['dsn']) )
|
||||
{
|
||||
$dsn = $this->config['dsn'];
|
||||
}
|
||||
else if( is_file($this->config['database']) )
|
||||
{
|
||||
$dsn = 'DRIVER=' . $host . ';DBQ=' . $this->config['database'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$dsn = 'DRIVER=' . $host . ';SERVER=' . $this->config['server'] . ';DATABASE=' . $this->config['database'];
|
||||
}
|
||||
|
||||
$connectMethod = $this->config['pconnect'] === true ? 'odbc_pconnect' : 'odbc_connect';
|
||||
|
||||
$this->connect = $connectMethod($dsn, $this->config['user'], $this->config['password']);
|
||||
|
||||
if( empty($this->connect) )
|
||||
{
|
||||
throw new ConnectionErrorException(NULL, 'connection');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exec($query, $security = NULL)
|
||||
{
|
||||
if( empty($query) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return odbc_exec($this->connect, $this->comma($query));
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple Queries
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = []
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function multiQuery($query, $security = [])
|
||||
{
|
||||
return (bool) $this->query($query, $security);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function query($query, $security = [])
|
||||
{
|
||||
if( $this->query = odbc_prepare($this->connect, $this->comma($query)) )
|
||||
{
|
||||
return odbc_execute($this->query, $security);
|
||||
}
|
||||
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transStart()
|
||||
{
|
||||
return odbc_autocommit($this->connect, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transRollback()
|
||||
{
|
||||
$rollback = odbc_rollback($this->connect);
|
||||
odbc_autocommit($this->connect, true);
|
||||
return $rollback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transCommit()
|
||||
{
|
||||
$commit = odbc_commit($this->connect);
|
||||
odbc_autocommit($this->connect, true);
|
||||
return $commit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert Last ID
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
public function insertID()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns column data
|
||||
*
|
||||
* @param string $column
|
||||
*
|
||||
* @return array|object
|
||||
*/
|
||||
public function columnData($col = '')
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
$numFields = $this->numFields();
|
||||
|
||||
for( $index = 1; $index <= $numFields; $index++ )
|
||||
{
|
||||
$fieldName = odbc_field_name($this->query, $index);
|
||||
|
||||
$columns[$fieldName] = new stdClass();
|
||||
$columns[$fieldName]->name = $fieldName;
|
||||
$columns[$fieldName]->type = odbc_field_type($this->query, $index);
|
||||
$columns[$fieldName]->maxLength = odbc_field_len($this->query, $index);
|
||||
$columns[$fieldName]->primaryKey = NULL;
|
||||
$columns[$fieldName]->default = NULL;
|
||||
}
|
||||
|
||||
return $columns[$col] ?? $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numrows
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function numRows()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return odbc_num_rows($this->query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function columns()
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
$numFields = $this->numFields();
|
||||
|
||||
for( $index = 1; $index <= $numFields; $index++ )
|
||||
{
|
||||
$columns[] = odbc_field_name($this->query, $index);
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numfields
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function numFields()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return odbc_num_fields($this->query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Real Escape String
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function realEscapeString($data = '')
|
||||
{
|
||||
return Security\Injection::escapeStringEncode($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string description of the last error.
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function error()
|
||||
{
|
||||
if( ! empty($this->connect) )
|
||||
{
|
||||
return odbc_error($this->connect) ? (odbc_errormsg($this->connect) ?: false) : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a result row as an associative, a numeric array, or both
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchArray()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return odbc_fetch_array($this->query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a result row as an associative array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchAssoc()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return odbc_fetch_array($this->query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a result row as an enumerated array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchRow()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return odbc_fetch_array($this->query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows in a previous MySQL operation
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the MySQL server as an integer
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function version()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function comma($query)
|
||||
{
|
||||
return Base::suffix(trim($query), ';');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php namespace ZN\Database\ODBC;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Database\DriverForge;
|
||||
|
||||
class DBForge extends DriverForge
|
||||
{
|
||||
/**
|
||||
* Truncate table
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function truncate($table)
|
||||
{
|
||||
return 'DELETE FROM '.$table.';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename column
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renameColumn($table, $column)
|
||||
{
|
||||
return 'ALTER TABLE '.$table.' RENAME COLUMN '.rtrim($column, ',').';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropIndex($indexName, $table)
|
||||
{
|
||||
return 'DROP INDEX ' . $indexName . ' ON ' . $table . ';';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php namespace ZN\Database\ODBC;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Database\DriverTool;
|
||||
|
||||
class DBTool extends DriverTool
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,396 @@
|
||||
<?php namespace ZN\Database\Oracle;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use stdClass;
|
||||
use ZN\Support;
|
||||
use ZN\Security;
|
||||
use ZN\ErrorHandling\Errors;
|
||||
use ZN\Database\DriverMappingAbstract;
|
||||
use ZN\Database\Exception\ConnectionErrorException;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class DB extends DriverMappingAbstract
|
||||
{
|
||||
/**
|
||||
* Keep Operators
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $operators =
|
||||
[
|
||||
'like' => '%'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keep Statements
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $statements =
|
||||
[
|
||||
'autoincrement' => 'CREATE SEQUENCE % MINVALUE 1 STARVALUE WITH 1 INCREMENT BY 1;',
|
||||
'primarykey' => 'PRIMARY KEY',
|
||||
'foreignkey' => 'FOREIGN KEY',
|
||||
'unique' => 'UNIQUE',
|
||||
'null' => 'NULL',
|
||||
'notnull' => 'NOT NULL',
|
||||
'exists' => 'EXISTS',
|
||||
'notexists' => 'NOT EXISTS',
|
||||
'constraint' => 'CONSTRAINT',
|
||||
'default' => 'DEFAULT'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keep Variable Types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $variableTypes =
|
||||
[
|
||||
'int' => 'NUMBER',
|
||||
'smallint' => 'NUMBER',
|
||||
'tinyint' => 'NUMBER',
|
||||
'mediumint' => 'NUMBER',
|
||||
'bigint' => 'NUMBER',
|
||||
'decimal' => 'DECIMAL',
|
||||
'double' => 'FLOAT',
|
||||
'float' => 'FLOAT',
|
||||
'char' => 'CHAR',
|
||||
'varchar' => 'VARCHAR2',
|
||||
'tinytext' => ':VARCHAR2(255)',
|
||||
'text' => ':VARCHAR2(65535)',
|
||||
'mediumtext' => ':VARCHAR2(16277215)',
|
||||
'longtext' => ':CLOB',
|
||||
'date' => ':DATE',
|
||||
'datetime' => 'TIMESTAMP',
|
||||
'time' => 'TIMESTAMP',
|
||||
'timestamp' => 'TIMESTAMP'
|
||||
];
|
||||
|
||||
/**
|
||||
* Magic Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
Support::func('oci_connect', 'Oracle 8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Connection
|
||||
*
|
||||
* @param array $config = []
|
||||
*/
|
||||
public function connect($config = [])
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
$dsn = ( ! empty($this->config['dsn']))
|
||||
? $this->config['dsn']
|
||||
: $this->config['host'];
|
||||
|
||||
$connectMethod = $this->config['pconnect'] === true ? 'oci_pconnect' : 'oci_connect';
|
||||
|
||||
$this->connect = $connectMethod($this->config['user'], $this->config['password'], $dsn);
|
||||
|
||||
if( empty($this->connect) )
|
||||
{
|
||||
throw new ConnectionErrorException(NULL, oci_error($this->connect)['message']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exec($query, $security = NULL)
|
||||
{
|
||||
if( empty($query) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$que = oci_parse($this->connect, $query);
|
||||
oci_execute($que);
|
||||
|
||||
return $que;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple Queries
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function multiQuery($query, $security = NULL)
|
||||
{
|
||||
return (bool) $this->query($query, $security);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function query($query, $security = [])
|
||||
{
|
||||
$this->query = oci_parse($this->connect, $query);
|
||||
return oci_execute($this->query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transStart()
|
||||
{
|
||||
$this->exec(OCI_NO_AUTO_COMMIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transRollback()
|
||||
{
|
||||
oci_rollback($this->connect);
|
||||
return $this->exec(OCI_COMMIT_ON_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transCommit()
|
||||
{
|
||||
oci_commit($this->connect);
|
||||
return $this->exec(OCI_COMMIT_ON_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns column data
|
||||
*
|
||||
* @param string $column
|
||||
*
|
||||
* @return array|object
|
||||
*/
|
||||
public function columnData($col = '')
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
$numFields = $this->numFields();
|
||||
|
||||
for( $i = 1; $i <= $numFields; $i++ )
|
||||
{
|
||||
$fieldName = oci_field_name($this->query, $i);
|
||||
|
||||
$columns[$fieldName] = new stdClass();
|
||||
$columns[$fieldName]->name = $fieldName;
|
||||
$columns[$fieldName]->type = oci_field_type($this->query, $i);
|
||||
$columns[$fieldName]->maxLength = oci_field_size($this->query, $i);
|
||||
$columns[$fieldName]->primaryKey = NULL;
|
||||
$columns[$fieldName]->default = NULL;
|
||||
}
|
||||
|
||||
return $columns[$col] ?? $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numrows
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function numRows()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return oci_num_rows($this->query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function columns()
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
$numFields = $this->numFields();
|
||||
|
||||
for( $i = 0; $i < $numFields; $i++ )
|
||||
{
|
||||
$columns[] = oci_field_name($this->query, $i);
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numfields
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function numFields()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return oci_num_fields($this->query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Real Escape String
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function realEscapeString($data = '')
|
||||
{
|
||||
return Security\Injection::escapeStringEncode($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string description of the last error.
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function error()
|
||||
{
|
||||
if( ! empty($this->connect) )
|
||||
{
|
||||
$error = oci_error($this->connect);
|
||||
|
||||
return ! empty($error['code']) ? ($error['message'] ?: false) : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a result row as an associative, a numeric array, or both
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchArray()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return oci_fetch_array($this->query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a result row as an associative array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchAssoc()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return oci_fetch_assoc($this->query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a result row as an enumerated array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchRow()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return oci_fetch_row($this->query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows in a previous MySQL operation
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
if( ! empty($this->connect) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the MySQL server as an integer
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function version()
|
||||
{
|
||||
if( ! empty($this->connect) )
|
||||
{
|
||||
return oci_server_version($this->connect);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php namespace ZN\Database\Oracle;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Database\DriverForge;
|
||||
|
||||
class DBForge extends DriverForge
|
||||
{
|
||||
/**
|
||||
* Create Temporary Table
|
||||
*
|
||||
* @param string $tabşe
|
||||
* @param array $columns
|
||||
* @param string $extras
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createTempTable($table, $columns, $extras)
|
||||
{
|
||||
return 'CREATE GLOBAL TEMPORARY TABLE ' . $this->createTableColumnsSyntax($table, $columns, $extras) . ' ON COMMIT PRESERVE ROWS;';
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $column
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renameColumn($table, $column)
|
||||
{
|
||||
return 'ALTER TABLE '.$table.' RENAME COLUMN '.key($column).' TO '.current($column).';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropIndex($indexName, $table = NULL)
|
||||
{
|
||||
return 'DROP INDEX ' . $indexName . ';';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php namespace ZN\Database\Oracle;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Database\DriverTool;
|
||||
|
||||
class DBTool extends DriverTool
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
<?php namespace ZN\Database\Postgres;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use stdClass;
|
||||
use ZN\Support;
|
||||
use ZN\Database\Properties;
|
||||
use ZN\ErrorHandling\Errors;
|
||||
use ZN\Database\DriverMappingAbstract;
|
||||
use ZN\Database\Exception\ConnectionErrorException;
|
||||
|
||||
class DB extends DriverMappingAbstract
|
||||
{
|
||||
/**
|
||||
* Keep Operators
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $operators =
|
||||
[
|
||||
'like' => '%'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keep Statements
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $statements =
|
||||
[
|
||||
'autoincrement' => 'BIGSERIAL',
|
||||
'primarykey' => 'PRIMARY KEY',
|
||||
'foreignkey' => 'FOREIGN KEY',
|
||||
'unique' => 'UNIQUE',
|
||||
'null' => 'NULL',
|
||||
'notnull' => 'NOT NULL',
|
||||
'exists' => 'EXISTS',
|
||||
'notexists' => 'NOT EXISTS',
|
||||
'constraint' => 'CONSTRAINT',
|
||||
'default' => 'DEFAULT'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keep Variable Types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $variableTypes =
|
||||
[
|
||||
'int' => ':INTEGER',
|
||||
'smallint' => ':SMALLINT',
|
||||
'tinyint' => ':SMALLINT',
|
||||
'mediumint' => ':INTEGER',
|
||||
'bigint' => ':BIGINT',
|
||||
'decimal' => ':DECIMAL',
|
||||
'double' => ':DOUBLE PRECISION',
|
||||
'float' => ':NUMERIC',
|
||||
'char' => 'CHARACTER',
|
||||
'varchar' => 'CHARACTER VARYING',
|
||||
'tinytext' => ':CHARACTER VARYING(255)',
|
||||
'text' => ':TEXT',
|
||||
'mediumtext' => ':TEXT',
|
||||
'longtext' => ':TEXT',
|
||||
'date' => ':DATE',
|
||||
'datetime' => 'TIMESTAMP',
|
||||
'time' => 'TIME',
|
||||
'timestamp' => 'TIMESTAMP'
|
||||
];
|
||||
|
||||
/**
|
||||
* Magic Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
Support::func('pg_connect', 'Postgres');
|
||||
}
|
||||
|
||||
/**
|
||||
* Connection
|
||||
*
|
||||
* @param array $config = []
|
||||
*/
|
||||
public function connect($config = [])
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
$dsn = 'host='.$this->config['host'].' ';
|
||||
|
||||
if( ! empty($this->config['port']) ) $dsn .= 'port='.$this->config['port'].' ';
|
||||
if( ! empty($this->config['database']) ) $dsn .= 'dbname='.$this->config['database'].' ';
|
||||
if( ! empty($this->config['user']) ) $dsn .= 'user='.$this->config['user'].' ';
|
||||
if( ! empty($this->config['password']) ) $dsn .= 'password='.$this->config['password'].' ';
|
||||
|
||||
if( ! empty($this->config['dsn']) )
|
||||
{
|
||||
$dsn = $this->config['dsn']; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$connectMethod = $this->config['pconnect'] === true ? 'pg_pconnect' : 'pg_connect';
|
||||
|
||||
$this->connect = $connectMethod(rtrim($dsn));
|
||||
|
||||
if( empty($this->connect) )
|
||||
{
|
||||
throw new ConnectionErrorException(NULL, 'connection'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if( ! empty($this->config['charset']) )
|
||||
{
|
||||
$charset = $this->config['charset'] === 'utf8' ? 'UNICODE' : $this->config['charset'];
|
||||
|
||||
pg_set_client_encoding($this->connect, $charset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exec($query, $security = NULL)
|
||||
{
|
||||
if( empty($query) )
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
set_error_handler(function(){});
|
||||
|
||||
$return = pg_query($this->connect, $query);
|
||||
|
||||
restore_error_handler();
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple Queries
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function multiQuery($query, $security = NULL)
|
||||
{
|
||||
return (bool) $this->query($query, $security);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function query($query, $security = [])
|
||||
{
|
||||
return $this->query = $this->exec($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transStart()
|
||||
{
|
||||
return (bool) pg_query($this->connect, 'BEGIN');
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transRollback()
|
||||
{
|
||||
return (bool) pg_query($this->connect, 'ROLLBACK');
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function transCommit()
|
||||
{
|
||||
return (bool) pg_query($this->connect, 'COMMIT');
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert Last ID
|
||||
*
|
||||
* @return int|string
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function insertID()
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$returningId = Properties::$returningId;
|
||||
|
||||
Properties::$returningId = 'id';
|
||||
|
||||
return $returningId === '*' ? (object) $this->fetchAssoc() : ( $this->fetchAssoc()[$returningId] ?? false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns column data
|
||||
*
|
||||
* @param string $column
|
||||
*
|
||||
* @return array|object
|
||||
*/
|
||||
public function columnData($col = '')
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
$numFields = $this->numFields();
|
||||
|
||||
for( $i = 0; $i < $numFields; $i++ )
|
||||
{
|
||||
$fieldName = pg_field_name($this->query, $i);
|
||||
|
||||
$columns[$fieldName] = new stdClass();
|
||||
$columns[$fieldName]->name = $fieldName;
|
||||
$columns[$fieldName]->type = pg_field_type($this->query, $i);
|
||||
$columns[$fieldName]->maxLength = pg_field_size($this->query, $i);
|
||||
$columns[$fieldName]->primaryKey = NULL;
|
||||
$columns[$fieldName]->default = NULL;
|
||||
}
|
||||
|
||||
return $columns[$col] ?? $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numrows
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function numRows()
|
||||
{
|
||||
return ! empty($this->query) ? pg_num_rows($this->query) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function columns()
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return []; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
$numFields = $this->numFields();
|
||||
|
||||
for( $i = 0; $i < $numFields; $i++ )
|
||||
{
|
||||
$columns[] = pg_field_name($this->query, $i);
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numfields
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function numFields()
|
||||
{
|
||||
return ! empty($this->query) ? pg_num_fields($this->query) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Real Escape String
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function realEscapeString($data = '')
|
||||
{
|
||||
return pg_escape_string($this->connect, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string description of the last error.
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function error()
|
||||
{
|
||||
return is_resource($this->connect) ? ( pg_last_error($this->connect) ?: false ) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a result row as an associative, a numeric array, or both
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchArray()
|
||||
{
|
||||
return ! empty($this->query) ? pg_fetch_array($this->query) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a result row as an associative array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchAssoc()
|
||||
{
|
||||
return ! empty($this->query) ? pg_fetch_assoc($this->query) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a result row as an enumerated array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchRow()
|
||||
{
|
||||
return ! empty($this->query) ? pg_fetch_row($this->query) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows in a previous MySQL operation
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
return ! empty($this->query) ? pg_affected_rows($this->query) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the MySQL server as an integer
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function version()
|
||||
{
|
||||
return is_resource($this->connect) ? pg_version($this->connect)['client'] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* protected get insert extras by drvier
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getInsertExtrasByDriver()
|
||||
{
|
||||
return ' RETURNING ' . Properties::$returningId . ';';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php namespace ZN\Database\Postgres;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Database\DriverForge;
|
||||
|
||||
class DBForge extends DriverForge
|
||||
{
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function extras($extras)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $column
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function modifyColumn($table, $column)
|
||||
{
|
||||
$col = key($column); $values = (array) current($column); $query = '';
|
||||
|
||||
foreach( $values as $value )
|
||||
{
|
||||
$type = preg_match('/(NULL|DEFAULT|CONSTRAINT|EXISTS|UNIQUE|KEY|BIGSERIAL)/i', $value ?? '') ? 'SET' : 'TYPE';
|
||||
|
||||
$query .= 'ALTER TABLE ' . $table . ' ALTER COLUMN ' . $this->buildForgeColumnsSyntax([$col => [$value]], $type) . ';';
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rename Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $column
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renameColumn($table, $column)
|
||||
{
|
||||
return 'ALTER TABLE '.$table.' RENAME COLUMN ' . $this->buildForgeColumnsSyntax($column, 'TO') . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $column
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function addColumn($table, $columns)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' ADD ' . $this->buildForgeColumnsQuery($columns) . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop index
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropIndex($indexName, $table)
|
||||
{
|
||||
return 'DROP INDEX ' . $indexName . ';';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php namespace ZN\Database\Postgres;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Database\DriverTool;
|
||||
|
||||
class DBTool extends DriverTool
|
||||
{
|
||||
/**
|
||||
* List Databases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listDatabases($query = 'SELECT datname FROM pg_database')
|
||||
{
|
||||
return $this->runListQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* List Tables
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listTables($query = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'")
|
||||
{
|
||||
return $this->runListQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function statusTables($table)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function optimizeTables($table)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function repairTables($table, $query = '', $message = '')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function backup($tables, $fileName, $path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php namespace ZN\Database;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
class Properties
|
||||
{
|
||||
/**
|
||||
* Keeps Table Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $table = NULL;
|
||||
|
||||
/**
|
||||
* Keeps Table Prefix
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $prefix = NULL;
|
||||
|
||||
/**
|
||||
* Keeps Postgres Driver Returning ID
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $returningId = 'id';
|
||||
}
|
||||
@@ -0,0 +1,452 @@
|
||||
<?php namespace ZN\Database\SQLServer;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use stdClass;
|
||||
use ZN\Support;
|
||||
use ZN\Security;
|
||||
use ZN\ErrorHandling\Errors;
|
||||
use ZN\Database\Exception\ConnectionErrorException;
|
||||
use ZN\Database\DriverMappingAbstract;
|
||||
|
||||
class DB extends DriverMappingAbstract
|
||||
{
|
||||
/**
|
||||
* Keep Operators
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $operators =
|
||||
[
|
||||
'like' => '%'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keep Statements
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $statements =
|
||||
[
|
||||
'autoincrement' => 'IDENTITY(1,1)',
|
||||
'primarykey' => 'PRIMARY KEY',
|
||||
'foreignkey' => 'FOREIGN KEY',
|
||||
'unique' => 'UNIQUE',
|
||||
'null' => 'NULL',
|
||||
'notnull' => 'NOT NULL',
|
||||
'exists' => 'EXISTS',
|
||||
'notexists' => 'NOT EXISTS',
|
||||
'constraint' => 'CONSTRAINT',
|
||||
'default' => 'DEFAULT'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keep Variable Types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $variableTypes =
|
||||
[
|
||||
'int' => ':INT',
|
||||
'smallint' => ':SMALLINT',
|
||||
'tinyint' => ':TINYINT',
|
||||
'mediumint' => ':INT',
|
||||
'bigint' => ':BIGINT',
|
||||
'decimal' => 'DECIMAL',
|
||||
'double' => 'FLOAT',
|
||||
'float' => 'FLOAT',
|
||||
'char' => 'CHAR',
|
||||
'varchar' => 'VARCHAR',
|
||||
'tinytext' => ':VARCHAR(255)',
|
||||
'text' => ':VARCHAR(65535)',
|
||||
'mediumtext' => ':VARCHAR(16277215)',
|
||||
'longtext' => ':VARCHAR(16277215)',
|
||||
'date' => ':DATE',
|
||||
'datetime' => ':DATETIME',
|
||||
'time' => ':TIME',
|
||||
'timestamp' => ':TIMESTAMP'
|
||||
];
|
||||
|
||||
/**
|
||||
* Magic Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
Support::func('sqlsrv_connect', 'SQL Server');
|
||||
}
|
||||
|
||||
/**
|
||||
* Connection
|
||||
*
|
||||
* @param array $config = []
|
||||
*/
|
||||
public function connect($config = [])
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
$server = ( ! empty($this->config['server']) )
|
||||
? $this->config['server'] // @codeCoverageIgnore
|
||||
: $this->config['host'];
|
||||
|
||||
if( ! empty($this->config['port']) )
|
||||
{
|
||||
$server .= ', '.$this->config['port'];
|
||||
}
|
||||
|
||||
$charset = $this->config['charset'] === 'utf8' ? 'utf-8' : $this->config['charset'];
|
||||
|
||||
$connection =
|
||||
[
|
||||
'UID' => $this->config['user'],
|
||||
'PWD' => $this->config['password'],
|
||||
'Database' => $this->config['database'],
|
||||
'ConnectionPooling' => $this->config['pconnect'] === true ? 1 : 0,
|
||||
'CharacterSet' => $charset ?: 'utf-8',
|
||||
'Encrypt' => $this->config['encode'] ?: false,
|
||||
'ReturnDatesAsStrings' => 1
|
||||
];
|
||||
|
||||
$this->connect = @sqlsrv_connect($server, $connection);
|
||||
|
||||
if( empty($this->connect) )
|
||||
{
|
||||
throw new ConnectionErrorException(NULL, sqlsrv_errors(SQLSRV_ERR_ERRORS)[0]['message']); // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exec($query, $security = NULL)
|
||||
{
|
||||
if( empty($query) )
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return sqlsrv_query($this->connect, $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple Queries
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function multiQuery($query, $security = NULL)
|
||||
{
|
||||
return (bool) $this->query($query, $security);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function query($query, $security = NULL)
|
||||
{
|
||||
return $this->query = $this->exec($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transStart()
|
||||
{
|
||||
return sqlsrv_begin_transaction($this->connect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transRollback()
|
||||
{
|
||||
return sqlsrv_rollback($this->connect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transCommit()
|
||||
{
|
||||
return sqlsrv_commit($this->connect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert Last ID
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
public function insertID()
|
||||
{
|
||||
$this->query('SELECT @@IDENTITY AS insert_id');
|
||||
|
||||
return $this->fetchAssoc()['insert_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns column data
|
||||
*
|
||||
* @param string $column
|
||||
*
|
||||
* @return array|object
|
||||
*/
|
||||
public function columnData($col = '')
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
|
||||
foreach( sqlsrv_field_metadata($this->query) as $field )
|
||||
{
|
||||
$fieldName = $field['Name'];
|
||||
|
||||
$columns[$fieldName] = new stdClass();
|
||||
$columns[$fieldName]->name = $fieldName;
|
||||
$columns[$fieldName]->type = $field['Type'];
|
||||
$columns[$fieldName]->maxLength = $field['Size'];
|
||||
$columns[$fieldName]->primaryKey = NULL;
|
||||
$columns[$fieldName]->default = NULL;
|
||||
}
|
||||
|
||||
return $columns[$col] ?? $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numrows
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function numRows()
|
||||
{
|
||||
$this->query('select @@RowCount');
|
||||
|
||||
return $this->fetchRow()[0] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function columns()
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return []; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
|
||||
$getFieldData = sqlsrv_field_metadata($this->query);
|
||||
|
||||
foreach( $getFieldData as $field )
|
||||
{
|
||||
$columns[] = $field['Name'];
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numfields
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function numFields()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return sqlsrv_num_fields($this->query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Real Escape String
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function realEscapeString($data)
|
||||
{
|
||||
return Security\Injection::escapeStringEncode($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string description of the last error.
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function error()
|
||||
{
|
||||
if( ! empty($this->connect) )
|
||||
{
|
||||
$error = sqlsrv_errors(SQLSRV_ERR_ERRORS)[0] ?? [];
|
||||
|
||||
return ! empty($error['code']) ? ($error['code'] === 15477 ? false : ($error['message'] ?: false)) : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a result row as an associative, a numeric array, or both
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchArray()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return sqlsrv_fetch_array($this->query, SQLSRV_FETCH_BOTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
return []; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a result row as an associative array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchAssoc()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return sqlsrv_fetch_array($this->query, SQLSRV_FETCH_ASSOC);
|
||||
}
|
||||
else
|
||||
{
|
||||
return []; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a result row as an enumerated array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchRow()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return sqlsrv_fetch_array($this->query, SQLSRV_FETCH_NUMERIC);
|
||||
}
|
||||
else
|
||||
{
|
||||
return []; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows in a previous MySQL operation
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return sqlsrv_rows_affected($this->query);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the MySQL server as an integer
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function version()
|
||||
{
|
||||
if( ! empty($this->connect) )
|
||||
{
|
||||
return sqlsrv_server_info($this->connect)['SQLServerVersion'];
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit
|
||||
*
|
||||
* @param int $start = NULL
|
||||
* @param int $limit = 0
|
||||
*
|
||||
* @return DB
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function limit($start = NULL, int $limit = 0)
|
||||
{
|
||||
if( $limit === 0 )
|
||||
{
|
||||
$limit = $start;
|
||||
$start = 0;
|
||||
}
|
||||
|
||||
return ' OFFSET ' . $start . ' ROWS FETCH NEXT ' . $limit . ' ROWS ONLY';
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Clean Limit
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function cleanLimit($data)
|
||||
{
|
||||
return preg_replace('/OFFSET\s+[0-9]+\s+ROWS\sFETCH\sNEXT\s+[0-9]+\s+ROWS\sONLY/xi', '', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected Get Limit Values
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getLimitValues($data)
|
||||
{
|
||||
preg_match('/OFFSET\s+(?<start>[0-9]+)\s+ROWS\sFETCH\sNEXT\s+(?<limit>[0-9]+)\s+ROWS\sONLY/xi', $data ?? '', $match);
|
||||
|
||||
return $match;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php namespace ZN\Database\SQLServer;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Database\DriverForge;
|
||||
|
||||
class DBForge extends DriverForge
|
||||
{
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function extras($extras)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $column
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function renameColumn($table, $column)
|
||||
{
|
||||
return "sp_rename '$table." . key($column) . "', '" . current($column) . "', 'COLUMN';";
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropIndex($indexName, $table)
|
||||
{
|
||||
return 'DROP INDEX ' . $table . '.' . $indexName . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename Table
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $newname
|
||||
* 1
|
||||
* @return string
|
||||
*/
|
||||
public function renameTable($name, $newName)
|
||||
{
|
||||
return "sp_rename '$name', '$newName';";
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function addColumn($table, $columns)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' ADD ' . $this->buildForgeColumnsQuery($columns) . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* MOdify Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function modifyColumn($table, $columns)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' ALTER COLUMN ' . $this->buildForgeColumnsQuery($columns) . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop Column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropColumn($table, $column)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' DROP COLUMN ' . $column . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create index
|
||||
*
|
||||
* 5.7.4[added]
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
* @param string $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createFulltextIndex($indexName, $table, $columns)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php namespace ZN\Database\SQLServer;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Config;
|
||||
use ZN\Database\DriverTool;
|
||||
|
||||
class DBTool extends DriverTool
|
||||
{
|
||||
/**
|
||||
* List Databases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listDatabases($query = 'SELECT name FROM master.dbo.sysdatabases')
|
||||
{
|
||||
return $this->runListQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* List Tables
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listTables($query = "")
|
||||
{
|
||||
$query = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG='".($this->settings['database'] ?? Config::get('Database', 'database')['database'])."'";
|
||||
|
||||
return $this->runListQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function statusTables($table)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function optimizeTables($table)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function repairTables($table, $query = '', $message = '')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function backup($tables, $fileName, $path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,416 @@
|
||||
<?php namespace ZN\Database\SQLite;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use SQLite3;
|
||||
use stdClass;
|
||||
use Exception;
|
||||
use ZN\Support;
|
||||
use ZN\ErrorHandling\Errors;
|
||||
use ZN\Database\DriverMappingAbstract;
|
||||
use ZN\Database\Exception\ConnectionErrorException;
|
||||
|
||||
class DB extends DriverMappingAbstract
|
||||
{
|
||||
/**
|
||||
* Keep Operators
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $operators =
|
||||
[
|
||||
'like' => '%'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keep Statements
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $statements =
|
||||
[
|
||||
'autoincrement' => 'AUTOINCREMENT',
|
||||
'primarykey' => 'PRIMARY KEY',
|
||||
'foreignkey' => 'FOREIGN KEY',
|
||||
'unique' => 'UNIQUE',
|
||||
'null' => 'NULL',
|
||||
'notnull' => 'NOT NULL',
|
||||
'exists' => 'EXISTS',
|
||||
'notexists' => 'NOT EXISTS',
|
||||
'constraint' => 'CONSTRAINT',
|
||||
'default' => 'DEFAULT'
|
||||
];
|
||||
|
||||
/**
|
||||
* Keep Variable Types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $variableTypes =
|
||||
[
|
||||
'int' => ':INTEGER',
|
||||
'smallint' => ':SMALLINT',
|
||||
'tinyint' => ':TINYINT',
|
||||
'mediumint' => ':MEDIUMINT',
|
||||
'bigint' => ':BIGINT',
|
||||
'decimal' => 'DECIMAL',
|
||||
'double' => ':DOUBLE',
|
||||
'float' => ':FLOAT',
|
||||
'char' => 'CHARACTER',
|
||||
'varchar' => 'VARCHAR',
|
||||
'tinytext' => ':VARCHAR(255)',
|
||||
'text' => ':TEXT',
|
||||
'mediumtext' => ':CLOB',
|
||||
'longtext' => ':BLOB',
|
||||
'date' => ':DATE',
|
||||
'datetime' => ':DATETIME',
|
||||
'time' => ':DATETIME',
|
||||
'timestamp' => ':DATETIME'
|
||||
];
|
||||
|
||||
/**
|
||||
* Magic Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
Support::extension('SQLite3');
|
||||
}
|
||||
|
||||
/**
|
||||
* Connection
|
||||
*
|
||||
* @param array $config = []
|
||||
*/
|
||||
public function connect($config = [])
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
try
|
||||
{
|
||||
$this->connect = ( ! empty($this->config['password']) )
|
||||
? new SQLite3($this->config['database'], SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE, $this->config['password'])
|
||||
: new SQLite3($this->config['database']);
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
catch( Exception $e )
|
||||
{
|
||||
throw new ConnectionErrorException(NULL, $this->connect->lastErrorMsg());
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function exec($query, $security = NULL)
|
||||
{
|
||||
if( empty($query) )
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $this->connect->exec($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple Queries
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function multiQuery($query, $security = NULL)
|
||||
{
|
||||
return (bool) $this->query($query, $security);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $security = NULL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function query($query, $security = [])
|
||||
{
|
||||
return $this->query = $this->connect->query($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transStart()
|
||||
{
|
||||
return $this->connect->exec('BEGIN TRANSACTION');
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transRollback()
|
||||
{
|
||||
return $this->connect->exec('ROLLBACK');
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit Transaction Query
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function transCommit()
|
||||
{
|
||||
return $this->connect->exec('END TRANSACTION');
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert Last ID
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
public function insertID()
|
||||
{
|
||||
if( empty($this->connect) )
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $this->connect->lastInsertRowID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns column data
|
||||
*
|
||||
* @param string $column
|
||||
*
|
||||
* @return array|object
|
||||
*/
|
||||
public function columnData($col = '')
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$dataTypes =
|
||||
[
|
||||
SQLITE3_INTEGER => 'integer',
|
||||
SQLITE3_FLOAT => 'float',
|
||||
SQLITE3_TEXT => 'text',
|
||||
SQLITE3_BLOB => 'blob',
|
||||
SQLITE3_NULL => 'null'
|
||||
];
|
||||
|
||||
$columns = [];
|
||||
$numFields = $this->numFields();
|
||||
|
||||
for( $i = 0; $i < $numFields; $i++ )
|
||||
{
|
||||
$type = $this->query->columnType($i);
|
||||
$fieldName = $this->query->columnName($i);
|
||||
|
||||
$columns[$fieldName] = new stdClass();
|
||||
$columns[$fieldName]->name = $fieldName;
|
||||
$columns[$fieldName]->type = $dataTypes[$type] ?? $type;
|
||||
$columns[$fieldName]->maxLength = NULL;
|
||||
$columns[$fieldName]->primaryKey = NULL;
|
||||
$columns[$fieldName]->default = NULL;
|
||||
}
|
||||
|
||||
return $columns[$col] ?? $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numrows
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function numRows()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return count($this->result());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns columns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function columns()
|
||||
{
|
||||
if( empty($this->query) )
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
$columns = [];
|
||||
$numFields = $this->numFields();
|
||||
|
||||
for( $i = 0; $i < $numFields; $i++ )
|
||||
{
|
||||
$columns[] = $this->query->columnName($i);
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numfields
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function numFields()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return $this->query->numColumns();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Real Escape String
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function realEscapeString($data)
|
||||
{
|
||||
if( empty($this->connect) )
|
||||
{
|
||||
return $data; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $this->connect->escapeString($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string description of the last error.
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function error()
|
||||
{
|
||||
if( ! empty($this->connect) && $this->connect->lastErrorCode() )
|
||||
{
|
||||
return $this->connect->lastErrorMsg();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a result row as an associative, a numeric array, or both
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchArray()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return $this->query->fetchArray(SQLITE3_BOTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
return []; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a result row as an associative array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchAssoc()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return $this->query->fetchArray(SQLITE3_ASSOC);
|
||||
}
|
||||
else
|
||||
{
|
||||
return []; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a result row as an enumerated array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchRow()
|
||||
{
|
||||
if( ! empty($this->query) )
|
||||
{
|
||||
return $this->query->fetchArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of affected rows in a previous MySQL operation
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function affectedRows()
|
||||
{
|
||||
if( ! empty($this->connect) )
|
||||
{
|
||||
return $this->connect->changes();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the MySQL server as an integer
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function version($v = 'versionString')
|
||||
{
|
||||
if( ! empty($this->connect) )
|
||||
{
|
||||
$version = SQLite3::version();
|
||||
|
||||
return $version[$v];
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php namespace ZN\Database\SQLite;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Database\DriverForge;
|
||||
|
||||
class DBForge extends DriverForge
|
||||
{
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function extras($extras)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate
|
||||
*
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function truncate($table)
|
||||
{
|
||||
return 'DELETE FROM '.$table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function dropColumn($table, $column)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function modifyColumn($table, $column)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function renameColumn($table, $column)
|
||||
{
|
||||
return 'ALTER TABLE '.$table.' RENAME COLUMN ' . $this->buildForgeColumnsSyntax($column, 'TO') . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add column
|
||||
*
|
||||
* @param string $table
|
||||
* @param array $columns
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function addColumn($table, $columns)
|
||||
{
|
||||
return 'ALTER TABLE ' . $table . ' ADD ' . $this->buildForgeColumnsQuery($columns) . ';';
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop index
|
||||
*
|
||||
* @param string $indexName
|
||||
* @param string $table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function dropIndex($indexName, $table)
|
||||
{
|
||||
return 'DROP INDEX ' . $indexName . ';';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php namespace ZN\Database\SQLite;
|
||||
/**
|
||||
* ZN PHP Web Framework
|
||||
*
|
||||
* "Simplicity is the ultimate sophistication." ~ Da Vinci
|
||||
*
|
||||
* @package ZN
|
||||
* @license MIT [http://opensource.org/licenses/MIT]
|
||||
* @author Ozan UYKUN [ozan@znframework.com]
|
||||
*/
|
||||
|
||||
use ZN\Database\DriverTool, Config;
|
||||
|
||||
class DBTool extends DriverTool
|
||||
{
|
||||
/**
|
||||
* List Databases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listDatabases($query = "")
|
||||
{
|
||||
return [Config::get('Database', 'database')['database']];
|
||||
}
|
||||
|
||||
/**
|
||||
* List Tables
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listTables($query = "SELECT name FROM sqlite_master WHERE type = 'table'")
|
||||
{
|
||||
return $this->runListQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function statusTables($table)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function optimizeTables($table)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function repairTables($table, $query = '', $message = '')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported
|
||||
*/
|
||||
public function backup($tables, $fileName, $path)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user