Files
youlegames/codes/agent/game/dlweb/api/common/DatabaseHelper.php
2026-03-15 01:27:05 +08:00

8823 lines
233 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**************************************************************************
* 文件名: DatabaseHelper.php
* 版本号: v1.0
* 创建日期: 2016-03-21
* 最后修改日期: 2018-04-27
* 功能: 对PDO类的简单封装暂仅支持MSSQL、MYSQL、ORACLE
* by: bahamut
**************************************************************************
* 2016-03-21
* 创建文件。
* 2016-03-22
* 增加ORACLE支持。
* 2016-03-25
* 增加EXCEL文件导出。
* 2016-03-29
* Request方法新增回调函数的支持ExportToFile方法支持指定新的查询语句和参数。
* 2016-04-14:
* 增加Succeeded方法来判断pdo类的errorcode值是否成功。
* 增加对MYSQL的支持MYSQLHelper类在Connect方法中创建PDO对象后立即执行"use database;"语句如果不执行mysql会报'no selected database'的错误。)。
* 2016-04-20:
* 修改Connect方法参数提供默认参数并可支持数组方式传递。
* 2016-05-01:
* 新增LastInsertId方法用来获取最后一次新增数据时产生的自动编号。
* 2016-05-10:
* 新增错误返回值(ERRORCODE_CUSTOMFIRST、ERRORCODE_CUSTOMLAST),用于提供后期扩展。
* 2016-05-11:
* 新增ReplaceValue函数用来处理特殊字符。
* 2016-05-12:
* 修改SetErrors方法errorinfo总是获取最后一个元素如果是对象或者数组
* 2016-05-20:
* 增加FetchStyle成员, 用来设置提取记录时的提取方式默认PDO::FETCH_OBJ
* 2016-07-08:
* MYSQLHelper增加可用参数charset用来指定数据库的编码默认为utf8
* 2016-08-05:
* 新增GetParameterList方法用来处理传入类型为array与object的参数。
* 2017-01-05:
* 新增BindParameter和LoadStream属性, 用来支持大数据类型。
* BindParameter为true表示强制按传入的参数大小绑定参数到pdo对象中
* LoadStream为true表示将判断查询语句中的返回值类型如果为resorce则会用stream_get_contents去读取这个资源的实际值
* 2017-04-01:
* 新增接口IDatabaseHelper用于描述DatabaseHelper类的方法。
* 2017-04-06:
* 新增SQLCommand类来实现sql语句的封装。
* 2017-04-10:
* 新增CommandParameters类和CommandParameter类用于扩展DatabaseHelper的Request和Execute方法。
* 扩展DatabaseHelper的Request和Execute方法让传入的参数支持CommandParameter类型。
* 作废BindParameter和LoadStream属性, 总是支持大数据类型.
* 2017-07-03:
* ISQLCommand新增CallStoredProcedure方法用来调用存储过程或函数.
* 2017-07-16:
* ISQLCommand新增Union方法用来连接其他结果集union all语句.
* 2017-07-24:
* IDatabaseHelper接口增加方法NextRowset用来移动当前记录集指针用于多记录集时切换记录集操作
* IDatabaseHelper接口增加方法Records用来获取当前已打开的记录集
* DatabaseHelper类增加属性OnConnected(连接), OnDisconnected(断开连接), OnBeforeOpen(打开记录前), OnAfterOpen(打开记录后), OnBeforeExecute(执行命令前), OnAfterExecute(执行命令后), OnError(错误)用来捕捉事件。
* 2017-12-14:
* 解決了在設置條件時where, join on, having等當設置值為null時出現的bug.
* 2018-01-21:
* 增加ExportToBrowser方法无需服务器端缓存临时文件。用于导出excel文件。
* ExportToBrowser方法导出并没有做分页处理如果后期出现out of memory的情况则需要做分页导出。
* 2018-04-27:
* IDatabaseHelper改名为IPDOHelper, DatabaseHelper改名为PDOHelper.
* 2018-05-28:
* PDOHelper增加CacheRecord属性用来控制在执行有回调函数的查询语句时是否把查询到的记录缓存到本地。
**************************************************************************/
require_once __DIR__ . '/CommonConstant.php';
class ConnectParameter
{
public $Hostname;
public $Hostport;
public $Database;
public $Username;
public $Password;
public $Persistent;
public $Charset;
public function __construct($Hostname = '', $Hostport = 0, $Database = '', $Username = '', $Password = '', $Persistent = false, $Charset = '')
{
$this->Hostname = $Hostname;
$this->Hostport = $Hostport;
$this->Database = $Database;
$this->Username = $Username;
$this->Password = $Password;
$this->Charset = $Charset;
$this->Persistent = $Persistent;
}
static public function NewParameter($Hostname = '', $Hostport = 0, $Database = '', $Username = '', $Password = '', $Persistent = false, $Charset = '')
{
return new ConnectParameter($Hostname, $Hostport, $Database, $Username, $Password, $Persistent, $Charset);
}
}
/// 2017-04-10: expand pdo request or execute parameter.
class CommandParameters
{
/**
* @var array of CommandParameter
*/
private $Parameters;
/**
* CommandParameters constructor.
*/
public function __construct()
{
$this->Parameters = array();
}
/**
*
*/
public function __destruct()
{
$this->Clear();
}
/**
* @param int $Index
* @return CommandParameter
*/
public function GetParameter($Index)
{
if (is_integer($Index) && is_array($this->Parameters) && !empty($this->Parameters) && ($Index >= 0) && ($Index < count($this->Parameters)))
return $this->Parameters[$Index];
else
return null;
}
/**
* @param CommandParameter $Parameter
* @return int
*/
public function Append($Parameter)
{
$Parameter->Owner = $this;
array_push($this->Parameters, $Parameter);
return count($this->Parameters);
}
/**
* @param int $Index
* @return int
*/
public function Delete($Index)
{
if (is_integer($Index) && is_array($this->Parameters) && !empty($this->Parameters) && ($Index >= 0) && ($Index < count($this->Parameters)))
array_splice($this->Parameters, $Index, 1);
return count($this->Parameters);
}
/**
* @return int
*/
public function Clear()
{
$this->Parameters = array();
return 0;
}
/**
* @return int
*/
public function GetCount()
{
return count($this->Parameters);
}
/**
* @param string $Name
* @param string $Type
* @param null $Value
* @param int $Size
* @param bool $Raw
* @param bool $Output
* @return CommandParameter
*/
public function CreateParameter($Name = '', $Type = TYPENAME_STRING, $Value = null, $Size = 0, $Raw = false, $Output = false)
{
$Return = new CommandParameter($this);
$this->Append($Return);
$Return->Name = $Name;
$Return->Type = $Type;
$Return->Value = empty($Value) ? '' : $Value;
$Return->Size = empty($Size) ? strlen($Value) : $Size;
$Return->Raw = $Raw;
$Return->Output = $Output;
return $Return;
}
}
class CommandParameter
{
/**
* @var CommandParameters
*/
public $Owner;
/**
* @var string
*/
public $Name;
/**
* @var string
*/
public $Type;
/**
* @var mixed
*/
public $Value;
/**
* @var int
*/
public $Size;
/**
* @var bool
*/
public $Raw;
/**
* @var bool
*/
public $Output;
/**
* CommandParameter constructor.
* @param $Parameter
*/
public function __construct($Parameter)
{
if ($Parameter instanceof CommandParameters)
{
$this->Owner = $Parameter;
$this->Name = '';
$this->Type = TYPENAME_STRING;
$this->Value = '';
$this->Size = 0;
$this->Raw = false;
$this->Output = false;
}
elseif (!empty($Parameter))
{
$this->ParseArray($Parameter);
}
else
{
$this->Owner = null;
$this->Name = '';
$this->Type = TYPENAME_STRING;
$this->Value = '';
$this->Size = 0;
$this->Raw = false;
$this->Output = false;
}
}
/**
* 从数组中获取值
* @param array $Parameter
* @return bool
* @link
* @auther 应俊
*/
public function ParseArray($Parameter)
{
if (empty($Parameter))
return false;
switch (gettype($Parameter))
{
case 'object':
{
if (method_exists($Parameter, 'GetObjectPropertyList'))
$Keys = $Parameter->GetObjectPropertyList();
else
$Keys = array_keys((array)$Parameter);
foreach ($Keys as $K)
{
$V = $Parameter->$K;
if (is_string($V) && null != ($o = JsonStringToJsonObject($V)) && is_object($o))
$this->$K = $o;
else
$this->$K = $V;
}
break;
}
case 'array':
{
foreach ($Parameter as $K => $V)
{
if (is_string($V) && null != ($o = JsonStringToJsonObject($V)) && is_object($o))
$this->$K = $o;
else
$this->$K = $V;
}
break;
}
default:
return false;
}
return true;
}
/**
* @param CommandParameters $Owner
* @param string $Name
* @param string $Type
* @param null $Value
* @param int $Size
* @param bool $Raw
* @param bool $Output
* @return CommandParameter
*/
static public function Parameter($Owner = null, $Name = '', $Type = TYPENAME_STRING, $Value = null, $Size = 0, $Raw = false, $Output = false)
{
$Return = new CommandParameter($Owner);
if ($Owner instanceof CommandParameters)
{
$Owner->Append($Return);
}
elseif (!is_array($Owner))
{
$Return->Name = $Name;
$Return->Type = $Type;
$Return->Value = empty($Value) ? '' : $Value;
$Return->Size = empty($Size) ? strlen($Value) : $Size;
$Return->Raw = $Raw;
$Return->Output = $Output;
}
return $Return;
}
}
/*******************************
* name: CommandInformation.
* note: sql command information class.
*******************************/
class CommandInformation
{
public $Command;
public $Paramer;
public function __construct($Command = '', $Paramer = array())
{
$this->Command = $Command;
$this->Paramer = $Paramer;
}
/**
* @param CommandInformation $CommandInformation
* @return bool.
*/
public function Merge($CommandInformation)
{
if (!($CommandInformation instanceof CommandInformation))
return false;
$this->Command .= $CommandInformation->Command;
foreach ((array)$CommandInformation->Paramer as $Key => $Value)
{
array_push($this->Paramer, $Value);
}
return true;
}
static public function NewCommandInformation($Command = '', $Paramer = array())
{
return new CommandInformation($Command, $Paramer);
}
}
/// ====================================================================================================================
interface IItem
{
/**
* @return IList
*/
public function GetOwner();
/**
* @param IList $Owner
*/
public function SetOwner($Owner);
}
interface IList
{
/**
* @param integer $Index
* @return IItem
*/
public function GetItem($Index);
/**
* @return integer
*/
public function GetCount();
/**
* @param IItem $Item
* @return integer
*/
public function Append($Item);
/**
* @param integer $Index
* @return integer
*/
public function Delete($Index);
/**
* @return integer
*/
public function Clear();
}
interface IField extends IItem
{
/**
* @note get field name.
* @return string
*/
public function GetName();
/**
* @note get field data type.
* @return string
*/
public function GetType();
/**
* @note get field data size.
* @return integer
*/
public function GetSize();
/**
* @note get field default value.
* @return mixed
*/
public function GetDefaultValue();
/**
* @return IFields
*/
public function GetOwner();
/**
* @param IFields $Owner
*/
public function SetOwner($Owner);
}
interface IFields extends IList
{
/**
* @return ITable
*/
public function GetOwner();
/**
* @param ITable $Owner
*/
public function SetOwner($Owner);
}
interface ITable extends IItem
{
/**
* @note get table field list.
* @return IFields
*/
public function GetFields();
/**
* @note get table name.
* @return string
*/
public function GetName();
public function Select();
public function Filter();
public function Limit();
public function WithPage();
public function Request();
/**
* @return ITables
*/
public function GetOwner();
/**
* @param ITables $Owner
*/
public function SetOwner($Owner);
}
interface ITables extends IList
{
/**
* @return IPDOHelper
*/
public function GetOwner();
/**
* @param IPDOHelper $Owner
*/
public function SetOwner($Owner);
}
/*******************************
* name: IPDOHelper.
* note: database helper base interface.
*******************************/
interface IPDOHelper
{
/*******************************
* name: Succeeded.
* note: test the success of the code.
* parameters: code.
* return: true if the code succeeded, false otherwise.
*******************************
* @param string|int $Code
* @return bool
*******************************/
public function Succeeded($Code);
/*******************************
* name: IsDone.
* note: test the success of the last code.
* parameters: none.
* return: true if the code succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function IsDone();
/*******************************
* name: Connect.
* note: connect to database.
* parameters: look at the derived class.
* return: true if the method call succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function Connect();
/*******************************
* name: Connect.
* note: close active connected.
* parameters: none.
* return: true if the method call succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function Close();
/*******************************
* name: GetTables.
* note: get the database all tables.
* parameters: none.
* return: table list if the method call succeeded, null otherwise.
*******************************
* @return ITables
*******************************/
public function GetTables();
/*******************************
* name: GetTableFields.
* note: get the table fields.
* parameters: table name.
* return: field list if the method call succeeded, null otherwise.
*******************************
* @param string $Tablename
* @return ITables
*******************************/
public function GetTableFields($Tablename);
/*******************************
* name: Request.
* note: request data from database(recordset was returned).
* parameters: sql command, parameter list.
* 2016-03-29: append the callback support(first parameter).
* return: recordset as array if the method call succeeded, null otherwise.
*******************************
* param callable $Callable
* param string $SqlCommand
* param mixed $Parameters...
* @return mixed|null
*******************************/
public function Request(/* $Callable, $SqlCommand, $Parameters, ... */);
/*******************************
* name: Execute.
* note: execute command from database(no recordset was returned).
* parameters: sql command, parameter list
* return: true if the method call succeeded, false otherwise.
*******************************
* param string $SqlCommand
* param mixed $Parameters...
* @return bool
*******************************/
public function Execute(/* $SqlCommand, $Parameters, ... */);
/*******************************
* name: LastInsertId.
* note: This method may not return a meaningful or consistent result across different PDO drivers, because the underlying database may not even support the notion of auto-increment fields or sequences.
* parameters: name
* return: PDO::lastInsertId method return value.
*******************************
* @param null|string $Name
* @return bool|string
******************************/
public function LastInsertId($Name = null);
/*******************************
* name: ColumnNames.
* note: get all field name of current recordset.
* parameters: none
* return: all field name of current recordset.
*******************************
* @return array|bool
*******************************/
public function ColumnNames();
/*******************************
* name: Records.
* note: return record list, deleted, or changed by the last statement.
* parameters: none
* return: the record list, deleted, or changed.
*******************************
* @return array
*******************************/
public function GetRecords();
/*******************************
* name: InTransaction.
* note: Checks if inside a transaction.
* parameters: none
* return: true if a transaction is currently active, false otherwise.
*******************************
* @return bool
*******************************/
public function InTransaction();
/*******************************
* name: BeginTransaction.
* note: turns off auto commit mode and begins a transaction.
* parameters: none
* return: true if the method call succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function BeginTransaction();
/*******************************
* name: Commit.
* note: sends commands to the database that were issued after calling BeginTransaction and returns the connection to auto commit mode.
* parameters: none
* return: true if the method call succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function Commit();
/*******************************
* name: Rollback.
* note: discards database commands that were issued after calling BeginTransaction and returns the connection to auto commit mode.
* parameters: none
* return: true if the method call succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function Rollback();
/*******************************
* name: Quote.
* note: quotes a string for use in a query.
* param value The string to be quoted.
* param type Provides a data type hint for drivers that have alternate quoting styles.
* return string a quoted string that is theoretically safe to pass into an SQL statement. Returns FALSE if the driver does not support quoting in this way.
*******************************
* @param string $Value The string to be quoted.
* @param int $ValueType [optional] Provides a data type hint for drivers that have alternate quoting styles.
* @return string a quoted string that is theoretically safe to pass into an SQL statement. Returns <b>FALSE</b> if the driver does not support quoting in this way.
*******************************/
public function Quote($Value, $ValueType = PDO::PARAM_STR);
/*******************************
* name: NextRowset.
* note: moves the cursor to the next result set.
* parameters: none
* return: true if the method call succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function NextRowset();
/*******************************
* name: RowCount.
* note: returns the number of rows added, deleted, or changed by the last statement.
* parameters: none
* return: the number of rows added, deleted, or changed.
*******************************
* @return int
*******************************/
public function GetRowCount();
/*******************************
* name: ColCount.
* note: returns the number of columns in a result set.
* parameters: none
* return: returns the number of columns in a result set. returns zero if the result set is empty.
*******************************
* @return int
*******************************/
public function GetColCount();
/*******************************
* name: ExportToFile.
* note: save request data to file.
* parameters: filename, sql command, parameter list
* return: true if the method call succeeded, false otherwise.
*******************************
* param string filename
* param string sqlcommand
* param mixed parameters...
* @return bool
*******************************/
public function ExportToFile(/* filename, sqlcommand, parameters */);
/*******************************
* name: ExportToBrowser.
* note: save request data to browser.
* parameters: sql command, parameter list
* return: true if the method call succeeded, false otherwise.
*******************************
* param string sqlcommand
* param mixed parameters...
* @return bool
*******************************/
public function ExportToBrowser(/* sqlcommand, parameters */);
/*******************************
* name: SaveArrayToFile.
* note: save data to file.
* parameters: filename, data
* return: true if the method call succeeded, false otherwise.
*******************************
* @param string $Filename
* @param array|mixed $Data
* @return bool
*******************************/
public function SaveArrayToFile($Filename, $Data);
/*******************************
* name: SaveArrayToBrowser.
* note: save data to browser.
* parameters: data
* return: true if the method call succeeded, false otherwise.
*******************************
* @param array|mixed $Data
* @return bool
*******************************/
public function SaveArrayToBrowser($Data);
/*******************************
* name: GetConnectParameter.
* note: get the parameter with connect method.
* parameters: nan
* return: connect parameter if the method call succeeded, null otherwise.
*******************************
* @return ConnectParameter
*******************************/
public function GetConnectParameter();
/*******************************
* name: GetCommandParameter.
* note: get the parameter with run sql command.
* parameters: nan
* return: command parameter if the method call succeeded, null otherwise.
*******************************
* @return CommandParameters
*******************************/
public function GetCommandParameter();
/*******************************
* name: GetConnected.
* note: get the connected status.
* parameters: nan
* return: current connected status succeeded, null otherwise.
*******************************
* @return ConnectParameter
*******************************/
public function GetConnected();
/*******************************
* name: GetConnectType.
* note: get the connect database type.
* parameters: nan
* return: connect database type if the method call succeeded, null otherwise.
*******************************
* @return null|string
*******************************/
public function GetConnectType();
/*******************************
* name: GetErrorCode.
* note: get the last method call return code.
* parameters: none.
* return: get the last method call return code.
*******************************
* @return int
*******************************/
public function GetErrorCode();
/*******************************
* name: GetErrorInfo.
* note: get the last method call return info.
* parameters: none.
* return: get the last method call return info.
*******************************
* @return mixed
*******************************/
public function GetErrorInfo();
/*******************************
* name: GetErrors.
* note: get the last method call return code and info.
* parameters: none.
* return: get the last method call return code and info.
*******************************
* @return array
*******************************/
public function GetErrors();
}
/**
* @note the sql command helper of database interface.
**************sample***************
* $this
* ->Select(...)
* ->From(...)
* ->InnerJoin|LeftJoin|RightJoin(...)
* ->On(...)
* ->Where(...)
* ->GroupBy(...)
* ->Having(...)
* ->OrderBy(...)
* ->WithPage(...)
* ->Request()
**********************************
* $this
* ->Insert(...)
* ->Fields(...)
* ->Values(...)
* ->Execute()
**********************************
* $this
* ->Update(...)
* ->Fields(...)
* ->Values(...)
* ->Where(...)
* ->Execute()
**********************************
* $this
* ->Delete(...)
* ->Where(...)
* ->Execute()
**********************************
* $this
* ->Truncate(...)
* ->Execute()
**********************************
* $this
* ->Merge(...)
* ->Fields(...)
* ->Values(...)
* ->MergeOn(...)
* ->Execute()
**********************************
* $this
* ->CallStoredProcedure(...)
* ->Values(...)
* ->Request()/Execute()
**********************************/
interface ISQLCommand
{
/*******************************
* name: GetIdentifiers.
* note: processing the identifier.
* parameters: field.
* return: always return locale instance.
*******************************
* @param string $Identifiers need processing identifier
* @param bool $Quoted need quoted?
* @param array|mixed $Specialchar need special treatment string.
* @return string
*******************************/
public function GetIdentifiers($Identifiers, $Quoted = false, $Specialchar = null);
/*******************************
* name: From.
* note: set the datasource or table information.
* parameters: datasource or table.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function From();
/*******************************
* name: Where.
* note: set the where condition information.
* parameters: where condition.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Where();
/*******************************
* name: GroupBy.
* note: set the group expression information.
* parameters: group expression.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function GroupBy();
/*******************************
* name: Having.
* note: set the having condition information by group field.
* parameters: having condition.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Having();
/*******************************
* name: OrderBy.
* note: set the order information.
* parameters: order expression.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function OrderBy();
/*******************************
* name: WithPage.
* note: set paging select information.
* parameters: PageIndex, PageSize.
* return: always return locale instance.
*******************************
* @param int $PageIndex
* @param int $PageSize
* @return ISQLCommand
*******************************/
public function WithPage($PageIndex, $PageSize);
/*******************************
* name: Limit.
* note: set select max record count.
* parameters: maxcount.
* return: always return locale instance.
*******************************
* @param int $MaxCount
* @return ISQLCommand
*******************************/
public function Limit($MaxCount);
/*******************************
* name: Fields.
* note: set update column list.
* parameters: column list.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Fields();
/*******************************
* name: Values.
* note: set update value list.
* parameters: value list.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Values();
/*******************************
* name: Select.
* note: set the select field information.
* parameters: field.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Select();
/*******************************
* name: Insert.
* note: set the insert table or datasource information.
* parameters: table or datasource.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Insert();
/*******************************
* name: Update.
* note: set the update table or datasource information.
* parameters: table or datasource.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Update();
/*******************************
* name: delete.
* note: set the delete table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Delete();
/*******************************
* name: Truncate.
* note: set the truncate table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Truncate();
/*******************************
* name: Merge.
* note: set the merge table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Merge();
/*******************************
* name: Merge.
* note: set call stored procedure name.
* parameters: procedure name.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function CallStoredProcedure();
/*******************************
* name: InnerJoin.
* note: set the inner join table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param array|string
* @return ISQLCommand
*******************************/
public function InnerJoin();
/*******************************
* name: LeftJoin.
* note: set the left join table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param array|string
* @return ISQLCommand
*******************************/
public function LeftJoin();
/*******************************
* name: RightJoin.
* note: set the right join table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param array|string
* @return ISQLCommand
*******************************/
public function RightJoin();
/*******************************
* name: OuterJoin.
* note: set the outer join table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param array|string
* @return ISQLCommand
*******************************/
public function OuterJoin();
/*******************************
* name: On.
* note: set the join condition information.
* parameters: join condition.
* return: always return locale instance.
*******************************
* @param array|string
* @return ISQLCommand
*******************************/
public function On();
/*******************************
* name: MergeOn.
* note: set the merge condition information.
* parameters: merge condition.
* return: always return locale instance.
*******************************
* @param array|string
* @return ISQLCommand
*******************************/
public function MergeOn();
/*******************************
* name: Union.
* note: set the union object or sql command.
* parameters: union mixed.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string
* @return ISQLCommand
*******************************/
public function Union();
/*******************************
* name: BindParameters.
* note: bind other parameters of sql command needed.
* parameters: needed bind parameter list.
* return: always return locale instance.
*******************************
* @param array|string|CommandParameter
* @return ISQLCommand
*******************************/
public function BindParameters();
/**
* 2016-12-08增加
* @note 字符串转换为日期型的表达式
* @param string $StringTime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function String2DatetimeFormat($StringTime, $Quoted = true);
/**
* 2016-12-08增加
* @note 日期转换为字符串型的表达式
* @param string $Datetime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function Datetime2StringFormat($Datetime, $Quoted = true);
/**
* 2016-12-08增加
* @note 时间戳转换为日期型的表达式
* @param string $Timestamp 要转换的字段或表达式
* @return string
* @note 应俊
*/
public function Timestamp2DatetimeFormat($Timestamp);
/**
* 2016-12-08增加
* @note 日期转换为时间戳型的表达式
* @param string $Datetime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function Datetime2TimestampFormat($Datetime, $Quoted = true);
/**
* 2016-12-08增加
* @note 浮点转换为字符串型的表达式
* @param string $Float 要转换的字段或表达式
* @return string
* @note 应俊
*/
public function Float2StringFormat($Float);
/**
* 2016-01-16增加
* @note 获取当前服务器系统时间(或表达式)
* @param bool $IsRaw 是否返回数据库表达式
* @return string
* @note 应俊
*/
public function GetSystemTime($IsRaw = false);
/*******************************
* name: GetConnection.
* note: get database helper.
* parameters: nan.
* return: the database helper object.
*******************************
* @return IPDOHelper
*******************************/
public function GetConnection();
/*******************************
* name: GetCommandInformation.
* note: get sql command string.
* parameters: nan.
* return: sql command and parameter list as array if the method call succeeded, null otherwise.
*******************************
* @return CommandInformation
*******************************/
public function GetCommandInformation();
/*******************************
* name: Request.
* note: request data from database(recordset was returned).
* parameters: sql command, parameter list.
* return: recordset as array if the method call succeeded, null otherwise.
*******************************
* prarm clearmembers
*******************************
* param callable $Callable
* param string $SqlCommand
* param mixed $Parameters...
* @return mixed|null
*******************************/
public function Request(/* $Callable, $SqlCommand, $Parameters, ... */);
/*******************************
* name: Execute.
* note: execute command from database(no recordset was returned).
* parameters: sql command, parameter list
* return: true if the method call succeeded, false otherwise.
*******************************
* prarm clearmembers
*******************************
* param string $SqlCommand
* param mixed $Parameters...
* @return bool
*******************************/
public function Execute(/* $SqlCommand, $Parameters, ... */);
}
/// ====================================================================================================================
class CItem implements IItem
{
/**
* @var IList
*/
private $Owner;
/**
* @return IList
*/
public function GetOwner()
{
return $this->Owner;
}
/**
* @param IList $Owner
*/
public function SetOwner($Owner)
{
$this->Owner = $Owner;
}
}
class CList implements IList
{
protected $Items;
/**
* CList constructor.
*/
public function __construct()
{
$this->Items = array();
}
/**
*
*/
public function __destruct()
{
$this->Clear();
}
/**
* @param string $Name
* @return mixed
* @throws Exception
*/
public function __get($Name)
{
$Item = $this->GetItem($Name);
if (!empty($Item))
return $Item;
else
throw new Exception('undefined property: ' . get_class($this) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
}
/**
* @param integer $Index
* @return mixed
*/
public function GetItem($Index)
{
if (is_integer($Index) && is_array($this->Items) && !empty($this->Items) && ($Index >= 0) && ($Index < count($this->Items)))
return $this->Items[$Index];
else
return null;
}
/**
* @return integer
*/
public function GetCount()
{
return count($this->Items);
}
/**
* @param mixed $Item
* @return integer
*/
public function Append($Item)
{
if (is_object($Item))
{
if (method_exists($Item, 'SetOwner'))
$Item->SetOwner($this);
elseif (isset($Item->Owner))
$Item->Owner = $this;
}
array_push($this->Items, $Item);
return count($this->Items);
}
/**
* @param integer $Index
* @return integer
*/
public function Delete($Index)
{
if (is_integer($Index) && is_array($this->Items) && !empty($this->Items) && ($Index >= 0) && ($Index < count($this->Items)))
array_splice($this->Items, $Index, 1);
return count($this->Items);
}
/**
* @return integer
*/
public function Clear()
{
$this->Items = array();
return 0;
}
}
class Field extends CItem implements IField
{
/**
* @var string
*/
private $Name;
/**
* @var string
*/
private $Type;
/**
* @var int
*/
private $Size;
/**
* @var mixed
*/
private $DefaultValue;
public function __construct($Name, $Type, $Size, $DefaultValue)
{
$this->Name = $Name;
$this->Type = $Type;
$this->Size = $Size;
$this->DefaultValue = $DefaultValue;
}
/**
* @note get field name.
* @return string
*/
public function GetName()
{
return $this->Name;
}
/**
* @note get field data type.
* @return string
*/
public function GetType()
{
return $this->Type;
}
/**
* @note get field data size.
* @return integer
*/
public function GetSize()
{
return $this->Size;
}
/**
* @note get field default value.
* @return mixed
*/
public function GetDefaultValue()
{
return $this->DefaultValue;
}
}
class Fields extends CList implements IFields
{
/**
* @var ITable
*/
private $Owner;
public function __construct($Owner)
{
parent::__construct();
$this->SetOwner($Owner);
}
/**
* @param integer $Index
* @return IField
*/
public function GetItem($Index)
{
if (is_string($Index))
{
foreach ($this->Items as $Field)
{
if (!($Field instanceof IField))
continue;
if (strcasecmp($Field->GetName(), $Index) == 0)
return $Field;
}
}
return parent::GetItem($Index);
}
/**
* @param mixed $Item
* @return integer
*/
public function Append($Item)
{
if ($Item instanceof IField)
return parent::Append($Item);
else
return -1;
}
/**
* @return ITable
*/
public function GetOwner()
{
return $this->Owner;
}
/**
* @param ITable $Owner
*/
public function SetOwner($Owner)
{
$this->Owner = $Owner;
}
}
class Table extends CItem implements ITable
{
/**
* @var string
*/
private $Name;
/**
* @var ISQLCommand
*/
private $Command;
/**
* @var IFields
*/
private $Fields;
public function __construct($Name = '')
{
$this->Name = $Name;
$this->Fields = null;
}
/**
* @param string $Name
* @return mixed
* @throws Exception
*/
public function __get($Name)
{
if (is_null($this->Fields))
$this->RefreshFields();
if (!empty($this->Fields))
$Field = $this->Fields->GetItem($Name);
else
$Field = null;
if (!empty($Field))
return $Field;
throw new Exception('undefined property: ' . get_class($this) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
}
private function RefreshFields()
{
$this->Fields = null;
if (!method_exists($this->GetOwner(), 'GetOwner'))
return false;
$Helper = $this->GetOwner()->GetOwner();
if (empty($Helper) || !($Helper instanceof IPDOHelper))
return false;
$this->Fields = $Helper->GetTableFields($this->Name);
$this->Fields->SetOwner($this);
return !empty($this->Fields);
}
private function RefreshCommand()
{
$this->Command = null;
if (!method_exists($this->GetOwner(), 'GetOwner'))
return false;
$Helper = $this->GetOwner()->GetOwner();
if (empty($Helper) || !($Helper instanceof IPDOHelper))
return false;
$this->Command = new CommandDelegator($Helper);
return !empty($this->Command);
}
/**
* @note get table field list.
* @return IFields
*/
public function GetFields()
{
if (is_null($this->Fields))
$this->RefreshFields();
return $this->Fields;
}
/**
* @note get table name.
* @return string
*/
public function GetName()
{
return $this->Name;
}
public function Select()
{
if (is_null($this->Command))
$this->RefreshCommand();
if (is_null($this->Fields))
$this->RefreshFields();
if (0 == func_num_args())
{
$Fields = array();
for ($Index = 0; $Index < $this->Fields->GetCount(); $Index++)
{
if (method_exists($this->Fields, 'GetItem'))
$Item = call_user_func_array(array(&$this->Fields, 'GetItem'), array($Index));
else
$Item = null;
if (method_exists($Item, 'GetName'))
array_push($Fields, call_user_func(array(&$Item, 'GetName')));
}
}
else
$Fields = func_get_args();
call_user_func_array(array(&$this->Command, 'Select'), $Fields);
call_user_func_array(array(&$this->Command, 'From'), array($this->Name));
return $this;
}
public function Filter()
{
if (empty($this->Command))
$this->RefreshCommand();
call_user_func_array(array(&$this->Command, 'Where'), func_get_args());
return $this;
}
public function Limit()
{
if (empty($this->Command))
$this->RefreshCommand();
call_user_func_array(array(&$this->Command, 'Limit'), func_get_args());
return $this;
}
public function WithPage()
{
if (empty($this->Command))
$this->RefreshCommand();
call_user_func_array(array(&$this->Command, 'WithPage'), func_get_args());
return $this;
}
public function Request()
{
if (empty($this->Command))
$this->RefreshCommand();
return call_user_func_array(array(&$this->Command, 'Request'), func_get_args());
}
}
class Tables extends CList implements ITables
{
/**
* @var IPDOHelper
*/
private $Owner;
/**
* Tables constructor.
* @param IPDOHelper $Owner
*/
public function __construct($Owner)
{
parent::__construct();
$this->SetOwner($Owner);
}
/**
* @param integer $Index
* @return IField
*/
public function GetItem($Index)
{
if (is_string($Index))
{
foreach ($this->Items as $Table)
{
if (!($Table instanceof ITable))
continue;
if (strcasecmp($Table->GetName(), $Index) == 0)
return $Table;
}
}
return parent::GetItem($Index);
}
/**
* @param mixed $Item
* @return integer
*/
public function Append($Item)
{
if ($Item instanceof ITable)
return parent::Append($Item);
else
return -1;
}
/**
* @return IPDOHelper
*/
public function GetOwner()
{
return $this->Owner;
}
/**
* @param IPDOHelper $Owner
*/
public function SetOwner($Owner)
{
$this->Owner = $Owner;
}
}
/// ====================================================================================================================
/*******************************
* name: PDOHelper.
* note: database helper base class.
*******************************/
abstract class PDOHelper implements IPDOHelper
{
/**
* @note PDO object.
* @var PDO
*/
protected $Database;
/**
* @note PDOStatement object.
* @var PDOStatement
*/
private $Command;
/**
* @note request record row, properties map to columns.
* @var array
*/
private $Recordset;
/**
* @note request dataset fields.
* @var array
*/
private $Cols;
/**
* @note request recordsets, array of records.
* @var array
*/
private $Rows;
/**
* @note parameter list.
* @var CommandParameters
*/
protected $CommandParameters;
/**
* @note the connect database parameter
* @var ConnectParameter
*/
protected $ConnectParameter;
/**
* @note 2018-05-28: save data to $this->Rows
* @var bool
*/
public $CacheRecord;
/**
* @note fetch record style(default PDO::FETCH_OBJ)
* @var int
*/
public $FetchStyle;
/**
* @note load resource field by record, not used on 2017-04-10 later.
* @var bool
*/
private $LoadStream;
/**
* @note call bindParam, not used on 2017-04-10 later.
* @var bool
*/
private $BindParameter;
/**
* @note the last error code, 0 on success, otherwise other value.
* @var int
*/
private $ErrorCode;
/**
* @note the last error info, null on success, otherwise message.
* @var string|mixed
*/
private $ErrorInfo;
/// events
public $OnError;
public $OnConnected;
public $OnDisconnected;
public $OnBeforeOpen;
public $OnAfterOpen;
public $OnBeforeExecute;
public $OnAfterExecute;
/*******************************
* name: __construct.
* note: the construct function for class.
* parameters: nan.
* return: new object if the method call succeeded, null otherwise.
*******************************
* PDOHelper constructor.
*******************************/
public function __construct()
{
//parent::__construct();
$this->Database = null;
$this->CommandParameters = new CommandParameters();
$this->CacheRecord = true;
$this->FetchStyle = PDO::FETCH_OBJ;
$this->LoadStream = false;
$this->BindParameter = false;
$this->ClearMember();
}
/*******************************
* name: __destruct.
* note: the destruct function for class.
* parameters: nan.
* return: nan.
*******************************
* PDOHelper destructor.
*******************************/
public function __destruct()
{
$this->ClearMember();
$this->Database = null;
//parent::__destruct();
}
/**
* name GetParameterList
* @param Mixed $ParameterArrays
* @return array
*/
protected function GetParameterList($ParameterArrays)
{
$Result = array();
if ($ParameterArrays instanceof CommandParameter)
{
array_push($Result, $ParameterArrays);
}
else
{
switch (gettype($ParameterArrays))
{
case 'array':
{
foreach ($ParameterArrays as $Parameter)
{
foreach ($this->GetParameterList($Parameter) as $Item)
{
array_push($Result, $Item);
}
}
break;
}
case 'object':
{
if (class_exists('ReflectionClass'))
{
$Reflect = new ReflectionClass($ParameterArrays);
$Keys = array_keys($Reflect->getDefaultProperties());
}
else
{
$Keys = array();
}
$Keys += array_keys((array)$ParameterArrays);
foreach ($Keys as $Key)
{
if (isset($ParameterArrays->$Key))
{
$Parameter = $ParameterArrays->$Key;
foreach ($this->GetParameterList($Parameter) as $Item)
{
array_push($Result, $Item);
}
}
}
break;
}
default:
{
array_push($Result, $ParameterArrays);
break;
}
}
}
return $Result;
}
/*******************************
* name: InvokeEvent.
* note: call the event.
* parameters: event, parameters....
* return: bool
*******************************
* @return bool
*******************************/
protected function InvokeEvent()
{
if (0 == func_num_args())
return false;
$Parameters = func_get_args();
$Events = $Parameters[0];
if (is_callable($Events) || (is_object($Events) && strcasecmp('Closure', get_class($Events)) == 0))
{
try
{
$Parameters[0] = &$this;
return call_user_func_array($Events, $Parameters);
}
catch (Exception $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
}
else
return false;
}
/*******************************
* name: ClearMember.
* note: clear all member for class.
* parameters: nan.
* return: nan.
*******************************
*
*******************************/
private function ClearMember()
{
//$this->Database = null;
$this->Command = null;
$this->Recordset = null;
$this->Cols = null;
$this->Rows = null;
$this->CommandParameters->Clear();
//$this->ConnectParameter = null;
$this->ErrorCode = null;
$this->ErrorInfo = null;
}
/*******************************
* name: GetRecord.
* note: convert record object.
* parameters: record.
* return: record.
*******************************
* @param mixed $Record
* @return mixed
*******************************/
protected function GetRecord($Record)
{
if (is_object($Record))
{
$Propertys = get_object_vars($Record);
foreach ($Propertys as $Name => $Value)
{
$Record->$Name = $this->GetRecord($Value);
}
}
elseif (is_array($Record))
{
foreach ($Record as $Name => $Value)
{
$Record[$Name] = $this->GetRecord($Value);
}
}
elseif (is_resource($Record))
{
$Record = stream_get_contents($Record);
}
return $Record;
}
/*******************************
* name: Characet.
* note: convert string code page.
* parameters: string, charset
* return: string if the function call succeeded, null otherwise.
*******************************
* @param string $String
* @param string $Charset
* @return string
*******************************/
protected function Characet($String, $Charset = USEDCHARSET)
{
if (!empty ($String))
{
$Encoding = mb_detect_encoding($String, array('ASCII', 'UTF-8', 'GBK', 'GB2312', 'LATIN1', 'BIG5',));
if (0 != strcasecmp($Encoding, $Charset))
$String = mb_convert_encoding($String, $Charset, $Encoding);
}
return $String;
}
/*******************************
* name: Succeeded.
* note: test the success of the code.
* parameters: code.
* return: true if the code succeeded, false otherwise.
*******************************
* @param string|int $Code
* @return bool
*******************************/
public function Succeeded($Code)
{
return (bool)(is_int($Code) && ERRORCODE_SUCCESS == intval($Code));
}
/*******************************
* name: IsDone.
* note: test the success of the last code.
* parameters: none.
* return: true if the code succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function IsDone()
{
return (bool)$this->Succeeded($this->ErrorCode);
}
/*******************************
* name: Connect.
* note: connect to database.
* parameters: look at the derived class.
* return: true if the method call succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function Connect()
{
$this->Close();
//$this->SetErrors(ERRORCODE_NOIMPLEMENT, ERRORINFO_NOIMPLEMENT);
//$this->ConnectParameter = null;
return false;
}
/*******************************
* name: Connect.
* note: close active connected.
* parameters: none.
* return: true if the method call succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function Close()
{
if (isset($this->Database) && ($this->Database instanceof PDO))
{
$this->ClearMember();
$this->Database = null;
$this->ConnectParameter = null;
$this->SetErrors(ERRORCODE_SUCCESS, ERRORINFO_SUCCESS);
$this->InvokeEvent($this->OnDisconnected);
return true;
}
else
return false;
}
/*******************************
* name: GetTables.
* note: get the database all tables.
* parameters: none.
* return: table list if the method call succeeded, null otherwise.
*******************************
* @return ITables
*******************************/
abstract public function GetTables();
/*******************************
* name: GetTableFields.
* note: get the table fields.
* parameters: table name.
* return: field list if the method call succeeded, null otherwise.
*******************************
* @param string $Tablename
* @return ITables
*******************************/
abstract public function GetTableFields($Tablename);
/*******************************
* name: Request.
* note: request data from database(recordset was returned).
* parameters: sql command, parameter list.
* 2016-03-29: append the callback support(first parameter).
* return: recordset as array if the method call succeeded, null otherwise.
*******************************
* param callable $Callable
* param string $SqlCommand
* param mixed $Parameters...
* @return mixed|null
*******************************/
public function Request(/* $Callable, $SqlCommand, $Parameters, ... */)
{
$this->InvokeEvent($this->OnBeforeOpen);
if (!isset($this->Database) && !($this->Database instanceof PDO))
{
$this->SetErrors(ERRORCODE_NOCONNECTED, ERRORINFO_NOCONNECTED);
return null;
}
$this->ClearMember();
$this->SetErrors(ERRORCODE_SUCCESS, ERRORINFO_SUCCESS);
try
{
/// get parameters
$Parameters = func_get_args();
/// $Parameters[0] => callable
/// $Parameters[1] => sql command
/// $Parameters[...] => the parameters ...
/// call parent request field
//parent::Request($Parameters);
/// if no any parameter then exit
if (0 == count($Parameters))
{
$this->SetErrors(ERRORCODE_NOPARAMETER, ERRORINFO_NOPARAMETER);
return null;
}
/// lookup first parameter. save callback if it is function.
$Callable = null;
if (is_callable($Parameters[0]) || (is_object($Parameters[0]) && strcasecmp('Closure', get_class($Parameters[0])) == 0))
{
$Callable = $Parameters[0];
//unset($Parameters[0]); /// remove first.
//$Parameters = array_values($Parameters); /// reset parameters
array_shift($Parameters);
/// if no any parameter then exit
if (0 == count($Parameters))
{
$this->SetErrors(ERRORCODE_NOPARAMETER, ERRORINFO_NOPARAMETER);
return null;
}
}
/// the first parameter is the sql command string.
$this->Command = $this->Database->prepare($Parameters[0]);
if (null == $this->Command)
{
$this->SetErrors($this->Database->errorCode(), $this->Database->errorInfo());
return null;
}
/// reset parameters
//unset($Parameters[0]);
//$Parameters = array_values($Parameters);
array_shift($Parameters);
/// 2016-08-05: get all parameter
$Parameters = $this->GetParameterList($Parameters);
// /// 2017-01-05: now call bindParam method support to lob type(blob/clob/nclob)
// /// 2017-04-10: disabled this..
// if ($this->BindParameter)
// {
// /// bind parameter.
// for ($Index = 0; $Index < count($Parameters); $Index++)
// {
// $this->Command->bindParam($Index + 1, $Parameters[$Index], PDO::PARAM_STR, strlen($Parameters[$Index]));
// }
//
// /// run command.
// $Return = $this->Command->execute();
// }
// else
// {
// /// run command.
// $Return = $this->Command->execute($Parameters);
// }
/// 2017-04-10: expand parameter to class(CommandParameter)
/// bind parameter.
for ($Index = 0; $Index < count($Parameters); $Index++)
{
if ($Parameters[$Index] instanceof CommandParameter)
{
$Parameter = $Parameters[$Index];
$this->CommandParameters->Append($Parameter);
$this->Command->bindParam(
//$Index + 1,
$Parameter->Name,
$Parameter->Value,
(TYPENAME_LOB == $Parameter->Type ? PDO::PARAM_LOB : PDO::PARAM_STR) | ($Parameter->Output ? PDO::PARAM_INPUT_OUTPUT : 0),
$Parameter->Size);
}
else
{
if (is_numeric($Parameters[$Index]))
{
$Type = TYPENAME_NUMBER;
$Value = strval($Parameters[$Index]);
}
elseif (is_resource($Parameters[$Index]))
{
$Type = TYPENAME_LOB;
$Value = $Parameters[$Index];
}
else
{
$Type = TYPENAME_STRING;
$Value = $Parameters[$Index];
}
$this->CommandParameters->CreateParameter('', $Type, $Value, strlen($Value));
$this->Command->bindParam(
$Index + 1,
$Parameters[$Index],
PDO::PARAM_STR,
strlen($Parameters[$Index]));
}
}
$Return = $this->Command->execute();
/// 2017-04-10 end.
if (!$Return)
{
$this->SetErrors($this->Command->errorCode(), $this->Command->errorInfo());
return null;
}
/// if succeed fetch record to return object.
$this->Rows = array(); /// init return array
/// fetch record into array.
// /// 2017-04-10: disabled this..
// if ($this->LoadStream)
// {
if (null != $Callable)
{
//while ($this->Recordset = $this->GetRecord($this->Command->fetchObject()))
while ($this->Recordset = $this->GetRecord($this->Command->fetch($this->FetchStyle)))
{
/// callback function.
if (function_exists('call_user_func_array'))
$UserCallResult = call_user_func_array($Callable, array(&$this->Recordset)); /// must pass &$xxx in php4.x
// elseif (version_compare(PHP_VERSION, '5.4.0') < 0) /// less php 5.4
// $UserCallResult = $Callable(&$this->Recordset);
else
$UserCallResult = $Callable($this->Recordset);
if (!$UserCallResult)
{
$this->SetErrors(ERRORCODE_CANCELLED, ERRORINFO_CANCELLED);
break; /// break loop if return false;
}
/// 2018-05-28: if CacheRecord is set, save this record to Rows array.
if ($this->CacheRecord)
array_push($this->Rows, $this->Recordset);
$this->Recordset = null;
}
}
else
{
//while ($this->Recordset = $this->GetRecord($this->Command->fetchObject()))
while ($this->Recordset = $this->GetRecord($this->Command->fetch($this->FetchStyle)))
{
array_push($this->Rows, $this->Recordset);
$this->Recordset = null;
}
}
// /// 2017-04-10: disabled this..
// }
// else
// {
// if (null != $Callable)
// {
// while ($this->Recordset = $this->Command->fetch($this->FetchStyle))
// {
// /// callback function.
// if (function_exists('call_user_func'))
// $UserCallResult = call_user_func($Callable, $this->Recordset); /// must pass &$xxx in php4.x
// else
// $UserCallResult = $Callable($this->Recordset);
// if (!$UserCallResult)
// {
// $this->SetErrors(ERRORCODE_CANCELLED, ERRORINFO_CANCELLED);
// break; /// break loop if return false;
// }
//
// /// 2018-05-28: if CacheRecord is set, save this record to Rows array.
// if ($this->CacheRecord)
// array_push($this->Rows, $this->Recordset);
// $this->Recordset = null;
// }
// }
// else
// {
// while ($this->Recordset = $this->Command->fetch($this->FetchStyle))
// {
// array_push($this->Rows, $this->Recordset);
// $this->Recordset = null;
// }
// }
// }
/// if has record fetch all column names to array.
if (!empty($this->Rows) && !empty($this->Rows[0]))
{
/// get all column names
//$prop = get_object_vars($this->Rows[0]);
//$this->Cols = array_keys($prop); /// fetch into columns object.
$this->Cols = array_keys((array)$this->Rows[0]);
}
$this->InvokeEvent($this->OnAfterOpen);
return $this->Rows;
}
catch (PDOException $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return null;
}
catch (Exception $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return null;
}
}
/*******************************
* name: Execute.
* note: execute command from database(no recordset was returned).
* parameters: sql command, parameter list
* return: true if the method call succeeded, false otherwise.
*******************************
* param string $SqlCommand
* param mixed $Parameters...
* @return bool
*******************************/
public function Execute(/* sqlcommand, parameters, ... */)
{
$this->InvokeEvent($this->OnBeforeExecute);
if (!isset($this->Database) && !($this->Database instanceof PDO))
{
$this->SetErrors(ERRORCODE_NOCONNECTED, ERRORINFO_NOCONNECTED);
return false;
}
$this->ClearMember();
$this->SetErrors(ERRORCODE_SUCCESS, ERRORINFO_SUCCESS);
try
{
/// get parameters
$Parameters = func_get_args();
/// $Parameters[0] => sql command
/// $Parameters[...] => the parameters ...
/// call parent execute field.
//parent::Execute($Parameters);
/// if no any parameter then exit
if (0 == count($Parameters))
{
$this->SetErrors(ERRORCODE_NOPARAMETER, ERRORINFO_NOPARAMETER);
return false;
}
/// the first parameter is the sql command string.
$this->Command = $this->Database->prepare($Parameters[0]);
if (null == $this->Command)
{
$this->SetErrors($this->Database->errorCode(), $this->Database->errorInfo());
return false;
}
/// reset parameters
//unset($Parameters[0]);
//$Parameters = array_values($Parameters);
array_shift($Parameters);
/// 2016-08-05: get all parameter
$Parameters = $this->GetParameterList($Parameters);
// /// 2017-01-05: now call bindParam method support to lob type(blob/clob/nclob)
// /// 2017-04-10: disabled this..
// if ($this->BindParameter)
// {
// /// bind parameter.
// for ($Index = 0; $Index < count($Parameters); $Index++)
// {
// $this->Command->bindParam($Index + 1, $Parameters[$Index], PDO::PARAM_STR, strlen($Parameters[$Index]));
// }
//
// /// run command.
// $Return = $this->Command->execute();
// }
// else
// {
// /// run command.
// $Return = $this->Command->execute($Parameters);
// }
/// 2017-04-10: expand parameter to class(CommandParameter)
/// bind parameter.
for ($Index = 0; $Index < count($Parameters); $Index++)
{
if ($Parameters[$Index] instanceof CommandParameter)
{
$Parameter = $Parameters[$Index];
$this->CommandParameters->Append($Parameter);
$this->Command->bindParam(
//$Index + 1,
$Parameter->Name,
$Parameter->Value,
(TYPENAME_LOB == $Parameter->Type ? PDO::PARAM_LOB : PDO::PARAM_STR) | ($Parameter->Output ? PDO::PARAM_INPUT_OUTPUT : 0),
$Parameter->Size);
}
else
{
if (is_numeric($Parameters[$Index]))
{
$Type = TYPENAME_NUMBER;
$Value = strval($Parameters[$Index]);
}
elseif (is_resource($Parameters[$Index]))
{
$Type = TYPENAME_LOB;
$Value = $Parameters[$Index];
}
else
{
$Type = TYPENAME_STRING;
$Value = $Parameters[$Index];
}
$this->CommandParameters->CreateParameter('', $Type, $Value, strlen($Value));
$this->Command->bindParam(
$Index + 1,
$Parameters[$Index],
PDO::PARAM_STR,
strlen($Parameters[$Index]));
}
}
$Return = $this->Command->execute();
/// 2017-04-10 end.
if (!$Return)
$this->SetErrors($this->Command->errorCode(), $this->Command->errorInfo());
else
$this->InvokeEvent($this->OnAfterExecute);
return $Return;
}
catch (PDOException $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
catch (Exception $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
}
/*******************************
* name: LastInsertId.
* note: This method may not return a meaningful or consistent result across different PDO drivers, because the underlying database may not even support the notion of auto-increment fields or sequences.
* parameters: name
* return: PDO::lastInsertId method return value.
*******************************
* @param null|string $Name
* @return bool|string
******************************/
public function LastInsertId($Name = null)
{
if (isset($this->Database) && ($this->Database instanceof PDO))
{
$Return = $this->Database->lastInsertId($Name);
$this->SetErrors($this->Database->errorCode(), $this->Database->errorInfo());
return $Return;
}
else
{
$this->SetErrors(ERRORCODE_NOCONNECTED, ERRORINFO_NOCONNECTED);
return false;
}
}
/*******************************
* name: ColumnNames.
* note: get all field name of current recordset.
* parameters: none
* return: all field name of current recordset.
*******************************
* @return array|bool
*******************************/
public function ColumnNames()
{
if (isset($this->Cols) && !empty($this->Cols))
return $this->Cols;
else
{
$this->SetErrors(ERRORCODE_UNKNOWN, ERRORINFO_UNKNOWN);
return false;
}
}
/*******************************
* name: Records.
* note: return record list, deleted, or changed by the last statement.
* parameters: none
* return: the record list, deleted, or changed.
*******************************
* @return array
*******************************/
public function GetRecords()
{
return $this->Rows;
}
/*******************************
* name: InTransaction.
* note: Checks if inside a transaction.
* parameters: none
* return: true if a transaction is currently active, false otherwise.
*******************************
* @return bool
*******************************/
public function InTransaction()
{
if (isset($this->Database) && ($this->Database instanceof PDO))
{
$Return = $this->Database->inTransaction();
$this->SetErrors($this->Database->errorCode(), $this->Database->errorInfo());
return $Return;
}
else
{
$this->SetErrors(ERRORCODE_NOCONNECTED, ERRORINFO_NOCONNECTED);
return false;
}
}
/*******************************
* name: BeginTransaction.
* note: turns off auto commit mode and begins a transaction.
* parameters: none
* return: true if the method call succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function BeginTransaction()
{
if (isset($this->Database) && ($this->Database instanceof PDO))
{
$Return = $this->Database->beginTransaction();
$this->SetErrors($this->Database->errorCode(), $this->Database->errorInfo());
return $Return;
}
else
{
$this->SetErrors(ERRORCODE_NOCONNECTED, ERRORINFO_NOCONNECTED);
return false;
}
}
/*******************************
* name: Commit.
* note: sends commands to the database that were issued after calling BeginTransaction and returns the connection to auto commit mode.
* parameters: none
* return: true if the method call succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function Commit()
{
if (isset($this->Database) && ($this->Database instanceof PDO))
{
$Return = $this->Database->commit();
$this->SetErrors($this->Database->errorCode(), $this->Database->errorInfo());
return $Return;
}
else
{
$this->SetErrors(ERRORCODE_NOCONNECTED, ERRORINFO_NOCONNECTED);
return false;
}
}
/*******************************
* name: Rollback.
* note: discards database commands that were issued after calling BeginTransaction and returns the connection to auto commit mode.
* parameters: none
* return: true if the method call succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function Rollback()
{
if (isset($this->Database) && ($this->Database instanceof PDO))
{
$Return = $this->Database->rollBack();
$this->SetErrors($this->Database->errorCode(), $this->Database->errorInfo());
return $Return;
}
else
{
$this->SetErrors(ERRORCODE_NOCONNECTED, ERRORINFO_NOCONNECTED);
return false;
}
}
/*******************************
* name: Quote.
* note: quotes a string for use in a query.
* param value The string to be quoted.
* param type Provides a data type hint for drivers that have alternate quoting styles.
* return string a quoted string that is theoretically safe to pass into an SQL statement. Returns FALSE if the driver does not support quoting in this way.
*******************************
* @param string $Value The string to be quoted.
* @param int $ValueType [optional] Provides a data type hint for drivers that have alternate quoting styles.
* @return string a quoted string that is theoretically safe to pass into an SQL statement. Returns <b>FALSE</b> if the driver does not support quoting in this way.
*******************************/
public function Quote($Value, $ValueType = PDO::PARAM_STR)
{
if (isset($this->Database) && ($this->Database instanceof PDO))
{
$Return = $this->Database->Quote($Value, $ValueType);
$this->SetErrors($this->Database->errorCode(), $this->Database->errorInfo());
return $Return;
}
else
{
$this->SetErrors(ERRORCODE_NOCONNECTED, ERRORINFO_NOCONNECTED);
return false;
}
}
/*******************************
* name: NextRowset.
* note: moves the cursor to the next result set.
* parameters: none
* return: true if the method call succeeded, false otherwise.
*******************************
* @return bool
*******************************/
public function NextRowset()
{
if (isset($this->Command) && ($this->Command instanceof PDOStatement))
return $this->Command->nextRowset();
else
{
$this->SetErrors(ERRORCODE_NOCOMMANDED, ERRORINFO_NOCOMMANDED);
return -1;
}
}
/*******************************
* name: RowCount.
* note: returns the number of rows added, deleted, or changed by the last statement.
* parameters: none
* return: the number of rows added, deleted, or changed.
*******************************
* @return int
*******************************/
public function GetRowCount()
{
if (isset($this->Command) && ($this->Command instanceof PDOStatement))
{
$Return = $this->Command->rowCount();
$this->SetErrors($this->Command->errorCode(), $this->Command->errorInfo());
return $Return;
}
else
{
$this->SetErrors(ERRORCODE_NOCOMMANDED, ERRORINFO_NOCOMMANDED);
return -1;
}
}
/*******************************
* name: ColCount.
* note: returns the number of columns in a result set.
* parameters: none
* return: returns the number of columns in a result set. returns zero if the result set is empty.
*******************************
* @return int
*******************************/
public function GetColCount()
{
if (isset($this->Command) && ($this->Command instanceof PDOStatement))
{
$Return = $this->Command->columnCount();
$this->SetErrors($this->Command->errorCode(), $this->Command->errorInfo());
return $Return;
}
else
{
$this->SetErrors(ERRORCODE_NOCOMMANDED, ERRORINFO_NOCOMMANDED);
return -1;
}
}
/*******************************
* name: ExportToFile.
* note: save request data to file.
* parameters: filename, sql command, parameter list
* return: true if the method call succeeded, false otherwise.
*******************************
* param string filename
* param string sqlcommand
* param mixed parameters...
* @return bool
*******************************/
public function ExportToFile(/* filename, sqlcommand, parameters */)
{
if (!isset($this->Database) && !($this->Database instanceof PDO))
{
$this->SetErrors(ERRORCODE_NOCONNECTED, ERRORINFO_NOCONNECTED);
return false;
}
$this->SetErrors(ERRORCODE_SUCCESS, ERRORINFO_SUCCESS);
try
{
/// get parameters
$Parameters = func_get_args();
/// $Parameters[0] => export file name
/// $Parameters[1] => sql command
/// $Parameters[...] => the parameters ...
$ParameterCount = func_num_args();
if (0 == $ParameterCount)
{
$this->SetErrors(ERRORCODE_NOPARAMETER, ERRORINFO_NOPARAMETER);
return false;
}
$Filename = $Parameters[0];
// if (file_exists($Filename))
// unlink($Filename);
//unset($Parameters[0]);
//$Parameters = array_values($Parameters);
array_shift($Parameters);
/// call request method.
if (function_exists('call_user_func_array') && $ParameterCount > 1)
call_user_func_array(array(&$this, 'Request'), $Parameters); /// must pass &$xxx in php4.x
$Headers = '';
foreach ($this->Cols as $Key => $Value) /// all field names.
{
$Headers .= $Value . ",";
}
$Headers .= PHP_EOL;
$Lines = '';
foreach ($this->GetRecords() as $RowKey => $RowValue) /// all data.
{
$array = (array)$RowValue;
foreach ($array as $ColKey => $ColValue)
{
$Lines .= $ColValue . ',';
}
$Lines .= PHP_EOL;
}
$Text = $this->Characet($Headers . $Lines, 'GBK');
//$Encoding = mb_detect_encoding($Text, array('ASCII', 'UTF-8', 'GBK', 'GB2312', 'LATIN1', 'BIG5'));
//if (0 != strcasecmp('gbk', $Encoding))
// $Text = mb_convert_encoding($Text, 'gbk', $Encoding);
//$Lines = mb_convert_encoding($Lines, 'gbk', 'utf-8');
//$Lines = iconv('utf-8', 'gbk', $Lines);
if ($File = fopen($Filename, 'a+')) /// write to file
{
fwrite($File, $Text);
fclose($File);
}
return true;
}
catch (PDOException $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
catch (Exception $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
}
/*******************************
* name: ExportToBrowser.
* note: save request data to browser.
* parameters: sql command, parameter list
* return: true if the method call succeeded, false otherwise.
*******************************
* param string sqlcommand
* param mixed parameters...
* @return bool
*******************************/
public function ExportToBrowser(/* sqlcommand, parameters */)
{
if (!isset($this->Database) && !($this->Database instanceof PDO))
{
$this->SetErrors(ERRORCODE_NOCONNECTED, ERRORINFO_NOCONNECTED);
return false;
}
$this->SetErrors(ERRORCODE_SUCCESS, ERRORINFO_SUCCESS);
try
{
/// get parameters
$Parameters = func_get_args();
/// $Parameters[0] => export file name
/// $Parameters[1] => sql command
/// $Parameters[...] => the parameters ...
$ParameterCount = func_num_args();
if (0 == $ParameterCount)
{
$this->SetErrors(ERRORCODE_NOPARAMETER, ERRORINFO_NOPARAMETER);
return false;
}
global $Handles;
global $First;
$Handles = fopen('php://output', 'a'); /// open the output stream.
$First = true;
$Callable = function (&$Record)
{
global $Handles;
global $First;
/// if the first record, must to get column names.
if ($First)
{
$First = false;
$Headers = array();
/// get key names
foreach (array_keys((array)$Record) as $Key => $Value)
{
/// write the header.
array_push($Headers, Characet($Value, 'GBK'));
}
fputcsv($Handles, $Headers);
}
/// write the record data.
$Lines = array();
foreach ((array)$Record as $Key => $Value)
{
array_push($Lines, Characet($Value, 'GBK'));
}
fputcsv($Handles, $Lines);
ob_flush();
flush();
unset($Lines);
unset($Record);
return true;
};
// $Callable = '
//global $Handles;
//global $First;
//
///// if the first record, must to get column names.
//if ($First)
//{
// $First = false;
//
// $Headers = array();
// /// get key names
// foreach (array_keys((array)$Record) as $Key => $Value)
// {
// /// write the header.
// array_push($Headers, Characet($Value, \'GBK\'));
// }
// fputcsv($Handles, $Headers);
//}
//
///// write the record data.
//$Lines = array();
//foreach ((array)$Record as $Key => $Value)
//{
// array_push($Lines, Characet($Value, \'GBK\'));
//}
//fputcsv($Handles, $Lines);
//
//ob_flush();
//flush();
//
//unset($Record);
//
//return true;
//';
// $Callable = create_function('$Record', $Callable);
array_splice($Parameters, 0, 0, $Callable);
/// echo http header.
$Filename = date('YmdHis');
header("Content-type:application/vnd.ms-excel");
header("Content-Disposition:filename={$Filename}.csv");
/// saved max execute time count.
$MaxExecuteTime = ini_get('max_execution_time');
/// disable timeout limit.
set_time_limit(0);
/// 2018-05-28: saved CacheRecord settings
$SavedCacheRecord = $this->CacheRecord;
$this->CacheRecord = false;
/// call request method.
if (function_exists('call_user_func_array'))
call_user_func_array(array(&$this, 'Request'), $Parameters); /// must pass &$xxx in php4.x
/// 2018-05-28: restore CacheRecord settings
$this->CacheRecord = $SavedCacheRecord;
/// close the handle of file.
fclose($Handles);
/// restore max execute time count.
set_time_limit($MaxExecuteTime);
/// destroy the global variable.
unset($First);
unset($Handles);
return true;
}
catch (PDOException $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
catch (Exception $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
}
/*******************************
* name: SaveArrayToFile.
* note: save data to file.
* parameters: filename, data
* return: true if the method call succeeded, false otherwise.
*******************************
* @param string $Filename
* @param array|mixed $Data
* @return bool
*******************************/
public function SaveArrayToFile($Filename, $Data)
{
if (empty($Data))
{
$this->SetErrors(ERRORCODE_INVALIDPARAMETER, ERRORINFO_INVALIDPARAMETER);
return false;
}
$this->SetErrors(ERRORCODE_SUCCESS, ERRORINFO_SUCCESS);
try
{
if (is_object($Data))
$Data = (array)$Data;
if (!is_array($Data))
{
$this->SetErrors(ERRORCODE_INVALIDPARAMETER, ERRORINFO_INVALIDPARAMETER);
return false;
}
$Text = '';
foreach ($Data as $Line)
{
if (is_object($Line))
$Line = (array)$Line;
if (is_array($Line))
{
foreach ($Line as $Value)
{
$Text .= $Value . ",";
}
}
else
$Text .= $Line;
$Text .= PHP_EOL;
}
$Text = $this->Characet($Text, 'GBK');
//$Encoding = mb_detect_encoding($Text, array('ASCII', 'UTF-8', 'GBK', 'GB2312', 'LATIN1', 'BIG5'));
//if (0 != strcasecmp('gbk', $Encoding))
// $Text = mb_convert_encoding($Text, 'gbk', $Encoding);
if ($File = fopen($Filename, 'w+')) /// write to file
{
fwrite($File, $Text);
fclose($File);
}
return true;
}
catch (Exception $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
}
/*******************************
* name: SaveArrayToBrowser.
* note: save data to browser.
* parameters: data
* return: true if the method call succeeded, false otherwise.
*******************************
* @param array|mixed $Data
* @return bool
*******************************/
public function SaveArrayToBrowser($Data)
{
if (empty($Data))
{
$this->SetErrors(ERRORCODE_INVALIDPARAMETER, ERRORINFO_INVALIDPARAMETER);
return false;
}
$this->SetErrors(ERRORCODE_SUCCESS, ERRORINFO_SUCCESS);
try
{
if (is_object($Data))
$Data = (array)$Data;
if (!is_array($Data))
{
$this->SetErrors(ERRORCODE_INVALIDPARAMETER, ERRORINFO_INVALIDPARAMETER);
return false;
}
$Text = '';
foreach ($Data as $Line)
{
if (is_object($Line))
$Line = (array)$Line;
if (is_array($Line))
{
foreach ($Line as $Value)
{
$Text .= $Value . ",";
}
}
else
$Text .= $Line;
$Text .= PHP_EOL;
}
$Text = $this->Characet($Text, 'GBK');
//$Encoding = mb_detect_encoding($Text, array('ASCII', 'UTF-8', 'GBK', 'GB2312', 'LATIN1', 'BIG5'));
//if (0 != strcasecmp('gbk', $Encoding))
// $Text = mb_convert_encoding($Text, 'gbk', $Encoding);
if ($File = fopen('php://output', 'a')) /// write to file
{
/// echo http header.
$Filename = date('YmdHis');
header("Content-type:application/vnd.ms-excel");
header("Content-Disposition:filename={$Filename}.csv");
/// saved max execute time count.
$MaxExecuteTime = ini_get('max_execution_time');
/// disable timeout limit.
set_time_limit(0);
fwrite($File, $Text);
fclose($File);
/// restore max execute time count.
set_time_limit($MaxExecuteTime);
}
return true;
}
catch (Exception $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
}
/*******************************
* name: GetConnectParameter.
* note: get the parameter with connect method.
* parameters: nan
* return: connect parameter if the method call succeeded, null otherwise.
*******************************
* @return ConnectParameter
*******************************/
public function GetConnectParameter()
{
return $this->ConnectParameter;
}
/*******************************
* name: GetCommandParameter.
* note: get the parameter with run sql command.
* parameters: nan
* return: command parameter if the method call succeeded, null otherwise.
*******************************
* @return CommandParameters
*******************************/
public function GetCommandParameter()
{
return $this->CommandParameters;
}
/*******************************
* name: GetConnected.
* note: get the connected status.
* parameters: nan
* return: current connected status succeeded, null otherwise.
*******************************
* @return ConnectParameter
*******************************/
public function GetConnected()
{
return null != $this->ConnectParameter;
}
/*******************************
* name: GetConnectType.
* note: get the connect database type.
* parameters: nan
* return: connect database type if the method call succeeded, null otherwise.
*******************************
* @return null|string
*******************************/
public function GetConnectType()
{
return null;
}
/*******************************
* name: GetErrorCode.
* note: get the last method call return code.
* parameters: none.
* return: get the last method call return code.
*******************************
* @return int
*******************************/
public function GetErrorCode()
{
return $this->ErrorCode;
}
/*******************************
* name: GetErrorInfo.
* note: get the last method call return info.
* parameters: none.
* return: get the last method call return info.
*******************************
* @return mixed
*******************************/
public function GetErrorInfo()
{
return $this->ErrorInfo;
}
/*******************************
* name: GetErrors.
* note: get the last method call return code and info.
* parameters: none.
* return: get the last method call return code and info.
*******************************
* @return array
*******************************/
public function GetErrors()
{
return array('ErrorCode' => $this->ErrorCode,'ErrorInfo' => $this->ErrorInfo,);
}
/*******************************
* name: SetErrors.
* note: set the last method call return code and info.
* parameters: code, info.
* return: always return true.
*******************************
* @param int $ErrorCode
* @param mixed $ErrorInfo
* @return bool
*******************************/
protected function SetErrors($ErrorCode, $ErrorInfo)
{
if (is_object($ErrorInfo))
$ErrorInfo = (array)$ErrorInfo;
if (is_array($ErrorInfo))
{
//array_keys
$Keys = array_keys($ErrorInfo);
$ErrorInfo = $ErrorInfo[$Keys[count($Keys) - 1]];
}
//if (is_object($ErrorInfo) || is_array($ErrorInfo))
//{
// $ErrorInfo = serialize($ErrorInfo);
//}
$this->ErrorCode = $ErrorCode;
$this->ErrorInfo = $ErrorInfo;
if (!$this->IsDone())
$this->InvokeEvent($this->OnError);
return true;
// switch (gettype($ErrorInfo))
// {
// case 'object':
// case 'array':
// $ErrorInfo = JsonObjectToJsonString($ErrorInfo);
// break;
// }
//
// $this->ErrorCode = $ErrorCode;
// $this->ErrorInfo = Characet($ErrorInfo);
//
// return true;
}
}
/*******************************
* name: ORACLEHelper.
* note: oracle helper.
*******************************/
class ORACLEHelper extends PDOHelper
{
/*******************************
* name: Succeeded.
* note: test the success of the code.
* parameters: code.
* return: true if the code succeeded, false otherwise.
*******************************
* @param string|int $Code
* @return bool
*******************************/
public function Succeeded($Code)
{
return (bool) (/*strcasecmp('HY000', $Code) == 0 ||*/ strcasecmp('00000', $Code) == 0 || strcasecmp('01000', $Code) == 0 || parent::Succeeded($Code));
}
/*******************************
* name: Connect.
* note: connect to database.
* parameters: hostname, hostport, servicename, username, password.
* return: true if the method call succeeded, false otherwise.
*******************************
* param string hostname
* param int|string hostport
* param string servicename
* param string username
* param string password
* @return bool
*******************************/
public function Connect(/* hostname, hostport, servicename, username, password */)
{
/// call parent connect field.
parent::Connect();
$this->SetErrors(ERRORCODE_SUCCESS, ERRORINFO_SUCCESS);
try
{
/// get parameters
$Parameters = func_get_args();
/// $Parameters[0] => hostname
/// $Parameters[1] => hostport
/// $Parameters[2] => database
/// $Parameters[3] => username
/// $Parameters[4] => password
$ParameterCount = func_num_args();
if (0 == $ParameterCount)
{
$Hostname = null;
$Hostport = null;
$Database = null;
$Username = null;
$Password = null;
$Persistent = null;
}
elseif (is_array($Parameters[0]))
{
$Hostname = isset($Parameters[0][PARAMETERNAME_HOSTNAME]) ? $Parameters[0][PARAMETERNAME_HOSTNAME] : null;
$Hostport = isset($Parameters[0][PARAMETERNAME_HOSTPORT]) ? $Parameters[0][PARAMETERNAME_HOSTPORT] : null;
$Database = isset($Parameters[0][PARAMETERNAME_DATABASE]) ? $Parameters[0][PARAMETERNAME_DATABASE] : null;
$Username = isset($Parameters[0][PARAMETERNAME_USERNAME]) ? $Parameters[0][PARAMETERNAME_USERNAME] : null;
$Password = isset($Parameters[0][PARAMETERNAME_PASSWORD]) ? $Parameters[0][PARAMETERNAME_PASSWORD] : null;
$Persistent = isset($Parameters[0][PARAMETERNAME_PERSISTENT]) ? $Parameters[0][PARAMETERNAME_PERSISTENT] : null;
}
elseif ($Parameters[0] instanceof ConnectParameter)
{
$Hostname = isset($Parameters[0]->Hostname) ? $Parameters[0]->Hostname : null;
$Hostport = isset($Parameters[0]->Hostport) ? $Parameters[0]->Hostport : null;
$Database = isset($Parameters[0]->Database) ? $Parameters[0]->Database : null;
$Username = isset($Parameters[0]->Username) ? $Parameters[0]->Username : null;
$Password = isset($Parameters[0]->Password) ? $Parameters[0]->Password : null;
$Persistent = isset($Parameters[0]->Persistent) ? $Parameters[0]->Persistent : null;
}
else
{
$Hostname = isset($Parameters[0]) ? $Parameters[0] : null;
$Hostport = isset($Parameters[1]) ? $Parameters[1] : null;
$Database = isset($Parameters[2]) ? $Parameters[2] : null;
$Username = isset($Parameters[3]) ? $Parameters[3] : null;
$Password = isset($Parameters[4]) ? $Parameters[4] : null;
$Persistent = isset($Parameters[5]) ? $Parameters[5] : null;
}
if (empty($Hostname))
$Hostname = DEFAULTHOSTNAME_ORACLE;
if (empty($Hostport))
$Hostport = DEFAULTHOSTPORT_ORACLE;
if (empty($Database))
$Database = DEFAULTDATABASE_ORACLE;
if (empty($Username))
$Username = DEFAULTUSERNAME_ORACLE;
if (empty($Password))
$Password = DEFAULTPASSWORD_ORACLE;
if (empty($Persistent))
$Persistent = DEFAULTPERSISTENT_ORACLE;
$this->ConnectParameter = new ConnectParameter($Hostname, $Hostport, $Database, $Username, $Password, $Persistent);
/// connect to database by oracle.
$driver = sprintf('oci:dbname=
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = %s)(PORT = %s))
)
(CONNECT_DATA =
(SERVICE_NAME = %s)
)
);', $Hostname, $Hostport, $Database);
$this->Database = new PDO($driver, $Username, $Password, array(PDO::ATTR_PERSISTENT => (bool)$Persistent));
$this->InvokeEvent($this->OnConnected);
return true;
}
catch (PDOException $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
catch (Exception $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
}
/*******************************
* name: GetTables.
* note: get the database all tables.
* parameters: none.
* return: table list if the method call succeeded, null otherwise.
*******************************
* @return ITables
*******************************/
public function GetTables()
{
$CommandString = /** @lang text */
'select' . PHP_EOL .
' table_name,' . PHP_EOL .
' tablespace_name,' . PHP_EOL .
' temporary' . PHP_EOL .
'from' . PHP_EOL .
' user_tables' . PHP_EOL .
'/*' . PHP_EOL .
'union all' . PHP_EOL .
'select' . PHP_EOL .
' view_name,' . PHP_EOL .
' null,' . PHP_EOL .
' null' . PHP_EOL .
'from' . PHP_EOL .
' user_views' . PHP_EOL .
'*/' . PHP_EOL;
$Return = new Tables($this);
$Tables = $this->Request($CommandString);
foreach ($Tables as $Table)
{
$Table = (array)$Table;
$Return->Append(new Table($Table['table_name']));
}
return $Return;
}
/*******************************
* name: GetTableFields.
* note: get the table fields.
* parameters: table name.
* return: field list if the method call succeeded, null otherwise.
*******************************
* @param string $Tablename
* @return ITables
*******************************/
public function GetTableFields($Tablename)
{
$CommandString = /** @lang text */
'select' . PHP_EOL .
' column_id,' . PHP_EOL .
' table_name,' . PHP_EOL .
' column_name,' . PHP_EOL .
' data_type,' . PHP_EOL .
' data_length,' . PHP_EOL .
' data_precision,' . PHP_EOL .
' data_scale,' . PHP_EOL .
' data_default' . PHP_EOL .
'from' . PHP_EOL .
' user_tab_columns' . PHP_EOL .
'where' . PHP_EOL .
' upper(table_name) = upper(?)' . PHP_EOL .
'order by' . PHP_EOL .
' column_id' . PHP_EOL;
$Return = new Fields(null);
$Fields = $this->Request($CommandString, $Tablename);
foreach ($Fields as $Field)
{
$Field = (array)$Field;
$Return->Append(new Field($Field['column_name'], $Field['data_type'], $Field['data_length'], $Field['data_default']));
}
return $Return;
}
/*******************************
* name: GetConnectType.
* note: get the connect database type.
* parameters: nan
* return: connect database type if the method call succeeded, null otherwise.
*******************************
* @return null|string
*******************************/
public function GetConnectType()
{
return DATABASE_TYPE_ORACLE;
}
}
/*******************************
* name: SQLSRVHelper.
* note: sql server helper.
*******************************/
class SQLSRVHelper extends PDOHelper
{
/*******************************
* name: Connect.
* note: connect to database.
* parameters: hostname, hostport, database, username, password
* return: true if the method call succeeded, false otherwise.
*******************************
* param string hostname
* param int|string hostport
* param string database
* param string username
* param string password
* @return bool
*******************************/
public function Connect(/* hostname, hostport, database, username, password */)
{
/// call parent connect field.
parent::Connect();
$this->SetErrors(ERRORCODE_SUCCESS, ERRORINFO_SUCCESS);
try
{
/// get parameters
$Parameters = func_get_args();
/// $Parameters[0] => hostname
/// $Parameters[1] => hostport
/// $Parameters[2] => database
/// $Parameters[3] => username
/// $Parameters[4] => password
$ParameterCount = func_num_args();
if (0 == $ParameterCount)
{
$Hostname = null;
$Hostport = null;
$Database = null;
$Username = null;
$Password = null;
$Persistent = null;
}
elseif (is_array($Parameters[0]))
{
$Hostname = isset($Parameters[0][PARAMETERNAME_HOSTNAME]) ? $Parameters[0][PARAMETERNAME_HOSTNAME] : null;
$Hostport = isset($Parameters[0][PARAMETERNAME_HOSTPORT]) ? $Parameters[0][PARAMETERNAME_HOSTPORT] : null;
$Database = isset($Parameters[0][PARAMETERNAME_DATABASE]) ? $Parameters[0][PARAMETERNAME_DATABASE] : null;
$Username = isset($Parameters[0][PARAMETERNAME_USERNAME]) ? $Parameters[0][PARAMETERNAME_USERNAME] : null;
$Password = isset($Parameters[0][PARAMETERNAME_PASSWORD]) ? $Parameters[0][PARAMETERNAME_PASSWORD] : null;
$Persistent = isset($Parameters[0][PARAMETERNAME_PERSISTENT]) ? $Parameters[0][PARAMETERNAME_PERSISTENT] : null;
}
elseif ($Parameters[0] instanceof ConnectParameter)
{
$Hostname = isset($Parameters[0]->Hostname) ? $Parameters[0]->Hostname : null;
$Hostport = isset($Parameters[0]->Hostport) ? $Parameters[0]->Hostport : null;
$Database = isset($Parameters[0]->Database) ? $Parameters[0]->Database : null;
$Username = isset($Parameters[0]->Username) ? $Parameters[0]->Username : null;
$Password = isset($Parameters[0]->Password) ? $Parameters[0]->Password : null;
$Persistent = isset($Parameters[0]->Persistent) ? $Parameters[0]->Persistent : null;
}
else
{
$Hostname = isset($Parameters[0]) ? $Parameters[0] : null;
$Hostport = isset($Parameters[1]) ? $Parameters[1] : null;
$Database = isset($Parameters[2]) ? $Parameters[2] : null;
$Username = isset($Parameters[3]) ? $Parameters[3] : null;
$Password = isset($Parameters[4]) ? $Parameters[4] : null;
$Persistent = isset($Parameters[5]) ? $Parameters[5] : null;
}
if (empty($Hostname))
$Hostname = DEFAULTHOSTNAME_SQLSRV;
if (empty($Hostport))
$Hostport = DEFAULTHOSTPORT_SQLSRV;
if (empty($Database))
$Database = DEFAULTDATABASE_SQLSRV;
if (empty($Username))
$Username = DEFAULTUSERNAME_SQLSRV;
if (empty($Password))
$Password = DEFAULTPASSWORD_SQLSRV;
if (empty($Persistent))
$Persistent = DEFAULTPERSISTENT_SQLSRV;
$this->ConnectParameter = new ConnectParameter($Hostname, $Hostport, $Database, $Username, $Password, $Persistent);
/// connect to database by sql server.
$driver = sprintf('sqlsrv:server=%s,%s;Database=%s;', $Hostname, $Hostport, $Database);
$this->Database = new PDO($driver, $Username, $Password, array(PDO::ATTR_PERSISTENT => (bool)$Persistent));
$this->InvokeEvent($this->OnConnected);
return true;
}
catch (PDOException $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
catch (Exception $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
}
/*******************************
* name: GetTables.
* note: get the database all tables.
* parameters: none.
* return: table list if the method call succeeded, null otherwise.
*******************************
* @return ITables
*******************************/
public function GetTables()
{
$CommandString = /** @lang text */
'select' . PHP_EOL .
' name table_name,' . PHP_EOL .
' crdate createdate,' . PHP_EOL .
' uid userid' . PHP_EOL .
'from' . PHP_EOL .
' sysobjects' . PHP_EOL .
'where' . PHP_EOL .
' --xtype in (N\'u\', N\'v\')' . PHP_EOL .
' xtype = N\'u\'' . PHP_EOL;
$Return = new Tables($this);
$Tables = $this->Request($CommandString);
foreach ($Tables as $Table)
{
$Table = (array)$Table;
$Return->Append(new Table($Table['table_name']));
}
return $Return;
}
/*******************************
* name: GetTableFields.
* note: get the table fields.
* parameters: table name.
* return: field list if the method call succeeded, null otherwise.
*******************************
* @param string $Tablename
* @return ITables
*******************************/
public function GetTableFields($Tablename)
{
$CommandString = /** @lang text */
'select' . PHP_EOL .
' a.colid column_id,' . PHP_EOL .
' c.name table_name,' . PHP_EOL .
' a.name column_name,' . PHP_EOL .
' b.name data_type,' . PHP_EOL .
' a.length data_length,' . PHP_EOL .
' a.xprec,' . PHP_EOL .
' a.xscale,' . PHP_EOL .
' a.isnullable' . PHP_EOL .
'from' . PHP_EOL .
' syscolumns a, systypes b, sysobjects c' . PHP_EOL .
'where' . PHP_EOL .
' a.xtype = b.xusertype and a.id = c.id and c.name = N?' . PHP_EOL .
'order by' . PHP_EOL .
' a.colid' . PHP_EOL;
$Return = new Fields(null);
$Fields = $this->Request($CommandString, $Tablename);
foreach ($Fields as $Field)
{
$Field = (array)$Field;
$Return->Append(new Field($Field['column_name'], $Field['data_type'], $Field['data_length'], null));
}
return $Return;
}
/*******************************
* name: GetConnectType.
* note: get the connect database type.
* parameters: nan
* return: connect database type if the method call succeeded, null otherwise.
*******************************
* @return null|string
*******************************/
public function GetConnectType()
{
return DATABASE_TYPE_SQLSRV;
}
}
/*******************************
* name: MYSQLHelper.
* note: mysql helper.
*******************************/
class MYSQLHelper extends PDOHelper
{
/*******************************
* name: Succeeded.
* note: test the success of the code.
* parameters: code.
* return: true if the code succeeded, false otherwise.
*******************************
* @param string|int $Code
* @return bool
*******************************/
public function Succeeded($Code)
{
return (bool) ( strcasecmp('00000', $Code) == 0 || strcasecmp('01000', $Code) == 0 || parent::Succeeded($Code) );
}
/*******************************
* name: Connect.
* note: connect to database.
* parameters: hostname, hostport, database, username, password, charset.
* return: true if the method call succeeded, false otherwise.
*******************************
* param string hostname
* param int|string hostport
* param string database
* param string username
* param string password
* param string charset
* @return bool
*******************************/
public function Connect(/* hostname, hostport, databasename, username, password, charset */)
{
/// call parent connect field.
parent::Connect();
$this->SetErrors(ERRORCODE_SUCCESS, ERRORINFO_SUCCESS);
try
{
/// get parameters
$Parameters = func_get_args();
/// $Parameters[0] => hostname
/// $Parameters[1] => hostport
/// $Parameters[2] => database
/// $Parameters[3] => username
/// $Parameters[4] => password
/// $Parameters[5] => charset
$ParameterCount = func_num_args();
if (0 == $ParameterCount)
{
$Hostname = null;
$Hostport = null;
$Database = null;
$Username = null;
$Password = null;
$Persistent = null;
$Charset = null;
}
elseif (is_array($Parameters[0]))
{
$Hostname = isset($Parameters[0][PARAMETERNAME_HOSTNAME]) ? $Parameters[0][PARAMETERNAME_HOSTNAME] : null;
$Hostport = isset($Parameters[0][PARAMETERNAME_HOSTPORT]) ? $Parameters[0][PARAMETERNAME_HOSTPORT] : null;
$Database = isset($Parameters[0][PARAMETERNAME_DATABASE]) ? $Parameters[0][PARAMETERNAME_DATABASE] : null;
$Username = isset($Parameters[0][PARAMETERNAME_USERNAME]) ? $Parameters[0][PARAMETERNAME_USERNAME] : null;
$Password = isset($Parameters[0][PARAMETERNAME_PASSWORD]) ? $Parameters[0][PARAMETERNAME_PASSWORD] : null;
$Persistent = isset($Parameters[0][PARAMETERNAME_PERSISTENT]) ? $Parameters[0][PARAMETERNAME_PERSISTENT] : null;
$Charset = isset($Parameters[0][PARAMETERNAME_CHARSET]) ? $Parameters[0][PARAMETERNAME_CHARSET] : null;
}
elseif ($Parameters[0] instanceof ConnectParameter)
{
$Hostname = isset($Parameters[0]->Hostname) ? $Parameters[0]->Hostname : null;
$Hostport = isset($Parameters[0]->Hostport) ? $Parameters[0]->Hostport : null;
$Database = isset($Parameters[0]->Database) ? $Parameters[0]->Database : null;
$Username = isset($Parameters[0]->Username) ? $Parameters[0]->Username : null;
$Password = isset($Parameters[0]->Password) ? $Parameters[0]->Password : null;
$Persistent = isset($Parameters[0]->Persistent) ? $Parameters[0]->Persistent : null;
$Charset = isset($Parameters[0]->Charset) ? $Parameters[0]->Charset : null;
}
else
{
$Hostname = isset($Parameters[0]) ? $Parameters[0] : null;
$Hostport = isset($Parameters[1]) ? $Parameters[1] : null;
$Database = isset($Parameters[2]) ? $Parameters[2] : null;
$Username = isset($Parameters[3]) ? $Parameters[3] : null;
$Password = isset($Parameters[4]) ? $Parameters[4] : null;
$Persistent = isset($Parameters[6]) ? $Parameters[6] : null;
$Charset = isset($Parameters[5]) ? $Parameters[5] : null;
}
if (empty($Hostname))
$Hostname = DEFAULTHOSTNAME_MYSQL;
if (empty($Hostport))
$Hostport = DEFAULTHOSTPORT_MYSQL;
if (empty($Database))
$Database = DEFAULTDATABASE_MYSQL;
if (empty($Username))
$Username = DEFAULTUSERNAME_MYSQL;
if (empty($Password))
$Password = DEFAULTPASSWORD_MYSQL;
if (empty($Persistent))
$Persistent = DEFAULTPERSISTENT_MYSQL;
if (empty($Charset))
$Charset = DEFAULTCHARSET_MYSQL;
$this->ConnectParameter = new ConnectParameter($Hostname, $Hostport, $Database, $Username, $Password, $Persistent, $Charset);
/// connect to database by mysql.
$driver = sprintf('mysql:host=%s;port=%s;dbname=%s;charset=%s;', $Hostname, $Hostport, $Database, $Charset);
$this->Database = new PDO($driver, $Username, $Password, array(PDO::ATTR_PERSISTENT => (bool)$Persistent));
/// select database
if (!($this->Database->exec('use ' . $Database . ';') || $this->Succeeded($this->Database->errorCode())))
{
$this->SetErrors($this->Database->errorCode(), $this->Database->errorInfo());
return false;
}
else
{
$this->InvokeEvent($this->OnConnected);
return true;
}
}
catch (PDOException $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
catch (Exception $Exception)
{
$this->SetErrors($Exception->GetCode(), $Exception->GetMessage());
return false;
}
}
/*******************************
* name: GetTables.
* note: get the database all tables.
* parameters: none.
* return: table list if the method call succeeded, null otherwise.
*******************************
* @return ITables
*******************************/
public function GetTables()
{
$CommandString = /** @lang text */
'select' . PHP_EOL .
' table_name' . PHP_EOL .
'from' . PHP_EOL .
' information_schema.tables' . PHP_EOL .
'where' . PHP_EOL .
' table_schema = ? and table_type = \'base table\'' . PHP_EOL;
$Return = new Tables($this);
$Tables = $this->Request($CommandString, $this->ConnectParameter->Database);
foreach ($Tables as $Table)
{
$Table = (array)$Table;
$Return->Append(new Table($Table['table_name']));
}
return $Return;
}
/*******************************
* name: GetTableFields.
* note: get the table fields.
* parameters: table name.
* return: field list if the method call succeeded, null otherwise.
*******************************
* @param string $Tablename
* @return ITables
*******************************/
public function GetTableFields($Tablename)
{
$CommandString = /** @lang text */
'select' . PHP_EOL .
' column_name,' . PHP_EOL .
' data_type,' . PHP_EOL .
' column_default' . PHP_EOL .
'from' . PHP_EOL .
' information_schema.columns' . PHP_EOL .
'where' . PHP_EOL .
' table_schema = ? and table_name = ?' . PHP_EOL .
'order by' . PHP_EOL .
' ordinal_position' . PHP_EOL;
$Return = new Fields(null);
$Fields = $this->Request($CommandString, $this->ConnectParameter->Database, $Tablename);
foreach ($Fields as $Field)
{
$Field = (array)$Field;
$Return->Append(new Field($Field['column_name'], $Field['data_type'], 0, $Field['column_default']));
}
return $Return;
}
/*******************************
* name: GetConnectType.
* note: get the connect database type.
* parameters: nan
* return: connect database type if the method call succeeded, null otherwise.
*******************************
* @return null|string
*******************************/
public function GetConnectType()
{
return DATABASE_TYPE_MYSQL;
}
}
/// ====================================================================================================================
/**
* @note the sql command helper of database interface.
**************sample***************
* $this
* ->Select(...)
* ->From(...)
* ->InnerJoin|LeftJoin|RightJoin(...)
* ->On(...)
* ->Where(...)
* ->GroupBy(...)
* ->Having(...)
* ->OrderBy(...)
* ->WithPage(...)
* ->Request()
**********************************
* $this
* ->Insert(...)
* ->Fields(...)
* ->Values(...)
* ->Execute()
**********************************
* $this
* ->Update(...)
* ->Fields(...)
* ->Values(...)
* ->Where(...)
* ->Execute()
**********************************
* $this
* ->Delete(...)
* ->Where(...)
* ->Execute()
**********************************
* $this
* ->Truncate(...)
* ->Execute()
**********************************
* $this
* ->Merge(...)
* ->Fields(...)
* ->Values(...)
* ->MergeOn(...)
* ->Execute()
**********************************
* $this
* ->CallStoredProcedure(...)
* ->Values(...)
* ->Request()/Execute()
**********************************/
abstract class SQLCommand implements ISQLCommand
{
/**
* @var IPDOHelper
*/
protected $Connection;
//private $ReferenceCharacter;
/**
* @var string
*/
protected $RefCharLeft;
/**
* @var string
*/
protected $RefCharRight;
/**
* @var string
*/
protected $CommandType; /// 语句类型
/**
* @var array of mixed
*/
protected $DataFieldNames; /// 字段名
/**
* @var array of string
*/
protected $DataFieldAlias; /// 别名
/**
* @var array of mixed
*/
protected $InternalSourceNames; /// 数据源
/**
* @var array of string
*/
protected $InternalSourceAlias; /// 数据源别名
/**
* @var string
*/
protected $StoredProcedureName; /// 存储过程、函数名
/**
* @var array of mixed
*/
//protected $ExternalSourceNames; /// 要插入|修改|合并的数据源
/**
* @var array of string
*/
//protected $ExternalSourceAlias; /// 要插入|修改|合并的数据源别名
/**
* @var array of string
*/
protected $WhereConditionColumn; /// 过滤字段
/**
* @var array of mixed
*/
protected $WhereConditionValues; /// 过滤字段值描述
/**
* @var array of mixed
*/
protected $WhereConditionParams; /// 过滤字段值参数
/**
* @var array of string
*/
protected $GroupFieldList; /// 分组字段
/**
* @var array of string
*/
protected $HavingConditionColumn; /// 过滤分组信息的条件
/**
* @var array of mixed
*/
protected $HavingConditionValues; /// 过滤分组信息条件带的参数列表
/**
* @var array of mixed
*/
protected $HavingConditionParams; /// 过滤分组信息条件带的参数列表
/**
* @var array of string
*/
protected $OrderFieldNames; /// 排序信息
protected $OrderFieldTypes; /// 排序类型
protected $PageIndex; /// 分组时的页序号
protected $PageSize; /// 分组时的页大小
protected $MaxRequestCount; /// 限制查询的记录数
/**
* @var array of mixed
*/
protected $ChangeFields; /// 要插入|修改|合并的字段名
/**
* @var array of mixed
*/
protected $ChangeValues; /// 要插入|修改|合并的值描述
/**
* @var array of mixed
*/
protected $ChangeParams; /// 要插入|修改|合并的值参数
/**
* @var int
*/
protected $JoinCount; /// 连接个数
/**
* @var string
*/
protected $JoinType; /// 连接方式
/**
* @var string
*/
protected $JoinSourceNames; /// 连接源
/**
* @var array
*/
protected $JoinSourceAlias; /// 连接源别名
/**
* @var array of string
*/
protected $JoinConditionColumn; /// 连接的字段(列)
/**
* @var array of mixed
*/
protected $JoinConditionValues; /// 连接的字段(列)的值描述
/**
* @var array of mixed
*/
protected $JoinConditionParams; /// 连接的字段(列)的值的参数列表
/**
* @var string
*/
protected $MergeJoinSourceNames; /// 连接源
/**
* @var array
*/
protected $MergeJoinSourceAlias; /// 连接源别名
/**
* @var array of string
*/
protected $MergeJoinConditionColumn; /// 连接的字段(列)
/**
* @var array of mixed
*/
protected $MergeJoinConditionValues; /// 连接的字段(列)的值描述
/**
* @var array of mixed
*/
protected $MergeJoinConditionParams; /// 连接的字段(列)的值的参数列表
/**
* @var array of ISQLCommand|string
*/
protected $UnionSourceNames; /// 需要链接的对象或语句。
/**
* @var array of mixed
*/
protected $OtherParameterList; /// 需要绑定的其他参数
/*******************************
* name: __construct.
* note: the construct function for class.
* parameters: Connection for PDOHelper.
* return: new object if the method call succeeded, null otherwise.
*******************************
* SQLCommand constructor.
* @param IPDOHelper $Connection
* @throws Exception
*******************************/
public function __construct($Connection)
{
if (null == $Connection || !($Connection instanceof IPDOHelper))
throw new Exception('the $Connection is invalid IPDOHelper instance! in ' . __FILE__ . ' on line ' . __LINE__);
$this->ClearMethod();
$this->Connection = $Connection;
}
/*******************************
* name: __destruct.
* note: the destruct function for class.
* parameters: nan.
* return: nan.
*******************************
* SQLCommand destructor.
*******************************/
public function __destruct()
{
$this->ClearMethod();
}
// function __call($Name, $Args)
// {
// $Reflect = new ReflectionClass($this->Connection);
// if ($Method = $Reflect->getMethod($Name))
// {
// if ($Method->isPublic() && !$Method->isAbstract())
// {
// return $Method->invokeArgs($this->Connection, $Args);
// }
// }
// }
// function __get($Name)
// {
// $Reflect = new ReflectionClass($this->Connection);
// if ($Property = $Reflect->getProperty($Name))
// {
// if ($Property->isPublic())
// {
// return $Property->getValue($this->Connection);
// }
// }
// }
// function __set($Name, $Value)
// {
// $Reflect = new ReflectionClass($this->Connection);
// if ($Property = $Reflect->GetProperty($Name))
// {
// if ($Property->IsPublic())
// {
// return $Property->SetValue($this->Connection, $Value);
// }
// }
// }
/*******************************
* name: ClearMember.
* note: clear all member for class.
* parameters: nan.
* return: nan.
*******************************
*
*******************************/
protected function ClearMethod()
{
$this->CommandType = ''; /// 语句类型
$this->DataFieldNames = array(); /// 字段名
$this->DataFieldAlias = array(); /// 字段别名
$this->InternalSourceNames = array(); /// 数据源
$this->InternalSourceAlias = array(); /// 数据源别名
$this->StoredProcedureName = ''; /// 要调用的存储过程或函数名
//$this->ExternalSourceNames = array(); /// 要插入|修改|合并的数据源
//$this->ExternalSourceAlias = array(); /// 要插入|修改|合并的数据源别名
$this->WhereConditionColumn = array(); /// 过滤列
$this->WhereConditionValues = array(); /// 过滤值的描述
$this->WhereConditionParams = array(); /// 过滤值的参数
$this->GroupFieldList = array(); /// 分组字段
$this->HavingConditionColumn = array(); /// 过滤分组信息的列
$this->HavingConditionValues = array(); /// 过滤分组信息的值的描述
$this->HavingConditionParams = array(); /// 过滤分组信息的值的参数
$this->OrderFieldNames = array(); /// 排序字段
$this->OrderFieldTypes = array(); /// 排序类型
$this->PageIndex = 0; /// 分组时的页序号
$this->PageSize = 0; /// 分组时的页大小
$this->MaxRequestCount = 0; /// 限制要查询的记录数
$this->ChangeFields = array(); /// 要插入|修改|合并的字段名
$this->ChangeValues = array(); /// 要插入|修改|合并的值描述
$this->ChangeParams = array(); /// 要插入|修改|合并的值参数
/// 用于多表联查
$this->JoinCount = 0; /// 连接个数
$this->JoinType = array(); /// 连接方式
$this->JoinSourceNames = array(); /// 连接源
$this->JoinSourceAlias = array(); /// 连接源的别名
$this->JoinConditionColumn = array(); /// 连接条件
$this->JoinConditionValues = array(); /// 连接条件的参数列表
$this->JoinConditionParams = array(); /// 链接条件的参数值
/// 用于多表合并
$this->MergeJoinSourceNames = array(); /// 连接源
$this->MergeJoinSourceAlias = array(); /// 连接源的别名
$this->MergeJoinConditionColumn = array(); /// 连接条件
$this->MergeJoinConditionValues = array(); /// 连接条件的参数列表
$this->MergeJoinConditionParams = array(); /// 链接条件的参数值
/// 用于多表链接
$this->UnionSourceNames = array(); /// 需要链接的对象或语句。
///
$this->OtherParameterList = array(); /// 需要绑定的其他参数
}
/*******************************
* name: ProcessSelectColumn.
* note: get the select field information.
* parameters: expressions, return field list, return alias list.
* return: field list and alias list as array if the method call succeeded, null otherwise.
*******************************
* @param ISQLCommand|string|array|mixed $Expressions
* @param array $FieldList
* @param array $AliasList
* @return bool
*******************************/
private function ProcessSelectColumn($Expressions, &$FieldList, &$AliasList)
{
$FieldList = array();
$AliasList = array();
if (empty($Expressions))
return false;
if ($Expressions instanceof ISQLCommand)
{
array_push($FieldList, $Expressions);
array_push($AliasList, $this->CreateRandString('nsfa_'));
return true;
}
if (is_object($Expressions))
$Expressions = (array)$Expressions;
if (is_array($Expressions))
{
foreach ($Expressions as $Alias => $Field)
{
if (is_null($Field))
continue;
elseif ($Field instanceof ISQLCommand)
{
array_push($FieldList, $Field);
array_push($AliasList, $this->GetIdentifiers($Alias));
continue;
}
elseif (is_object($Field) || is_array($Field))
{
$TempFieldList = $TempAliasList = array();
if ($this->ProcessSelectColumn($Field, $TempFieldList, $TempAliasList))
{
$this->MergeArray($FieldList, $TempFieldList);
$this->MergeArray($AliasList, $TempAliasList);
}
continue;
}
$Value = mb_strstr($Field, '.', false, USEDCHARSET);
if (!empty($Value)) /// 包含.则两边增加限定符。
{
$Field = $this->GetObjectName($Field);
$SubLen = mb_strlen('.', USEDCHARSET);
$Value = $this->GetIdentifiers(mb_substr($Value, $SubLen, mb_strlen($Value, USEDCHARSET) - $SubLen, USEDCHARSET));
}
else
{
$Field = $this->GetObjectName($Field);
$Value = $Field;
}
/// 别名
if (!empty($Alias) && !is_numeric($Alias))
$Value = $this->GetObjectName($Alias);
array_push($FieldList, $Field);
array_push($AliasList, $Value);
}
}
else
{
array_push($FieldList, $Expressions);
array_push($AliasList, $Expressions);
}
return true;
}
/*******************************
* name: ProcessDataSource.
* note: get the datasource or table information.
* parameters: datasource or table.
* return: table list and alias list as array if the method call succeeded, null otherwise.
*******************************
* @param ISQLCommand|string|array|mixed $Expressions
* @param array $TableList
* @param array $AliasList
* @return bool
*******************************/
private function ProcessDataSource($Expressions, &$TableList, &$AliasList)
{
$TableList = array();
$AliasList = array();
if (empty($Expressions))
return false;
if ($Expressions instanceof ISQLCommand)
{
array_push($TableList, $Expressions);
array_push($AliasList, $this->CreateRandString('nds_'));
return true;
}
if (is_object($Expressions))
$Expressions = (array)$Expressions;
if (is_array($Expressions))
{
foreach ($Expressions as $Alias => $Table)
{
if (is_null($Table))
continue;
elseif ($Table instanceof ISQLCommand)
{
array_push($TableList, $Table);
array_push($AliasList, $this->GetObjectName($Alias));
continue;
}
elseif (is_array($Table) || is_object($Table))
{
$TempTableList = $TempAliasList = array();
if ($this->ProcessDataSource($Table, $TempTableList, $TempAliasList))
{
$this->MergeArray($TableList, $TempTableList);
$this->MergeArray($AliasList, $TempAliasList);
}
continue;
}
array_push($TableList, $this->GetObjectName($Table));
array_push($AliasList, (!empty($Alias) && !is_numeric($Alias)) ? $this->GetObjectName($Alias) : '');
}
}
else
{
array_push($TableList, $Expressions);
array_push($AliasList, $Expressions);
}
return true;
}
/*******************************
* name: ProcessCondition.
* note: get the condition information.
* parameters: condition.
* return: condition list and value list as array if the method call succeeded, null otherwise.
*******************************
* @param ISQLCommand|string|array|mixed $Expressions
* @param array $ConditionsColumn
* @param array $ConditionsValues
* @param array $ConditionsParams
* @return array
*******************************/
private function ProcessCondition($Expressions, &$ConditionsColumn, &$ConditionsValues, &$ConditionsParams)
{
$ConditionsColumn = array(); /// colunm name
$ConditionsValues = array(); /// column mask or value
$ConditionsParams = array(); /// column parameter value
if (empty($Expressions))
return false;
elseif ($Expressions instanceof CommandParameter)
$Expressions = array($Expressions);
elseif (is_object($Expressions))
$Expressions = (array)$Expressions;
if (is_array($Expressions))
{
foreach ($Expressions as $Key => $Value)
{
array_push($ConditionsColumn, $this->GetObjectName($Key));
if (is_null($Value))
{
array_push($ConditionsValues, '?');
array_push($ConditionsParams, null);
continue;
}
elseif ($Value instanceof ISQLCommand)
{
array_push($ConditionsValues, $Value);
array_push($ConditionsParams, null);
continue;
}
elseif ($Value instanceof CommandParameter)
{
$IsRaw = $Value->Raw;
$Type = $Value->Type;
$Value = $Value->Value;
}
else
{
$IsRaw = false;
$Type = TYPENAME_RAW;
if (is_array($Value) || is_object($Value))
$Value = JsonObjectToJsonString((array)$Value);
}
if ($IsRaw)
{
switch ($Type)
{
case TYPENAME_DATE:
{
if (is_numeric($Value))
array_push($ConditionsValues, $this->Timestamp2DatetimeFormat($Value));
else
array_push($ConditionsValues, $this->String2DatetimeFormat($Value));
break;
}
case TYPENAME_TIMESTAMP:
{
if (is_numeric($Value))
array_push($ConditionsValues, $Value);
else
array_push($ConditionsValues, $this->Datetime2TimestampFormat($Value));
break;
}
case TYPENAME_STRING:
{
array_push($ConditionsValues, $this->GetIdentifiers($Value, true));
break;
}
default:
{
array_push($ConditionsValues, $Value);
break;
}
}
array_push($ConditionsParams, null);
}
else
{
switch ($Type)
{
case TYPENAME_DATE:
{
if (is_numeric($Value))
array_push($ConditionsValues, $this->Timestamp2DatetimeFormat('?'));
else
array_push($ConditionsValues, $this->String2DatetimeFormat('?', false));
break;
}
case TYPENAME_TIMESTAMP:
{
if (is_numeric($Value))
array_push($ConditionsValues, '?');
else
array_push($ConditionsValues, $this->Datetime2TimestampFormat('?', false));
break;
}
default:
{
array_push($ConditionsValues, '?');
break;
}
}
array_push($ConditionsParams, $Value);
}
}
}
else
{
array_push($ConditionsColumn, $Expressions);
array_push($ConditionsValues, null);
array_push($ConditionsParams, null);
}
return true;
}
/*******************************
* name: ProcessGroupColumn.
* note: get the group expression information.
* parameters: group expression.
* return: group field list as string if the method call succeeded, null otherwise.
*******************************
* @param string|array $Expressions
* @param array $FieldList
* @return bool
*******************************/
private function ProcessGroupColumn($Expressions, &$FieldList)
{
$FieldList = array();
if (empty($Expressions))
return false;
if (is_object($Expressions))
$Expressions = (array)$Expressions;
if (is_array($Expressions))
{
foreach ($Expressions as $Alias => $Field)
{
array_push($FieldList, $this->GetObjectName($Field));
}
}
else
$FieldList = (array)$Expressions;
return true;
}
/*******************************
* name: ProcessOrderColumn.
* note: get the order expression.
* parameters: order expression.
* return: field and type list as string if the method call succeeded, null otherwise.
*******************************
* @param ISQLCommand|string|array|mixed $Expressions
* @param array $FieldList
* @param array $OrderList
* @return array
*******************************/
private function ProcessOrderColumn($Expressions, &$FieldList, &$OrderList)
{
$FieldList = array();
$OrderList = array();
if (empty($Expressions))
{
return false;
}
if (is_object($Expressions))
{
$Expressions = (array)$Expressions;
}
if (is_array($Expressions))
{
foreach ($Expressions as $Order => $Field)
{
if (strcasecmp('asc', $Order) != 0 && strcasecmp('desc', $Order) != 0)
$Order = 'asc';
array_push($FieldList, $this->GetObjectName($Field));
array_push($OrderList, $Order);
}
}
else
{
array_push($FieldList, $Expressions);
array_push($OrderList, 'asc');
}
return true;
}
/*******************************
* name: ProcessSourceColumn.
* note: get the insert or update column list.
* parameters: insert or update column list.
* return: insert or update column list as array if the method call succeeded, null otherwise.
*******************************
* @param string|array $Expressions
* @param array $Columns
* @return array
*******************************/
private function ProcessSourceColumn($Expressions, &$Columns)
{
$Columns = array();
if (empty($Expressions))
return false;
if (is_object($Expressions))
$Expressions = (array)$Expressions;
if (is_array($Expressions))
{
foreach ($Expressions as $Value)
{
if (is_object($Value) || is_array($Value))
{
$List = array();
if ($this->ProcessSourceColumn($Value, $List))
$this->MergeArray($Columns, $List);
continue;
}
elseif (is_null($Value))
continue;
array_push($Columns, $this->GetObjectName($Value));
}
}
else
array_push($Columns, $Expressions);
return true;
}
/*******************************
* name: ProcessTargetColumn.
* note: get the insert or update column list.
* parameters: insert or update column list.
* return: true if the method call succeeded, false otherwise.
*******************************
* @param string|array $Expressions
* @param array $Values
* @param array $Params
* @return boolean
*******************************/
private function ProcessTargetColumn($Expressions, &$Values, &$Params)
{
$Values = array();
$Params = array();
if (empty($Expressions))
return false;
if ($Expressions instanceof ISQLCommand)
{
array_push($Values, $Expressions);
array_push($Params, null);
return true;
}
elseif ($Expressions instanceof CommandParameter)
$Expressions = array($Expressions);
elseif (is_object($Expressions))
$Expressions = (array)$Expressions;
if (is_array($Expressions))
{
/// 分解字段,并拼接成需要的格式
foreach ($Expressions as $Value)
{
if (is_null($Value))
continue;
elseif ($Value instanceof CommandParameter)
{
$IsRaw = $Value->Raw;
$Type = $Value->Type;
$Value = $Value->Value;
}
else
{
$IsRaw = false;
$Type = TYPENAME_RAW;
if (is_array($Value) || is_object($Value))
$Value = JsonObjectToJsonString((array)$Value);
}
/// 处理参数值
if ($IsRaw)
{
switch ($Type)
{
case TYPENAME_DATE:
{
if (is_numeric($Value))
array_push($Values, $this->Timestamp2DatetimeFormat($Value));
else
array_push($Values, $this->String2DatetimeFormat($Value));
break;
}
case TYPENAME_TIMESTAMP:
{
if (is_numeric($Value))
array_push($Values, $Value);
else
array_push($Values, $this->Datetime2TimestampFormat($Value));
break;
}
case TYPENAME_RAW:
{
array_push($Values, $Value);
break;
}
default:
{
array_push($Values, $this->GetIdentifiers($Value, true));
break;
}
}
/// 为null表示不传参
array_push($Params, null);
}
else
{
switch ($Type)
{
case TYPENAME_DATE:
{
if (is_numeric($Value))
array_push($Values, $this->Timestamp2DatetimeFormat('?'));
else
array_push($Values, $this->String2DatetimeFormat('?', false));
break;
}
case TYPENAME_TIMESTAMP:
{
if (is_numeric($Value))
array_push($Values, '?');
else
array_push($Values, $this->Datetime2TimestampFormat('?', false));
break;
}
default:
{
array_push($Values, '?');
break;
}
}
/// 把字段值加入参数列表中
array_push($Params, $Value);
}
}
}
else
{
array_push($Values, $Expressions);
array_push($Params, null);
}
return true;
}
/*******************************
* name: ProcessBindParameter.
* note: get the bind others parameter list.
* parameters: others parameter list.
* return: true if the method call succeeded, false otherwise.
*******************************
* @param string|array $Expressions
* @param array $Params
* @return boolean
*******************************/
private function ProcessBindParameter($Expressions, &$Params)
{
$Params = array();
if (empty($Expressions))
return false;
if ($Expressions instanceof CommandParameter)
{
array_push($Params, $Expressions);
return true;
}
elseif (is_object($Expressions))
$Expressions = (array)$Expressions;
if (is_array($Expressions))
{
foreach ($Expressions as $Value)
{
if (is_object($Value) || is_array($Value))
{
$List = array();
if ($this->ProcessBindParameter($Value, $List))
$this->MergeArray($Params, $List);
continue;
}
elseif (is_null($Value))
continue;
array_push($Params, $Value);
}
}
else
array_push($Params, $Expressions);
return true;
}
/// =====================================================================================================================
/*******************************
* name: ReceiveSelectColumn.
* note: receive the select field information.
* parameters: expressions.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveSelectColumn() /// select ...
{
$Args = func_get_args();
$Count = func_num_args();
$this->DataFieldNames = array();
$this->DataFieldAlias = array();
for ($Index = 0; $Index < $Count; $Index++)
{
$Field = array();
$Alias = array();
if ($this->ProcessSelectColumn((array)$Args[$Index], $Field, $Alias))
{
$this->MergeArray($this->DataFieldNames, $Field);
$this->MergeArray($this->DataFieldAlias, $Alias);
}
}
}
/*******************************
* name: ReceiveInternalSource.
* note: receive the datasource or table information by source.
* parameters: datasource or table.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveInternalSource() /// [select from|insert into|update|merge into] ...
{
$Args = func_get_args();
$Count = func_num_args();
$this->InternalSourceNames = array();
$this->InternalSourceAlias = array();
for ($Index = 0; $Index < $Count; $Index++)
{
if ($Args[$Index] instanceof ISQLCommand)
{
$Table = array($Args[$Index]);
$Alias = array($this->CreateRandString('nds_'));
}
else
{
$Table = array();
$Alias = array();
if (!$this->ProcessDataSource((array)$Args[$Index], $Table, $Alias))
{
$Table = array();
$Alias = array();
}
}
$this->MergeArray($this->InternalSourceNames, $Table);
$this->MergeArray($this->InternalSourceAlias, $Alias);
}
}
/*******************************
* name: ReceiveStoredProcedureName.
* note: receive the name of stored procedure.
* parameters: stored procedure name.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveStoredProcedureName($StoredProcedureName)
{
/// $Args = func_get_args();
/// $Count = func_num_args();
$this->StoredProcedureName = $StoredProcedureName;
}
/*******************************
* name: ReceiveExternalSource.
* note: receive the datasource or table information by target.
* parameters: datatarget or table.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
// private function ReceiveExternalSource() /// [] ...
// {
// $Args = func_get_args();
// $Count = func_num_args();
//
// $this->ExternalSourceNames = array();
// $this->ExternalSourceAlias = array();
//
// for ($Index = 0; $Index < $Count; $Index++)
// {
// if ($Args[$Index] instanceof ISQLCommand)
// {
// $Table = array($Args[$Index]);
// $Alias = array($this->CreateRandString('ndt_'));
// }
// else
// {
// $Table = array();
// $Alias = array();
// if (!$this->ProcessDataSource((array)$Args[$Index], $Table, $Alias))
// {
// $Table = array();
// $Alias = array();
// }
// }
//
// $this->MergeArray($this->ExternalSourceNames, $Table);
// $this->MergeArray($this->ExternalSourceAlias, $Alias);
// }
// }
/*******************************
* name: ReceiveExternalSource.
* note: receive the datasource or table information by join source.
* parameters: datatarget or table.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveJoinSource() /// [inner|left|right|outer] join ...
{
$Args = func_get_args();
$Count = func_num_args();
$this->JoinSourceNames[$this->JoinCount - 1] = array();
$this->JoinSourceAlias[$this->JoinCount - 1] = array();
for ($Index = 0; $Index < $Count; $Index++)
{
if ($Args[$Index] instanceof ISQLCommand)
{
$Table = array($Args[$Index]);
$Alias = array($this->CreateRandString('ndt_'));
}
else
{
$Table = array();
$Alias = array();
if (!$this->ProcessDataSource((array)$Args[$Index], $Table, $Alias))
{
$Table = array();
$Alias = array();
}
}
$this->MergeArray($this->JoinSourceNames[$this->JoinCount - 1], $Table);
$this->MergeArray($this->JoinSourceAlias[$this->JoinCount - 1], $Alias);
}
}
/*******************************
* name: ReceiveJoinCondition.
* note: receive the datasource or table condition information by join source.
* parameters: join condition.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveJoinCondition() /// join on ...
{
$Args = func_get_args();
$Count = func_num_args();
$this->JoinConditionColumn[$this->JoinCount - 1] = array();
$this->JoinConditionValues[$this->JoinCount - 1] = array();
$this->JoinConditionParams[$this->JoinCount - 1] = array();
for ($Index = 0; $Index < $Count; $Index++)
{
$ConditionColumn = array();
$ConditionValues = array();
$ConditionParams = array();
if ($this->ProcessCondition($Args[$Index], $ConditionColumn, $ConditionValues, $ConditionParams))
{
$this->MergeArray($this->JoinConditionColumn[$this->JoinCount - 1], $ConditionColumn);
$this->MergeArray($this->JoinConditionValues[$this->JoinCount - 1], $ConditionValues);
$this->MergeArray($this->JoinConditionParams[$this->JoinCount - 1], $ConditionParams);
}
}
}
/*******************************
* name: ReceiveMergeJoinCondition.
* note: receive the datasource or table condition information by join source.
* parameters: join condition.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveMergeJoinCondition()
{
$Args = func_get_args();
$Count = func_num_args();
$this->MergeJoinConditionColumn = array();
$this->MergeJoinConditionValues = array();
$this->MergeJoinConditionParams = array();
for ($Index = 0; $Index < $Count; $Index++)
{
$ConditionColumn = array();
$ConditionValues = array();
$ConditionParams = array();
if ($this->ProcessCondition($Args[$Index], $ConditionColumn, $ConditionValues, $ConditionParams))
{
$this->MergeArray($this->MergeJoinConditionColumn, $ConditionColumn);
$this->MergeArray($this->MergeJoinConditionValues, $ConditionValues);
$this->MergeArray($this->MergeJoinConditionParams, $ConditionParams);
}
}
}
/*******************************
* name: ReceiveWhereCondition.
* note: receive the where condition information.
* parameters: condition.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveWhereCondition() /// where ...
{
$Args = func_get_args();
$Count = func_num_args();
$this->WhereConditionColumn = array();
$this->WhereConditionValues = array();
$this->WhereConditionParams = array();
for ($Index = 0; $Index < $Count; $Index++)
{
$ConditionColumn = array();
$ConditionValues = array();
$ConditionParams = array();
if ($this->ProcessCondition($Args[$Index], $ConditionColumn, $ConditionValues, $ConditionParams))
{
$this->MergeArray($this->WhereConditionColumn, $ConditionColumn);
$this->MergeArray($this->WhereConditionValues, $ConditionValues);
$this->MergeArray($this->WhereConditionParams, $ConditionParams);
}
}
}
/*******************************
* name: ReceiveGroupExpression.
* note: receive the group express information.
* parameters: group express.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveGroupExpression() /// group by ...
{
$this->GroupFieldList = array();
$this->ProcessGroupColumn(func_get_args(), $this->GroupFieldList);
}
/*******************************
* name: ReceiveHavingCondition.
* note: receive the having condition information by group express.
* parameters: having condition.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveHavingCondition() /// having ...
{
$Args = func_get_args();
$Count = func_num_args();
$this->HavingConditionColumn = array();
$this->HavingConditionValues = array();
$this->HavingConditionParams = array();
for ($Index = 0; $Index < $Count; $Index++)
{
$ConditionColumn = array();
$ConditionValues = array();
$ConditionParams = array();
if ($this->ProcessCondition($Args[$Index], $ConditionColumn, $ConditionValues, $ConditionParams))
{
$this->MergeArray($this->HavingConditionColumn, $ConditionColumn);
$this->MergeArray($this->HavingConditionValues, $ConditionValues);
$this->MergeArray($this->HavingConditionParams, $ConditionParams);
}
}
}
/*******************************
* name: ReceiveOrderExpression.
* note: receive the order express information.
* parameters: order express.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveOrderExpression() /// order by ...
{
$Args = func_get_args();
$Count = func_num_args();
$this->OrderFieldNames = array();
$this->OrderFieldTypes = array();
for ($Index = 0; $Index < $Count; $Index++)
{
$FieldList = array();
$OrderList = array();
if ($this->ProcessOrderColumn((array)$Args[$Index], $FieldList, $OrderList))
{
$this->MergeArray($this->OrderFieldNames, $FieldList);
$this->MergeArray($this->OrderFieldTypes, $OrderList);
}
}
}
/*******************************
* name: ReceiveInternalColumn.
* note: receive the source column information.
* parameters: source column.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveInternalColumn()
{
$this->ProcessSourceColumn(func_get_args(), $this->ChangeFields);
}
/*******************************
* name: ReceiveExternalColumn.
* note: receive the target column information.
* parameters: target column.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveExternalColumn()
{
$this->ChangeValues = array();
$this->ChangeParams = array();
$Args = func_get_args();
$Count = func_num_args();
for ($Index = 0; $Index < $Count; $Index++)
{
if ($Args[$Index] instanceof ISQLCommand)
{
array_push($this->ChangeValues, $Args[$Index]);
array_push($this->ChangeParams, null);
}
else
{
$Values = array();
$Params = array();
if ($this->ProcessTargetColumn(is_object($Args[$Index]) ? $Args[$Index] : (array)$Args[$Index], $Values, $Params))
{
$this->MergeArray($this->ChangeValues, $Values);
$this->MergeArray($this->ChangeParams, $Params);
}
}
}
}
/*******************************
* name: ReceiveUnionSource.
* note: receive the union source information.
* parameters: union source.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveUnionSource()
{
$this->UnionSourceNames = array();
$Args = func_get_args();
$Count = func_num_args();
for ($Index = 0; $Index < $Count; $Index++)
{
array_push($this->UnionSourceNames, $Args[$Index]);
}
}
/*******************************
* name: ReceiveBindParameters.
* note: receive the bind others parameter list.
* parameters: needed bind parameter list.
* return: nan.
*******************************
* @param ISQLCommand|string|array|mixed
*******************************/
private function ReceiveBindParameters()
{
$this->OtherParameterList = array();
$Args = func_get_args();
$Count = func_num_args();
for ($Index = 0; $Index < $Count; $Index++)
{
$Parameters = array();
if ($this->ProcessBindParameter($Args[$Index], $Parameters))
$this->MergeArray($this->OtherParameterList, $Parameters);
}
}
/// =====================================================================================================================
/*******************************
* name: CreateRandString.
* note: create a rand string.
* parameters: string prefix.
* return: string.
*******************************
* @param string $Prefix
* @return string
*******************************/
protected function CreateRandString($Prefix = '')
{
return (empty($Prefix) ? '' : $Prefix) . rand(100000, 999999);
}
/*******************************
* name: SetReferenceCharacter.
* note: set left and right reference character.
* parameters: reference character.
* return: nan.
*******************************
* @param string $Left left reference character
* @param string $Right right reference character
* @return ISQLCommand
*******************************/
protected function SetReferenceCharacter($Left, $Right)
{
$this->RefCharLeft = $Left;
$this->RefCharRight = $Right;
}
/*******************************
* name: SelectFieldListToCommandInformation.
* note: connect select field array to string.
* parameters: name array, alia array.
* return: CommandInformation.
*******************************
* @param array $Columns need to connect to the array.
* @param array $Alias need to connect to the alia for array.
* @return CommandInformation
*******************************/
protected function SelectFieldListToCommandInformation($Columns, $Alias)
{
$Return = new CommandInformation();
if (!(is_array($Columns) && is_array($Alias)))
return $Return;
for ($Index = 0; $Index < count($Columns); $Index++)
{
if ($Columns[$Index] instanceof ISQLCommand)
{
$Command = call_user_func(array(&$Columns[$Index], 'GetCommandInformation')); /// must pass &$xxx in php4.x
$Return->Command .= ", ({$Command->Command}) {$Alias[$Index]}";
$this->MergeArray($Return->Paramer, $Command->Paramer);
}
elseif (!empty($Alias[$Index]) && ($Alias[$Index] != $Columns[$Index]))
$Return->Command .= ", {$Columns[$Index]} {$Alias[$Index]}";
else
$Return->Command .= ", {$Columns[$Index]}";
}
$SubLen = mb_strlen(', ', USEDCHARSET);
$Return->Command = mb_substr($Return->Command, $SubLen, mb_strlen($Return->Command, USEDCHARSET), USEDCHARSET);
return $Return;
}
/*******************************
* name: ConditionsListToCommandInformation.
* note: connect conditions list to string.
* parameters: name array, value array, param array.
* return: CommandInformation.
*******************************
* @param array $Columns need to connect to the array.
* @param array $Values need to connect to the value description for array.
* @param array $Params need to connect to the param for value of array.
* @return CommandInformation
*******************************/
protected function ConditionsListToCommandInformation($Columns, $Values, $Params)
{
$Return = new CommandInformation();
if (!(is_array($Columns) && is_array($Values) && is_array($Params)))
return $Return;
for ($Index = 0; $Index < count($Columns); $Index++)
{
if ($Values[$Index] instanceof ISQLCommand)
{
$Command = call_user_func(array(&$Values[$Index], 'GetCommandInformation')); /// must pass &$xxx in php4.x
$Return->Command .= " and ({$Columns[$Index]} = ({$Command->Command}))";
$this->MergeArray($Return->Paramer, $Command->Paramer);
}
else
{
if (is_null($Values[$Index]))
$Return->Command .= " and ({$Columns[$Index]})";
elseif (is_null($Params[$Index]))
$Return->Command .= " and ({$Columns[$Index]} is null)"; /// 2017-12-14: if value is null use this command.
else
$Return->Command .= " and ({$Columns[$Index]} = {$Values[$Index]})";
if (!is_null($Params[$Index]))
$this->MergeArray($Return->Paramer, $Params[$Index]);
}
}
$SubLen = mb_strlen(' and ', USEDCHARSET);
$Return->Command = mb_substr($Return->Command, $SubLen, mb_strlen($Return->Command, USEDCHARSET), USEDCHARSET);
return $Return;
}
/*******************************
* name: ValueFieldListToCommandInformation.
* note: connect source field array to string.
* parameters: name array, alia array.
* return: CommandInformation.
*******************************
* @param array $Columns need to connect to the array.
* @param array $Values need to connect to the value for field.
* @param array $Params need to connect to the param for field
* @return CommandInformation
*******************************/
protected function ValueFieldListToCommandInformation($Columns, $Values, $Params)
{
if ($Columns instanceof ISQLCommand)
return call_user_func(array(&$Columns, 'GetCommandInformation')); /// must pass &$xxx in php4.x
$Return = new CommandInformation();
if (!is_array($Columns))
return $Return;
for ($Index = 0; $Index < count($Columns); $Index++)
{
if ($Columns[$Index] instanceof ISQLCommand)
{
$Command = call_user_func(array(&$Columns[$Index], 'GetCommandInformation')); /// must pass &$xxx in php4.x
$Return->Command .= ", {$Command->Command}";
$this->MergeArray($Return->Paramer, $Command->Paramer);
}
elseif (!is_null($Columns[$Index]))
$Return->Command .= ", {$Columns[$Index]}";
elseif (is_null($Params))
$Return->Command .= ', null';
if (!is_null($Values))
{
/// 2017-12-14: if value is null use this command.
if (!isset($Values[$Index]))
{
$Return->Command .= ' = null';
continue;
}
if ($Values[$Index] instanceof ISQLCommand)
{
$Command = call_user_func(array(&$Values[$Index], 'GetCommandInformation')); /// must pass &$xxx in php4.x
$Return->Command .= " = ({$Command->Command})";
$this->MergeArray($Return->Paramer, $Command->Paramer);
}
elseif (!is_null($Values[$Index]))
$Return->Command .= " = {$Values[$Index]}";
}
if (!is_null($Params[$Index]))
$this->MergeArray($Return->Paramer, $Params[$Index]);
}
$SubLen = mb_strlen(', ', USEDCHARSET);
$Return->Command = mb_substr($Return->Command, $SubLen, mb_strlen($Return->Command, USEDCHARSET), USEDCHARSET);
return $Return;
}
/*******************************
* name: SourceListToCommandInformation.
* note: connect the union source list to CommandInformation array.
* parameters: array of union source.
* return: CommandInformation.
*******************************
* @param array $Sources need to union of the source.
* @return CommandInformation
*******************************/
protected function SourceListToCommandInformation($Sources)
{
$Return = new CommandInformation();
if ($Sources instanceof ISQLCommand)
{
$Return = call_user_func(array(&$Sources, 'GetCommandInformation')); /// must pass &$xxx in php4.x
$Return->Command = PHP_EOL . 'union all' . PHP_EOL . "({$Return->Command})";
}
elseif (is_string($Sources))
{
$Return->Command = PHP_EOL . 'union all' . PHP_EOL . "({$Sources})";
}
elseif (is_array($Sources))
{
for ($Index = 0; $Index < count($Sources); $Index++)
{
if ($Sources[$Index] instanceof ISQLCommand)
{
$Command = call_user_func(array(&$Sources[$Index], 'GetCommandInformation')); /// must pass &$xxx in php4.x
$Return->Command .= PHP_EOL . 'union all' . PHP_EOL . "({$Command->Command})";
$this->MergeArray($Return->Paramer, $Command->Paramer);
}
elseif (!is_null($Sources[$Index]))
$Return->Command .= PHP_EOL . 'union all' . PHP_EOL . "({$Sources[$Index]})";
}
}
return $Return;
}
/// =====================================================================================================================
protected function GetSelectColumns()
{
return $this->SelectFieldListToCommandInformation($this->DataFieldNames, $this->DataFieldAlias);
}
protected function GetSelectAliaColumns()
{
return $this->SelectFieldListToCommandInformation($this->DataFieldAlias, $this->DataFieldAlias);
}
protected function GetInternalSource()
{
return $this->SelectFieldListToCommandInformation($this->InternalSourceNames, $this->InternalSourceAlias);
}
// protected function GetExternalSource()
// {
// return $this->SelectFieldListToCommandInformation($this->ExternalSourceNames, $this->ExternalSourceAlias);
// }
protected function GetJoinSources($Index)
{
return $this->SelectFieldListToCommandInformation($this->JoinSourceNames[$Index], $this->JoinSourceAlias[$Index]);
}
protected function GetJoinConditions($Index)
{
return $this->ConditionsListToCommandInformation($this->JoinConditionColumn[$Index], $this->JoinConditionValues[$Index], $this->JoinConditionParams[$Index]);
}
protected function GetMergeJoinConditions()
{
return $this->ConditionsListToCommandInformation($this->MergeJoinConditionColumn, $this->MergeJoinConditionValues, $this->MergeJoinConditionParams);
}
protected function GetWhereConditions()
{
return $this->ConditionsListToCommandInformation($this->WhereConditionColumn, $this->WhereConditionValues, $this->WhereConditionParams);
}
protected function GetGroupColumns()
{
return $this->ValueFieldListToCommandInformation($this->GroupFieldList, null, null);
}
protected function GetHavingConditions()
{
return $this->ConditionsListToCommandInformation($this->HavingConditionColumn, $this->HavingConditionValues, $this->HavingConditionParams);
}
protected function GetOrderColumns()
{
return $this->SelectFieldListToCommandInformation($this->OrderFieldNames, $this->OrderFieldTypes);
}
protected function GetChangeFields()
{
if ($this->ChangeFields[0] instanceof ISQLCommand)
return $this->ValueFieldListToCommandInformation($this->ChangeFields[0], null, null);
else
return $this->ValueFieldListToCommandInformation($this->ChangeFields, null, null);
}
protected function GetChangeValues()
{
if ($this->ChangeValues[0] instanceof ISQLCommand)
return $this->ValueFieldListToCommandInformation($this->ChangeValues[0], null, $this->ChangeParams);
else
return $this->ValueFieldListToCommandInformation($this->ChangeValues, null, $this->ChangeParams);
}
protected function GetChangeAllColumns()
{
return $this->ValueFieldListToCommandInformation($this->ChangeFields, $this->ChangeValues, $this->ChangeParams);
}
protected function GetUnionSources()
{
return $this->SourceListToCommandInformation($this->UnionSourceNames);
}
/// =====================================================================================================================
public function GetDataFieldNames()
{
return $this->DataFieldNames;
}
public function GetDataFieldAlias()
{
return $this->DataFieldAlias;
}
/// =====================================================================================================================
/*******************************
* name: GetIdentifiers.
* note: processing the identifier.
* parameters: identifier, quoted, Special char.
* return: processed identifier.
*******************************
* @param string $Identifiers need processing identifier
* @param bool $Quoted need quoted?
* @param array|mixed $Specialchar need special treatment string.
* @return string
*******************************/
public function GetIdentifiers($Identifiers, $Quoted = false, $Specialchar = null)
{
if (is_null($Identifiers) || '' == $Identifiers)
{
return '';
}
elseif ($Quoted)
{
if (method_exists($this->Connection, 'Quote'))
return $this->Connection->Quote($Identifiers);
else
{
$Length = mb_strlen($Identifiers, USEDCHARSET);
if ("'" == mb_substr($Identifiers, 0, 1, USEDCHARSET))
{
$Length--;
$Identifiers = mb_substr($Identifiers, 1, $Length, USEDCHARSET);
}
if ("'" == mb_substr($Identifiers, $Length - 1, 1, USEDCHARSET))
{
$Length--;
$Identifiers = mb_substr($Identifiers, 0, $Length, USEDCHARSET);
}
return "'" . str_replace("'", "''", $Identifiers) . "'";
}
}
else
{
if (!empty($Specialchar))
{
$Specialchar = (array)$Specialchar;
foreach ($Specialchar as $Key => $Value)
{
$Identifiers = str_replace($Value, $this->RefCharRight . $Value . $this->RefCharLeft, $Identifiers);
}
}
return $this->RefCharLeft . $Identifiers . $this->RefCharRight;
}
}
/*******************************
* name: GetObjectName.
* note: processing the objectname identifier.
* parameters: objectname.
* return: processed object name.
*******************************
* @param string $ObjectName need processing identifier
* @return string
*******************************/
protected function GetObjectName($ObjectName)
{
return $this->GetIdentifiers($ObjectName, false, array('.', ',', ' '));
}
/*******************************
* name: RemoveReferenceCharacter.
* note: remove the identifier reference character.
* parameters: identifier.
* return: identifier.
*******************************
* @param string $Identifiers need processing identifier
* @return string
*******************************/
protected function RemoveReferenceCharacter($Identifiers)
{
if (is_object($Identifiers))
{
$Reflect = new ReflectionClass($Identifiers);
$Properties = $Reflect->GetProperties(ReflectionProperty::IS_PUBLIC);
foreach ($Properties as $Property)
{
//$Name = $Property->GetName();
$Value = $Property->GetValue($Identifiers);
$Value = $this->RemoveReferenceCharacter($Value);
$Property->SetValue($Identifiers, $Value);
}
}
elseif (is_array($Identifiers))
{
foreach($Identifiers as $Key => $Value)
{
$Identifiers->$Key = $this->RemoveReferenceCharacter($Value);
}
}
else
{
$Identifiers = str_replace($this->RefCharLeft, '', $Identifiers);
$Identifiers = str_replace($this->RefCharRight, '', $Identifiers);
}
return $Identifiers;
}
/*******************************
* name: GetSelectCommandInformation.
* note: get the select command information(not support page).
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetSelectCommandInformation()
{
$Return = new CommandInformation();
$Fields = $this->GetSelectColumns();
/// select 部分
$Return->Command = "select {$Fields->Command}";
$Return->Paramer = $Fields->Paramer;
/// from 部分
if (!empty($this->InternalSourceNames))
{
$Tables = $this->GetInternalSource();
$Return->Command .= " from {$Tables->Command}";
$this->MergeArray($Return->Paramer, $Tables->Paramer);
}
/// join 部分
for ($Index = 0; $Index < $this->JoinCount; $Index++)
{
if (!empty($this->JoinType[$Index]))
{
$Joins = $this->GetJoinSources($Index);
$JoinCondition = $this->GetJoinConditions($Index);
switch ($this->JoinType[$Index])
{
case JOINTYPE_INNER:
{
$Return->Command .= " inner join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_LEFT:
{
$Return->Command .= " left outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_RIGHT:
{
$Return->Command .= " right outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_OUTER:
{
$Return->Command .= " full outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
default:
{
$this->JoinSourceNames[$Index] = array();
$this->JoinSourceAlias[$Index] = array();
$this->JoinConditionColumn[$Index] = array();
$this->JoinConditionValues[$Index] = array();
$this->JoinConditionParams[$Index] = array();
break;
}
}
$this->MergeArray($Return->Paramer, $Joins->Paramer);
$this->MergeArray($Return->Paramer, $JoinCondition->Paramer);
}
}
/// where 部分
if (!empty($this->WhereConditionColumn))
{
$WhereCondition = $this->GetWhereConditions();
$Return->Command .= " where {$WhereCondition->Command}";
$this->MergeArray($Return->Paramer, $WhereCondition->Paramer);
}
/// group by 和 having 部分
if (!empty($this->GroupFieldList))
{
$GroupFields = $this->GetGroupColumns();
$Return->Command .= " group by {$GroupFields->Command}";
if (!empty($this->HavingConditionColumn))
{
$HavingCondition = $this->GetHavingConditions();
$Return->Command .= " having {$HavingCondition->Command}";
$this->MergeArray($Return->Paramer, $HavingCondition->Paramer);
}
}
/// order by 部分
if (!empty($this->OrderFieldNames))
{
$OrderFields = $this->GetOrderColumns();
$Return->Command .= " order by {$OrderFields->Command}";
}
return $Return;
}
/*******************************
* name: GetUnionCommandInformation.
* note: get the select union command information.
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetUnionCommandInformation()
{
return $this->GetUnionSources();
}
/*******************************
* name: GetInsertCommandInformation.
* note: get the insert command information.
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetInsertCommandInformation()
{
$Return = new CommandInformation();
$Tables = $this->GetInternalSource();
$Return->Command = /** @lang text */ "insert into {$Tables->Command}";
$Return->Paramer = $Tables->Paramer;
$Fields = $this->GetChangeFields();
$Values = $this->GetChangeValues();
/// 如果包含select表示则表示是一个子查询, 那么就不用values包裹了.
if (mb_stristr($Values->Command, 'select', false, USEDCHARSET))
$Return->Command .= " ({$Fields->Command}) {$Values->Command}";
else
$Return->Command .= " ({$Fields->Command}) values ({$Values->Command})";
$this->MergeArray($Return->Paramer, $Fields->Paramer);
$this->MergeArray($Return->Paramer, $Values->Paramer);
return $Return;
}
/*******************************
* name: GetUpdateCommandInformation.
* note: get the update command information(not support join method).
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetUpdateCommandInformation()
{
$Return = new CommandInformation();
$Tables = $this->GetInternalSource();
$Return->Command = "update {$Tables->Command}";
$Return->Paramer = $Tables->Paramer;
$Fields = $this->GetChangeAllColumns();
$Return->Command .= " set {$Fields->Command}";
$this->MergeArray($Return->Paramer, $Fields->Paramer);
if (!empty($this->WhereConditionColumn))
{
$WhereCondition = $this->GetWhereConditions();
$Return->Command .= " where {$WhereCondition->Command}";
$this->MergeArray($Return->Paramer, $WhereCondition->Paramer);
}
return $Return;
}
/*******************************
* name: GetDeleteCommandInformation.
* note: get the delete command information(not support join method).
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetDeleteCommandInformation()
{
$Return = new CommandInformation();
$Tables = $this->GetInternalSource();
$Return->Command = /** @lang text */ "delete from {$Tables->Command}";
$Return->Paramer = $Tables->Paramer;
if (!empty($this->WhereConditionColumn))
{
$WhereCondition = $this->GetWhereConditions();
$Return->Command .= " where {$WhereCondition->Command}";
$this->MergeArray($Return->Paramer, $WhereCondition->Paramer);
}
return $Return;
}
/*******************************
* name: GetTruncCommandInformation.
* note: get the truncate table command information.
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetTruncCommandInformation()
{
$Return = new CommandInformation();
$Tables = $this->GetInternalSource();
$Return->Command = "truncate table {$Tables->Command}";
$Return->Paramer = $Tables->Paramer;
return $Return;
}
/*******************************
* name: GetMergeCommandInformation.
* note: get the merge into command information(not implement).
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
abstract protected function GetMergeCommandInformation();
/*******************************
* name: GetCallStoredProcedureCommandInformation.
* note: get the call stored procedure command information(not implement).
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetCallStoredProcedureCommandInformation()
{
$Return = new CommandInformation();
$Return->Command = "call {$this->StoredProcedureName}";
$Values = $this->GetChangeValues();
if (!empty($Values))
{
$Return->Command .= "($Values->Command)";
$this->MergeArray($Return->Paramer, $Values->Paramer);
}
return $Return;
}
/*******************************
* name: MergeArray.
* note: merge array.
* parameters: array, sub.
* return: true if the method call succeeded, false otherwise.
*******************************
* @param array $Array
* @param array $SubArray
* @return bool
*******************************/
public function MergeArray(&$Array, $SubArray = array())
{
if (!is_array($Array))
return false;
foreach ((array)$SubArray as $Key => $Value)
{
array_push($Array, $Value);
}
return true;
}
/*******************************
* name: From.
* note: set the datasource or table information.
* parameters: datasource or table.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function From()
{
call_user_func_array(array(&$this, 'ReceiveInternalSource'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: InnerJoin.
* note: set the inner join table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string
* @return ISQLCommand
*******************************/
public function InnerJoin()
{
$Index = $this->JoinCount++;
$this->JoinType[$Index] = JOINTYPE_INNER;
$this->JoinSourceNames[$Index] = array();
$this->JoinSourceAlias[$Index] = array();
$this->JoinConditionColumn[$Index] = array();
$this->JoinConditionValues[$Index] = array();
$this->JoinConditionParams[$Index] = array();
call_user_func_array(array(&$this, 'ReceiveJoinSource'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: LeftJoin.
* note: set the left join table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string
* @return ISQLCommand
*******************************/
public function LeftJoin()
{
$Index = $this->JoinCount++;
$this->JoinType[$Index] = JOINTYPE_LEFT;
$this->JoinSourceNames[$Index] = array();
$this->JoinSourceAlias[$Index] = array();
$this->JoinConditionColumn[$Index] = array();
$this->JoinConditionValues[$Index] = array();
$this->JoinConditionParams[$Index] = array();
call_user_func_array(array(&$this, 'ReceiveJoinSource'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: RightJoin.
* note: set the right join table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string
* @return ISQLCommand
*******************************/
public function RightJoin()
{
$Index = $this->JoinCount++;
$this->JoinType[$Index] = JOINTYPE_RIGHT;
$this->JoinSourceNames[$Index] = array();
$this->JoinSourceAlias[$Index] = array();
$this->JoinConditionColumn[$Index] = array();
$this->JoinConditionValues[$Index] = array();
$this->JoinConditionParams[$Index] = array();
call_user_func_array(array(&$this, 'ReceiveJoinSource'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: OuterJoin.
* note: set the outer join table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string
* @return ISQLCommand
*******************************/
public function OuterJoin()
{
$Index = $this->JoinCount++;
$this->JoinType[$Index] = JOINTYPE_OUTER;
$this->JoinSourceNames[$Index] = array();
$this->JoinSourceAlias[$Index] = array();
$this->JoinConditionColumn[$Index] = array();
$this->JoinConditionValues[$Index] = array();
$this->JoinConditionParams[$Index] = array();
call_user_func_array(array(&$this, 'ReceiveJoinSource'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: On.
* note: set the join condition information.
* parameters: join condition.
* return: always return locale instance.
*******************************
* @param array|string
* @return ISQLCommand
*******************************/
public function On()
{
call_user_func_array(array(&$this, 'ReceiveJoinCondition'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: MergeOn.
* note: set the merge condition information.
* parameters: merge condition.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string
* @return ISQLCommand
*******************************/
public function MergeOn()
{
call_user_func_array(array(&$this, 'ReceiveMergeJoinCondition'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: Union.
* note: set the union object or sql command.
* parameters: union mixed.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string
* @return ISQLCommand
*******************************/
public function Union()
{
call_user_func_array(array(&$this, 'ReceiveUnionSource'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: BindParameters.
* note: bind other parameters of sql command needed.
* parameters: needed bind parameter list.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string
* @return ISQLCommand
*******************************/
public function BindParameters()
{
call_user_func_array(array(&$this, 'ReceiveBindParameters'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: Where.
* note: set the where condition information.
* parameters: where condition.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Where()
{
//array_walk($Args, create_function('&$Value, $Key, $Sender', '$Value = $Sender->ProcessCondition($Value);'), $this);
call_user_func_array(array(&$this, 'ReceiveWhereCondition'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: GroupBy.
* note: set the group expression information.
* parameters: group expression.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function GroupBy()
{
call_user_func_array(array(&$this, 'ReceiveGroupExpression'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: Having.
* note: set the having condition information by group field.
* parameters: having condition.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Having()
{
call_user_func_array(array(&$this, 'ReceiveHavingCondition'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: OrderBy.
* note: set the order information.
* parameters: order expression.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function OrderBy()
{
call_user_func_array(array(&$this, 'ReceiveOrderExpression'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: WithPage.
* note: set paging select information.
* parameters: PageIndex, PageSize.
* return: always return locale instance.
*******************************
* @param int $PageIndex
* @param int $PageSize
* @return ISQLCommand
*******************************/
public function WithPage($PageIndex, $PageSize)
{
$this->PageIndex = $PageIndex;
$this->PageSize = $PageSize;
return $this;
}
/*******************************
* name: Limit.
* note: set select max record count.
* parameters: maxcount.
* return: always return locale instance.
*******************************
* @param int $MaxCount
* @return ISQLCommand
*******************************/
public function Limit($MaxCount)
{
$this->MaxRequestCount = $MaxCount;
return $this;
}
/*******************************
* name: Fields.
* note: set update column list.
* parameters: column list.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Fields()
{
call_user_func_array(array(&$this, 'ReceiveInternalColumn'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: Values.
* note: set update value list.
* parameters: value list.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return array
*******************************/
public function Values()
{
call_user_func_array(array(&$this, 'ReceiveExternalColumn'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: Select.
* note: set the select field information.
* parameters: field.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Select()
{
$this->CommandType = COMMANDTYPE_SELECT;
call_user_func_array(array(&$this, 'ReceiveSelectColumn'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: Insert.
* note: set the insert table or datasource information.
* parameters: table or datasource.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Insert()
{
$this->CommandType = COMMANDTYPE_INSERT;
call_user_func_array(array(&$this, 'ReceiveInternalSource'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: Update.
* note: set the update table or datasource information.
* parameters: table or datasource.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Update()
{
$this->CommandType = COMMANDTYPE_UPDATE;
call_user_func_array(array(&$this, 'ReceiveInternalSource'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: delete.
* note: set the delete table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Delete()
{
$this->CommandType = COMMANDTYPE_DELETE;
call_user_func_array(array(&$this, 'ReceiveInternalSource'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: Truncate.
* note: set the truncate table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Truncate()
{
$this->CommandType = COMMANDTYPE_TRUNC;
call_user_func_array(array(&$this, 'ReceiveInternalSource'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: Merge.
* note: set the merge table information.
* parameters: table.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function Merge()
{
$this->CommandType = COMMANDTYPE_MERGE;
call_user_func_array(array(&$this, 'ReceiveInternalSource'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/*******************************
* name: Merge.
* note: set call stored procedure name.
* parameters: procedure name.
* return: always return locale instance.
*******************************
* @param ISQLCommand|string|array|mixed
* @return ISQLCommand
*******************************/
public function CallStoredProcedure()
{
$this->CommandType = COMMANDTYPE_CALLSTOREDPROCEDURE;
call_user_func_array(array(&$this, 'ReceiveStoredProcedureName'), func_get_args()); /// must pass &$xxx in php4.x
return $this;
}
/**
* 2016-12-08增加
* @note 字符串转换为日期型的表达式
* @param string $StringTime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function String2DatetimeFormat($StringTime, $Quoted = true)
{
if ($Quoted)
$StringTime = $this->GetIdentifiers($StringTime, true);
return $StringTime;
}
/**
* 2016-12-08增加
* @note 日期转换为字符串型的表达式
* @param string $Datetime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function Datetime2StringFormat($Datetime, $Quoted = true)
{
if ($Quoted)
$Datetime = $this->GetIdentifiers($Datetime, true);
return $Datetime;
}
/**
* 2016-12-08增加
* @note 时间戳转换为日期型的表达式
* @param string $Timestamp 要转换的字段或表达式
* @return string
* @note 应俊
*/
public function Timestamp2DatetimeFormat($Timestamp)
{
return $Timestamp;
}
/**
* 2016-12-08增加
* @note 日期转换为时间戳型的表达式
* @param string $Datetime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function Datetime2TimestampFormat($Datetime, $Quoted = true)
{
if ($Quoted)
$Datetime = $this->GetIdentifiers($Datetime, true);
return $Datetime;
}
/**
* 2016-12-08增加
* @note 浮点转换为字符串型的表达式
* @param string $Float 要转换的字段或表达式
* @return string
* @note 应俊
*/
public function Float2StringFormat($Float)
{
return $Float;
}
/**
* 2016-01-16增加
* @note 获取当前服务器系统时间(或表达式)
* @param bool $IsRaw 是否返回数据库表达式
* @return string
* @note 应俊
*/
public function GetSystemTime($IsRaw = false)
{
return date('Y-m-d H:i:s');
}
/*******************************
* name: GetConnection.
* note: get database helper.
* parameters: nan.
* return: the database helper object.
*******************************
* @return IPDOHelper
*******************************/
public function GetConnection()
{
return $this->Connection;
}
/*******************************
* name: GetCommandInformation.
* note: get sql command string.
* parameters: nan.
* return: sql command and parameter list as array if the method call succeeded, null otherwise.
*******************************
* @return CommandInformation
*******************************/
public function GetCommandInformation()
{
$Return = null;
switch ($this->CommandType)
{
/// select 语句(未实现分页查询)
case COMMANDTYPE_SELECT:
/// 获取基础的查询
$Return = $this->GetSelectCommandInformation();
/// 获取union链接的查询
$Union = $this->GetUnionCommandInformation();
if (($Union instanceof CommandInformation) && !empty($Union->Command))
{
$Return->Command = "({$Return->Command})";
$Return->Merge($Union);
}
break;
/// insert 语句(已支持from子句)
case COMMANDTYPE_INSERT:
$Return = $this->GetInsertCommandInformation();
break;
/// update 语句(不支持into关联语句)
case COMMANDTYPE_UPDATE:
$Return = $this->GetUpdateCommandInformation();
break;
/// delete 语句(不支持into关联语句)
case COMMANDTYPE_DELETE:
$Return = $this->GetDeleteCommandInformation();
break;
/// truncate 语句
case COMMANDTYPE_TRUNC:
$Return = $this->GetTruncCommandInformation();
break;
/// merge into 语句(由子类实现)
case COMMANDTYPE_MERGE:
$Return = $this->GetMergeCommandInformation();
break;
/// call 语句(调用存储过程、函数)
case COMMANDTYPE_CALLSTOREDPROCEDURE:
$Return = $this->GetCallStoredProcedureCommandInformation();
break;
/// 其他语句
default:
$Return = null;
break;
}
if ($Return)
$this->MergeArray($Return->Paramer, $this->OtherParameterList);
return $Return;
}
/*******************************
* name: Request.
* note: request data from database(recordset was returned).
* parameters: sql command, parameter list.
* return: recordset as array if the method call succeeded, null otherwise.
*******************************
* prarm clearmembers
*******************************
* param callable $Callable
* param string $SqlCommand
* param mixed $Parameters...
* @return mixed|null
*******************************/
public function Request(/* $Callable, $SqlCommand, $Parameters, ... */)
{
$Return = null;
$Param = func_get_args();
$Count = func_num_args();
if (0 == $Count)
$Param = array(true);
if (is_bool($Param[0]))
{
if ($Command = $this->GetCommandInformation())
{
/** @noinspection PhpIncludeInspection */
//$Return = $this->Connection->Request($Command->Command, $Command->Paramer);
$Return = call_user_func_array(array(&$this->Connection, 'Request'), array($Command->Command, $Command->Paramer)); /// must pass &$xxx in php4.x
if ($Param[0])
$this->ClearMethod();
}
}
else
$Return = call_user_func_array(array(&$this->Connection, 'Request'), $Param); /// must pass &$xxx in php4.x
return $Return;
}
/*******************************
* name: Execute.
* note: execute command from database(no recordset was returned).
* parameters: sql command, parameter list
* return: true if the method call succeeded, false otherwise.
*******************************
* prarm clearmembers
*******************************
* param string $SqlCommand
* param mixed $Parameters...
* @return bool
*******************************/
public function Execute(/* sqlcommand, parameters, ... */)
{
$Return = null;
$Param = func_get_args();
$Count = func_num_args();
if (0 == $Count)
$Param = array(true);
if (is_bool($Param[0]))
{
if ($Command = $this->GetCommandInformation())
{
/** @noinspection PhpIncludeInspection */
//$Return = $this->Connection->Execute($Command->Command, $Command->Paramer);
$Return = call_user_func_array(array(&$this->Connection, 'Execute'), array($Command->Command, $Command->Paramer)); /// must pass &$xxx in php4.x
if ($Param[0])
$this->ClearMethod();
}
}
else
$Return = call_user_func_array(array(&$this->Connection, 'Execute'), $Param); /// must pass &$xxx in php4.x
return $Return;
}
}
class ORACLECommand extends SQLCommand
{
/*******************************
* name: __construct.
* note: the construct function for class.
* parameters: Connection for PDOHelper.
* return: new object if the method call succeeded, null otherwise.
*******************************
* SQLCommand constructor.
* @param IPDOHelper $Connection
* @throws Exception
*******************************/
public function __construct($Connection)
{
parent::__construct($Connection);
//$this->Connection = new ORACLEHelper();
$this->SetReferenceCharacter('', '');
}
/*******************************
* name: ClearMember.
* note: clear all member for class.
* parameters: nan.
* return: nan.
*******************************
*
*******************************/
public function ClearMethod()
{
parent::ClearMethod();
$this->From('dual');
}
/*******************************
* name: GetSelectCommandInformation.
* note: get the select command string(the page method was support).
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetSelectCommandInformation()
{
$Return = new CommandInformation();
/// 限制记录条数
$MaxRequestCount = intval($this->MaxRequestCount);
$Limit = $MaxRequestCount > 0 ? "(rownum <= {$MaxRequestCount})" : null;
if (0 == $this->PageIndex || 0 == $this->PageSize)
{
$Fields = $this->GetSelectColumns();
/// select 部分
$Return->Command = "select {$Fields->Command}";
$Return->Paramer = $Fields->Paramer;
/// from 部分
if (!empty($this->InternalSourceNames))
{
$Tables = $this->GetInternalSource();
$Return->Command .= " from {$Tables->Command}";
$this->MergeArray($Return->Paramer, $Tables->Paramer);
}
/// join 部分
for ($Index = 0; $Index < $this->JoinCount; $Index++)
{
if (!empty($this->JoinType[$Index]))
{
$Joins = $this->GetJoinSources($Index);
$JoinCondition = $this->GetJoinConditions($Index);
switch ($this->JoinType[$Index])
{
case JOINTYPE_INNER:
{
$Return->Command .= " inner join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_LEFT:
{
$Return->Command .= " left outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_RIGHT:
{
$Return->Command .= " right outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_OUTER:
{
$Return->Command .= " full outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
default:
{
$this->JoinSourceNames[$Index] = array();
$this->JoinSourceAlias[$Index] = array();
$this->JoinConditionColumn[$Index] = array();
$this->JoinConditionValues[$Index] = array();
$this->JoinConditionParams[$Index] = array();
break;
}
}
$this->MergeArray($Return->Paramer, $Joins->Paramer);
$this->MergeArray($Return->Paramer, $JoinCondition->Paramer);
}
}
/// where 部分
if (!empty($this->WhereConditionColumn))
{
$WhereCondition = $this->GetWhereConditions();
$Return->Command .= " where {$WhereCondition->Command}" . (!empty($Limit) ? " and {$Limit}" : '');
$this->MergeArray($Return->Paramer, $WhereCondition->Paramer);
}
elseif (!empty($Limit))
{
$Return->Command .= " where {$Limit}";
}
/// group by 部分
if (!empty($this->GroupFieldList))
{
$GroupFields = $this->GetGroupColumns();
$Return->Command .= " group by {$GroupFields->Command}";
if (!empty($this->HavingConditionColumn))
{
$HavingCondition = $this->GetHavingConditions();
$Return->Command .= " having {$HavingCondition->Command}";
$this->MergeArray($Return->Paramer, $HavingCondition->Paramer);
}
}
/// order by 部分
if (!empty($this->OrderFieldNames))
{
$OrderFields = $this->GetOrderColumns();
$Return->Command .= " order by {$OrderFields->Command}";
}
}
else
{
/// 处理分页处
$Start = (intval(@$this->PageIndex) - 1) * intval(@$this->PageSize) + 1; /// 起始序号
$Stop = intval(@$this->PageIndex) * intval(@$this->PageSize); /// 终止序号
if (0 == $MaxRequestCount || $Stop < $MaxRequestCount)
$Limit = "(rownum <= {$Stop})";
$SelectColumns = $this->GetSelectColumns();
$OrderColumns = $this->GetOrderColumns();
$SortField = $this->GetIdentifiers($this->CreateRandString('nfs_'));
/// select 部分order by放在这里用于开窗函数row_number()使用)
$Return->Command = "select {$SelectColumns->Command}, row_number() over(order by {$OrderColumns->Command}) {$SortField}";
$Return->Paramer = $SelectColumns->Paramer;
/// from 部分
if (!empty($this->InternalSourceNames))
{
$Tables = $this->GetInternalSource();
$Return->Command .= " from {$Tables->Command}";
$this->MergeArray($Return->Paramer, $Tables->Paramer);
}
else
{
$Return->Command .= " from dual";
}
/// join 部分
for ($Index = 0; $Index < $this->JoinCount; $Index++)
{
if (!empty($this->JoinType[$Index]))
{
$Joins = $this->GetJoinSources($Index);
$JoinCondition = $this->GetJoinConditions($Index);
switch ($this->JoinType[$Index])
{
case JOINTYPE_INNER:
{
$Return->Command .= " inner join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_LEFT:
{
$Return->Command .= " left outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_RIGHT:
{
$Return->Command .= " right outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_OUTER:
{
$Return->Command .= " full outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
default:
{
$this->JoinSourceNames[$Index] = array();
$this->JoinSourceAlias[$Index] = array();
$this->JoinConditionColumn[$Index] = array();
$this->JoinConditionValues[$Index] = array();
$this->JoinConditionParams[$Index] = array();
break;
}
}
$this->MergeArray($Return->Paramer, $Joins->Paramer);
$this->MergeArray($Return->Paramer, $JoinCondition->Paramer);
}
}
/// where 部分
if (!empty($this->WhereConditionColumn))
{
$WhereCondition = $this->GetWhereConditions();
$Return->Command .= " where {$WhereCondition->Command}" . (!empty($Limit) ? " and {$Limit}" : '');
$this->MergeArray($Return->Paramer, $WhereCondition->Paramer);
}
elseif (!empty($Limit))
{
$Return->Command .= " where {$Limit}";
}
/// group by 部分
if (!empty($this->GroupFieldList))
{
$GroupFields = $this->GetGroupColumns();
$Return->Command .= " group by {$GroupFields->Command}";
if (!empty($this->HavingConditionColumn))
{
$HavingCondition = $this->GetHavingConditions();
$Return->Command .= " having {$HavingCondition->Command}";
$this->MergeArray($Return->Paramer, $HavingCondition->Paramer);
}
}
$SortTable = $this->GetIdentifiers($this->CreateRandString('nst_'));
$Alias = $this->GetSelectAliaColumns();
$Return->Command = /** @lang text */ "select {$Alias->Command} from ({$Return->Command}) {$SortTable} where ({$SortField} between {$Start} and {$Stop})";
}
return $Return;
}
/*******************************
* name: GetMergeCommandInformation.
* note: get the merge into command string(implemented. but delete not support.).
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetMergeCommandInformation()
{
$Return = new CommandInformation();
/// merge into 表名 别名
/// using 源记录集 别名
/// on (关联关系)
/// when matched then
/// 修改
/// when not matched then
/// 新增
/// 目标表别名
$Target = $this->GetIdentifiers($this->CreateRandString('ndt_'));
/// 源数据别名
$Source = $this->GetIdentifiers($this->CreateRandString('nds_'));
/// 要插入的目标表
$Table = $this->GetInternalSource();
/// 要查询的字段(源数据集的字段)
$SelectColumn = '';
/// 源数据集
$SourceFields = '';
/// 目标数据集
$TargetFields = '';
/// 合并关系
$UpdateFields = '';
/// 关联关系
$JoinCondition = $this->GetMergeJoinConditions();
/// 从关联关系中提取出需要忽略的字段
$Ignore = explode(' ', str_replace('=', ' ', $this->RemoveReferenceCharacter($JoinCondition->Command)));
if ($this->ChangeValues[0] instanceof ISQLCommand)
{
$SelectColumn = call_user_func(array(&$this->ChangeValues[0], 'GetCommandInformation')); /// must pass &$xxx in php4.x
$Fields = call_user_func(array(&$this->ChangeValues[0], 'GetDataFieldAlias')); /// must pass &$xxx in php4.x
for ($Index = 0; $Index < count($this->ChangeFields); $Index++)
{
$SourceField = $Fields[$Index];
$TargetField = $this->ChangeFields[$Index];
$SourceFields .= ", {$Source}.{$SourceField}";
$TargetFields .= ", {$Target}.{$TargetField}";
$UpdateFields .= ", {$Target}.{$TargetField} = {$Source}.{$SourceField}";
}
$SubLen = mb_strlen(', ', USEDCHARSET);
if (!empty($SourceFields))
$SourceFields = mb_substr($SourceFields, $SubLen, mb_strlen($SourceFields, USEDCHARSET), USEDCHARSET);
if (!empty($TargetFields))
$TargetFields = mb_substr($TargetFields, $SubLen, mb_strlen($TargetFields, USEDCHARSET), USEDCHARSET);
if (!empty($UpdateFields))
$UpdateFields = mb_substr($UpdateFields, $SubLen, mb_strlen($UpdateFields, USEDCHARSET), USEDCHARSET);
$SelectParams = $SelectColumn->Paramer;
$SelectColumn = "({$SelectColumn->Command}) {$Source}";
}
else
{
$Fields = $this->ChangeFields;
$Values = $this->ChangeValues;
for ($Index = 0; $Index < count($this->ChangeFields); $Index++)
{
$Field = $Fields[$Index];
$Value = $Values[$Index];
$SelectColumn .= ", {$Value} {$Field}";
$SourceFields .= ", {$Source}.{$Field}";
$TargetFields .= ", {$Target}.{$Field}";
/// 这里要忽略掉关联关系中参照的字段。
//if (!mb_strstr($JoinCondition->Command, $Field, false, USEDCHARSET))
if (!in_array($this->RemoveReferenceCharacter($Field), $Ignore))
$UpdateFields .= ", {$Target}.{$Field} = {$Source}.{$Field}";
}
$SubLen = mb_strlen(', ', USEDCHARSET);
if (!empty($SelectColumn))
$SelectColumn = mb_substr($SelectColumn, $SubLen, mb_strlen($SelectColumn, USEDCHARSET), USEDCHARSET);
if (!empty($SourceFields))
$SourceFields = mb_substr($SourceFields, $SubLen, mb_strlen($SourceFields, USEDCHARSET), USEDCHARSET);
if (!empty($TargetFields))
$TargetFields = mb_substr($TargetFields, $SubLen, mb_strlen($TargetFields, USEDCHARSET), USEDCHARSET);
if (!empty($UpdateFields))
$UpdateFields = mb_substr($UpdateFields, $SubLen, mb_strlen($UpdateFields, USEDCHARSET), USEDCHARSET);
$SelectParams = $this->ChangeParams;
$SelectColumn = "(select {$SelectColumn} from dual) {$Source}";
}
$Return->Command =
"merge into {$Table->Command} {$Target}" . PHP_EOL .
"using {$SelectColumn}" . PHP_EOL .
"on ({$JoinCondition->Command})" . PHP_EOL .
"when matched then" . PHP_EOL .
" update set {$UpdateFields}" . PHP_EOL .
"when not matched then" . PHP_EOL .
" insert" . PHP_EOL .
" ({$TargetFields})" . PHP_EOL .
" values" . PHP_EOL .
" ({$SourceFields})";
$this->MergeArray($Return->Paramer, $Table->Paramer);
$this->MergeArray($Return->Paramer, $SelectParams);
$this->MergeArray($Return->Paramer, $JoinCondition->Paramer);
return $Return;
}
/**
* 2016-12-08增加
* @note 字符串转换为日期型的表达式
* @param string $StringTime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function String2DatetimeFormat($StringTime, $Quoted = true)
{
if ($Quoted)
$StringTime = $this->GetIdentifiers($StringTime, true);
return "(to_date({$StringTime}, 'yyyy-mm-dd hh24:mi:ss'))";
}
/**
* 2016-12-08增加
* @note 日期转换为字符串型的表达式
* @param string $Datetime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function Datetime2StringFormat($Datetime, $Quoted = true)
{
if ($Quoted)
$Datetime = $this->GetIdentifiers($Datetime, true);
return "(to_char({$Datetime}, 'yyyy-mm-dd hh24:mi:ss'))";
}
/**
* 2016-12-08增加
* @note 时间戳转换为日期型的表达式
* @param string $Timestamp 要转换的字段或表达式
* @return string
* @note 应俊
*/
public function Timestamp2DatetimeFormat($Timestamp)
{
return "(to_date('19700101', 'yyyymmdd') + {$Timestamp} / 86400 + to_number(substr(tz_offset(sessiontimezone), 1, 3)) / 24)";
}
/**
* 2016-12-08增加
* @note 日期转换为时间戳型的表达式
* @param string $Datetime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function Datetime2TimestampFormat($Datetime, $Quoted = true)
{
if ($Quoted)
$Datetime = $this->GetIdentifiers($Datetime, true);
return "((to_date({$Datetime}, 'yyyy-mm-dd hh24:mi:ss') - to_date('19700101', 'yyyymmdd')) * 86400 - to_number(substr(tz_offset(sessiontimezone), 1, 3)) * 3600)";
}
/**
* 2016-12-08增加
* @note 浮点转换为字符串型的表达式
* @param string $Float 要转换的字段或表达式
* @return string
* @note 应俊
*/
public function Float2StringFormat($Float)
{
return "(to_char({$Float}, 'fm99999990.00'))";
}
/**
* 2016-01-16增加
* @note 获取当前服务器系统时间(或表达式)
* @param bool $IsRaw 是否返回数据库表达式
* @return string
* @note 应俊
*/
public function GetSystemTime($IsRaw = false)
{
if ($IsRaw)
return 'sysdate';
else
return parent::GetSystemTime($IsRaw);
}
}
class SQLSRVCommand extends SQLCommand
{
/*******************************
* name: __construct.
* note: the construct function for class.
* parameters: Connection for PDOHelper.
* return: new object if the method call succeeded, null otherwise.
*******************************
* SQLCommand constructor.
* @param IPDOHelper $Connection
* @throws Exception
*******************************/
public function __construct($Connection)
{
parent::__construct($Connection);
$this->SetReferenceCharacter('[', ']');
}
/*******************************
* name: GetSelectCommandInformation.
* note: get the select command string(the page method was support).
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetSelectCommandInformation()
{
$Return = new CommandInformation();
/// 限定记录条数
$MaxRequestCount = intval($this->MaxRequestCount);
$Limit = $MaxRequestCount > 0 ? " top {$MaxRequestCount} " : ' ';
if (0 == $this->PageIndex || 0 == $this->PageSize)
{
$Fields = $this->GetSelectColumns();
/// select 部分
$Return->Command = "select{$Limit}{$Fields->Command}";
$Return->Paramer = $Fields->Paramer;
/// from 部分
if (!empty($this->InternalSourceNames))
{
$Tables = $this->GetInternalSource();
$Return->Command .= " from {$Tables->Command}";
$this->MergeArray($Return->Paramer, $Tables->Paramer);
}
/// join 部分
for ($Index = 0; $Index < $this->JoinCount; $Index++)
{
if (!empty($this->JoinType[$Index]))
{
$Joins = $this->GetJoinSources($Index);
$JoinCondition = $this->GetJoinConditions($Index);
switch ($this->JoinType[$Index])
{
case JOINTYPE_INNER:
{
$Return->Command .= " inner join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_LEFT:
{
$Return->Command .= " left outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_RIGHT:
{
$Return->Command .= " right outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_OUTER:
{
$Return->Command .= " full outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
default:
{
$this->JoinSourceNames[$Index] = array();
$this->JoinSourceAlias[$Index] = array();
$this->JoinConditionColumn[$Index] = array();
$this->JoinConditionValues[$Index] = array();
$this->JoinConditionParams[$Index] = array();
break;
}
}
$this->MergeArray($Return->Paramer, $Joins->Paramer);
$this->MergeArray($Return->Paramer, $JoinCondition->Paramer);
}
}
/// where 部分
if (!empty($this->WhereConditionColumn))
{
$WhereCondition = $this->GetWhereConditions();
$Return->Command .= " where {$WhereCondition->Command}";
$this->MergeArray($Return->Paramer, $WhereCondition->Paramer);
}
/// group by 和 having 部分
if (!empty($this->GroupFieldList))
{
$GroupFields = $this->GetGroupColumns();
$Return->Command .= " group by {$GroupFields->Command}";
if (!empty($this->HavingConditionColumn))
{
$HavingCondition = $this->GetHavingConditions();
$Return->Command .= " having {$HavingCondition->Command}";
$this->MergeArray($Return->Paramer, $HavingCondition->Paramer);
}
}
/// order 部分
if (!empty($this->OrderFieldNames))
{
$OrderFields = $this->GetOrderColumns();
$Return->Command .= " order by {$OrderFields->Command}";
}
}
else
{
/// 处理分页处
$Start = (intval(@$this->PageIndex) - 1) * intval(@$this->PageSize) + 1; /// 起始序号
$Stop = intval(@$this->PageIndex) * intval(@$this->PageSize); /// 终止序号
if (0 == $MaxRequestCount || $Stop < $MaxRequestCount)
$Limit = " top {$Stop} ";
$SelectColumns = $this->GetSelectColumns();
$OrderColumns = $this->GetOrderColumns();
$SortField = $this->GetIdentifiers($this->CreateRandString('nfs_'));
/// select 部分order排序放在这里用于row_number函数使用
$Return->Command = "select{$Limit}{$SelectColumns->Command}, row_number() over(order by {$OrderColumns->Command}) {$SortField}";
$Return->Paramer = $SelectColumns->Paramer;
/// from 部分
if (!empty($this->InternalSourceNames))
{
$Tables = $this->GetInternalSource();
$Return->Command .= " from {$Tables->Command}";
$this->MergeArray($Return->Paramer, $Tables->Paramer);
}
/// join 部分
for ($Index = 0; $Index < $this->JoinCount; $Index++)
{
if (!empty($this->JoinType[$Index]))
{
$Joins = $this->GetJoinSources($Index);
$JoinCondition = $this->GetJoinConditions($Index);
switch ($this->JoinType[$Index])
{
case JOINTYPE_INNER:
{
$Return->Command .= " inner join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_LEFT:
{
$Return->Command .= " left outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_RIGHT:
{
$Return->Command .= " right outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_OUTER:
{
$Return->Command .= " full outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
default:
{
$this->JoinSourceNames[$Index] = array();
$this->JoinSourceAlias[$Index] = array();
$this->JoinConditionColumn[$Index] = array();
$this->JoinConditionValues[$Index] = array();
$this->JoinConditionParams[$Index] = array();
break;
}
}
$this->MergeArray($Return->Paramer, $Joins->Paramer);
$this->MergeArray($Return->Paramer, $JoinCondition->Paramer);
}
}
/// where 部分
if (!empty($this->WhereConditionColumn))
{
$WhereCondition = $this->GetWhereConditions();
$Return->Command .= " where {$WhereCondition->Command}";
$this->MergeArray($Return->Paramer, $WhereCondition->Paramer);
}
/// group by 和 having 部分
if (!empty($this->GroupFieldList))
{
$GroupFields = $this->GetGroupColumns();
$Return->Command .= " group by {$GroupFields->Command}";
if (!empty($this->HavingConditionColumn))
{
$HavingCondition = $this->GetHavingConditions();
$Return->Command .= " having {$HavingCondition->Command}";
$this->MergeArray($Return->Paramer, $HavingCondition->Paramer);
}
}
$SortTable = $this->GetIdentifiers($this->CreateRandString('nst_'));
$Alias = $this->GetSelectAliaColumns();
$Return->Command = /** @lang text */ "select {$Alias->Command} from ({$Return->Command}) {$SortTable} where ({$SortField} between {$Start} and {$Stop})";
}
return $Return;
}
/*******************************
* name: GetUpdateCommandInformation.
* note: get the update command string(the join method was support).
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetUpdateCommandInformation()
{
$Return = new CommandInformation();
$Tables = $this->GetInternalSource();
$Return->Command = "update {$Tables->Command}";
$Return->Paramer = $Tables->Paramer;
$Fields = $this->GetChangeAllColumns();
$Return->Command .= " set {$Fields->Command}";
$this->MergeArray($Return->Paramer, $Fields->Paramer);
if (!empty($this->InternalSourceNames))
{
$Tables = $this->GetInternalSource();
$Return->Command .= " from {$Tables->Command}";
$this->MergeArray($Return->Paramer, $Tables->Paramer);
}
for ($Index = 0; $Index < $this->JoinCount; $Index++)
{
if (!empty($this->JoinType[$Index]))
{
$Joins = $this->GetJoinSources($Index);
$JoinCondition = $this->GetJoinConditions($Index);
switch ($this->JoinType[$Index])
{
case JOINTYPE_INNER:
{
$Return->Command .= " inner join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_LEFT:
{
$Return->Command .= " left outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_RIGHT:
{
$Return->Command .= " right outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_OUTER:
{
$Return->Command .= " full outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
default:
{
$this->JoinSourceNames[$Index] = array();
$this->JoinSourceAlias[$Index] = array();
$this->JoinConditionColumn[$Index] = array();
$this->JoinConditionValues[$Index] = array();
$this->JoinConditionParams[$Index] = array();
break;
}
}
$this->MergeArray($Return->Paramer, $Joins->Paramer);
$this->MergeArray($Return->Paramer, $JoinCondition->Paramer);
}
}
if (!empty($this->WhereConditionColumn))
{
$WhereCondition = $this->GetWhereConditions();
$Return->Command .= " where {$WhereCondition->Command}";
$this->MergeArray($Return->Paramer, $WhereCondition->Paramer);
}
return $Return;
}
/*******************************
* name: GetDeleteCommandInformation.
* note: get the delete command string(the join method was support).
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetDeleteCommandInformation()
{
$Return = new CommandInformation();
$Tables = $this->GetInternalSource();
$Return->Command = /** @lang text */ "delete from {$Tables->Command}";
$Return->Paramer = $Tables->Paramer;
for ($Index = 0; $Index < $this->JoinCount; $Index++)
{
if (!empty($this->JoinType[$Index]))
{
$Joins = $this->GetJoinSources($Index);
$JoinCondition = $this->GetJoinConditions($Index);
switch ($this->JoinType[$Index])
{
case JOINTYPE_INNER:
{
$Return->Command .= " inner join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_LEFT:
{
$Return->Command .= " left outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_RIGHT:
{
$Return->Command .= " right outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
case JOINTYPE_OUTER:
{
$Return->Command .= " full outer join {$Joins->Command} on {$JoinCondition->Command}";
break;
}
default:
{
$this->JoinSourceNames[$Index] = array();
$this->JoinSourceAlias[$Index] = array();
$this->JoinConditionColumn[$Index] = array();
$this->JoinConditionValues[$Index] = array();
$this->JoinConditionParams[$Index] = array();
break;
}
}
$this->MergeArray($Return->Paramer, $Joins->Paramer);
$this->MergeArray($Return->Paramer, $JoinCondition->Paramer);
}
}
if (!empty($this->WhereConditionColumn))
{
$WhereCondition = $this->GetWhereConditions();
$Return->Command .= " where {$WhereCondition->Command}";
$this->MergeArray($Return->Paramer, $WhereCondition->Paramer);
}
return $Return;
}
/*******************************
* name: GetMergeCommandInformation(implemented. but delete not support.).
* note: get the merge into command string.
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetMergeCommandInformation()
{
$Return = new CommandInformation();
/// merge into 表名 别名
/// using 源记录集 别名
/// on (关联关系)
/// when matched then
/// 修改
/// when not matched then
/// 新增
/// 目标表别名
$Target = $this->GetIdentifiers($this->CreateRandString('ndt_'));
/// 源数据别名
$Source = $this->GetIdentifiers($this->CreateRandString('nds_'));
/// 要插入的目标表
$Table = $this->GetInternalSource();
/// 要查询的字段(源数据集的字段)
$SelectColumn = '';
/// 源数据集
$SourceFields = '';
/// 目标数据集
$TargetFields = '';
/// 合并关系
$UpdateFields = '';
/// 关联关系
$JoinCondition = $this->GetMergeJoinConditions();
/// 从关联关系中提取出需要忽略的字段
$Ignore = explode(' ', str_replace('=', ' ', $this->RemoveReferenceCharacter($JoinCondition->Command)));
if ($this->ChangeValues[0] instanceof ISQLCommand)
{
$SelectColumn = call_user_func(array(&$this->ChangeValues[0], 'GetCommandInformation')); /// must pass &$xxx in php4.x
$Fields = call_user_func(array(&$this->ChangeValues[0], 'GetDataFieldAlias')); /// must pass &$xxx in php4.x
for ($Index = 0; $Index < count($this->ChangeFields); $Index++)
{
$SourceField = $Fields[$Index];
$TargetField = $this->ChangeFields[$Index];
$SourceFields .= ", {$Source}.{$SourceField}";
$TargetFields .= ", {$Target}.{$TargetField}";
$UpdateFields .= ", {$Target}.{$TargetField} = {$Source}.{$SourceField}";
}
$SubLen = mb_strlen(', ', USEDCHARSET);
if (!empty($SourceFields))
$SourceFields = mb_substr($SourceFields, $SubLen, mb_strlen($SourceFields, USEDCHARSET), USEDCHARSET);
if (!empty($TargetFields))
$TargetFields = mb_substr($TargetFields, $SubLen, mb_strlen($TargetFields, USEDCHARSET), USEDCHARSET);
if (!empty($UpdateFields))
$UpdateFields = mb_substr($UpdateFields, $SubLen, mb_strlen($UpdateFields, USEDCHARSET), USEDCHARSET);
$SelectParams = $SelectColumn->Paramer;
$SelectColumn = "({$SelectColumn->Command}) {$Source}";
}
else
{
$Fields = $this->ChangeFields;
$Values = $this->ChangeValues;
for ($Index = 0; $Index < count($this->ChangeFields); $Index++)
{
$Field = $Fields[$Index];
$Value = $Values[$Index];
$SelectColumn .= ", {$Value} {$Field}";
$SourceFields .= ", {$Source}.{$Field}";
$TargetFields .= ", {$Target}.{$Field}";
/// 这里要忽略掉关联关系中参照的字段。
//if (!mb_strstr($JoinCondition->Command, $Field, false, USEDCHARSET))
if (!in_array($this->RemoveReferenceCharacter($Field), $Ignore))
$UpdateFields .= ", {$Target}.{$Field} = {$Source}.{$Field}";
}
$SubLen = mb_strlen(', ', USEDCHARSET);
if (!empty($SelectColumn))
$SelectColumn = mb_substr($SelectColumn, $SubLen, mb_strlen($SelectColumn, USEDCHARSET), USEDCHARSET);
if (!empty($SourceFields))
$SourceFields = mb_substr($SourceFields, $SubLen, mb_strlen($SourceFields, USEDCHARSET), USEDCHARSET);
if (!empty($TargetFields))
$TargetFields = mb_substr($TargetFields, $SubLen, mb_strlen($TargetFields, USEDCHARSET), USEDCHARSET);
if (!empty($UpdateFields))
$UpdateFields = mb_substr($UpdateFields, $SubLen, mb_strlen($UpdateFields, USEDCHARSET), USEDCHARSET);
$SelectParams = $this->ChangeParams;
$SelectColumn = "(select {$SelectColumn}) {$Source}";
}
$Return->Command =
"merge into {$Table->Command} {$Target}" . PHP_EOL .
"using {$SelectColumn}" . PHP_EOL .
"on ({$JoinCondition->Command})" . PHP_EOL .
"when matched then" . PHP_EOL .
" update set {$UpdateFields}" . PHP_EOL .
"when not matched then" . PHP_EOL .
" insert" . PHP_EOL .
" ({$TargetFields})" . PHP_EOL .
" values" . PHP_EOL .
" ({$SourceFields})";
$this->MergeArray($Return->Paramer, $Table->Paramer);
$this->MergeArray($Return->Paramer, $SelectParams);
$this->MergeArray($Return->Paramer, $JoinCondition->Paramer);
return $Return;
}
/**
* 2016-12-08增加
* @note 字符串转换为日期型的表达式
* @param string $StringTime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function String2DatetimeFormat($StringTime, $Quoted = true)
{
if ($Quoted)
$StringTime = $this->GetIdentifiers($StringTime, true);
return "(convert(datetime, {$StringTime}, 120))";
}
/**
* 2016-12-08增加
* @note 日期转换为字符串型的表达式
* @param string $Datetime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function Datetime2StringFormat($Datetime, $Quoted = true)
{
if ($Quoted)
$Datetime = $this->GetIdentifiers($Datetime, true);
return "(convert(varchar, {$Datetime}, 120))";
}
/**
* 2016-12-08增加
* @note 时间戳转换为日期型的表达式
* @param string $Timestamp 要转换的字段或表达式
* @return string
* @note 应俊
*/
public function Timestamp2DatetimeFormat($Timestamp)
{
return "(dateadd(S, {$Timestamp} + 8 * 3600, '1970-01-01 00:00:00'))";
}
/**
* 2016-12-08增加
* @note 日期转换为时间戳型的表达式
* @param string $Datetime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function Datetime2TimestampFormat($Datetime, $Quoted = true)
{
if ($Quoted)
$Datetime = $this->GetIdentifiers($Datetime, true);
return "(datediff(S, '1970-01-01 00:00:00', {$Datetime}) - 8 * 3600)";
}
/**
* 2016-12-08增加
* @note 浮点转换为字符串型的表达式
* @param string $Float 要转换的字段或表达式
* @return string
* @note 应俊
*/
public function Float2StringFormat($Float)
{
return "(cast(convert(decimal(18, 2), {$Float}) as char))";
}
/**
* 2016-01-16增加
* @note 获取当前服务器系统时间(或表达式)
* @param bool $IsRaw 是否返回数据库表达式
* @return string
* @note 应俊
*/
public function GetSystemTime($IsRaw = false)
{
if ($IsRaw)
return 'getdate()';
else
return parent::GetSystemTime($IsRaw);
}
}
class MYSQLCommand extends SQLCommand
{
/*******************************
* name: __construct.
* note: the construct function for class.
* parameters: Connection for PDOHelper.
* return: new object if the method call succeeded, null otherwise.
*******************************
* SQLCommand constructor.
* @param IPDOHelper $Connection
* @throws Exception
*******************************/
public function __construct($Connection)
{
parent::__construct($Connection);
//$this->Connection = new ORACLEHelper();
$this->SetReferenceCharacter('`', '`');
}
/*******************************
* name: GetSelectCommandInformation.
* note: get the select command string(the page method was support).
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetSelectCommandInformation()
{
$Return = parent::GetSelectCommandInformation();
if (0 != $this->PageIndex && 0 != $this->PageSize)
{
/// 处理分页处
$Offset = (intval(@$this->PageIndex) - 1) * intval(@$this->PageSize); /// 起始偏移
$PageSize = intval(@$this->PageSize); /// 记录条目
$MaxRequestCount = intval($this->MaxRequestCount);
if ($MaxRequestCount > 0 && $PageSize > intval($this->MaxRequestCount))
$PageSize = $this->MaxRequestCount;
$Return->Command .= " limit {$Offset}, {$PageSize}";
}
// $Return = new CommandInformation();
// /// 不分页
// if (0 == $this->PageIndex || 0 == $this->PageSize)
// {
// $Return = parent::GetSelectCommandInformation();
// }
// else
// {
// /// 处理分页处
// $Start = (intval(@$this->PageIndex) - 1) * intval(@$this->PageSize) + 1; /// 起始序号
// $Stop = intval(@$this->PageIndex) * intval(@$this->PageSize); /// 终止序号
// if ($Stop < intval($this->MaxRequestCount))
// $Limit = $Stop;
// else
// $Limit = $this->MaxRequestCount;
//
// $SelectColumns = $this->GetSelectColumns();
// $SortField = $this->GetIdentifiers($this->CreateRandString('nfs_'));
// $SortTable = $this->GetIdentifiers($this->CreateRandString('nst_'));
//
// /// select 部分(用全局变量@Index模拟row_number() over()函数来实现分页)
// $Return->Command = "select {$SelectColumns->Command}, @Index := @Index + 1 {$SortField}";
// $Return->Paramer = $SelectColumns->Paramer;
//
// /// from 部分
// if (!empty($this->InternalSourceNames))
// {
// $Tables = $this->GetInternalSource();
// $Return->Command .= " from {$Tables->Command}, (select @Index := 0) {$SortTable}";
// $this->MergeArray($Return->Paramer, $Tables->Paramer);
// }
//
// /// join 部分
// for ($Index = 0; $Index < $this->JoinCount; $Index++)
// {
// if (!empty($this->JoinType[$Index]))
// {
// $Joins = $this->GetJoinSources($Index);
// $JoinCondition = $this->GetJoinConditions($Index);
//
// switch ($this->JoinType[$Index])
// {
// case JOINTYPE_INNER:
// {
// $Return->Command .= " inner join {$Joins->Command} on {$JoinCondition->Command}";
// break;
// }
// case JOINTYPE_LEFT:
// {
// $Return->Command .= " left outer join {$Joins->Command} on {$JoinCondition->Command}";
// break;
// }
// case JOINTYPE_RIGHT:
// {
// $Return->Command .= " right outer join {$Joins->Command} on {$JoinCondition->Command}";
// break;
// }
// case JOINTYPE_OUTER:
// {
// $Return->Command .= " full outer join {$Joins->Command} on {$JoinCondition->Command}";
// break;
// }
// default:
// {
// $this->JoinSourceNames[$Index] = array();
// $this->JoinSourceAlias[$Index] = array();
// $this->JoinConditionColumn[$Index] = array();
// $this->JoinConditionValues[$Index] = array();
// $this->JoinConditionParams[$Index] = array();
// break;
// }
//
// }
//
// $this->MergeArray($Return->Paramer, $Joins->Paramer);
// $this->MergeArray($Return->Paramer, $JoinCondition->Paramer);
// }
// }
//
// /// where 部分
// if (!empty($this->WhereConditionColumn))
// {
// $WhereCondition = $this->GetWhereConditions();
//
// $Return->Command .= " where {$WhereCondition->Command}";
// $this->MergeArray($Return->Paramer, $WhereCondition->Paramer);
// }
//
// /// group by 和 having 部分
// if (!empty($this->GroupFieldList))
// {
// $GroupFields = $this->GetGroupColumns();
// $Return->Command .= " group by {$GroupFields->Command}";
// if (!empty($this->HavingConditionColumn))
// {
// $HavingCondition = $this->GetHavingConditions();
// $Return->Command .= " having {$HavingCondition->Command}";
// $this->MergeArray($Return->Paramer, $HavingCondition->Paramer);
// }
// }
//
// /// order 部分
// if (!empty($this->OrderFieldNames))
// {
// $OrderFields = $this->GetOrderColumns();
// $Return->Command .= " order by {$OrderFields->Command}";
// }
//
// $Alias = $this->GetSelectAliaColumns();
// $Return->Command = /** @lang text */ "select {$Alias->Command} from ({$Return->Command} limit {$Limit}) {$SortTable} where ({$SortField} between {$Start} and {$Stop})";
// }
return $Return;
}
/*******************************
* name: GetMergeCommandInformation.
* note: get the merge into command string(implemented. but delete not support.).
* parameters: none.
* return: object of CommandInformation.
*******************************
* @return CommandInformation
*******************************/
protected function GetMergeCommandInformation()
{
$Return = new CommandInformation();
$Tables = $this->GetInternalSource();
$Return->Command = /** @lang text */ "replace into {$Tables->Command}";
$Return->Paramer = $Tables->Paramer;
$Fields = $this->GetChangeFields();
$Values = $this->GetChangeValues();
/// 如果包含select表示则表示是一个子查询, 那么就不用values包裹了.
if (mb_stristr($Values->Command, 'select', false, USEDCHARSET))
$Return->Command .= " ({$Fields->Command}) {$Values->Command}";
else
$Return->Command .= " ({$Fields->Command}) values ({$Values->Command})";
$this->MergeArray($Return->Paramer, $Fields->Paramer);
$this->MergeArray($Return->Paramer, $Values->Paramer);
return $Return;
}
/**
* 2016-12-08增加
* @note 字符串转换为日期型的表达式
* @param string $StringTime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function String2DatetimeFormat($StringTime, $Quoted = true)
{
if ($Quoted)
$StringTime = $this->GetIdentifiers($StringTime, true);
return "(STR_TO_DATE({$StringTime}, '%Y-%m-%d %H:%i:%s'))";
}
/**
* 2016-12-08增加
* @note 日期转换为字符串型的表达式
* @param string $Datetime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function Datetime2StringFormat($Datetime, $Quoted = true)
{
if ($Quoted)
$Datetime = $this->GetIdentifiers($Datetime, true);
return "(date_format({$Datetime}, '%Y-%m-%d %H:%i:%s'))";
}
/**
* 2016-12-08增加
* @note 时间戳转换为日期型的表达式
* @param string $Timestamp 要转换的字段或表达式
* @return string
* @note 应俊
*/
public function Timestamp2DatetimeFormat($Timestamp)
{
return "(from_unixtime({$Timestamp}))";
}
/**
* 2016-12-08增加
* @note 日期转换为时间戳型的表达式
* @param string $Datetime 要转换的字段或表达式
* @param bool $Quoted 是否需要处理(增加)引号
* @return string
* @note 应俊
*/
public function Datetime2TimestampFormat($Datetime, $Quoted = true)
{
if ($Quoted)
$Datetime = $this->GetIdentifiers($Datetime, true);
return "(unix_timestamp({$Datetime}))";
}
/**
* 2016-12-08增加
* @note 浮点转换为字符串型的表达式
* @param string $Float 要转换的字段或表达式
* @return string
* @note 应俊
*/
public function Float2StringFormat($Float)
{
return "(cast(convert({$Float}, decimal(18, 2)) as char))";
}
/**
* 2016-01-16增加
* @note 获取当前服务器系统时间(或表达式)
* @param bool $IsRaw 是否返回数据库表达式
* @return string
* @note 应俊
*/
public function GetSystemTime($IsRaw = false)
{
if ($IsRaw)
return 'now()';
else
return parent::GetSystemTime($IsRaw);
}
}
class Delegator
{
/**
* @var mixed
*/
protected $Helper;
/**
* @return mixed
*/
public function GetHelper()
{
return $this->Helper;
}
/**
* @param mixed $Helper
*/
public function SetHelper($Helper)
{
$this->Helper = $Helper;
}
/**
* @param string $Name
* @param mixed $Args
* @return mixed
* @throws Exception
*/
public function __call($Name, $Args)
{
$Reflect = new ReflectionClass($this->Helper);
if ($Method = $Reflect->getMethod($Name))
{
if ($Method->isPublic() && !$Method->isAbstract())
return $Method->invokeArgs($this->Helper, $Args);
elseif ($Method->isPrivate())
throw new Exception('can not call private method: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
elseif ($Method->isProtected())
throw new Exception('can not call protected method: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
elseif ($Method->isAbstract())
throw new Exception('can not call abstract method: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
else
throw new Exception('can not call unknown method: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
}
else
throw new Exception('undefined method: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
}
/**
* @param string $Name
* @return mixed
* @throws Exception
*/
public function __get($Name)
{
$Reflect = new ReflectionClass($this->Helper);
if ($Property = $Reflect->getProperty($Name))
{
if ($Property->isPublic())
return $Property->getValue($this->Helper);
elseif ($Property->isPrivate())
throw new Exception('can not access private property: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
elseif ($Property->isProtected())
throw new Exception('can not access protected property: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
else
throw new Exception('can not access unknown property: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
}
else
throw new Exception('undefined property: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
}
/**
* @param string $Name
* @param mixed $Value
* @throws Exception
*/
public function __set($Name, $Value)
{
$Reflect = new ReflectionClass($this->Helper);
if ($Property = $Reflect->GetProperty($Name))
{
if ($Property->IsPublic())
//return $Property->SetValue($this->Helper, $Value);
$Property->SetValue($this->Helper, $Value);
elseif ($Property->IsPrivate())
throw new Exception('can not access private property: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
elseif ($Property->IsProtected())
throw new Exception('can not access protected property: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
else
throw new Exception('can not access unknown property: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
}
else
throw new Exception('undefined property: ' . get_class($this->Helper) . '::' . $Name . ' in ' . __FILE__ . ' on line ' . __LINE__);
}
}
/*******************************
* name: PDODelegator.
* note: delegator of database helper.
******************************/
class PDODelegator extends Delegator
{
/**
* PDODelegator constructor.
* @param string $Type
* @throws Exception
*/
public function __construct($Type)
{
switch ($Type)
{
case DATABASE_TYPE_ORACLE:
$this->Helper = new ORACLEHelper();
break;
case DATABASE_TYPE_SQLSRV:
$this->Helper = new SQLSRVHelper();
break;
case DATABASE_TYPE_MYSQL:
$this->Helper = new MYSQLHelper();
break;
default:
$this->Helper = null;
throw new Exception('unknown database type: ' . $Type . ' in ' . __FILE__ . ' on line ' . __LINE__);
break;
}
}
/**
* @return IPDOHelper
*/
public function GetHelper()
{
return parent::GetHelper(); // TODO: Change the autogenerated stub
}
}
class CommandDelegator extends Delegator
{
/**
* CommandDelegator constructor.
* @param IPDOHelper|PDODelegator $Connection
* @throws Exception
*/
public function __construct($Connection)
{
if ($Connection instanceof PDODelegator)
$Connection = $Connection->GetHelper();
elseif (!($Connection instanceof IPDOHelper))
{
switch ($Type = gettype($Connection))
{
case 'object':
case 'interface':
$Message = 'Incompatible types: IPDOHelper or PDODelegator and ' . get_class($Connection) . ' with parameter $Connection!';
break;
default:
$Message = 'Incompatible types: IPDOHelper or PDODelegator and ' . $Type . ' with parameter $Connection!';
break;
}
throw new Exception($Message);
}
switch ($Connection->GetConnectType())
{
case DATABASE_TYPE_ORACLE:
$this->Helper = new ORACLECommand($Connection);
break;
case DATABASE_TYPE_SQLSRV:
$this->Helper = new SQLSRVCommand($Connection);
break;
case DATABASE_TYPE_MYSQL:
$this->Helper = new MYSQLCommand($Connection);
break;
default:
$this->Helper = null;
throw new Exception('unkonwn database type: ' . $Connection->GetConnectType() . '!');
break;
}
}
/**
* @return ISQLCommand
*/
public function GetHelper()
{
return parent::GetHelper(); // TODO: Change the autogenerated stub
}
}
function ReplaceValue($str)
{
$ret = str_ireplace("'", '', $str);
$ret = str_ireplace('"', '', $ret);
$ret = str_ireplace(',', '', $ret);
$ret = str_ireplace('.', '。', $ret);
$ret = str_ireplace(':', '', $ret);
$ret = str_ireplace(';', '', $ret);
$ret = str_ireplace('(', '', $ret);
$ret = str_ireplace(')', '', $ret);
$ret = str_ireplace('[', '【', $ret);
$ret = str_ireplace(']', '】', $ret);
$ret = str_ireplace('{', '〖', $ret);
$ret = str_ireplace('}', '〗', $ret);
$ret = str_ireplace("\r", ' ', $ret);
$ret = str_ireplace("\n", ' ', $ret);
$ret = str_ireplace("\t", ' ', $ret);
$ret = str_ireplace(' ', ' ', $ret);
$ret = str_ireplace('\\', '\\\\', $ret);
return $ret;
}
/*******************************
* name: UnicodeCodeToUnicodeString.
* note: convert unicodecode to string(\uxxxx-->xx).
* parameters: string
* return: unicodestring if the function call succeeded, null otherwise.
*******************************
* @param string $String
* @return string
*******************************/
function UnicodeCodeToUnicodeString($String)
{
try
{
if (function_exists('preg_replace_callback'))
return preg_replace_callback('#\\\u([0-9a-f]{4})#i', function ($r) { return iconv('UCS-2BE', 'UTF-8', pack('H4', $r[1])); }, $String);
elseif (function_exists('preg_replace'))
return preg_replace('#\\\u([0-9a-f]{4})#ie', 'iconv(\'UCS-2BE\', \'UTF-8\', pack(\'H4\', \'\\1\'))', $String);
else
return $String;
}
catch (Exception $Exception)
{
return null;
}
}
/*******************************
* name: JsonObjectToJsonString.
* note: convert object to string on json_encode function.
* parameters: mixed object
* return: return value for json_encode.
*******************************
* @param mixed $Object
* @return string
*******************************/
function JsonObjectToJsonString($Object)
{
/// http://php.net/manual/zh/function.json-encode.php
if (defined('JSON_UNESCAPED_UNICODE'))
return json_encode($Object, JSON_UNESCAPED_UNICODE);
else
return UnicodeCodeToUnicodeString(json_encode($Object));
}
/*******************************
* name: JsonStringToJsonObject.
* note: convert string to object on json_decode function.
* parameters: string
* return: object if the function call succeeded, null otherwise.
*******************************
* @param string $String
* @return mixed
*******************************/
function JsonStringToJsonObject($String)
{
/// http://php.net/manual/zh/function.json-decode.php
if (!$Object = json_decode($String))
{
//$Object = json_decode(addslashes($String));
//stripslashes
/** @noinspection PhpIncludeInspection */
///$String = preg_replace_callback('/' . preg_quote('\\') . '/', function ($char){return '\\\\';}, $String);
$String = str_replace('\\', '\\\\', $String);
$Object = json_decode($String);
if (!$Object)
$Object = $String;
}
return $Object;
}
function XmlObjectToXmlString($Object)
{
if (is_object($Object))
$Xml = (array)$Object;
else
$Xml = $Object;
if (!is_array($Xml))
return strval($Xml);
elseif (Count($Xml) <= 0)
return '';
$Result = '<xml>';
foreach ($Xml as $Key => $Value)
{
if (is_numeric($Value))
{
$Result .= "<{$Key}>{$Value}</{$Key}>";
}
elseif (is_object($Value) || is_array($Value))
{
$Value = XmlObjectToXmlString($Value);
$Result .= "<{$Key}><![CDATA[{$Value}]]></{$Key}>";
}
else
{
$Result .= "<{$Key}><![CDATA[{$Value}]]></{$Key}>";
}
}
$Result .= '</xml>';
return $Result;
}
function XmlStringToXmlObject($String)
{
// 将XML转为array
// 禁止引用外部xml实体
libxml_disable_entity_loader(true);
$Result = @simplexml_load_string($String, 'SimpleXMLElement', LIBXML_NOCDATA);
return $Result ? $Result : $String;
}
function ObjectToLinkString($Object)
{
if (is_object($Object))
$Object = (array)$Object;
if (!is_array($Object))
return strval($Object);
$Result = array();
foreach($Object as $Name => $Value)
{
if (is_object($Value) || is_array($Value))
$Value = JsonObjectToJsonString($Value);
array_push($Result, "{$Name}={$Value}");
}
return implode('&', $Result);
}
function LinkStringToObject($String)
{
$Params = explode('&', $String);
$Result = array();
foreach ($Params as $Param)
{
$Param = explode('=', $Param);
$Result[$Param[0]] = $Param[1];
}
return $Result;
}
/*******************************
* name: Characet.
* note: convert string code page.
* parameters: string, charset
* return: string if the function call succeeded, null otherwise.
*******************************
* @param string $String
* @param string $Charset
* @return string
*******************************/
function Characet($String, $Charset = USEDCHARSET)
{
if (!empty ($String))
{
$Encoding = mb_detect_encoding($String, array('ASCII', 'UTF-8', 'GBK', 'GB2312', 'LATIN1', 'BIG5',));
if (0 != strcasecmp($Encoding, $Charset))
$String = mb_convert_encoding($String, $Charset, $Encoding);
}
return $String;
}
/*
spl_autoload_register(
function ($class)
{
if (strcasecmp('PDOHelper', $class) == 0 ||
strcasecmp('ORACLEHelper', $class) == 0 ||
strcasecmp('SQLSRVHelper', $class) == 0 ||
strcasecmp('MYSQLHelper', $class) == 0)
require_once($_SERVER['PHP_SELF']);
}
);
/// html header.
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
*/
if (!(function_exists('call_user_func') && function_exists('call_user_func_array')))
throw new Exception('Don\'t support the current version. The code requires PHP 5.0 or later.');
/*
if (!function_exists('call_user_func_array'))
{
function call_user_func_array($Callable, array $Parameters)
{
/// 第一个参数如果不是合法的回调对象则直接返回false;
if (!is_callable($Callable))
return null;
/// 回调对象,定义成全局对象是为了在字符串代码中可以截获这个对象。
global $__global__method__callable__owner__;
/// 回调时需要的参数
global $__global__method__parameter__;
$__global__method__parameter__ = $Parameters;
$Parameter = '';
foreach ($Parameters as $Key => $Value)
$Parameter .= '$__global__method__parameter__[' . $Key . '], ';
$len = mb_strlen($Parameter);
$sublen = mb_strlen(', ');
if ($len > 0)
$Parameter = mb_substr($Parameter, 0, $len - $sublen);
/// 要执行的代码
$Code = '';
/// 如果回调对象是一个数组并且数组元素不少于2个元素则表示是调用类中的方法
/// 其中:
/// 第一个元素是宿主,宿主可以是类或实例。
/// 第二个元素是需要调用的方法名。
if (is_array($Callable) && count($Callable) >= 2)
{
$__global__method__callable__owner__ = $Callable[0];
if (is_object($Callable[0])) /// 对象表示是一个实例。
$Code =
'global $__global__method__callable__owner__;' . PHP_EOL .
'global $__global__method__parameter__;' . PHP_EOL .
'return $__global__method__callable__owner__->' . "{$Callable[1]}({$Parameter});";
else /// 其他类型表示是一个类。
$Code =
'global $__global__method__parameter__;' . PHP_EOL .
"return {$Callable[0]}::{$Callable[1]}({$Parameter});";
}
else /// 非数组表示调用静态方法
$Code =
'global $__global__method__parameter__;' . PHP_EOL .
"return {$Callable}({$Parameter})";
///echo $Code;
return eval($Code);
}
}
if (!function_exists('call_user_func'))
{
function call_user_func($function, $Parameter = null, $_ = null)
{
$Parameters = func_get_args();
array_shift($Parameters);
return call_user_func_array($function, $Parameters);
}
}
*/
///** @var IPDOHelper $db */
//$db = new PDODelegator(DATABASE_TYPE_MYSQL);
//$db->Connect('120.76.97.225', 3309, 'game_db', 'root', 'root_root');
//$callable = function($Record)
//{
// echo $Record->NickName, '<br>';
// return true;
//};
//$db->Request($callable, 'select play_playerid id, play_nickname NickName from player where 1 = ?', 2);