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 FALSE 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 FALSE 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 = ''; foreach ($Xml as $Key => $Value) { if (is_numeric($Value)) { $Result .= "<{$Key}>{$Value}"; } elseif (is_object($Value) || is_array($Value)) { $Value = XmlObjectToXmlString($Value); $Result .= "<{$Key}>"; } else { $Result .= "<{$Key}>"; } } $Result .= ''; 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, '
'; // return true; //}; //$db->Request($callable, 'select play_playerid id, play_nickname NickName from player where 1 = ?', 2);