summaryrefslogtreecommitdiff
path: root/vendor/adodb/adodb-php/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/adodb/adodb-php/drivers')
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-access.inc.php88
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-ado.inc.php660
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-ado5.inc.php708
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-ado_access.inc.php50
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-ado_mssql.inc.php150
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-ads.inc.php776
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-borland_ibase.inc.php89
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-csv.inc.php209
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-db2.inc.php843
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-db2oci.inc.php226
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-db2ora.inc.php86
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-fbsql.inc.php267
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-firebird.inc.php73
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-ibase.inc.php918
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-informix.inc.php41
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-informix72.inc.php525
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-ldap.inc.php428
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-mssql.inc.php1194
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-mssql_n.inc.php250
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-mssqlnative.inc.php1200
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-mssqlpo.inc.php58
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-mysql.inc.php893
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-mysqli.inc.php1295
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-mysqlpo.inc.php128
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-mysqlt.inc.php137
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-netezza.inc.php157
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-oci8.inc.php1826
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-oci805.inc.php55
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-oci8po.inc.php286
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-oci8quercus.inc.php89
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-odbc.inc.php735
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-odbc_db2.inc.php369
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-odbc_mssql.inc.php365
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-odbc_oracle.inc.php108
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-odbtp.inc.php839
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-odbtp_unicode.inc.php35
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-oracle.inc.php343
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-pdo.inc.php815
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-pdo_mssql.inc.php62
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-pdo_mysql.inc.php313
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-pdo_oci.inc.php102
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-pdo_pgsql.inc.php232
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-pdo_sqlite.inc.php206
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-pdo_sqlsrv.inc.php49
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-postgres.inc.php14
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-postgres64.inc.php1118
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-postgres7.inc.php388
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-postgres8.inc.php50
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-postgres9.inc.php32
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-proxy.inc.php33
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-sapdb.inc.php185
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-sqlanywhere.inc.php165
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-sqlite.inc.php453
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-sqlite3.inc.php440
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-sqlitepo.inc.php58
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-sybase.inc.php445
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-sybase_ase.inc.php120
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-text.inc.php388
-rw-r--r--vendor/adodb/adodb-php/drivers/adodb-vfp.inc.php103
59 files changed, 22270 insertions, 0 deletions
diff --git a/vendor/adodb/adodb-php/drivers/adodb-access.inc.php b/vendor/adodb/adodb-php/drivers/adodb-access.inc.php
new file mode 100644
index 0000000..813b71b
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-access.inc.php
@@ -0,0 +1,88 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence. See License.txt.
+ Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Microsoft Access data driver. Requires ODBC. Works only on MS Windows.
+*/
+if (!defined('_ADODB_ODBC_LAYER')) {
+ if (!defined('ADODB_DIR')) die();
+
+ include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
+}
+ if (!defined('_ADODB_ACCESS')) {
+ define('_ADODB_ACCESS',1);
+
+class ADODB_access extends ADODB_odbc {
+ var $databaseType = 'access';
+ var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE
+ var $fmtDate = "#Y-m-d#";
+ var $fmtTimeStamp = "#Y-m-d h:i:sA#"; // note not comma
+ var $_bindInputArray = false; // strangely enough, setting to true does not work reliably
+ var $sysDate = "FORMAT(NOW,'yyyy-mm-dd')";
+ var $sysTimeStamp = 'NOW';
+ var $hasTransactions = false;
+ var $upperCase = 'ucase';
+
+ function __construct()
+ {
+ global $ADODB_EXTENSION;
+
+ $ADODB_EXTENSION = false;
+ parent::__construct();
+ }
+
+ function Time()
+ {
+ return time();
+ }
+
+ function BeginTrans() { return false;}
+
+ function IfNull( $field, $ifNull )
+ {
+ return " IIF(IsNull($field), $ifNull, $field) "; // if Access
+ }
+/*
+ function MetaTables()
+ {
+ global $ADODB_FETCH_MODE;
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $qid = odbc_tables($this->_connectionID);
+ $rs = new ADORecordSet_odbc($qid);
+ $ADODB_FETCH_MODE = $savem;
+ if (!$rs) return false;
+
+ $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
+
+ $arr = $rs->GetArray();
+ //print_pre($arr);
+ $arr2 = array();
+ for ($i=0; $i < sizeof($arr); $i++) {
+ if ($arr[$i][2] && $arr[$i][3] != 'SYSTEM TABLE')
+ $arr2[] = $arr[$i][2];
+ }
+ return $arr2;
+ }*/
+}
+
+
+class ADORecordSet_access extends ADORecordSet_odbc {
+
+ var $databaseType = "access";
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+}// class
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-ado.inc.php b/vendor/adodb/adodb-php/drivers/adodb-ado.inc.php
new file mode 100644
index 0000000..866f4b1
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-ado.inc.php
@@ -0,0 +1,660 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Microsoft ADO data driver. Requires ADO. Works only on MS Windows.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+define("_ADODB_ADO_LAYER", 1 );
+/*--------------------------------------------------------------------------------------
+--------------------------------------------------------------------------------------*/
+
+
+class ADODB_ado extends ADOConnection {
+ var $databaseType = "ado";
+ var $_bindInputArray = false;
+ var $fmtDate = "'Y-m-d'";
+ var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $dataProvider = "ado";
+ var $hasAffectedRows = true;
+ var $adoParameterType = 201; // 201 = long varchar, 203=long wide varchar, 205 = long varbinary
+ var $_affectedRows = false;
+ var $_thisTransactions;
+ var $_cursor_type = 3; // 3=adOpenStatic,0=adOpenForwardOnly,1=adOpenKeyset,2=adOpenDynamic
+ var $_cursor_location = 3; // 2=adUseServer, 3 = adUseClient;
+ var $_lock_type = -1;
+ var $_execute_option = -1;
+ var $poorAffectedRows = true;
+ var $charPage;
+
+ function __construct()
+ {
+ $this->_affectedRows = new VARIANT;
+ }
+
+ function ServerInfo()
+ {
+ if (!empty($this->_connectionID)) $desc = $this->_connectionID->provider;
+ return array('description' => $desc, 'version' => '');
+ }
+
+ function _affectedrows()
+ {
+ if (PHP_VERSION >= 5) return $this->_affectedRows;
+
+ return $this->_affectedRows->value;
+ }
+
+ // you can also pass a connection string like this:
+ //
+ // $DB->Connect('USER ID=sa;PASSWORD=pwd;SERVER=mangrove;DATABASE=ai',false,false,'SQLOLEDB');
+ function _connect($argHostname, $argUsername, $argPassword, $argProvider= 'MSDASQL')
+ {
+ $u = 'UID';
+ $p = 'PWD';
+
+ if (!empty($this->charPage))
+ $dbc = new COM('ADODB.Connection',null,$this->charPage);
+ else
+ $dbc = new COM('ADODB.Connection');
+
+ if (! $dbc) return false;
+
+ /* special support if provider is mssql or access */
+ if ($argProvider=='mssql') {
+ $u = 'User Id'; //User parameter name for OLEDB
+ $p = 'Password';
+ $argProvider = "SQLOLEDB"; // SQL Server Provider
+
+ // not yet
+ //if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename";
+
+ //use trusted conection for SQL if username not specified
+ if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes";
+ } else if ($argProvider=='access')
+ $argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider
+
+ if ($argProvider) $dbc->Provider = $argProvider;
+
+ if ($argUsername) $argHostname .= ";$u=$argUsername";
+ if ($argPassword)$argHostname .= ";$p=$argPassword";
+
+ if ($this->debug) ADOConnection::outp( "Host=".$argHostname."<BR>\n version=$dbc->version");
+ // @ added below for php 4.0.1 and earlier
+ @$dbc->Open((string) $argHostname);
+
+ $this->_connectionID = $dbc;
+
+ $dbc->CursorLocation = $this->_cursor_location;
+ return $dbc->State > 0;
+ }
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argProvider='MSDASQL')
+ {
+ return $this->_connect($argHostname,$argUsername,$argPassword,$argProvider);
+ }
+
+/*
+ adSchemaCatalogs = 1,
+ adSchemaCharacterSets = 2,
+ adSchemaCollations = 3,
+ adSchemaColumns = 4,
+ adSchemaCheckConstraints = 5,
+ adSchemaConstraintColumnUsage = 6,
+ adSchemaConstraintTableUsage = 7,
+ adSchemaKeyColumnUsage = 8,
+ adSchemaReferentialContraints = 9,
+ adSchemaTableConstraints = 10,
+ adSchemaColumnsDomainUsage = 11,
+ adSchemaIndexes = 12,
+ adSchemaColumnPrivileges = 13,
+ adSchemaTablePrivileges = 14,
+ adSchemaUsagePrivileges = 15,
+ adSchemaProcedures = 16,
+ adSchemaSchemata = 17,
+ adSchemaSQLLanguages = 18,
+ adSchemaStatistics = 19,
+ adSchemaTables = 20,
+ adSchemaTranslations = 21,
+ adSchemaProviderTypes = 22,
+ adSchemaViews = 23,
+ adSchemaViewColumnUsage = 24,
+ adSchemaViewTableUsage = 25,
+ adSchemaProcedureParameters = 26,
+ adSchemaForeignKeys = 27,
+ adSchemaPrimaryKeys = 28,
+ adSchemaProcedureColumns = 29,
+ adSchemaDBInfoKeywords = 30,
+ adSchemaDBInfoLiterals = 31,
+ adSchemaCubes = 32,
+ adSchemaDimensions = 33,
+ adSchemaHierarchies = 34,
+ adSchemaLevels = 35,
+ adSchemaMeasures = 36,
+ adSchemaProperties = 37,
+ adSchemaMembers = 38
+
+*/
+
+ function MetaTables($ttype = false, $showSchema = false, $mask = false)
+ {
+ $arr= array();
+ $dbc = $this->_connectionID;
+
+ $adors=@$dbc->OpenSchema(20);//tables
+ if ($adors){
+ $f = $adors->Fields(2);//table/view name
+ $t = $adors->Fields(3);//table type
+ while (!$adors->EOF){
+ $tt=substr($t->value,0,6);
+ if ($tt!='SYSTEM' && $tt !='ACCESS')
+ $arr[]=$f->value;
+ //print $f->value . ' ' . $t->value.'<br>';
+ $adors->MoveNext();
+ }
+ $adors->Close();
+ }
+
+ return $arr;
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ $table = strtoupper($table);
+ $arr = array();
+ $dbc = $this->_connectionID;
+
+ $adors=@$dbc->OpenSchema(4);//tables
+
+ if ($adors){
+ $t = $adors->Fields(2);//table/view name
+ while (!$adors->EOF){
+
+
+ if (strtoupper($t->Value) == $table) {
+
+ $fld = new ADOFieldObject();
+ $c = $adors->Fields(3);
+ $fld->name = $c->Value;
+ $fld->type = 'CHAR'; // cannot discover type in ADO!
+ $fld->max_length = -1;
+ $arr[strtoupper($fld->name)]=$fld;
+ }
+
+ $adors->MoveNext();
+ }
+ $adors->Close();
+ }
+ $false = false;
+ return empty($arr) ? $false : $arr;
+ }
+
+
+
+
+ /* returns queryID or false */
+ function _query($sql,$inputarr=false)
+ {
+
+ $dbc = $this->_connectionID;
+ $false = false;
+
+ // return rs
+ if ($inputarr) {
+
+ if (!empty($this->charPage))
+ $oCmd = new COM('ADODB.Command',null,$this->charPage);
+ else
+ $oCmd = new COM('ADODB.Command');
+ $oCmd->ActiveConnection = $dbc;
+ $oCmd->CommandText = $sql;
+ $oCmd->CommandType = 1;
+
+ // Map by http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdmthcreateparam.asp
+ // Check issue http://bugs.php.net/bug.php?id=40664 !!!
+ foreach ($inputarr as $val) {
+ $type = gettype($val);
+ $len=strlen($val);
+ if ($type == 'boolean')
+ $this->adoParameterType = 11;
+ else if ($type == 'integer')
+ $this->adoParameterType = 3;
+ else if ($type == 'double')
+ $this->adoParameterType = 5;
+ elseif ($type == 'string')
+ $this->adoParameterType = 202;
+ else if (($val === null) || (!defined($val)))
+ $len=1;
+ else
+ $this->adoParameterType = 130;
+
+ // name, type, direction 1 = input, len,
+ $p = $oCmd->CreateParameter('name',$this->adoParameterType,1,$len,$val);
+
+ $oCmd->Parameters->Append($p);
+ }
+ $p = false;
+ $rs = $oCmd->Execute();
+ $e = $dbc->Errors;
+ if ($dbc->Errors->Count > 0) return $false;
+ return $rs;
+ }
+
+ $rs = @$dbc->Execute($sql,$this->_affectedRows, $this->_execute_option);
+
+ if ($dbc->Errors->Count > 0) return $false;
+ if (! $rs) return $false;
+
+ if ($rs->State == 0) {
+ $true = true;
+ return $true; // 0 = adStateClosed means no records returned
+ }
+ return $rs;
+ }
+
+
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+
+ if (isset($this->_thisTransactions))
+ if (!$this->_thisTransactions) return false;
+ else {
+ $o = $this->_connectionID->Properties("Transaction DDL");
+ $this->_thisTransactions = $o ? true : false;
+ if (!$o) return false;
+ }
+ @$this->_connectionID->BeginTrans();
+ $this->transCnt += 1;
+ return true;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if (!$ok) return $this->RollbackTrans();
+ if ($this->transOff) return true;
+
+ @$this->_connectionID->CommitTrans();
+ if ($this->transCnt) @$this->transCnt -= 1;
+ return true;
+ }
+ function RollbackTrans() {
+ if ($this->transOff) return true;
+ @$this->_connectionID->RollbackTrans();
+ if ($this->transCnt) @$this->transCnt -= 1;
+ return true;
+ }
+
+ /* Returns: the last error message from previous database operation */
+
+ function ErrorMsg()
+ {
+ if (!$this->_connectionID) return "No connection established";
+ $errc = $this->_connectionID->Errors;
+ if (!$errc) return "No Errors object found";
+ if ($errc->Count == 0) return '';
+ $err = $errc->Item($errc->Count-1);
+ return $err->Description;
+ }
+
+ function ErrorNo()
+ {
+ $errc = $this->_connectionID->Errors;
+ if ($errc->Count == 0) return 0;
+ $err = $errc->Item($errc->Count-1);
+ return $err->NativeError;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ if ($this->_connectionID) $this->_connectionID->Close();
+ $this->_connectionID = false;
+ return true;
+ }
+
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_ado extends ADORecordSet {
+
+ var $bind = false;
+ var $databaseType = "ado";
+ var $dataProvider = "ado";
+ var $_tarr = false; // caches the types
+ var $_flds; // and field objects
+ var $canSeek = true;
+ var $hideErrors = true;
+
+ function __construct($id,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ $this->fetchMode = $mode;
+ return parent::__construct($id,$mode);
+ }
+
+
+ // returns the field object
+ function FetchField($fieldOffset = -1) {
+ $off=$fieldOffset+1; // offsets begin at 1
+
+ $o= new ADOFieldObject();
+ $rs = $this->_queryID;
+ $f = $rs->Fields($fieldOffset);
+ $o->name = $f->Name;
+ $t = $f->Type;
+ $o->type = $this->MetaType($t);
+ $o->max_length = $f->DefinedSize;
+ $o->ado_type = $t;
+
+ //print "off=$off name=$o->name type=$o->type len=$o->max_length<br>";
+ return $o;
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+
+ function _initrs()
+ {
+ $rs = $this->_queryID;
+ $this->_numOfRows = $rs->RecordCount;
+
+ $f = $rs->Fields;
+ $this->_numOfFields = $f->Count;
+ }
+
+
+ // should only be used to move forward as we normally use forward-only cursors
+ function _seek($row)
+ {
+ $rs = $this->_queryID;
+ // absoluteposition doesn't work -- my maths is wrong ?
+ // $rs->AbsolutePosition->$row-2;
+ // return true;
+ if ($this->_currentRow > $row) return false;
+ @$rs->Move((integer)$row - $this->_currentRow-1); //adBookmarkFirst
+ return true;
+ }
+
+/*
+ OLEDB types
+
+ enum DBTYPEENUM
+ { DBTYPE_EMPTY = 0,
+ DBTYPE_NULL = 1,
+ DBTYPE_I2 = 2,
+ DBTYPE_I4 = 3,
+ DBTYPE_R4 = 4,
+ DBTYPE_R8 = 5,
+ DBTYPE_CY = 6,
+ DBTYPE_DATE = 7,
+ DBTYPE_BSTR = 8,
+ DBTYPE_IDISPATCH = 9,
+ DBTYPE_ERROR = 10,
+ DBTYPE_BOOL = 11,
+ DBTYPE_VARIANT = 12,
+ DBTYPE_IUNKNOWN = 13,
+ DBTYPE_DECIMAL = 14,
+ DBTYPE_UI1 = 17,
+ DBTYPE_ARRAY = 0x2000,
+ DBTYPE_BYREF = 0x4000,
+ DBTYPE_I1 = 16,
+ DBTYPE_UI2 = 18,
+ DBTYPE_UI4 = 19,
+ DBTYPE_I8 = 20,
+ DBTYPE_UI8 = 21,
+ DBTYPE_GUID = 72,
+ DBTYPE_VECTOR = 0x1000,
+ DBTYPE_RESERVED = 0x8000,
+ DBTYPE_BYTES = 128,
+ DBTYPE_STR = 129,
+ DBTYPE_WSTR = 130,
+ DBTYPE_NUMERIC = 131,
+ DBTYPE_UDT = 132,
+ DBTYPE_DBDATE = 133,
+ DBTYPE_DBTIME = 134,
+ DBTYPE_DBTIMESTAMP = 135
+
+ ADO Types
+
+ adEmpty = 0,
+ adTinyInt = 16,
+ adSmallInt = 2,
+ adInteger = 3,
+ adBigInt = 20,
+ adUnsignedTinyInt = 17,
+ adUnsignedSmallInt = 18,
+ adUnsignedInt = 19,
+ adUnsignedBigInt = 21,
+ adSingle = 4,
+ adDouble = 5,
+ adCurrency = 6,
+ adDecimal = 14,
+ adNumeric = 131,
+ adBoolean = 11,
+ adError = 10,
+ adUserDefined = 132,
+ adVariant = 12,
+ adIDispatch = 9,
+ adIUnknown = 13,
+ adGUID = 72,
+ adDate = 7,
+ adDBDate = 133,
+ adDBTime = 134,
+ adDBTimeStamp = 135,
+ adBSTR = 8,
+ adChar = 129,
+ adVarChar = 200,
+ adLongVarChar = 201,
+ adWChar = 130,
+ adVarWChar = 202,
+ adLongVarWChar = 203,
+ adBinary = 128,
+ adVarBinary = 204,
+ adLongVarBinary = 205,
+ adChapter = 136,
+ adFileTime = 64,
+ adDBFileTime = 137,
+ adPropVariant = 138,
+ adVarNumeric = 139
+*/
+ function MetaType($t,$len=-1,$fieldobj=false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+
+ if (!is_numeric($t)) return $t;
+
+ switch ($t) {
+ case 0:
+ case 12: // variant
+ case 8: // bstr
+ case 129: //char
+ case 130: //wc
+ case 200: // varc
+ case 202:// varWC
+ case 128: // bin
+ case 204: // varBin
+ case 72: // guid
+ if ($len <= $this->blobSize) return 'C';
+
+ case 201:
+ case 203:
+ return 'X';
+ case 128:
+ case 204:
+ case 205:
+ return 'B';
+ case 7:
+ case 133: return 'D';
+
+ case 134:
+ case 135: return 'T';
+
+ case 11: return 'L';
+
+ case 16:// adTinyInt = 16,
+ case 2://adSmallInt = 2,
+ case 3://adInteger = 3,
+ case 4://adBigInt = 20,
+ case 17://adUnsignedTinyInt = 17,
+ case 18://adUnsignedSmallInt = 18,
+ case 19://adUnsignedInt = 19,
+ case 20://adUnsignedBigInt = 21,
+ return 'I';
+ default: return 'N';
+ }
+ }
+
+ // time stamp not supported yet
+ function _fetch()
+ {
+ $rs = $this->_queryID;
+ if (!$rs or $rs->EOF) {
+ $this->fields = false;
+ return false;
+ }
+ $this->fields = array();
+
+ if (!$this->_tarr) {
+ $tarr = array();
+ $flds = array();
+ for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
+ $f = $rs->Fields($i);
+ $flds[] = $f;
+ $tarr[] = $f->Type;
+ }
+ // bind types and flds only once
+ $this->_tarr = $tarr;
+ $this->_flds = $flds;
+ }
+ $t = reset($this->_tarr);
+ $f = reset($this->_flds);
+
+ if ($this->hideErrors) $olde = error_reporting(E_ERROR|E_CORE_ERROR);// sometimes $f->value be null
+ for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
+ //echo "<p>",$t,' ';var_dump($f->value); echo '</p>';
+ switch($t) {
+ case 135: // timestamp
+ if (!strlen((string)$f->value)) $this->fields[] = false;
+ else {
+ if (!is_numeric($f->value)) # $val = variant_date_to_timestamp($f->value);
+ // VT_DATE stores dates as (float) fractional days since 1899/12/30 00:00:00
+ $val=(float) variant_cast($f->value,VT_R8)*3600*24-2209161600;
+ else
+ $val = $f->value;
+ $this->fields[] = adodb_date('Y-m-d H:i:s',$val);
+ }
+ break;
+ case 133:// A date value (yyyymmdd)
+ if ($val = $f->value) {
+ $this->fields[] = substr($val,0,4).'-'.substr($val,4,2).'-'.substr($val,6,2);
+ } else
+ $this->fields[] = false;
+ break;
+ case 7: // adDate
+ if (!strlen((string)$f->value)) $this->fields[] = false;
+ else {
+ if (!is_numeric($f->value)) $val = variant_date_to_timestamp($f->value);
+ else $val = $f->value;
+
+ if (($val % 86400) == 0) $this->fields[] = adodb_date('Y-m-d',$val);
+ else $this->fields[] = adodb_date('Y-m-d H:i:s',$val);
+ }
+ break;
+ case 1: // null
+ $this->fields[] = false;
+ break;
+ case 6: // currency is not supported properly;
+ ADOConnection::outp( '<b>'.$f->Name.': currency type not supported by PHP</b>');
+ $this->fields[] = (float) $f->value;
+ break;
+ case 11: //BIT;
+ $val = "";
+ if(is_bool($f->value)) {
+ if($f->value==true) $val = 1;
+ else $val = 0;
+ }
+ if(is_null($f->value)) $val = null;
+
+ $this->fields[] = $val;
+ break;
+ default:
+ $this->fields[] = $f->value;
+ break;
+ }
+ //print " $f->value $t, ";
+ $f = next($this->_flds);
+ $t = next($this->_tarr);
+ } // for
+ if ($this->hideErrors) error_reporting($olde);
+ @$rs->MoveNext(); // @ needed for some versions of PHP!
+
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ $this->fields = $this->GetRowAssoc();
+ }
+ return true;
+ }
+
+ function NextRecordSet()
+ {
+ $rs = $this->_queryID;
+ $this->_queryID = $rs->NextRecordSet();
+ //$this->_queryID = $this->_QueryId->NextRecordSet();
+ if ($this->_queryID == null) return false;
+
+ $this->_currentRow = -1;
+ $this->_currentPage = -1;
+ $this->bind = false;
+ $this->fields = false;
+ $this->_flds = false;
+ $this->_tarr = false;
+
+ $this->_inited = false;
+ $this->Init();
+ return true;
+ }
+
+ function _close() {
+ $this->_flds = false;
+ @$this->_queryID->Close();// by Pete Dishman (peterd@telephonetics.co.uk)
+ $this->_queryID = false;
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-ado5.inc.php b/vendor/adodb/adodb-php/drivers/adodb-ado5.inc.php
new file mode 100644
index 0000000..a7066ad
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-ado5.inc.php
@@ -0,0 +1,708 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Microsoft ADO data driver. Requires ADO. Works only on MS Windows. PHP5 compat version.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+define("_ADODB_ADO_LAYER", 1 );
+/*--------------------------------------------------------------------------------------
+--------------------------------------------------------------------------------------*/
+
+
+class ADODB_ado extends ADOConnection {
+ var $databaseType = "ado";
+ var $_bindInputArray = false;
+ var $fmtDate = "'Y-m-d'";
+ var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $dataProvider = "ado";
+ var $hasAffectedRows = true;
+ var $adoParameterType = 201; // 201 = long varchar, 203=long wide varchar, 205 = long varbinary
+ var $_affectedRows = false;
+ var $_thisTransactions;
+ var $_cursor_type = 3; // 3=adOpenStatic,0=adOpenForwardOnly,1=adOpenKeyset,2=adOpenDynamic
+ var $_cursor_location = 3; // 2=adUseServer, 3 = adUseClient;
+ var $_lock_type = -1;
+ var $_execute_option = -1;
+ var $poorAffectedRows = true;
+ var $charPage;
+
+ function __construct()
+ {
+ $this->_affectedRows = new VARIANT;
+ }
+
+ function ServerInfo()
+ {
+ if (!empty($this->_connectionID)) $desc = $this->_connectionID->provider;
+ return array('description' => $desc, 'version' => '');
+ }
+
+ function _affectedrows()
+ {
+ if (PHP_VERSION >= 5) return $this->_affectedRows;
+
+ return $this->_affectedRows->value;
+ }
+
+ // you can also pass a connection string like this:
+ //
+ // $DB->Connect('USER ID=sa;PASSWORD=pwd;SERVER=mangrove;DATABASE=ai',false,false,'SQLOLEDB');
+ function _connect($argHostname, $argUsername, $argPassword,$argDBorProvider, $argProvider= '')
+ {
+ // two modes
+ // - if $argProvider is empty, we assume that $argDBorProvider holds provider -- this is for backward compat
+ // - if $argProvider is not empty, then $argDBorProvider holds db
+
+
+ if ($argProvider) {
+ $argDatabasename = $argDBorProvider;
+ } else {
+ $argDatabasename = '';
+ if ($argDBorProvider) $argProvider = $argDBorProvider;
+ else if (stripos($argHostname,'PROVIDER') === false) /* full conn string is not in $argHostname */
+ $argProvider = 'MSDASQL';
+ }
+
+
+ try {
+ $u = 'UID';
+ $p = 'PWD';
+
+ if (!empty($this->charPage))
+ $dbc = new COM('ADODB.Connection',null,$this->charPage);
+ else
+ $dbc = new COM('ADODB.Connection');
+
+ if (! $dbc) return false;
+
+ /* special support if provider is mssql or access */
+ if ($argProvider=='mssql') {
+ $u = 'User Id'; //User parameter name for OLEDB
+ $p = 'Password';
+ $argProvider = "SQLOLEDB"; // SQL Server Provider
+
+ // not yet
+ //if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename";
+
+ //use trusted conection for SQL if username not specified
+ if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes";
+ } else if ($argProvider=='access')
+ $argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider
+
+ if ($argProvider) $dbc->Provider = $argProvider;
+
+ if ($argProvider) $argHostname = "PROVIDER=$argProvider;DRIVER={SQL Server};SERVER=$argHostname";
+
+
+ if ($argDatabasename) $argHostname .= ";DATABASE=$argDatabasename";
+ if ($argUsername) $argHostname .= ";$u=$argUsername";
+ if ($argPassword)$argHostname .= ";$p=$argPassword";
+
+ if ($this->debug) ADOConnection::outp( "Host=".$argHostname."<BR>\n version=$dbc->version");
+ // @ added below for php 4.0.1 and earlier
+ @$dbc->Open((string) $argHostname);
+
+ $this->_connectionID = $dbc;
+
+ $dbc->CursorLocation = $this->_cursor_location;
+ return $dbc->State > 0;
+ } catch (exception $e) {
+ if ($this->debug) echo "<pre>",$argHostname,"\n",$e,"</pre>\n";
+ }
+
+ return false;
+ }
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argProvider='MSDASQL')
+ {
+ return $this->_connect($argHostname,$argUsername,$argPassword,$argProvider);
+ }
+
+/*
+ adSchemaCatalogs = 1,
+ adSchemaCharacterSets = 2,
+ adSchemaCollations = 3,
+ adSchemaColumns = 4,
+ adSchemaCheckConstraints = 5,
+ adSchemaConstraintColumnUsage = 6,
+ adSchemaConstraintTableUsage = 7,
+ adSchemaKeyColumnUsage = 8,
+ adSchemaReferentialContraints = 9,
+ adSchemaTableConstraints = 10,
+ adSchemaColumnsDomainUsage = 11,
+ adSchemaIndexes = 12,
+ adSchemaColumnPrivileges = 13,
+ adSchemaTablePrivileges = 14,
+ adSchemaUsagePrivileges = 15,
+ adSchemaProcedures = 16,
+ adSchemaSchemata = 17,
+ adSchemaSQLLanguages = 18,
+ adSchemaStatistics = 19,
+ adSchemaTables = 20,
+ adSchemaTranslations = 21,
+ adSchemaProviderTypes = 22,
+ adSchemaViews = 23,
+ adSchemaViewColumnUsage = 24,
+ adSchemaViewTableUsage = 25,
+ adSchemaProcedureParameters = 26,
+ adSchemaForeignKeys = 27,
+ adSchemaPrimaryKeys = 28,
+ adSchemaProcedureColumns = 29,
+ adSchemaDBInfoKeywords = 30,
+ adSchemaDBInfoLiterals = 31,
+ adSchemaCubes = 32,
+ adSchemaDimensions = 33,
+ adSchemaHierarchies = 34,
+ adSchemaLevels = 35,
+ adSchemaMeasures = 36,
+ adSchemaProperties = 37,
+ adSchemaMembers = 38
+
+*/
+
+ function MetaTables($ttype = false, $showSchema = false, $mask = false)
+ {
+ $arr= array();
+ $dbc = $this->_connectionID;
+
+ $adors=@$dbc->OpenSchema(20);//tables
+ if ($adors){
+ $f = $adors->Fields(2);//table/view name
+ $t = $adors->Fields(3);//table type
+ while (!$adors->EOF){
+ $tt=substr($t->value,0,6);
+ if ($tt!='SYSTEM' && $tt !='ACCESS')
+ $arr[]=$f->value;
+ //print $f->value . ' ' . $t->value.'<br>';
+ $adors->MoveNext();
+ }
+ $adors->Close();
+ }
+
+ return $arr;
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ $table = strtoupper($table);
+ $arr= array();
+ $dbc = $this->_connectionID;
+
+ $adors=@$dbc->OpenSchema(4);//tables
+
+ if ($adors){
+ $t = $adors->Fields(2);//table/view name
+ while (!$adors->EOF){
+
+
+ if (strtoupper($t->Value) == $table) {
+
+ $fld = new ADOFieldObject();
+ $c = $adors->Fields(3);
+ $fld->name = $c->Value;
+ $fld->type = 'CHAR'; // cannot discover type in ADO!
+ $fld->max_length = -1;
+ $arr[strtoupper($fld->name)]=$fld;
+ }
+
+ $adors->MoveNext();
+ }
+ $adors->Close();
+ }
+
+ return $arr;
+ }
+
+ /* returns queryID or false */
+ function _query($sql,$inputarr=false)
+ {
+ try { // In PHP5, all COM errors are exceptions, so to maintain old behaviour...
+
+ $dbc = $this->_connectionID;
+
+ // return rs
+
+ $false = false;
+
+ if ($inputarr) {
+
+ if (!empty($this->charPage))
+ $oCmd = new COM('ADODB.Command',null,$this->charPage);
+ else
+ $oCmd = new COM('ADODB.Command');
+ $oCmd->ActiveConnection = $dbc;
+ $oCmd->CommandText = $sql;
+ $oCmd->CommandType = 1;
+
+ foreach ($inputarr as $val) {
+ $type = gettype($val);
+ $len=strlen($val);
+ if ($type == 'boolean')
+ $this->adoParameterType = 11;
+ else if ($type == 'integer')
+ $this->adoParameterType = 3;
+ else if ($type == 'double')
+ $this->adoParameterType = 5;
+ elseif ($type == 'string')
+ $this->adoParameterType = 202;
+ else if (($val === null) || (!defined($val)))
+ $len=1;
+ else
+ $this->adoParameterType = 130;
+
+ // name, type, direction 1 = input, len,
+ $p = $oCmd->CreateParameter('name',$this->adoParameterType,1,$len,$val);
+
+ $oCmd->Parameters->Append($p);
+ }
+
+ $p = false;
+ $rs = $oCmd->Execute();
+ $e = $dbc->Errors;
+ if ($dbc->Errors->Count > 0) return $false;
+ return $rs;
+ }
+
+ $rs = @$dbc->Execute($sql,$this->_affectedRows, $this->_execute_option);
+
+ if ($dbc->Errors->Count > 0) return $false;
+ if (! $rs) return $false;
+
+ if ($rs->State == 0) {
+ $true = true;
+ return $true; // 0 = adStateClosed means no records returned
+ }
+ return $rs;
+
+ } catch (exception $e) {
+
+ }
+ return $false;
+ }
+
+
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+
+ if (isset($this->_thisTransactions))
+ if (!$this->_thisTransactions) return false;
+ else {
+ $o = $this->_connectionID->Properties("Transaction DDL");
+ $this->_thisTransactions = $o ? true : false;
+ if (!$o) return false;
+ }
+ @$this->_connectionID->BeginTrans();
+ $this->transCnt += 1;
+ return true;
+ }
+ function CommitTrans($ok=true)
+ {
+ if (!$ok) return $this->RollbackTrans();
+ if ($this->transOff) return true;
+
+ @$this->_connectionID->CommitTrans();
+ if ($this->transCnt) @$this->transCnt -= 1;
+ return true;
+ }
+ function RollbackTrans() {
+ if ($this->transOff) return true;
+ @$this->_connectionID->RollbackTrans();
+ if ($this->transCnt) @$this->transCnt -= 1;
+ return true;
+ }
+
+ /* Returns: the last error message from previous database operation */
+
+ function ErrorMsg()
+ {
+ if (!$this->_connectionID) return "No connection established";
+ $errmsg = '';
+
+ try {
+ $errc = $this->_connectionID->Errors;
+ if (!$errc) return "No Errors object found";
+ if ($errc->Count == 0) return '';
+ $err = $errc->Item($errc->Count-1);
+ $errmsg = $err->Description;
+ }catch(exception $e) {
+ }
+ return $errmsg;
+ }
+
+ function ErrorNo()
+ {
+ $errc = $this->_connectionID->Errors;
+ if ($errc->Count == 0) return 0;
+ $err = $errc->Item($errc->Count-1);
+ return $err->NativeError;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ if ($this->_connectionID) $this->_connectionID->Close();
+ $this->_connectionID = false;
+ return true;
+ }
+
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_ado extends ADORecordSet {
+
+ var $bind = false;
+ var $databaseType = "ado";
+ var $dataProvider = "ado";
+ var $_tarr = false; // caches the types
+ var $_flds; // and field objects
+ var $canSeek = true;
+ var $hideErrors = true;
+
+ function __construct($id,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ $this->fetchMode = $mode;
+ return parent::__construct($id,$mode);
+ }
+
+
+ // returns the field object
+ function FetchField($fieldOffset = -1) {
+ $off=$fieldOffset+1; // offsets begin at 1
+
+ $o= new ADOFieldObject();
+ $rs = $this->_queryID;
+ if (!$rs) return false;
+
+ $f = $rs->Fields($fieldOffset);
+ $o->name = $f->Name;
+ $t = $f->Type;
+ $o->type = $this->MetaType($t);
+ $o->max_length = $f->DefinedSize;
+ $o->ado_type = $t;
+
+
+ //print "off=$off name=$o->name type=$o->type len=$o->max_length<br>";
+ return $o;
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+
+ function _initrs()
+ {
+ $rs = $this->_queryID;
+
+ try {
+ $this->_numOfRows = $rs->RecordCount;
+ } catch (Exception $e) {
+ $this->_numOfRows = -1;
+ }
+ $f = $rs->Fields;
+ $this->_numOfFields = $f->Count;
+ }
+
+
+ // should only be used to move forward as we normally use forward-only cursors
+ function _seek($row)
+ {
+ $rs = $this->_queryID;
+ // absoluteposition doesn't work -- my maths is wrong ?
+ // $rs->AbsolutePosition->$row-2;
+ // return true;
+ if ($this->_currentRow > $row) return false;
+ @$rs->Move((integer)$row - $this->_currentRow-1); //adBookmarkFirst
+ return true;
+ }
+
+/*
+ OLEDB types
+
+ enum DBTYPEENUM
+ { DBTYPE_EMPTY = 0,
+ DBTYPE_NULL = 1,
+ DBTYPE_I2 = 2,
+ DBTYPE_I4 = 3,
+ DBTYPE_R4 = 4,
+ DBTYPE_R8 = 5,
+ DBTYPE_CY = 6,
+ DBTYPE_DATE = 7,
+ DBTYPE_BSTR = 8,
+ DBTYPE_IDISPATCH = 9,
+ DBTYPE_ERROR = 10,
+ DBTYPE_BOOL = 11,
+ DBTYPE_VARIANT = 12,
+ DBTYPE_IUNKNOWN = 13,
+ DBTYPE_DECIMAL = 14,
+ DBTYPE_UI1 = 17,
+ DBTYPE_ARRAY = 0x2000,
+ DBTYPE_BYREF = 0x4000,
+ DBTYPE_I1 = 16,
+ DBTYPE_UI2 = 18,
+ DBTYPE_UI4 = 19,
+ DBTYPE_I8 = 20,
+ DBTYPE_UI8 = 21,
+ DBTYPE_GUID = 72,
+ DBTYPE_VECTOR = 0x1000,
+ DBTYPE_RESERVED = 0x8000,
+ DBTYPE_BYTES = 128,
+ DBTYPE_STR = 129,
+ DBTYPE_WSTR = 130,
+ DBTYPE_NUMERIC = 131,
+ DBTYPE_UDT = 132,
+ DBTYPE_DBDATE = 133,
+ DBTYPE_DBTIME = 134,
+ DBTYPE_DBTIMESTAMP = 135
+
+ ADO Types
+
+ adEmpty = 0,
+ adTinyInt = 16,
+ adSmallInt = 2,
+ adInteger = 3,
+ adBigInt = 20,
+ adUnsignedTinyInt = 17,
+ adUnsignedSmallInt = 18,
+ adUnsignedInt = 19,
+ adUnsignedBigInt = 21,
+ adSingle = 4,
+ adDouble = 5,
+ adCurrency = 6,
+ adDecimal = 14,
+ adNumeric = 131,
+ adBoolean = 11,
+ adError = 10,
+ adUserDefined = 132,
+ adVariant = 12,
+ adIDispatch = 9,
+ adIUnknown = 13,
+ adGUID = 72,
+ adDate = 7,
+ adDBDate = 133,
+ adDBTime = 134,
+ adDBTimeStamp = 135,
+ adBSTR = 8,
+ adChar = 129,
+ adVarChar = 200,
+ adLongVarChar = 201,
+ adWChar = 130,
+ adVarWChar = 202,
+ adLongVarWChar = 203,
+ adBinary = 128,
+ adVarBinary = 204,
+ adLongVarBinary = 205,
+ adChapter = 136,
+ adFileTime = 64,
+ adDBFileTime = 137,
+ adPropVariant = 138,
+ adVarNumeric = 139
+*/
+ function MetaType($t,$len=-1,$fieldobj=false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+
+ if (!is_numeric($t)) return $t;
+
+ switch ($t) {
+ case 0:
+ case 12: // variant
+ case 8: // bstr
+ case 129: //char
+ case 130: //wc
+ case 200: // varc
+ case 202:// varWC
+ case 128: // bin
+ case 204: // varBin
+ case 72: // guid
+ if ($len <= $this->blobSize) return 'C';
+
+ case 201:
+ case 203:
+ return 'X';
+ case 128:
+ case 204:
+ case 205:
+ return 'B';
+ case 7:
+ case 133: return 'D';
+
+ case 134:
+ case 135: return 'T';
+
+ case 11: return 'L';
+
+ case 16:// adTinyInt = 16,
+ case 2://adSmallInt = 2,
+ case 3://adInteger = 3,
+ case 4://adBigInt = 20,
+ case 17://adUnsignedTinyInt = 17,
+ case 18://adUnsignedSmallInt = 18,
+ case 19://adUnsignedInt = 19,
+ case 20://adUnsignedBigInt = 21,
+ return 'I';
+ default: return 'N';
+ }
+ }
+
+ // time stamp not supported yet
+ function _fetch()
+ {
+ $rs = $this->_queryID;
+ if (!$rs or $rs->EOF) {
+ $this->fields = false;
+ return false;
+ }
+ $this->fields = array();
+
+ if (!$this->_tarr) {
+ $tarr = array();
+ $flds = array();
+ for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
+ $f = $rs->Fields($i);
+ $flds[] = $f;
+ $tarr[] = $f->Type;
+ }
+ // bind types and flds only once
+ $this->_tarr = $tarr;
+ $this->_flds = $flds;
+ }
+ $t = reset($this->_tarr);
+ $f = reset($this->_flds);
+
+ if ($this->hideErrors) $olde = error_reporting(E_ERROR|E_CORE_ERROR);// sometimes $f->value be null
+ for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
+ //echo "<p>",$t,' ';var_dump($f->value); echo '</p>';
+ switch($t) {
+ case 135: // timestamp
+ if (!strlen((string)$f->value)) $this->fields[] = false;
+ else {
+ if (!is_numeric($f->value)) # $val = variant_date_to_timestamp($f->value);
+ // VT_DATE stores dates as (float) fractional days since 1899/12/30 00:00:00
+ $val= (float) variant_cast($f->value,VT_R8)*3600*24-2209161600;
+ else
+ $val = $f->value;
+ $this->fields[] = adodb_date('Y-m-d H:i:s',$val);
+ }
+ break;
+ case 133:// A date value (yyyymmdd)
+ if ($val = $f->value) {
+ $this->fields[] = substr($val,0,4).'-'.substr($val,4,2).'-'.substr($val,6,2);
+ } else
+ $this->fields[] = false;
+ break;
+ case 7: // adDate
+ if (!strlen((string)$f->value)) $this->fields[] = false;
+ else {
+ if (!is_numeric($f->value)) $val = variant_date_to_timestamp($f->value);
+ else $val = $f->value;
+
+ if (($val % 86400) == 0) $this->fields[] = adodb_date('Y-m-d',$val);
+ else $this->fields[] = adodb_date('Y-m-d H:i:s',$val);
+ }
+ break;
+ case 1: // null
+ $this->fields[] = false;
+ break;
+ case 20:
+ case 21: // bigint (64 bit)
+ $this->fields[] = (float) $f->value; // if 64 bit PHP, could use (int)
+ break;
+ case 6: // currency is not supported properly;
+ ADOConnection::outp( '<b>'.$f->Name.': currency type not supported by PHP</b>');
+ $this->fields[] = (float) $f->value;
+ break;
+ case 11: //BIT;
+ $val = "";
+ if(is_bool($f->value)) {
+ if($f->value==true) $val = 1;
+ else $val = 0;
+ }
+ if(is_null($f->value)) $val = null;
+
+ $this->fields[] = $val;
+ break;
+ default:
+ $this->fields[] = $f->value;
+ break;
+ }
+ //print " $f->value $t, ";
+ $f = next($this->_flds);
+ $t = next($this->_tarr);
+ } // for
+ if ($this->hideErrors) error_reporting($olde);
+ @$rs->MoveNext(); // @ needed for some versions of PHP!
+
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ $this->fields = $this->GetRowAssoc();
+ }
+ return true;
+ }
+
+ function NextRecordSet()
+ {
+ $rs = $this->_queryID;
+ $this->_queryID = $rs->NextRecordSet();
+ //$this->_queryID = $this->_QueryId->NextRecordSet();
+ if ($this->_queryID == null) return false;
+
+ $this->_currentRow = -1;
+ $this->_currentPage = -1;
+ $this->bind = false;
+ $this->fields = false;
+ $this->_flds = false;
+ $this->_tarr = false;
+
+ $this->_inited = false;
+ $this->Init();
+ return true;
+ }
+
+ function _close() {
+ $this->_flds = false;
+ try {
+ @$this->_queryID->Close();// by Pete Dishman (peterd@telephonetics.co.uk)
+ } catch (Exception $e) {
+ }
+ $this->_queryID = false;
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-ado_access.inc.php b/vendor/adodb/adodb-php/drivers/adodb-ado_access.inc.php
new file mode 100644
index 0000000..0e26499
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-ado_access.inc.php
@@ -0,0 +1,50 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+Released under both BSD license and Lesser GPL library license.
+Whenever there is any discrepancy between the two licenses,
+the BSD license will take precedence. See License.txt.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Microsoft Access ADO data driver. Requires ADO and ODBC. Works only on MS Windows.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (!defined('_ADODB_ADO_LAYER')) {
+ if (PHP_VERSION >= 5) include(ADODB_DIR."/drivers/adodb-ado5.inc.php");
+ else include(ADODB_DIR."/drivers/adodb-ado.inc.php");
+}
+
+class ADODB_ado_access extends ADODB_ado {
+ var $databaseType = 'ado_access';
+ var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE
+ var $fmtDate = "#Y-m-d#";
+ var $fmtTimeStamp = "#Y-m-d h:i:sA#";// note no comma
+ var $sysDate = "FORMAT(NOW,'yyyy-mm-dd')";
+ var $sysTimeStamp = 'NOW';
+ var $upperCase = 'ucase';
+
+ /*function BeginTrans() { return false;}
+
+ function CommitTrans() { return false;}
+
+ function RollbackTrans() { return false;}*/
+
+}
+
+
+class ADORecordSet_ado_access extends ADORecordSet_ado {
+
+ var $databaseType = "ado_access";
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-ado_mssql.inc.php b/vendor/adodb/adodb-php/drivers/adodb-ado_mssql.inc.php
new file mode 100644
index 0000000..dfb8035
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-ado_mssql.inc.php
@@ -0,0 +1,150 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Microsoft SQL Server ADO data driver. Requires ADO and MSSQL client.
+ Works only on MS Windows.
+
+ Warning: Some versions of PHP (esp PHP4) leak memory when ADO/COM is used.
+ Please check http://bugs.php.net/ for more info.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (!defined('_ADODB_ADO_LAYER')) {
+ if (PHP_VERSION >= 5) include(ADODB_DIR."/drivers/adodb-ado5.inc.php");
+ else include(ADODB_DIR."/drivers/adodb-ado.inc.php");
+}
+
+
+class ADODB_ado_mssql extends ADODB_ado {
+ var $databaseType = 'ado_mssql';
+ var $hasTop = 'top';
+ var $hasInsertID = true;
+ var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
+ var $sysTimeStamp = 'GetDate()';
+ var $leftOuter = '*=';
+ var $rightOuter = '=*';
+ var $ansiOuter = true; // for mssql7 or later
+ var $substr = "substring";
+ var $length = 'len';
+ var $_dropSeqSQL = "drop table %s";
+
+ //var $_inTransaction = 1; // always open recordsets, so no transaction problems.
+
+ function _insertid()
+ {
+ return $this->GetOne('select SCOPE_IDENTITY()');
+ }
+
+ function _affectedrows()
+ {
+ return $this->GetOne('select @@rowcount');
+ }
+
+ function SetTransactionMode( $transaction_mode )
+ {
+ $this->_transmode = $transaction_mode;
+ if (empty($transaction_mode)) {
+ $this->Execute('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
+ return;
+ }
+ if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
+ $this->Execute("SET TRANSACTION ".$transaction_mode);
+ }
+
+ function qstr($s,$magic_quotes=false)
+ {
+ $s = ADOConnection::qstr($s, $magic_quotes);
+ return str_replace("\0", "\\\\000", $s);
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ $table = strtoupper($table);
+ $arr= array();
+ $dbc = $this->_connectionID;
+
+ $osoptions = array();
+ $osoptions[0] = null;
+ $osoptions[1] = null;
+ $osoptions[2] = $table;
+ $osoptions[3] = null;
+
+ $adors=@$dbc->OpenSchema(4, $osoptions);//tables
+
+ if ($adors){
+ while (!$adors->EOF){
+ $fld = new ADOFieldObject();
+ $c = $adors->Fields(3);
+ $fld->name = $c->Value;
+ $fld->type = 'CHAR'; // cannot discover type in ADO!
+ $fld->max_length = -1;
+ $arr[strtoupper($fld->name)]=$fld;
+
+ $adors->MoveNext();
+ }
+ $adors->Close();
+ }
+ $false = false;
+ return empty($arr) ? $false : $arr;
+ }
+
+ function CreateSequence($seq='adodbseq',$start=1)
+ {
+
+ $this->Execute('BEGIN TRANSACTION adodbseq');
+ $start -= 1;
+ $this->Execute("create table $seq (id float(53))");
+ $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
+ if (!$ok) {
+ $this->Execute('ROLLBACK TRANSACTION adodbseq');
+ return false;
+ }
+ $this->Execute('COMMIT TRANSACTION adodbseq');
+ return true;
+ }
+
+ function GenID($seq='adodbseq',$start=1)
+ {
+ //$this->debug=1;
+ $this->Execute('BEGIN TRANSACTION adodbseq');
+ $ok = $this->Execute("update $seq with (tablock,holdlock) set id = id + 1");
+ if (!$ok) {
+ $this->Execute("create table $seq (id float(53))");
+ $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
+ if (!$ok) {
+ $this->Execute('ROLLBACK TRANSACTION adodbseq');
+ return false;
+ }
+ $this->Execute('COMMIT TRANSACTION adodbseq');
+ return $start;
+ }
+ $num = $this->GetOne("select id from $seq");
+ $this->Execute('COMMIT TRANSACTION adodbseq');
+ return $num;
+
+ // in old implementation, pre 1.90, we returned GUID...
+ //return $this->GetOne("SELECT CONVERT(varchar(255), NEWID()) AS 'Char'");
+ }
+
+ } // end class
+
+ class ADORecordSet_ado_mssql extends ADORecordSet_ado {
+
+ var $databaseType = 'ado_mssql';
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-ads.inc.php b/vendor/adodb/adodb-php/drivers/adodb-ads.inc.php
new file mode 100644
index 0000000..8d31b21
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-ads.inc.php
@@ -0,0 +1,776 @@
+<?php
+/*
+ (c) 2000-2014 John Lim (jlim#natsoft.com.my). All rights reserved.
+ Portions Copyright (c) 2007-2009, iAnywhere Solutions, Inc.
+ All rights reserved. All unpublished rights reserved.
+
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+
+Set tabs to 4 for best viewing.
+
+
+NOTE: This driver requires the Advantage PHP client libraries, which
+ can be downloaded for free via:
+ http://devzone.advantagedatabase.com/dz/content.aspx?key=20
+
+DELPHI FOR PHP USERS:
+ The following steps can be taken to utilize this driver from the
+ CodeGear Delphi for PHP product:
+ 1 - See note above, download and install the Advantage PHP client.
+ 2 - Copy the following files to the Delphi for PHP\X.X\php\ext directory:
+ ace32.dll
+ axcws32.dll
+ adsloc32.dll
+ php_advantage.dll (rename the existing php_advantage.dll.5.x.x file)
+ 3 - Add the following line to the Delphi for PHP\X.X\php\php.ini.template file:
+ extension=php_advantage.dll
+ 4 - To use: enter "ads" as the DriverName on a connection component, and set
+ a Host property similar to "DataDirectory=c:\". See the Advantage PHP
+ help file topic for ads_connect for details on connection path options
+ and formatting.
+ 5 - (optional) - Modify the Delphi for PHP\X.X\vcl\packages\database.packages.php
+ file and add ads to the list of strings returned when registering the
+ Database object's DriverName property.
+
+*/
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+ define("_ADODB_ADS_LAYER", 2 );
+
+/*--------------------------------------------------------------------------------------
+--------------------------------------------------------------------------------------*/
+
+
+class ADODB_ads extends ADOConnection {
+ var $databaseType = "ads";
+ var $fmt = "'m-d-Y'";
+ var $fmtTimeStamp = "'Y-m-d H:i:s'";
+ var $concat_operator = '';
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $dataProvider = "ads";
+ var $hasAffectedRows = true;
+ var $binmode = ODBC_BINMODE_RETURN;
+ var $useFetchArray = false; // setting this to true will make array elements in FETCH_ASSOC mode case-sensitive
+ // breaking backward-compat
+ //var $longreadlen = 8000; // default number of chars to return for a Blob/Long field
+ var $_bindInputArray = false;
+ var $curmode = SQL_CUR_USE_DRIVER; // See sqlext.h, SQL_CUR_DEFAULT == SQL_CUR_USE_DRIVER == 2L
+ var $_genSeqSQL = "create table %s (id integer)";
+ var $_autocommit = true;
+ var $_haserrorfunctions = true;
+ var $_has_stupid_odbc_fetch_api_change = true;
+ var $_lastAffectedRows = 0;
+ var $uCaseTables = true; // for meta* functions, uppercase table names
+
+
+ function __construct()
+ {
+ $this->_haserrorfunctions = ADODB_PHPVER >= 0x4050;
+ $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
+ }
+
+ // returns true or false
+ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('ads_connect')) return null;
+
+ if ($this->debug && $argDatabasename && $this->databaseType != 'vfp') {
+ ADOConnection::outp("For Advantage Connect(), $argDatabasename is not used. Place dsn in 1st parameter.");
+ }
+ $last_php_error = $this->resetLastError();
+ if ($this->curmode === false) $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword);
+ else $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword,$this->curmode);
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
+
+ return $this->_connectionID != false;
+ }
+
+ // returns true or false
+ function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('ads_connect')) return null;
+
+ $last_php_error = $this->resetLastError();
+ $this->_errorMsg = '';
+ if ($this->debug && $argDatabasename) {
+ ADOConnection::outp("For PConnect(), $argDatabasename is not used. Place dsn in 1st parameter.");
+ }
+ // print "dsn=$argDSN u=$argUsername p=$argPassword<br>"; flush();
+ if ($this->curmode === false) $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword);
+ else $this->_connectionID = ads_pconnect($argDSN,$argUsername,$argPassword,$this->curmode);
+
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ if ($this->_connectionID && $this->autoRollback) @ads_rollback($this->_connectionID);
+ if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
+
+ return $this->_connectionID != false;
+ }
+
+ // returns the Server version and Description
+ function ServerInfo()
+ {
+
+ if (!empty($this->host) && ADODB_PHPVER >= 0x4300) {
+ $stmt = $this->Prepare('EXECUTE PROCEDURE sp_mgGetInstallInfo()');
+ $res = $this->Execute($stmt);
+ if(!$res)
+ print $this->ErrorMsg();
+ else{
+ $ret["version"]= $res->fields[3];
+ $ret["description"]="Advantage Database Server";
+ return $ret;
+ }
+ }
+ else {
+ return ADOConnection::ServerInfo();
+ }
+ }
+
+
+ // returns true or false
+ function CreateSequence($seqname = 'adodbseq', $start = 1)
+ {
+ $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE");
+ if(!$res){
+ print $this->ErrorMsg();
+ return false;
+ }
+ else
+ return true;
+
+ }
+
+ // returns true or false
+ function DropSequence($seqname = 'adodbseq')
+ {
+ $res = $this->Execute("DROP TABLE $seqname");
+ if(!$res){
+ print $this->ErrorMsg();
+ return false;
+ }
+ else
+ return true;
+ }
+
+
+ // returns the generated ID or false
+ // checks if the table already exists, else creates the table and inserts a record into the table
+ // and gets the ID number of the last inserted record.
+ function GenID($seqname = 'adodbseq', $start = 1)
+ {
+ $go = $this->Execute("select * from $seqname");
+ if (!$go){
+ $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE");
+ if(!res){
+ print $this->ErrorMsg();
+ return false;
+ }
+ }
+ $res = $this->Execute("INSERT INTO $seqname VALUES( DEFAULT )");
+ if(!$res){
+ print $this->ErrorMsg();
+ return false;
+ }
+ else{
+ $gen = $this->Execute("SELECT LastAutoInc( STATEMENT ) FROM system.iota");
+ $ret = $gen->fields[0];
+ return $ret;
+ }
+
+ }
+
+
+
+
+ function ErrorMsg()
+ {
+ if ($this->_haserrorfunctions) {
+ if ($this->_errorMsg !== false) return $this->_errorMsg;
+ if (empty($this->_connectionID)) return @ads_errormsg();
+ return @ads_errormsg($this->_connectionID);
+ } else return ADOConnection::ErrorMsg();
+ }
+
+
+ function ErrorNo()
+ {
+
+ if ($this->_haserrorfunctions) {
+ if ($this->_errorCode !== false) {
+ // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
+ return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode;
+ }
+
+ if (empty($this->_connectionID)) $e = @ads_error();
+ else $e = @ads_error($this->_connectionID);
+
+ // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
+ // so we check and patch
+ if (strlen($e)<=2) return 0;
+ return $e;
+ } else return ADOConnection::ErrorNo();
+ }
+
+
+
+ function BeginTrans()
+ {
+ if (!$this->hasTransactions) return false;
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ $this->_autocommit = false;
+ return ads_autocommit($this->_connectionID,false);
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) return true;
+ if (!$ok) return $this->RollbackTrans();
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->_autocommit = true;
+ $ret = ads_commit($this->_connectionID);
+ ads_autocommit($this->_connectionID,true);
+ return $ret;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->_autocommit = true;
+ $ret = ads_rollback($this->_connectionID);
+ ads_autocommit($this->_connectionID,true);
+ return $ret;
+ }
+
+
+ // Returns tables,Views or both on succesfull execution. Returns
+ // tables by default on succesfull execustion.
+ function &MetaTables($ttype = false, $showSchema = false, $mask = false)
+ {
+ $recordSet1 = $this->Execute("select * from system.tables");
+ if(!$recordSet1){
+ print $this->ErrorMsg();
+ return false;
+ }
+ $recordSet2 = $this->Execute("select * from system.views");
+ if(!$recordSet2){
+ print $this->ErrorMsg();
+ return false;
+ }
+ $i=0;
+ while (!$recordSet1->EOF){
+ $arr["$i"] = $recordSet1->fields[0];
+ $recordSet1->MoveNext();
+ $i=$i+1;
+ }
+ if($ttype=='FALSE'){
+ while (!$recordSet2->EOF){
+ $arr["$i"] = $recordSet2->fields[0];
+ $recordSet2->MoveNext();
+ $i=$i+1;
+ }
+ return $arr;
+ }
+ elseif($ttype=='VIEWS'){
+ while (!$recordSet2->EOF){
+ $arrV["$i"] = $recordSet2->fields[0];
+ $recordSet2->MoveNext();
+ $i=$i+1;
+ }
+ return $arrV;
+ }
+ else{
+ return $arr;
+ }
+
+ }
+
+ function &MetaPrimaryKeys($table, $owner = false)
+ {
+ $recordSet = $this->Execute("select table_primary_key from system.tables where name='$table'");
+ if(!$recordSet){
+ print $this->ErrorMsg();
+ return false;
+ }
+ $i=0;
+ while (!$recordSet->EOF){
+ $arr["$i"] = $recordSet->fields[0];
+ $recordSet->MoveNext();
+ $i=$i+1;
+ }
+ return $arr;
+ }
+
+/*
+See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcdatetime_data_type_changes.asp
+/ SQL data type codes /
+#define SQL_UNKNOWN_TYPE 0
+#define SQL_CHAR 1
+#define SQL_NUMERIC 2
+#define SQL_DECIMAL 3
+#define SQL_INTEGER 4
+#define SQL_SMALLINT 5
+#define SQL_FLOAT 6
+#define SQL_REAL 7
+#define SQL_DOUBLE 8
+#if (ODBCVER >= 0x0300)
+#define SQL_DATETIME 9
+#endif
+#define SQL_VARCHAR 12
+
+
+/ One-parameter shortcuts for date/time data types /
+#if (ODBCVER >= 0x0300)
+#define SQL_TYPE_DATE 91
+#define SQL_TYPE_TIME 92
+#define SQL_TYPE_TIMESTAMP 93
+
+#define SQL_UNICODE (-95)
+#define SQL_UNICODE_VARCHAR (-96)
+#define SQL_UNICODE_LONGVARCHAR (-97)
+*/
+ function ODBCTypes($t)
+ {
+ switch ((integer)$t) {
+ case 1:
+ case 12:
+ case 0:
+ case -95:
+ case -96:
+ return 'C';
+ case -97:
+ case -1: //text
+ return 'X';
+ case -4: //image
+ return 'B';
+
+ case 9:
+ case 91:
+ return 'D';
+
+ case 10:
+ case 11:
+ case 92:
+ case 93:
+ return 'T';
+
+ case 4:
+ case 5:
+ case -6:
+ return 'I';
+
+ case -11: // uniqidentifier
+ return 'R';
+ case -7: //bit
+ return 'L';
+
+ default:
+ return 'N';
+ }
+ }
+
+ function &MetaColumns($table, $normalize = true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $false = false;
+ if ($this->uCaseTables) $table = strtoupper($table);
+ $schema = '';
+ $this->_findschema($table,$schema);
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ /*if (false) { // after testing, confirmed that the following does not work becoz of a bug
+ $qid2 = ads_tables($this->_connectionID);
+ $rs = new ADORecordSet_ads($qid2);
+ $ADODB_FETCH_MODE = $savem;
+ if (!$rs) return false;
+ $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
+ $rs->_fetch();
+
+ while (!$rs->EOF) {
+ if ($table == strtoupper($rs->fields[2])) {
+ $q = $rs->fields[0];
+ $o = $rs->fields[1];
+ break;
+ }
+ $rs->MoveNext();
+ }
+ $rs->Close();
+
+ $qid = ads_columns($this->_connectionID,$q,$o,strtoupper($table),'%');
+ } */
+
+ switch ($this->databaseType) {
+ case 'access':
+ case 'vfp':
+ $qid = ads_columns($this->_connectionID);#,'%','',strtoupper($table),'%');
+ break;
+
+
+ case 'db2':
+ $colname = "%";
+ $qid = ads_columns($this->_connectionID, "", $schema, $table, $colname);
+ break;
+
+ default:
+ $qid = @ads_columns($this->_connectionID,'%','%',strtoupper($table),'%');
+ if (empty($qid)) $qid = ads_columns($this->_connectionID);
+ break;
+ }
+ if (empty($qid)) return $false;
+
+ $rs = new ADORecordSet_ads($qid);
+ $ADODB_FETCH_MODE = $savem;
+
+ if (!$rs) return $false;
+ $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
+ $rs->_fetch();
+
+ $retarr = array();
+
+ /*
+ $rs->fields indices
+ 0 TABLE_QUALIFIER
+ 1 TABLE_SCHEM
+ 2 TABLE_NAME
+ 3 COLUMN_NAME
+ 4 DATA_TYPE
+ 5 TYPE_NAME
+ 6 PRECISION
+ 7 LENGTH
+ 8 SCALE
+ 9 RADIX
+ 10 NULLABLE
+ 11 REMARKS
+ */
+ while (!$rs->EOF) {
+ // adodb_pr($rs->fields);
+ if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[3];
+ $fld->type = $this->ODBCTypes($rs->fields[4]);
+
+ // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp
+ // access uses precision to store length for char/varchar
+ if ($fld->type == 'C' or $fld->type == 'X') {
+ if ($this->databaseType == 'access')
+ $fld->max_length = $rs->fields[6];
+ else if ($rs->fields[4] <= -95) // UNICODE
+ $fld->max_length = $rs->fields[7]/2;
+ else
+ $fld->max_length = $rs->fields[7];
+ } else
+ $fld->max_length = $rs->fields[7];
+ $fld->not_null = !empty($rs->fields[10]);
+ $fld->scale = $rs->fields[8];
+ $retarr[strtoupper($fld->name)] = $fld;
+ } else if (sizeof($retarr)>0)
+ break;
+ $rs->MoveNext();
+ }
+ $rs->Close(); //-- crashes 4.03pl1 -- why?
+
+ if (empty($retarr)) $retarr = false;
+ return $retarr;
+ }
+
+ // Returns an array of columns names for a given table
+ function &MetaColumnNames($table, $numIndexes = false, $useattnum = false)
+ {
+ $recordSet = $this->Execute("select name from system.columns where parent='$table'");
+ if(!$recordSet){
+ print $this->ErrorMsg();
+ return false;
+ }
+ else{
+ $i=0;
+ while (!$recordSet->EOF){
+ $arr["FIELD$i"] = $recordSet->fields[0];
+ $recordSet->MoveNext();
+ $i=$i+1;
+ }
+ return $arr;
+ }
+ }
+
+
+ function Prepare($sql)
+ {
+ if (! $this->_bindInputArray) return $sql; // no binding
+ $stmt = ads_prepare($this->_connectionID,$sql);
+ if (!$stmt) {
+ // we don't know whether odbc driver is parsing prepared stmts, so just return sql
+ return $sql;
+ }
+ return array($sql,$stmt,false);
+ }
+
+ /* returns queryID or false */
+ function _query($sql,$inputarr=false)
+ {
+ $last_php_error = $this->resetLastError();
+ $this->_errorMsg = '';
+
+ if ($inputarr) {
+ if (is_array($sql)) {
+ $stmtid = $sql[1];
+ } else {
+ $stmtid = ads_prepare($this->_connectionID,$sql);
+
+ if ($stmtid == false) {
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ return false;
+ }
+ }
+
+ if (! ads_execute($stmtid,$inputarr)) {
+ //@ads_free_result($stmtid);
+ if ($this->_haserrorfunctions) {
+ $this->_errorMsg = ads_errormsg();
+ $this->_errorCode = ads_error();
+ }
+ return false;
+ }
+
+ } else if (is_array($sql)) {
+ $stmtid = $sql[1];
+ if (!ads_execute($stmtid)) {
+ //@ads_free_result($stmtid);
+ if ($this->_haserrorfunctions) {
+ $this->_errorMsg = ads_errormsg();
+ $this->_errorCode = ads_error();
+ }
+ return false;
+ }
+ } else
+ {
+
+ $stmtid = ads_exec($this->_connectionID,$sql);
+
+ }
+
+ $this->_lastAffectedRows = 0;
+
+ if ($stmtid) {
+
+ if (@ads_num_fields($stmtid) == 0) {
+ $this->_lastAffectedRows = ads_num_rows($stmtid);
+ $stmtid = true;
+
+ } else {
+
+ $this->_lastAffectedRows = 0;
+ ads_binmode($stmtid,$this->binmode);
+ ads_longreadlen($stmtid,$this->maxblobsize);
+
+ }
+
+ if ($this->_haserrorfunctions) {
+ $this->_errorMsg = '';
+ $this->_errorCode = 0;
+ } else {
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ }
+ } else {
+ if ($this->_haserrorfunctions) {
+ $this->_errorMsg = ads_errormsg();
+ $this->_errorCode = ads_error();
+ } else {
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ }
+ }
+
+ return $stmtid;
+
+ }
+
+ /*
+ Insert a null into the blob field of the table first.
+ Then use UpdateBlob to store the blob.
+
+ Usage:
+
+ $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
+ $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
+ */
+ function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ {
+ $last_php_error = $this->resetLastError();
+ $sql = "UPDATE $table SET $column=? WHERE $where";
+ $stmtid = ads_prepare($this->_connectionID,$sql);
+ if ($stmtid == false){
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ return false;
+ }
+ if (! ads_execute($stmtid,array($val),array(SQL_BINARY) )){
+ if ($this->_haserrorfunctions){
+ $this->_errorMsg = ads_errormsg();
+ $this->_errorCode = ads_error();
+ }
+ return false;
+ }
+ return TRUE;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ $ret = @ads_close($this->_connectionID);
+ $this->_connectionID = false;
+ return $ret;
+ }
+
+ function _affectedrows()
+ {
+ return $this->_lastAffectedRows;
+ }
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_ads extends ADORecordSet {
+
+ var $bind = false;
+ var $databaseType = "ads";
+ var $dataProvider = "ads";
+ var $useFetchArray;
+ var $_has_stupid_odbc_fetch_api_change;
+
+ function __construct($id,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ $this->fetchMode = $mode;
+
+ $this->_queryID = $id;
+
+ // the following is required for mysql odbc driver in 4.3.1 -- why?
+ $this->EOF = false;
+ $this->_currentRow = -1;
+ //parent::__construct($id);
+ }
+
+
+ // returns the field object
+ function &FetchField($fieldOffset = -1)
+ {
+
+ $off=$fieldOffset+1; // offsets begin at 1
+
+ $o= new ADOFieldObject();
+ $o->name = @ads_field_name($this->_queryID,$off);
+ $o->type = @ads_field_type($this->_queryID,$off);
+ $o->max_length = @ads_field_len($this->_queryID,$off);
+ if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
+ else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
+ return $o;
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+
+ function _initrs()
+ {
+ global $ADODB_COUNTRECS;
+ $this->_numOfRows = ($ADODB_COUNTRECS) ? @ads_num_rows($this->_queryID) : -1;
+ $this->_numOfFields = @ads_num_fields($this->_queryID);
+ // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0
+ if ($this->_numOfRows == 0) $this->_numOfRows = -1;
+ //$this->useFetchArray = $this->connection->useFetchArray;
+ $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
+ }
+
+ function _seek($row)
+ {
+ return false;
+ }
+
+ // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated
+ function &GetArrayLimit($nrows,$offset=-1)
+ {
+ if ($offset <= 0) {
+ $rs =& $this->GetArray($nrows);
+ return $rs;
+ }
+ $savem = $this->fetchMode;
+ $this->fetchMode = ADODB_FETCH_NUM;
+ $this->Move($offset);
+ $this->fetchMode = $savem;
+
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ $this->fields =& $this->GetRowAssoc();
+ }
+
+ $results = array();
+ $cnt = 0;
+ while (!$this->EOF && $nrows != $cnt) {
+ $results[$cnt++] = $this->fields;
+ $this->MoveNext();
+ }
+
+ return $results;
+ }
+
+
+ function MoveNext()
+ {
+ if ($this->_numOfRows != 0 && !$this->EOF) {
+ $this->_currentRow++;
+ if( $this->_fetch() ) {
+ return true;
+ }
+ }
+ $this->fields = false;
+ $this->EOF = true;
+ return false;
+ }
+
+ function _fetch()
+ {
+ $this->fields = false;
+ if ($this->_has_stupid_odbc_fetch_api_change)
+ $rez = @ads_fetch_into($this->_queryID,$this->fields);
+ else {
+ $row = 0;
+ $rez = @ads_fetch_into($this->_queryID,$row,$this->fields);
+ }
+ if ($rez) {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ $this->fields =& $this->GetRowAssoc();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ function _close()
+ {
+ return @ads_free_result($this->_queryID);
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-borland_ibase.inc.php b/vendor/adodb/adodb-php/drivers/adodb-borland_ibase.inc.php
new file mode 100644
index 0000000..70a746a
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-borland_ibase.inc.php
@@ -0,0 +1,89 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Support Borland Interbase 6.5 and later
+
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR."/drivers/adodb-ibase.inc.php");
+
+class ADODB_borland_ibase extends ADODB_ibase {
+ var $databaseType = "borland_ibase";
+
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ $this->autoCommit = false;
+ $this->_transactionID = ibase_trans($this->ibasetrans, $this->_connectionID);
+ return $this->_transactionID;
+ }
+
+ function ServerInfo()
+ {
+ $arr['dialect'] = $this->dialect;
+ switch($arr['dialect']) {
+ case '':
+ case '1': $s = 'Interbase 6.5, Dialect 1'; break;
+ case '2': $s = 'Interbase 6.5, Dialect 2'; break;
+ default:
+ case '3': $s = 'Interbase 6.5, Dialect 3'; break;
+ }
+ $arr['version'] = '6.5';
+ $arr['description'] = $s;
+ return $arr;
+ }
+
+ // Note that Interbase 6.5 uses ROWS instead - don't you love forking wars!
+ // SELECT col1, col2 FROM table ROWS 5 -- get 5 rows
+ // SELECT col1, col2 FROM TABLE ORDER BY col1 ROWS 3 TO 7 -- first 5 skip 2
+ // Firebird uses
+ // SELECT FIRST 5 SKIP 2 col1, col2 FROM TABLE
+ function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ if ($nrows > 0) {
+ if ($offset <= 0) $str = " ROWS $nrows ";
+ else {
+ $a = $offset+1;
+ $b = $offset+$nrows;
+ $str = " ROWS $a TO $b";
+ }
+ } else {
+ // ok, skip
+ $a = $offset + 1;
+ $str = " ROWS $a TO 999999999"; // 999 million
+ }
+ $sql .= $str;
+
+ return ($secs2cache) ?
+ $this->CacheExecute($secs2cache,$sql,$inputarr)
+ :
+ $this->Execute($sql,$inputarr);
+ }
+
+};
+
+
+class ADORecordSet_borland_ibase extends ADORecordSet_ibase {
+
+ var $databaseType = "borland_ibase";
+
+ function __construct($id,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-csv.inc.php b/vendor/adodb/adodb-php/drivers/adodb-csv.inc.php
new file mode 100644
index 0000000..8e0766a
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-csv.inc.php
@@ -0,0 +1,209 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 4.
+
+ Currently unsupported: MetaDatabases, MetaTables and MetaColumns, and also inputarr in Execute.
+ Native types have been converted to MetaTypes.
+ Transactions not supported yet.
+
+ Limitation of url length. For IIS, see MaxClientRequestBuffer registry value.
+
+ http://support.microsoft.com/default.aspx?scid=kb;en-us;260694
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (! defined("_ADODB_CSV_LAYER")) {
+ define("_ADODB_CSV_LAYER", 1 );
+
+include_once(ADODB_DIR.'/adodb-csvlib.inc.php');
+
+class ADODB_csv extends ADOConnection {
+ var $databaseType = 'csv';
+ var $databaseProvider = 'csv';
+ var $hasInsertID = true;
+ var $hasAffectedRows = true;
+ var $fmtTimeStamp = "'Y-m-d H:i:s'";
+ var $_affectedrows=0;
+ var $_insertid=0;
+ var $_url;
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $hasTransactions = false;
+ var $_errorNo = false;
+
+ function __construct()
+ {
+ }
+
+ function _insertid()
+ {
+ return $this->_insertid;
+ }
+
+ function _affectedrows()
+ {
+ return $this->_affectedrows;
+ }
+
+ function MetaDatabases()
+ {
+ return false;
+ }
+
+
+ // returns true or false
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (strtolower(substr($argHostname,0,7)) !== 'http://') return false;
+ $this->_url = $argHostname;
+ return true;
+ }
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (strtolower(substr($argHostname,0,7)) !== 'http://') return false;
+ $this->_url = $argHostname;
+ return true;
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ return false;
+ }
+
+
+ // parameters use PostgreSQL convention, not MySQL
+ function SelectLimit($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs2cache = 0)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ $url = $this->_url.'?sql='.urlencode($sql)."&nrows=$nrows&fetch=".
+ (($this->fetchMode !== false)?$this->fetchMode : $ADODB_FETCH_MODE).
+ "&offset=$offset";
+ $err = false;
+ $rs = csv2rs($url,$err,false);
+
+ if ($this->debug) print "$url<br><i>$err</i><br>";
+
+ $at = strpos($err,'::::');
+ if ($at === false) {
+ $this->_errorMsg = $err;
+ $this->_errorNo = (integer)$err;
+ } else {
+ $this->_errorMsg = substr($err,$at+4,1024);
+ $this->_errorNo = -9999;
+ }
+ if ($this->_errorNo)
+ if ($fn = $this->raiseErrorFn) {
+ $fn($this->databaseType,'EXECUTE',$this->ErrorNo(),$this->ErrorMsg(),$sql,'');
+ }
+
+ if (is_object($rs)) {
+
+ $rs->databaseType='csv';
+ $rs->fetchMode = ($this->fetchMode !== false) ? $this->fetchMode : $ADODB_FETCH_MODE;
+ $rs->connection = $this;
+ }
+ return $rs;
+ }
+
+ // returns queryID or false
+ function _Execute($sql,$inputarr=false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ if (!$this->_bindInputArray && $inputarr) {
+ $sqlarr = explode('?',$sql);
+ $sql = '';
+ $i = 0;
+ foreach($inputarr as $v) {
+
+ $sql .= $sqlarr[$i];
+ if (gettype($v) == 'string')
+ $sql .= $this->qstr($v);
+ else if ($v === null)
+ $sql .= 'NULL';
+ else
+ $sql .= $v;
+ $i += 1;
+
+ }
+ $sql .= $sqlarr[$i];
+ if ($i+1 != sizeof($sqlarr))
+ print "Input Array does not match ?: ".htmlspecialchars($sql);
+ $inputarr = false;
+ }
+
+ $url = $this->_url.'?sql='.urlencode($sql)."&fetch=".
+ (($this->fetchMode !== false)?$this->fetchMode : $ADODB_FETCH_MODE);
+ $err = false;
+
+
+ $rs = csv2rs($url,$err,false);
+ if ($this->debug) print urldecode($url)."<br><i>$err</i><br>";
+ $at = strpos($err,'::::');
+ if ($at === false) {
+ $this->_errorMsg = $err;
+ $this->_errorNo = (integer)$err;
+ } else {
+ $this->_errorMsg = substr($err,$at+4,1024);
+ $this->_errorNo = -9999;
+ }
+
+ if ($this->_errorNo)
+ if ($fn = $this->raiseErrorFn) {
+ $fn($this->databaseType,'EXECUTE',$this->ErrorNo(),$this->ErrorMsg(),$sql,$inputarr);
+ }
+ if (is_object($rs)) {
+ $rs->fetchMode = ($this->fetchMode !== false) ? $this->fetchMode : $ADODB_FETCH_MODE;
+
+ $this->_affectedrows = $rs->affectedrows;
+ $this->_insertid = $rs->insertid;
+ $rs->databaseType='csv';
+ $rs->connection = $this;
+ }
+ return $rs;
+ }
+
+ /* Returns: the last error message from previous database operation */
+ function ErrorMsg()
+ {
+ return $this->_errorMsg;
+ }
+
+ /* Returns: the last error number from previous database operation */
+ function ErrorNo()
+ {
+ return $this->_errorNo;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ return true;
+ }
+} // class
+
+class ADORecordset_csv extends ADORecordset {
+ function __construct($id,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+
+ function _close()
+ {
+ return true;
+ }
+}
+
+} // define
diff --git a/vendor/adodb/adodb-php/drivers/adodb-db2.inc.php b/vendor/adodb/adodb-php/drivers/adodb-db2.inc.php
new file mode 100644
index 0000000..bfe99cd
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-db2.inc.php
@@ -0,0 +1,843 @@
+<?php
+/**
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+
+ This is a version of the ADODB driver for DB2. It uses the 'ibm_db2' PECL extension
+ for PHP (http://pecl.php.net/package/ibm_db2), which in turn requires DB2 V8.2.2 or
+ higher.
+
+ Originally tested with PHP 5.1.1 and Apache 2.0.55 on Windows XP SP2.
+ More recently tested with PHP 5.1.2 and Apache 2.0.55 on Windows XP SP2.
+
+ This file was ported from "adodb-odbc.inc.php" by Larry Menard, "larry.menard#rogers.com".
+ I ripped out what I believed to be a lot of redundant or obsolete code, but there are
+ probably still some remnants of the ODBC support in this file; I'm relying on reviewers
+ of this code to point out any other things that can be removed.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+ define("_ADODB_DB2_LAYER", 2 );
+
+/*--------------------------------------------------------------------------------------
+--------------------------------------------------------------------------------------*/
+
+
+
+
+
+class ADODB_db2 extends ADOConnection {
+ var $databaseType = "db2";
+ var $fmtDate = "'Y-m-d'";
+ var $concat_operator = '||';
+
+ var $sysTime = 'CURRENT TIME';
+ var $sysDate = 'CURRENT DATE';
+ var $sysTimeStamp = 'CURRENT TIMESTAMP';
+
+ var $fmtTimeStamp = "'Y-m-d H:i:s'";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $dataProvider = "db2";
+ var $hasAffectedRows = true;
+
+ var $binmode = DB2_BINARY;
+
+ var $useFetchArray = false; // setting this to true will make array elements in FETCH_ASSOC mode case-sensitive
+ // breaking backward-compat
+ var $_bindInputArray = false;
+ var $_genIDSQL = "VALUES NEXTVAL FOR %s";
+ var $_genSeqSQL = "CREATE SEQUENCE %s START WITH %s NO MAXVALUE NO CYCLE";
+ var $_dropSeqSQL = "DROP SEQUENCE %s";
+ var $_autocommit = true;
+ var $_haserrorfunctions = true;
+ var $_lastAffectedRows = 0;
+ var $uCaseTables = true; // for meta* functions, uppercase table names
+ var $hasInsertID = true;
+
+
+ function _insertid()
+ {
+ return ADOConnection::GetOne('VALUES IDENTITY_VAL_LOCAL()');
+ }
+
+ function __construct()
+ {
+ $this->_haserrorfunctions = ADODB_PHPVER >= 0x4050;
+ }
+
+ // returns true or false
+ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('db2_connect')) {
+ ADOConnection::outp("Warning: The old ODBC based DB2 driver has been renamed 'odbc_db2'. This ADOdb driver calls PHP's native db2 extension which is not installed.");
+ return null;
+ }
+ // This needs to be set before the connect().
+ // Replaces the odbc_binmode() call that was in Execute()
+ ini_set('ibm_db2.binmode', $this->binmode);
+
+ if ($argDatabasename && empty($argDSN)) {
+
+ if (stripos($argDatabasename,'UID=') && stripos($argDatabasename,'PWD=')) $this->_connectionID = db2_connect($argDatabasename,null,null);
+ else $this->_connectionID = db2_connect($argDatabasename,$argUsername,$argPassword);
+ } else {
+ if ($argDatabasename) $schema = $argDatabasename;
+ if (stripos($argDSN,'UID=') && stripos($argDSN,'PWD=')) $this->_connectionID = db2_connect($argDSN,null,null);
+ else $this->_connectionID = db2_connect($argDSN,$argUsername,$argPassword);
+ }
+
+ // For db2_connect(), there is an optional 4th arg. If present, it must be
+ // an array of valid options. So far, we don't use them.
+
+ $this->_errorMsg = @db2_conn_errormsg();
+ if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
+
+ if ($this->_connectionID && isset($schema)) $this->Execute("SET SCHEMA=$schema");
+ return $this->_connectionID != false;
+ }
+
+ // returns true or false
+ function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('db2_connect')) return null;
+
+ // This needs to be set before the connect().
+ // Replaces the odbc_binmode() call that was in Execute()
+ ini_set('ibm_db2.binmode', $this->binmode);
+
+ $this->_errorMsg = '';
+
+ if ($argDatabasename && empty($argDSN)) {
+
+ if (stripos($argDatabasename,'UID=') && stripos($argDatabasename,'PWD=')) $this->_connectionID = db2_pconnect($argDatabasename,null,null);
+ else $this->_connectionID = db2_pconnect($argDatabasename,$argUsername,$argPassword);
+ } else {
+ if ($argDatabasename) $schema = $argDatabasename;
+ if (stripos($argDSN,'UID=') && stripos($argDSN,'PWD=')) $this->_connectionID = db2_pconnect($argDSN,null,null);
+ else $this->_connectionID = db2_pconnect($argDSN,$argUsername,$argPassword);
+ }
+
+ $this->_errorMsg = @db2_conn_errormsg();
+ if ($this->_connectionID && $this->autoRollback) @db2_rollback($this->_connectionID);
+ if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
+
+ if ($this->_connectionID && isset($schema)) $this->Execute("SET SCHEMA=$schema");
+ return $this->_connectionID != false;
+ }
+
+ // format and return date string in database timestamp format
+ function DBTimeStamp($ts, $isfld = false)
+ {
+ if (empty($ts) && $ts !== 0) return 'null';
+ if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts);
+ return 'TO_DATE('.adodb_date($this->fmtTimeStamp,$ts).",'YYYY-MM-DD HH24:MI:SS')";
+ }
+
+ // Format date column in sql string given an input format that understands Y M D
+ function SQLDate($fmt, $col=false)
+ {
+ // use right() and replace() ?
+ if (!$col) $col = $this->sysDate;
+
+ /* use TO_CHAR() if $fmt is TO_CHAR() allowed fmt */
+ if ($fmt== 'Y-m-d H:i:s')
+ return 'TO_CHAR('.$col.", 'YYYY-MM-DD HH24:MI:SS')";
+
+ $s = '';
+
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ if ($s) $s .= $this->concat_operator;
+ $ch = $fmt[$i];
+ switch($ch) {
+ case 'Y':
+ case 'y':
+ if ($len==1) return "year($col)";
+ $s .= "char(year($col))";
+ break;
+ case 'M':
+ if ($len==1) return "monthname($col)";
+ $s .= "substr(monthname($col),1,3)";
+ break;
+ case 'm':
+ if ($len==1) return "month($col)";
+ $s .= "right(digits(month($col)),2)";
+ break;
+ case 'D':
+ case 'd':
+ if ($len==1) return "day($col)";
+ $s .= "right(digits(day($col)),2)";
+ break;
+ case 'H':
+ case 'h':
+ if ($len==1) return "hour($col)";
+ if ($col != $this->sysDate) $s .= "right(digits(hour($col)),2)";
+ else $s .= "''";
+ break;
+ case 'i':
+ case 'I':
+ if ($len==1) return "minute($col)";
+ if ($col != $this->sysDate)
+ $s .= "right(digits(minute($col)),2)";
+ else $s .= "''";
+ break;
+ case 'S':
+ case 's':
+ if ($len==1) return "second($col)";
+ if ($col != $this->sysDate)
+ $s .= "right(digits(second($col)),2)";
+ else $s .= "''";
+ break;
+ default:
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ $s .= $this->qstr($ch);
+ }
+ }
+ return $s;
+ }
+
+
+ function ServerInfo()
+ {
+ $row = $this->GetRow("SELECT service_level, fixpack_num FROM TABLE(sysproc.env_get_inst_info())
+ as INSTANCEINFO");
+
+
+ if ($row) {
+ $info['version'] = $row[0].':'.$row[1];
+ $info['fixpack'] = $row[1];
+ $info['description'] = '';
+ } else {
+ return ADOConnection::ServerInfo();
+ }
+
+ return $info;
+ }
+
+ function CreateSequence($seqname='adodbseq',$start=1)
+ {
+ if (empty($this->_genSeqSQL)) return false;
+ $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname,$start));
+ if (!$ok) return false;
+ return true;
+ }
+
+ function DropSequence($seqname = 'adodbseq')
+ {
+ if (empty($this->_dropSeqSQL)) return false;
+ return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
+ }
+
+ function SelectLimit($sql, $nrows = -1, $offset = -1, $inputArr = false, $secs2cache = 0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ if ($offset <= 0) {
+ // could also use " OPTIMIZE FOR $nrows ROWS "
+ if ($nrows >= 0) $sql .= " FETCH FIRST $nrows ROWS ONLY ";
+ $rs = $this->Execute($sql,$inputArr);
+ } else {
+ if ($offset > 0 && $nrows < 0);
+ else {
+ $nrows += $offset;
+ $sql .= " FETCH FIRST $nrows ROWS ONLY ";
+ }
+ $rs = ADOConnection::SelectLimit($sql,-1,$offset,$inputArr);
+ }
+
+ return $rs;
+ }
+
+ /*
+ This algorithm is not very efficient, but works even if table locking
+ is not available.
+
+ Will return false if unable to generate an ID after $MAXLOOPS attempts.
+ */
+ function GenID($seq='adodbseq',$start=1)
+ {
+ // if you have to modify the parameter below, your database is overloaded,
+ // or you need to implement generation of id's yourself!
+ $num = $this->GetOne("VALUES NEXTVAL FOR $seq");
+ return $num;
+ }
+
+
+ function ErrorMsg()
+ {
+ if ($this->_haserrorfunctions) {
+ if ($this->_errorMsg !== false) return $this->_errorMsg;
+ if (empty($this->_connectionID)) return @db2_conn_errormsg();
+ return @db2_conn_errormsg($this->_connectionID);
+ } else return ADOConnection::ErrorMsg();
+ }
+
+ function ErrorNo()
+ {
+
+ if ($this->_haserrorfunctions) {
+ if ($this->_errorCode !== false) {
+ // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
+ return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode;
+ }
+
+ if (empty($this->_connectionID)) $e = @db2_conn_error();
+ else $e = @db2_conn_error($this->_connectionID);
+
+ // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
+ // so we check and patch
+ if (strlen($e)<=2) return 0;
+ return $e;
+ } else return ADOConnection::ErrorNo();
+ }
+
+
+
+ function BeginTrans()
+ {
+ if (!$this->hasTransactions) return false;
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ $this->_autocommit = false;
+ return db2_autocommit($this->_connectionID,false);
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) return true;
+ if (!$ok) return $this->RollbackTrans();
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->_autocommit = true;
+ $ret = db2_commit($this->_connectionID);
+ db2_autocommit($this->_connectionID,true);
+ return $ret;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->_autocommit = true;
+ $ret = db2_rollback($this->_connectionID);
+ db2_autocommit($this->_connectionID,true);
+ return $ret;
+ }
+
+ function MetaPrimaryKeys($table, $owner = false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ if ($this->uCaseTables) $table = strtoupper($table);
+ $schema = '';
+ $this->_findschema($table,$schema);
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $qid = @db2_primarykeys($this->_connectionID,'',$schema,$table);
+
+ if (!$qid) {
+ $ADODB_FETCH_MODE = $savem;
+ return false;
+ }
+ $rs = new ADORecordSet_db2($qid);
+ $ADODB_FETCH_MODE = $savem;
+
+ if (!$rs) return false;
+
+ $arr = $rs->GetArray();
+ $rs->Close();
+ $arr2 = array();
+ for ($i=0; $i < sizeof($arr); $i++) {
+ if ($arr[$i][3]) $arr2[] = $arr[$i][3];
+ }
+ return $arr2;
+ }
+
+ function MetaForeignKeys($table, $owner = FALSE, $upper = FALSE, $asociative = FALSE )
+ {
+ global $ADODB_FETCH_MODE;
+
+ if ($this->uCaseTables) $table = strtoupper($table);
+ $schema = '';
+ $this->_findschema($table,$schema);
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $qid = @db2_foreign_keys($this->_connectionID,'',$schema,$table);
+ if (!$qid) {
+ $ADODB_FETCH_MODE = $savem;
+ return false;
+ }
+ $rs = new ADORecordSet_db2($qid);
+
+ $ADODB_FETCH_MODE = $savem;
+ /*
+ $rs->fields indices
+ 0 PKTABLE_CAT
+ 1 PKTABLE_SCHEM
+ 2 PKTABLE_NAME
+ 3 PKCOLUMN_NAME
+ 4 FKTABLE_CAT
+ 5 FKTABLE_SCHEM
+ 6 FKTABLE_NAME
+ 7 FKCOLUMN_NAME
+ */
+ if (!$rs) return false;
+
+ $foreign_keys = array();
+ while (!$rs->EOF) {
+ if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
+ if (!is_array($foreign_keys[$rs->fields[5].'.'.$rs->fields[6]]))
+ $foreign_keys[$rs->fields[5].'.'.$rs->fields[6]] = array();
+ $foreign_keys[$rs->fields[5].'.'.$rs->fields[6]][$rs->fields[7]] = $rs->fields[3];
+ }
+ $rs->MoveNext();
+ }
+
+ $rs->Close();
+ return $foreign_key;
+ }
+
+
+ function MetaTables($ttype = false, $schema = false, $mask = false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $qid = db2_tables($this->_connectionID);
+
+ $rs = new ADORecordSet_db2($qid);
+
+ $ADODB_FETCH_MODE = $savem;
+ if (!$rs) {
+ $false = false;
+ return $false;
+ }
+
+ $arr = $rs->GetArray();
+ $rs->Close();
+ $arr2 = array();
+
+ if ($ttype) {
+ $isview = strncmp($ttype,'V',1) === 0;
+ }
+ for ($i=0; $i < sizeof($arr); $i++) {
+ if (!$arr[$i][2]) continue;
+ $type = $arr[$i][3];
+ $owner = $arr[$i][1];
+ $schemaval = ($schema) ? $arr[$i][1].'.' : '';
+ if ($ttype) {
+ if ($isview) {
+ if (strncmp($type,'V',1) === 0) $arr2[] = $schemaval.$arr[$i][2];
+ } else if (strncmp($owner,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2];
+ } else if (strncmp($owner,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2];
+ }
+ return $arr2;
+ }
+
+/*
+See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2datetime_data_type_changes.asp
+/ SQL data type codes /
+#define SQL_UNKNOWN_TYPE 0
+#define SQL_CHAR 1
+#define SQL_NUMERIC 2
+#define SQL_DECIMAL 3
+#define SQL_INTEGER 4
+#define SQL_SMALLINT 5
+#define SQL_FLOAT 6
+#define SQL_REAL 7
+#define SQL_DOUBLE 8
+#if (DB2VER >= 0x0300)
+#define SQL_DATETIME 9
+#endif
+#define SQL_VARCHAR 12
+
+
+/ One-parameter shortcuts for date/time data types /
+#if (DB2VER >= 0x0300)
+#define SQL_TYPE_DATE 91
+#define SQL_TYPE_TIME 92
+#define SQL_TYPE_TIMESTAMP 93
+
+#define SQL_UNICODE (-95)
+#define SQL_UNICODE_VARCHAR (-96)
+#define SQL_UNICODE_LONGVARCHAR (-97)
+*/
+ function DB2Types($t)
+ {
+ switch ((integer)$t) {
+ case 1:
+ case 12:
+ case 0:
+ case -95:
+ case -96:
+ return 'C';
+ case -97:
+ case -1: //text
+ return 'X';
+ case -4: //image
+ return 'B';
+
+ case 9:
+ case 91:
+ return 'D';
+
+ case 10:
+ case 11:
+ case 92:
+ case 93:
+ return 'T';
+
+ case 4:
+ case 5:
+ case -6:
+ return 'I';
+
+ case -11: // uniqidentifier
+ return 'R';
+ case -7: //bit
+ return 'L';
+
+ default:
+ return 'N';
+ }
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $false = false;
+ if ($this->uCaseTables) $table = strtoupper($table);
+ $schema = '';
+ $this->_findschema($table,$schema);
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ $colname = "%";
+ $qid = db2_columns($this->_connectionID, "", $schema, $table, $colname);
+ if (empty($qid)) return $false;
+
+ $rs = new ADORecordSet_db2($qid);
+ $ADODB_FETCH_MODE = $savem;
+
+ if (!$rs) return $false;
+ $rs->_fetch();
+
+ $retarr = array();
+
+ /*
+ $rs->fields indices
+ 0 TABLE_QUALIFIER
+ 1 TABLE_SCHEM
+ 2 TABLE_NAME
+ 3 COLUMN_NAME
+ 4 DATA_TYPE
+ 5 TYPE_NAME
+ 6 PRECISION
+ 7 LENGTH
+ 8 SCALE
+ 9 RADIX
+ 10 NULLABLE
+ 11 REMARKS
+ */
+ while (!$rs->EOF) {
+ if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[3];
+ $fld->type = $this->DB2Types($rs->fields[4]);
+
+ // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp
+ // access uses precision to store length for char/varchar
+ if ($fld->type == 'C' or $fld->type == 'X') {
+ if ($rs->fields[4] <= -95) // UNICODE
+ $fld->max_length = $rs->fields[7]/2;
+ else
+ $fld->max_length = $rs->fields[7];
+ } else
+ $fld->max_length = $rs->fields[7];
+ $fld->not_null = !empty($rs->fields[10]);
+ $fld->scale = $rs->fields[8];
+ $fld->primary_key = false;
+ $retarr[strtoupper($fld->name)] = $fld;
+ } else if (sizeof($retarr)>0)
+ break;
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ if (empty($retarr)) $retarr = false;
+
+ $qid = db2_primary_keys($this->_connectionID, "", $schema, $table);
+ if (empty($qid)) return $false;
+
+ $rs = new ADORecordSet_db2($qid);
+ $ADODB_FETCH_MODE = $savem;
+
+ if (!$rs) return $retarr;
+ $rs->_fetch();
+
+ /*
+ $rs->fields indices
+ 0 TABLE_CAT
+ 1 TABLE_SCHEM
+ 2 TABLE_NAME
+ 3 COLUMN_NAME
+ 4 KEY_SEQ
+ 5 PK_NAME
+ */
+ while (!$rs->EOF) {
+ if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
+ $retarr[strtoupper($rs->fields[3])]->primary_key = true;
+ } else if (sizeof($retarr)>0)
+ break;
+ $rs->MoveNext();
+ }
+ $rs->Close();
+
+ if (empty($retarr)) $retarr = false;
+ return $retarr;
+ }
+
+
+ function Prepare($sql)
+ {
+ if (! $this->_bindInputArray) return $sql; // no binding
+ $stmt = db2_prepare($this->_connectionID,$sql);
+ if (!$stmt) {
+ // we don't know whether db2 driver is parsing prepared stmts, so just return sql
+ return $sql;
+ }
+ return array($sql,$stmt,false);
+ }
+
+ /* returns queryID or false */
+ function _query($sql,$inputarr=false)
+ {
+ $last_php_error = $this->resetLastError();
+ $this->_errorMsg = '';
+
+ if ($inputarr) {
+ if (is_array($sql)) {
+ $stmtid = $sql[1];
+ } else {
+ $stmtid = db2_prepare($this->_connectionID,$sql);
+
+ if ($stmtid == false) {
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ return false;
+ }
+ }
+
+ if (! db2_execute($stmtid,$inputarr)) {
+ if ($this->_haserrorfunctions) {
+ $this->_errorMsg = db2_stmt_errormsg();
+ $this->_errorCode = db2_stmt_error();
+ }
+ return false;
+ }
+
+ } else if (is_array($sql)) {
+ $stmtid = $sql[1];
+ if (!db2_execute($stmtid)) {
+ if ($this->_haserrorfunctions) {
+ $this->_errorMsg = db2_stmt_errormsg();
+ $this->_errorCode = db2_stmt_error();
+ }
+ return false;
+ }
+ } else
+ $stmtid = @db2_exec($this->_connectionID,$sql);
+
+ $this->_lastAffectedRows = 0;
+ if ($stmtid) {
+ if (@db2_num_fields($stmtid) == 0) {
+ $this->_lastAffectedRows = db2_num_rows($stmtid);
+ $stmtid = true;
+ } else {
+ $this->_lastAffectedRows = 0;
+ }
+
+ if ($this->_haserrorfunctions) {
+ $this->_errorMsg = '';
+ $this->_errorCode = 0;
+ } else {
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ }
+ } else {
+ if ($this->_haserrorfunctions) {
+ $this->_errorMsg = db2_stmt_errormsg();
+ $this->_errorCode = db2_stmt_error();
+ } else {
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ }
+ }
+ return $stmtid;
+ }
+
+ /*
+ Insert a null into the blob field of the table first.
+ Then use UpdateBlob to store the blob.
+
+ Usage:
+
+ $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
+ $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
+ */
+ function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ {
+ return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ $ret = @db2_close($this->_connectionID);
+ $this->_connectionID = false;
+ return $ret;
+ }
+
+ function _affectedrows()
+ {
+ return $this->_lastAffectedRows;
+ }
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_db2 extends ADORecordSet {
+
+ var $bind = false;
+ var $databaseType = "db2";
+ var $dataProvider = "db2";
+ var $useFetchArray;
+
+ function __construct($id,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ $this->fetchMode = $mode;
+
+ $this->_queryID = $id;
+ }
+
+
+ // returns the field object
+ function FetchField($offset = -1)
+ {
+ $o= new ADOFieldObject();
+ $o->name = @db2_field_name($this->_queryID,$offset);
+ $o->type = @db2_field_type($this->_queryID,$offset);
+ $o->max_length = db2_field_width($this->_queryID,$offset);
+ if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
+ else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
+ return $o;
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+
+ function _initrs()
+ {
+ global $ADODB_COUNTRECS;
+ $this->_numOfRows = ($ADODB_COUNTRECS) ? @db2_num_rows($this->_queryID) : -1;
+ $this->_numOfFields = @db2_num_fields($this->_queryID);
+ // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0
+ if ($this->_numOfRows == 0) $this->_numOfRows = -1;
+ }
+
+ function _seek($row)
+ {
+ return false;
+ }
+
+ // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated
+ function GetArrayLimit($nrows,$offset=-1)
+ {
+ if ($offset <= 0) {
+ $rs = $this->GetArray($nrows);
+ return $rs;
+ }
+ $savem = $this->fetchMode;
+ $this->fetchMode = ADODB_FETCH_NUM;
+ $this->Move($offset);
+ $this->fetchMode = $savem;
+
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ $this->fields = $this->GetRowAssoc();
+ }
+
+ $results = array();
+ $cnt = 0;
+ while (!$this->EOF && $nrows != $cnt) {
+ $results[$cnt++] = $this->fields;
+ $this->MoveNext();
+ }
+
+ return $results;
+ }
+
+
+ function MoveNext()
+ {
+ if ($this->_numOfRows != 0 && !$this->EOF) {
+ $this->_currentRow++;
+
+ $this->fields = @db2_fetch_array($this->_queryID);
+ if ($this->fields) {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ $this->fields = $this->GetRowAssoc();
+ }
+ return true;
+ }
+ }
+ $this->fields = false;
+ $this->EOF = true;
+ return false;
+ }
+
+ function _fetch()
+ {
+
+ $this->fields = db2_fetch_array($this->_queryID);
+ if ($this->fields) {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ $this->fields = $this->GetRowAssoc();
+ }
+ return true;
+ }
+ $this->fields = false;
+ return false;
+ }
+
+ function _close()
+ {
+ return @db2_free_result($this->_queryID);
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-db2oci.inc.php b/vendor/adodb/adodb-php/drivers/adodb-db2oci.inc.php
new file mode 100644
index 0000000..850a5d3
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-db2oci.inc.php
@@ -0,0 +1,226 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Microsoft Visual FoxPro data driver. Requires ODBC. Works only on MS Windows.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+include(ADODB_DIR."/drivers/adodb-db2.inc.php");
+
+
+if (!defined('ADODB_DB2OCI')){
+define('ADODB_DB2OCI',1);
+
+/*
+// regex code for smart remapping of :0, :1 bind vars to ? ?
+function _colontrack($p)
+{
+global $_COLONARR,$_COLONSZ;
+ $v = (integer) substr($p,1);
+ if ($v > $_COLONSZ) return $p;
+ $_COLONARR[] = $v;
+ return '?';
+}
+
+// smart remapping of :0, :1 bind vars to ? ?
+function _colonscope($sql,$arr)
+{
+global $_COLONARR,$_COLONSZ;
+
+ $_COLONARR = array();
+ $_COLONSZ = sizeof($arr);
+
+ $sql2 = preg_replace("/(:[0-9]+)/e","_colontrack('\\1')",$sql);
+
+ if (empty($_COLONARR)) return array($sql,$arr);
+
+ foreach($_COLONARR as $k => $v) {
+ $arr2[] = $arr[$v];
+ }
+
+ return array($sql2,$arr2);
+}
+*/
+
+/*
+ Smart remapping of :0, :1 bind vars to ? ?
+
+ Handles colons in comments -- and / * * / and in quoted strings.
+*/
+
+function _colonparser($sql,$arr)
+{
+ $lensql = strlen($sql);
+ $arrsize = sizeof($arr);
+ $state = 'NORM';
+ $at = 1;
+ $ch = $sql[0];
+ $ch2 = @$sql[1];
+ $sql2 = '';
+ $arr2 = array();
+ $nprev = 0;
+
+
+ while (strlen($ch)) {
+
+ switch($ch) {
+ case '/':
+ if ($state == 'NORM' && $ch2 == '*') {
+ $state = 'COMMENT';
+
+ $at += 1;
+ $ch = $ch2;
+ $ch2 = $at < $lensql ? $sql[$at] : '';
+ }
+ break;
+
+ case '*':
+ if ($state == 'COMMENT' && $ch2 == '/') {
+ $state = 'NORM';
+
+ $at += 1;
+ $ch = $ch2;
+ $ch2 = $at < $lensql ? $sql[$at] : '';
+ }
+ break;
+
+ case "\n":
+ case "\r":
+ if ($state == 'COMMENT2') $state = 'NORM';
+ break;
+
+ case "'":
+ do {
+ $at += 1;
+ $ch = $ch2;
+ $ch2 = $at < $lensql ? $sql[$at] : '';
+ } while ($ch !== "'");
+ break;
+
+ case ':':
+ if ($state == 'COMMENT' || $state == 'COMMENT2') break;
+
+ //echo "$at=$ch $ch2, ";
+ if ('0' <= $ch2 && $ch2 <= '9') {
+ $n = '';
+ $nat = $at;
+ do {
+ $at += 1;
+ $ch = $ch2;
+ $n .= $ch;
+ $ch2 = $at < $lensql ? $sql[$at] : '';
+ } while ('0' <= $ch && $ch <= '9');
+ #echo "$n $arrsize ] ";
+ $n = (integer) $n;
+ if ($n < $arrsize) {
+ $sql2 .= substr($sql,$nprev,$nat-$nprev-1).'?';
+ $nprev = $at-1;
+ $arr2[] = $arr[$n];
+ }
+ }
+ break;
+
+ case '-':
+ if ($state == 'NORM') {
+ if ($ch2 == '-') $state = 'COMMENT2';
+ $at += 1;
+ $ch = $ch2;
+ $ch2 = $at < $lensql ? $sql[$at] : '';
+ }
+ break;
+ }
+
+ $at += 1;
+ $ch = $ch2;
+ $ch2 = $at < $lensql ? $sql[$at] : '';
+ }
+
+ if ($nprev == 0) {
+ $sql2 = $sql;
+ } else {
+ $sql2 .= substr($sql,$nprev);
+ }
+
+ return array($sql2,$arr2);
+}
+
+class ADODB_db2oci extends ADODB_db2 {
+ var $databaseType = "db2oci";
+ var $sysTimeStamp = 'sysdate';
+ var $sysDate = 'trunc(sysdate)';
+ var $_bindInputArray = true;
+
+ function Param($name,$type='C')
+ {
+ return ':'.$name;
+ }
+
+
+ function MetaTables($ttype = false, $schema = false, $mask = false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $qid = db2_tables($this->_connectionID);
+
+ $rs = new ADORecordSet_db2($qid);
+
+ $ADODB_FETCH_MODE = $savem;
+ if (!$rs) {
+ $false = false;
+ return $false;
+ }
+
+ $arr = $rs->GetArray();
+ $rs->Close();
+ $arr2 = array();
+ // adodb_pr($arr);
+ if ($ttype) {
+ $isview = strncmp($ttype,'V',1) === 0;
+ }
+ for ($i=0; $i < sizeof($arr); $i++) {
+ if (!$arr[$i][2]) continue;
+ $type = $arr[$i][3];
+ $schemaval = ($schema) ? $arr[$i][1].'.' : '';
+ $name = $schemaval.$arr[$i][2];
+ $owner = $arr[$i][1];
+ if (substr($name,0,8) == 'EXPLAIN_') continue;
+ if ($ttype) {
+ if ($isview) {
+ if (strncmp($type,'V',1) === 0) $arr2[] = $name;
+ } else if (strncmp($type,'T',1) === 0 && strncmp($owner,'SYS',3) !== 0) $arr2[] = $name;
+ } else if (strncmp($type,'T',1) === 0 && strncmp($owner,'SYS',3) !== 0) $arr2[] = $name;
+ }
+ return $arr2;
+ }
+
+ function _Execute($sql, $inputarr=false )
+ {
+ if ($inputarr) list($sql,$inputarr) = _colonparser($sql, $inputarr);
+ return parent::_Execute($sql, $inputarr);
+ }
+};
+
+
+class ADORecordSet_db2oci extends ADORecordSet_db2 {
+
+ var $databaseType = "db2oci";
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+}
+
+} //define
diff --git a/vendor/adodb/adodb-php/drivers/adodb-db2ora.inc.php b/vendor/adodb/adodb-php/drivers/adodb-db2ora.inc.php
new file mode 100644
index 0000000..75cc9f5
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-db2ora.inc.php
@@ -0,0 +1,86 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Microsoft Visual FoxPro data driver. Requires ODBC. Works only on MS Windows.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+include(ADODB_DIR."/drivers/adodb-db2.inc.php");
+
+
+if (!defined('ADODB_DB2OCI')){
+define('ADODB_DB2OCI',1);
+
+
+/**
+ * Callback function for preg_replace in _colonscope()
+ * @param array $p matched patterns
+ * return string '?' if parameter replaced, :N if not
+ */
+function _colontrack($p)
+{
+ global $_COLONARR, $_COLONSZ;
+ $v = (integer) substr($p[1], 1);
+ if ($v > $_COLONSZ) return $p[1];
+ $_COLONARR[] = $v;
+ return '?';
+}
+
+/**
+ * smart remapping of :0, :1 bind vars to ? ?
+ * @param string $sql SQL statement
+ * @param array $arr parameters
+ * @return array
+ */
+function _colonscope($sql,$arr)
+{
+global $_COLONARR,$_COLONSZ;
+
+ $_COLONARR = array();
+ $_COLONSZ = sizeof($arr);
+
+ $sql2 = preg_replace_callback('/(:[0-9]+)/', '_colontrack', $sql);
+
+ if (empty($_COLONARR)) return array($sql,$arr);
+
+ foreach($_COLONARR as $k => $v) {
+ $arr2[] = $arr[$v];
+ }
+
+ return array($sql2,$arr2);
+}
+
+class ADODB_db2oci extends ADODB_db2 {
+ var $databaseType = "db2oci";
+ var $sysTimeStamp = 'sysdate';
+ var $sysDate = 'trunc(sysdate)';
+
+ function _Execute($sql, $inputarr = false)
+ {
+ if ($inputarr) list($sql,$inputarr) = _colonscope($sql, $inputarr);
+ return parent::_Execute($sql, $inputarr);
+ }
+};
+
+
+class ADORecordSet_db2oci extends ADORecordSet_odbc {
+
+ var $databaseType = "db2oci";
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+}
+
+} //define
diff --git a/vendor/adodb/adodb-php/drivers/adodb-fbsql.inc.php b/vendor/adodb/adodb-php/drivers/adodb-fbsql.inc.php
new file mode 100644
index 0000000..bc3d0a6
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-fbsql.inc.php
@@ -0,0 +1,267 @@
+<?php
+/*
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Contribution by Frank M. Kromann <frank@frontbase.com>.
+ Set tabs to 8.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (! defined("_ADODB_FBSQL_LAYER")) {
+ define("_ADODB_FBSQL_LAYER", 1 );
+
+class ADODB_fbsql extends ADOConnection {
+ var $databaseType = 'fbsql';
+ var $hasInsertID = true;
+ var $hasAffectedRows = true;
+ var $metaTablesSQL = "SHOW TABLES";
+ var $metaColumnsSQL = "SHOW COLUMNS FROM %s";
+ var $fmtTimeStamp = "'Y-m-d H:i:s'";
+ var $hasLimit = false;
+
+ function __construct()
+ {
+ }
+
+ function _insertid()
+ {
+ return fbsql_insert_id($this->_connectionID);
+ }
+
+ function _affectedrows()
+ {
+ return fbsql_affected_rows($this->_connectionID);
+ }
+
+ function MetaDatabases()
+ {
+ $qid = fbsql_list_dbs($this->_connectionID);
+ $arr = array();
+ $i = 0;
+ $max = fbsql_num_rows($qid);
+ while ($i < $max) {
+ $arr[] = fbsql_tablename($qid,$i);
+ $i += 1;
+ }
+ return $arr;
+ }
+
+ // returns concatenated string
+ function Concat()
+ {
+ $s = "";
+ $arr = func_get_args();
+ $first = true;
+
+ $s = implode(',',$arr);
+ if (sizeof($arr) > 0) return "CONCAT($s)";
+ else return '';
+ }
+
+ // returns true or false
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ $this->_connectionID = fbsql_connect($argHostname,$argUsername,$argPassword);
+ if ($this->_connectionID === false) return false;
+ if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ return true;
+ }
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ $this->_connectionID = fbsql_pconnect($argHostname,$argUsername,$argPassword);
+ if ($this->_connectionID === false) return false;
+ if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ return true;
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ if ($this->metaColumnsSQL) {
+
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
+
+ if ($rs === false) return false;
+
+ $retarr = array();
+ while (!$rs->EOF){
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $fld->type = $rs->fields[1];
+
+ // split type into type(length):
+ if (preg_match("/^(.+)\((\d+)\)$/", $fld->type, $query_array)) {
+ $fld->type = $query_array[1];
+ $fld->max_length = $query_array[2];
+ } else {
+ $fld->max_length = -1;
+ }
+ $fld->not_null = ($rs->fields[2] != 'YES');
+ $fld->primary_key = ($rs->fields[3] == 'PRI');
+ $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
+ $fld->binary = (strpos($fld->type,'blob') !== false);
+
+ $retarr[strtoupper($fld->name)] = $fld;
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ return $retarr;
+ }
+ return false;
+ }
+
+ // returns true or false
+ function SelectDB($dbName)
+ {
+ $this->database = $dbName;
+ if ($this->_connectionID) {
+ return @fbsql_select_db($dbName,$this->_connectionID);
+ }
+ else return false;
+ }
+
+
+ // returns queryID or false
+ function _query($sql,$inputarr=false)
+ {
+ return fbsql_query("$sql;",$this->_connectionID);
+ }
+
+ /* Returns: the last error message from previous database operation */
+ function ErrorMsg()
+ {
+ $this->_errorMsg = @fbsql_error($this->_connectionID);
+ return $this->_errorMsg;
+ }
+
+ /* Returns: the last error number from previous database operation */
+ function ErrorNo()
+ {
+ return @fbsql_errno($this->_connectionID);
+ }
+
+ // returns true or false
+ function _close()
+ {
+ return @fbsql_close($this->_connectionID);
+ }
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_fbsql extends ADORecordSet{
+
+ var $databaseType = "fbsql";
+ var $canSeek = true;
+
+ function __construct($queryID,$mode=false)
+ {
+ if (!$mode) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ switch ($mode) {
+ case ADODB_FETCH_NUM: $this->fetchMode = FBSQL_NUM; break;
+ case ADODB_FETCH_ASSOC: $this->fetchMode = FBSQL_ASSOC; break;
+ case ADODB_FETCH_BOTH:
+ default:
+ $this->fetchMode = FBSQL_BOTH; break;
+ }
+ return parent::__construct($queryID);
+ }
+
+ function _initrs()
+ {
+ GLOBAL $ADODB_COUNTRECS;
+ $this->_numOfRows = ($ADODB_COUNTRECS) ? @fbsql_num_rows($this->_queryID):-1;
+ $this->_numOfFields = @fbsql_num_fields($this->_queryID);
+ }
+
+
+
+ function FetchField($fieldOffset = -1) {
+ if ($fieldOffset != -1) {
+ $o = @fbsql_fetch_field($this->_queryID, $fieldOffset);
+ //$o->max_length = -1; // fbsql returns the max length less spaces -- so it is unrealiable
+ $f = @fbsql_field_flags($this->_queryID,$fieldOffset);
+ $o->binary = (strpos($f,'binary')!== false);
+ }
+ else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */
+ $o = @fbsql_fetch_field($this->_queryID);// fbsql returns the max length less spaces -- so it is unrealiable
+ //$o->max_length = -1;
+ }
+
+ return $o;
+ }
+
+ function _seek($row)
+ {
+ return @fbsql_data_seek($this->_queryID,$row);
+ }
+
+ function _fetch($ignore_fields=false)
+ {
+ $this->fields = @fbsql_fetch_array($this->_queryID,$this->fetchMode);
+ return ($this->fields == true);
+ }
+
+ function _close() {
+ return @fbsql_free_result($this->_queryID);
+ }
+
+ function MetaType($t,$len=-1,$fieldobj=false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+ $len = -1; // fbsql max_length is not accurate
+ switch (strtoupper($t)) {
+ case 'CHARACTER':
+ case 'CHARACTER VARYING':
+ case 'BLOB':
+ case 'CLOB':
+ case 'BIT':
+ case 'BIT VARYING':
+ if ($len <= $this->blobSize) return 'C';
+
+ // so we have to check whether binary...
+ case 'IMAGE':
+ case 'LONGBLOB':
+ case 'BLOB':
+ case 'MEDIUMBLOB':
+ return !empty($fieldobj->binary) ? 'B' : 'X';
+
+ case 'DATE': return 'D';
+
+ case 'TIME':
+ case 'TIME WITH TIME ZONE':
+ case 'TIMESTAMP':
+ case 'TIMESTAMP WITH TIME ZONE': return 'T';
+
+ case 'PRIMARY_KEY':
+ return 'R';
+ case 'INTEGER':
+ case 'SMALLINT':
+ case 'BOOLEAN':
+
+ if (!empty($fieldobj->primary_key)) return 'R';
+ else return 'I';
+
+ default: return 'N';
+ }
+ }
+
+} //class
+} // defined
diff --git a/vendor/adodb/adodb-php/drivers/adodb-firebird.inc.php b/vendor/adodb/adodb-php/drivers/adodb-firebird.inc.php
new file mode 100644
index 0000000..42aeb2b
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-firebird.inc.php
@@ -0,0 +1,73 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR."/drivers/adodb-ibase.inc.php");
+
+class ADODB_firebird extends ADODB_ibase {
+ var $databaseType = "firebird";
+ var $dialect = 3;
+
+ var $sysTimeStamp = "CURRENT_TIMESTAMP"; //"cast('NOW' as timestamp)";
+
+ function ServerInfo()
+ {
+ $arr['dialect'] = $this->dialect;
+ switch($arr['dialect']) {
+ case '':
+ case '1': $s = 'Firebird Dialect 1'; break;
+ case '2': $s = 'Firebird Dialect 2'; break;
+ default:
+ case '3': $s = 'Firebird Dialect 3'; break;
+ }
+ $arr['version'] = ADOConnection::_findvers($s);
+ $arr['description'] = $s;
+ return $arr;
+ }
+
+ // Note that Interbase 6.5 uses this ROWS instead - don't you love forking wars!
+ // SELECT col1, col2 FROM table ROWS 5 -- get 5 rows
+ // SELECT col1, col2 FROM TABLE ORDER BY col1 ROWS 3 TO 7 -- first 5 skip 2
+ function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false, $secs=0)
+ {
+ $nrows = (integer) $nrows;
+ $offset = (integer) $offset;
+ $str = 'SELECT ';
+ if ($nrows >= 0) $str .= "FIRST $nrows ";
+ $str .=($offset>=0) ? "SKIP $offset " : '';
+
+ $sql = preg_replace('/^[ \t]*select/i',$str,$sql);
+ if ($secs)
+ $rs = $this->CacheExecute($secs,$sql,$inputarr);
+ else
+ $rs = $this->Execute($sql,$inputarr);
+
+ return $rs;
+ }
+
+
+};
+
+
+class ADORecordSet_firebird extends ADORecordSet_ibase {
+
+ var $databaseType = "firebird";
+
+ function __construct($id,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-ibase.inc.php b/vendor/adodb/adodb-php/drivers/adodb-ibase.inc.php
new file mode 100644
index 0000000..639233e
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-ibase.inc.php
@@ -0,0 +1,918 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+
+ Latest version is available at http://adodb.org/
+
+ Interbase data driver. Requires interbase client. Works on Windows and Unix.
+
+ 3 Jan 2002 -- suggestions by Hans-Peter Oeri <kampfcaspar75@oeri.ch>
+ changed transaction handling and added experimental blob stuff
+
+ Docs to interbase at the website
+ http://www.synectics.co.za/php3/tutorial/IB_PHP3_API.html
+
+ To use gen_id(), see
+ http://www.volny.cz/iprenosil/interbase/ip_ib_code.htm#_code_creategen
+
+ $rs = $conn->Execute('select gen_id(adodb,1) from rdb$database');
+ $id = $rs->fields[0];
+ $conn->Execute("insert into table (id, col1,...) values ($id, $val1,...)");
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+class ADODB_ibase extends ADOConnection {
+ var $databaseType = "ibase";
+ var $dataProvider = "ibase";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $ibase_datefmt = '%Y-%m-%d'; // For hours,mins,secs change to '%Y-%m-%d %H:%M:%S';
+ var $fmtDate = "'Y-m-d'";
+ var $ibase_timestampfmt = "%Y-%m-%d %H:%M:%S";
+ var $ibase_timefmt = "%H:%M:%S";
+ var $fmtTimeStamp = "'Y-m-d, H:i:s'";
+ var $concat_operator='||';
+ var $_transactionID;
+ var $metaTablesSQL = "select rdb\$relation_name from rdb\$relations where rdb\$relation_name not like 'RDB\$%'";
+ //OPN STUFF start
+ var $metaColumnsSQL = "select a.rdb\$field_name, a.rdb\$null_flag, a.rdb\$default_source, b.rdb\$field_length, b.rdb\$field_scale, b.rdb\$field_sub_type, b.rdb\$field_precision, b.rdb\$field_type from rdb\$relation_fields a, rdb\$fields b where a.rdb\$field_source = b.rdb\$field_name and a.rdb\$relation_name = '%s' order by a.rdb\$field_position asc";
+ //OPN STUFF end
+ var $ibasetrans;
+ var $hasGenID = true;
+ var $_bindInputArray = true;
+ var $buffers = 0;
+ var $dialect = 1;
+ var $sysDate = "cast('TODAY' as timestamp)";
+ var $sysTimeStamp = "CURRENT_TIMESTAMP"; //"cast('NOW' as timestamp)";
+ var $ansiOuter = true;
+ var $hasAffectedRows = false;
+ var $poorAffectedRows = true;
+ var $blobEncodeType = 'C';
+ var $role = false;
+
+ function __construct()
+ {
+ if (defined('IBASE_DEFAULT')) $this->ibasetrans = IBASE_DEFAULT;
+ }
+
+
+ // returns true or false
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$persist=false)
+ {
+ if (!function_exists('ibase_pconnect')) return null;
+ if ($argDatabasename) $argHostname .= ':'.$argDatabasename;
+ $fn = ($persist) ? 'ibase_pconnect':'ibase_connect';
+ if ($this->role)
+ $this->_connectionID = $fn($argHostname,$argUsername,$argPassword,
+ $this->charSet,$this->buffers,$this->dialect,$this->role);
+ else
+ $this->_connectionID = $fn($argHostname,$argUsername,$argPassword,
+ $this->charSet,$this->buffers,$this->dialect);
+
+ if ($this->dialect != 1) { // http://www.ibphoenix.com/ibp_60_del_id_ds.html
+ $this->replaceQuote = "''";
+ }
+ if ($this->_connectionID === false) {
+ $this->_handleerror();
+ return false;
+ }
+
+ // PHP5 change.
+ if (function_exists('ibase_timefmt')) {
+ ibase_timefmt($this->ibase_datefmt,IBASE_DATE );
+ if ($this->dialect == 1) {
+ ibase_timefmt($this->ibase_datefmt,IBASE_TIMESTAMP );
+ }
+ else {
+ ibase_timefmt($this->ibase_timestampfmt,IBASE_TIMESTAMP );
+ }
+ ibase_timefmt($this->ibase_timefmt,IBASE_TIME );
+
+ } else {
+ ini_set("ibase.timestampformat", $this->ibase_timestampfmt);
+ ini_set("ibase.dateformat", $this->ibase_datefmt);
+ ini_set("ibase.timeformat", $this->ibase_timefmt);
+ }
+ return true;
+ }
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,true);
+ }
+
+
+ function MetaPrimaryKeys($table,$owner_notused=false,$internalKey=false)
+ {
+ if ($internalKey) {
+ return array('RDB$DB_KEY');
+ }
+
+ $table = strtoupper($table);
+
+ $sql = 'SELECT S.RDB$FIELD_NAME AFIELDNAME
+ FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON I.RDB$INDEX_NAME=S.RDB$INDEX_NAME
+ WHERE I.RDB$RELATION_NAME=\''.$table.'\' and I.RDB$INDEX_NAME like \'RDB$PRIMARY%\'
+ ORDER BY I.RDB$INDEX_NAME,S.RDB$FIELD_POSITION';
+
+ $a = $this->GetCol($sql,false,true);
+ if ($a && sizeof($a)>0) return $a;
+ return false;
+ }
+
+ function ServerInfo()
+ {
+ $arr['dialect'] = $this->dialect;
+ switch($arr['dialect']) {
+ case '':
+ case '1': $s = 'Interbase 5.5 or earlier'; break;
+ case '2': $s = 'Interbase 5.6'; break;
+ default:
+ case '3': $s = 'Interbase 6.0'; break;
+ }
+ $arr['version'] = ADOConnection::_findvers($s);
+ $arr['description'] = $s;
+ return $arr;
+ }
+
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ $this->autoCommit = false;
+ $this->_transactionID = $this->_connectionID;//ibase_trans($this->ibasetrans, $this->_connectionID);
+ return $this->_transactionID;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if (!$ok) {
+ return $this->RollbackTrans();
+ }
+ if ($this->transOff) {
+ return true;
+ }
+ if ($this->transCnt) {
+ $this->transCnt -= 1;
+ }
+ $ret = false;
+ $this->autoCommit = true;
+ if ($this->_transactionID) {
+ //print ' commit ';
+ $ret = ibase_commit($this->_transactionID);
+ }
+ $this->_transactionID = false;
+ return $ret;
+ }
+
+ // there are some compat problems with ADODB_COUNTRECS=false and $this->_logsql currently.
+ // it appears that ibase extension cannot support multiple concurrent queryid's
+ function _Execute($sql,$inputarr=false)
+ {
+ global $ADODB_COUNTRECS;
+
+ if ($this->_logsql) {
+ $savecrecs = $ADODB_COUNTRECS;
+ $ADODB_COUNTRECS = true; // force countrecs
+ $ret = ADOConnection::_Execute($sql,$inputarr);
+ $ADODB_COUNTRECS = $savecrecs;
+ } else {
+ $ret = ADOConnection::_Execute($sql,$inputarr);
+ }
+ return $ret;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ if ($this->transCnt) $this->transCnt -= 1;
+ $ret = false;
+ $this->autoCommit = true;
+ if ($this->_transactionID) {
+ $ret = ibase_rollback($this->_transactionID);
+ }
+ $this->_transactionID = false;
+
+ return $ret;
+ }
+
+ function MetaIndexes ($table, $primary = FALSE, $owner=false)
+ {
+ // save old fetch mode
+ global $ADODB_FETCH_MODE;
+ $false = false;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+ $table = strtoupper($table);
+ $sql = "SELECT * FROM RDB\$INDICES WHERE RDB\$RELATION_NAME = '".$table."'";
+ if (!$primary) {
+ $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$%'";
+ } else {
+ $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$FOREIGN%'";
+ }
+ // get index details
+ $rs = $this->Execute($sql);
+ if (!is_object($rs)) {
+ // restore fetchmode
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+ return $false;
+ }
+
+ $indexes = array();
+ while ($row = $rs->FetchRow()) {
+ $index = $row[0];
+ if (!isset($indexes[$index])) {
+ if (is_null($row[3])) {
+ $row[3] = 0;
+ }
+ $indexes[$index] = array(
+ 'unique' => ($row[3] == 1),
+ 'columns' => array()
+ );
+ }
+ $sql = "SELECT * FROM RDB\$INDEX_SEGMENTS WHERE RDB\$INDEX_NAME = '".$index."' ORDER BY RDB\$FIELD_POSITION ASC";
+ $rs1 = $this->Execute($sql);
+ while ($row1 = $rs1->FetchRow()) {
+ $indexes[$index]['columns'][$row1[2]] = $row1[1];
+ }
+ }
+ // restore fetchmode
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ return $indexes;
+ }
+
+
+ // See http://community.borland.com/article/0,1410,25844,00.html
+ function RowLock($tables,$where,$col=false)
+ {
+ if ($this->autoCommit) {
+ $this->BeginTrans();
+ }
+ $this->Execute("UPDATE $table SET $col=$col WHERE $where "); // is this correct - jlim?
+ return 1;
+ }
+
+
+ function CreateSequence($seqname = 'adodbseq', $startID = 1)
+ {
+ $ok = $this->Execute(("INSERT INTO RDB\$GENERATORS (RDB\$GENERATOR_NAME) VALUES (UPPER('$seqname'))" ));
+ if (!$ok) return false;
+ return $this->Execute("SET GENERATOR $seqname TO ".($startID-1).';');
+ }
+
+ function DropSequence($seqname = 'adodbseq')
+ {
+ $seqname = strtoupper($seqname);
+ $this->Execute("delete from RDB\$GENERATORS where RDB\$GENERATOR_NAME='$seqname'");
+ }
+
+ function GenID($seqname='adodbseq',$startID=1)
+ {
+ $getnext = ("SELECT Gen_ID($seqname,1) FROM RDB\$DATABASE");
+ $rs = @$this->Execute($getnext);
+ if (!$rs) {
+ $this->Execute(("INSERT INTO RDB\$GENERATORS (RDB\$GENERATOR_NAME) VALUES (UPPER('$seqname'))" ));
+ $this->Execute("SET GENERATOR $seqname TO ".($startID-1).';');
+ $rs = $this->Execute($getnext);
+ }
+ if ($rs && !$rs->EOF) {
+ $this->genID = (integer) reset($rs->fields);
+ }
+ else {
+ $this->genID = 0; // false
+ }
+
+ if ($rs) {
+ $rs->Close();
+ }
+
+ return $this->genID;
+ }
+
+ function SelectDB($dbName)
+ {
+ return false;
+ }
+
+ function _handleerror()
+ {
+ $this->_errorMsg = ibase_errmsg();
+ }
+
+ function ErrorNo()
+ {
+ if (preg_match('/error code = ([\-0-9]*)/i', $this->_errorMsg,$arr)) return (integer) $arr[1];
+ else return 0;
+ }
+
+ function ErrorMsg()
+ {
+ return $this->_errorMsg;
+ }
+
+ function Prepare($sql)
+ {
+ $stmt = ibase_prepare($this->_connectionID,$sql);
+ if (!$stmt) return false;
+ return array($sql,$stmt);
+ }
+
+ // returns query ID if successful, otherwise false
+ // there have been reports of problems with nested queries - the code is probably not re-entrant?
+ function _query($sql,$iarr=false)
+ {
+
+ if (!$this->autoCommit && $this->_transactionID) {
+ $conn = $this->_transactionID;
+ $docommit = false;
+ } else {
+ $conn = $this->_connectionID;
+ $docommit = true;
+ }
+ if (is_array($sql)) {
+ $fn = 'ibase_execute';
+ $sql = $sql[1];
+ if (is_array($iarr)) {
+ if (ADODB_PHPVER >= 0x4050) { // actually 4.0.4
+ if ( !isset($iarr[0]) ) $iarr[0] = ''; // PHP5 compat hack
+ $fnarr = array_merge( array($sql) , $iarr);
+ $ret = call_user_func_array($fn,$fnarr);
+ } else {
+ switch(sizeof($iarr)) {
+ case 1: $ret = $fn($sql,$iarr[0]); break;
+ case 2: $ret = $fn($sql,$iarr[0],$iarr[1]); break;
+ case 3: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2]); break;
+ case 4: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3]); break;
+ case 5: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4]); break;
+ case 6: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5]); break;
+ case 7: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6]); break;
+ default: ADOConnection::outp( "Too many parameters to ibase query $sql");
+ case 8: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6],$iarr[7]); break;
+ }
+ }
+ } else $ret = $fn($sql);
+ } else {
+ $fn = 'ibase_query';
+
+ if (is_array($iarr)) {
+ if (ADODB_PHPVER >= 0x4050) { // actually 4.0.4
+ if (sizeof($iarr) == 0) $iarr[0] = ''; // PHP5 compat hack
+ $fnarr = array_merge( array($conn,$sql) , $iarr);
+ $ret = call_user_func_array($fn,$fnarr);
+ } else {
+ switch(sizeof($iarr)) {
+ case 1: $ret = $fn($conn,$sql,$iarr[0]); break;
+ case 2: $ret = $fn($conn,$sql,$iarr[0],$iarr[1]); break;
+ case 3: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2]); break;
+ case 4: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3]); break;
+ case 5: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4]); break;
+ case 6: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5]); break;
+ case 7: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6]); break;
+ default: ADOConnection::outp( "Too many parameters to ibase query $sql");
+ case 8: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6],$iarr[7]); break;
+ }
+ }
+ } else $ret = $fn($conn,$sql);
+ }
+ if ($docommit && $ret === true) {
+ ibase_commit($this->_connectionID);
+ }
+
+ $this->_handleerror();
+ return $ret;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ if (!$this->autoCommit) {
+ @ibase_rollback($this->_connectionID);
+ }
+ return @ibase_close($this->_connectionID);
+ }
+
+ //OPN STUFF start
+ function _ConvertFieldType(&$fld, $ftype, $flen, $fscale, $fsubtype, $fprecision, $dialect3)
+ {
+ $fscale = abs($fscale);
+ $fld->max_length = $flen;
+ $fld->scale = null;
+ switch($ftype){
+ case 7:
+ case 8:
+ if ($dialect3) {
+ switch($fsubtype){
+ case 0:
+ $fld->type = ($ftype == 7 ? 'smallint' : 'integer');
+ break;
+ case 1:
+ $fld->type = 'numeric';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ case 2:
+ $fld->type = 'decimal';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ } // switch
+ } else {
+ if ($fscale !=0) {
+ $fld->type = 'decimal';
+ $fld->scale = $fscale;
+ $fld->max_length = ($ftype == 7 ? 4 : 9);
+ } else {
+ $fld->type = ($ftype == 7 ? 'smallint' : 'integer');
+ }
+ }
+ break;
+ case 16:
+ if ($dialect3) {
+ switch($fsubtype){
+ case 0:
+ $fld->type = 'decimal';
+ $fld->max_length = 18;
+ $fld->scale = 0;
+ break;
+ case 1:
+ $fld->type = 'numeric';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ case 2:
+ $fld->type = 'decimal';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ } // switch
+ }
+ break;
+ case 10:
+ $fld->type = 'float';
+ break;
+ case 14:
+ $fld->type = 'char';
+ break;
+ case 27:
+ if ($fscale !=0) {
+ $fld->type = 'decimal';
+ $fld->max_length = 15;
+ $fld->scale = 5;
+ } else {
+ $fld->type = 'double';
+ }
+ break;
+ case 35:
+ if ($dialect3) {
+ $fld->type = 'timestamp';
+ } else {
+ $fld->type = 'date';
+ }
+ break;
+ case 12:
+ $fld->type = 'date';
+ break;
+ case 13:
+ $fld->type = 'time';
+ break;
+ case 37:
+ $fld->type = 'varchar';
+ break;
+ case 40:
+ $fld->type = 'cstring';
+ break;
+ case 261:
+ $fld->type = 'blob';
+ $fld->max_length = -1;
+ break;
+ } // switch
+ }
+ //OPN STUFF end
+
+ // returns array of ADOFieldObjects for current table
+ function MetaColumns($table, $normalize=true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table)));
+
+ $ADODB_FETCH_MODE = $save;
+ $false = false;
+ if ($rs === false) {
+ return $false;
+ }
+
+ $retarr = array();
+ //OPN STUFF start
+ $dialect3 = ($this->dialect==3 ? true : false);
+ //OPN STUFF end
+ while (!$rs->EOF) { //print_r($rs->fields);
+ $fld = new ADOFieldObject();
+ $fld->name = trim($rs->fields[0]);
+ //OPN STUFF start
+ $this->_ConvertFieldType($fld, $rs->fields[7], $rs->fields[3], $rs->fields[4], $rs->fields[5], $rs->fields[6], $dialect3);
+ if (isset($rs->fields[1]) && $rs->fields[1]) {
+ $fld->not_null = true;
+ }
+ if (isset($rs->fields[2])) {
+
+ $fld->has_default = true;
+ $d = substr($rs->fields[2],strlen('default '));
+ switch ($fld->type)
+ {
+ case 'smallint':
+ case 'integer': $fld->default_value = (int) $d; break;
+ case 'char':
+ case 'blob':
+ case 'text':
+ case 'varchar': $fld->default_value = (string) substr($d,1,strlen($d)-2); break;
+ case 'double':
+ case 'float': $fld->default_value = (float) $d; break;
+ default: $fld->default_value = $d; break;
+ }
+ // case 35:$tt = 'TIMESTAMP'; break;
+ }
+ if ((isset($rs->fields[5])) && ($fld->type == 'blob')) {
+ $fld->sub_type = $rs->fields[5];
+ } else {
+ $fld->sub_type = null;
+ }
+ //OPN STUFF end
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
+ else $retarr[strtoupper($fld->name)] = $fld;
+
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ if ( empty($retarr)) return $false;
+ else return $retarr;
+ }
+
+ function BlobEncode( $blob )
+ {
+ $blobid = ibase_blob_create( $this->_connectionID);
+ ibase_blob_add( $blobid, $blob );
+ return ibase_blob_close( $blobid );
+ }
+
+ // since we auto-decode all blob's since 2.42,
+ // BlobDecode should not do any transforms
+ function BlobDecode($blob)
+ {
+ return $blob;
+ }
+
+
+
+
+ // old blobdecode function
+ // still used to auto-decode all blob's
+ function _BlobDecode_old( $blob )
+ {
+ $blobid = ibase_blob_open($this->_connectionID, $blob );
+ $realblob = ibase_blob_get( $blobid,$this->maxblobsize); // 2nd param is max size of blob -- Kevin Boillet <kevinboillet@yahoo.fr>
+ while($string = ibase_blob_get($blobid, 8192)){
+ $realblob .= $string;
+ }
+ ibase_blob_close( $blobid );
+
+ return( $realblob );
+ }
+
+ function _BlobDecode( $blob )
+ {
+ if (ADODB_PHPVER >= 0x5000) {
+ $blob_data = ibase_blob_info($this->_connectionID, $blob );
+ $blobid = ibase_blob_open($this->_connectionID, $blob );
+ } else {
+
+ $blob_data = ibase_blob_info( $blob );
+ $blobid = ibase_blob_open( $blob );
+ }
+
+ if( $blob_data[0] > $this->maxblobsize ) {
+
+ $realblob = ibase_blob_get($blobid, $this->maxblobsize);
+
+ while($string = ibase_blob_get($blobid, 8192)){
+ $realblob .= $string;
+ }
+ } else {
+ $realblob = ibase_blob_get($blobid, $blob_data[0]);
+ }
+
+ ibase_blob_close( $blobid );
+ return( $realblob );
+ }
+
+ function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
+ {
+ $fd = fopen($path,'rb');
+ if ($fd === false) return false;
+ $blob_id = ibase_blob_create($this->_connectionID);
+
+ /* fill with data */
+
+ while ($val = fread($fd,32768)){
+ ibase_blob_add($blob_id, $val);
+ }
+
+ /* close and get $blob_id_str for inserting into table */
+ $blob_id_str = ibase_blob_close($blob_id);
+
+ fclose($fd);
+ return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
+ }
+
+ /*
+ Insert a null into the blob field of the table first.
+ Then use UpdateBlob to store the blob.
+
+ Usage:
+
+ $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
+ $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
+ */
+ function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ {
+ $blob_id = ibase_blob_create($this->_connectionID);
+
+ // ibase_blob_add($blob_id, $val);
+
+ // replacement that solves the problem by which only the first modulus 64K /
+ // of $val are stored at the blob field ////////////////////////////////////
+ // Thx Abel Berenstein aberenstein#afip.gov.ar
+ $len = strlen($val);
+ $chunk_size = 32768;
+ $tail_size = $len % $chunk_size;
+ $n_chunks = ($len - $tail_size) / $chunk_size;
+
+ for ($n = 0; $n < $n_chunks; $n++) {
+ $start = $n * $chunk_size;
+ $data = substr($val, $start, $chunk_size);
+ ibase_blob_add($blob_id, $data);
+ }
+
+ if ($tail_size) {
+ $start = $n_chunks * $chunk_size;
+ $data = substr($val, $start, $tail_size);
+ ibase_blob_add($blob_id, $data);
+ }
+ // end replacement /////////////////////////////////////////////////////////
+
+ $blob_id_str = ibase_blob_close($blob_id);
+
+ return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
+
+ }
+
+
+ function OldUpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ {
+ $blob_id = ibase_blob_create($this->_connectionID);
+ ibase_blob_add($blob_id, $val);
+ $blob_id_str = ibase_blob_close($blob_id);
+ return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
+ }
+
+ // Format date column in sql string given an input format that understands Y M D
+ // Only since Interbase 6.0 - uses EXTRACT
+ // problem - does not zero-fill the day and month yet
+ function SQLDate($fmt, $col=false)
+ {
+ if (!$col) $col = $this->sysDate;
+ $s = '';
+
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ if ($s) $s .= '||';
+ $ch = $fmt[$i];
+ switch($ch) {
+ case 'Y':
+ case 'y':
+ $s .= "extract(year from $col)";
+ break;
+ case 'M':
+ case 'm':
+ $s .= "extract(month from $col)";
+ break;
+ case 'Q':
+ case 'q':
+ $s .= "cast(((extract(month from $col)+2) / 3) as integer)";
+ break;
+ case 'D':
+ case 'd':
+ $s .= "(extract(day from $col))";
+ break;
+ case 'H':
+ case 'h':
+ $s .= "(extract(hour from $col))";
+ break;
+ case 'I':
+ case 'i':
+ $s .= "(extract(minute from $col))";
+ break;
+ case 'S':
+ case 's':
+ $s .= "CAST((extract(second from $col)) AS INTEGER)";
+ break;
+
+ default:
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ $s .= $this->qstr($ch);
+ break;
+ }
+ }
+ return $s;
+ }
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordset_ibase extends ADORecordSet
+{
+
+ var $databaseType = "ibase";
+ var $bind=false;
+ var $_cacheType;
+
+ function __construct($id,$mode=false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $this->fetchMode = ($mode === false) ? $ADODB_FETCH_MODE : $mode;
+ parent::__construct($id);
+ }
+
+ /* Returns: an object containing field information.
+ Get column information in the Recordset object. fetchField() can be used in order to obtain information about
+ fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
+ fetchField() is retrieved. */
+
+ function FetchField($fieldOffset = -1)
+ {
+ $fld = new ADOFieldObject;
+ $ibf = ibase_field_info($this->_queryID,$fieldOffset);
+
+ $name = empty($ibf['alias']) ? $ibf['name'] : $ibf['alias'];
+
+ switch (ADODB_ASSOC_CASE) {
+ case ADODB_ASSOC_CASE_UPPER:
+ $fld->name = strtoupper($name);
+ break;
+ case ADODB_ASSOC_CASE_LOWER:
+ $fld->name = strtolower($name);
+ break;
+ case ADODB_ASSOC_CASE_NATIVE:
+ default:
+ $fld->name = $name;
+ break;
+ }
+
+ $fld->type = $ibf['type'];
+ $fld->max_length = $ibf['length'];
+
+ /* This needs to be populated from the metadata */
+ $fld->not_null = false;
+ $fld->has_default = false;
+ $fld->default_value = 'null';
+ return $fld;
+ }
+
+ function _initrs()
+ {
+ $this->_numOfRows = -1;
+ $this->_numOfFields = @ibase_num_fields($this->_queryID);
+
+ // cache types for blob decode check
+ for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
+ $f1 = $this->FetchField($i);
+ $this->_cacheType[] = $f1->type;
+ }
+ }
+
+ function _seek($row)
+ {
+ return false;
+ }
+
+ function _fetch()
+ {
+ $f = @ibase_fetch_row($this->_queryID);
+ if ($f === false) {
+ $this->fields = false;
+ return false;
+ }
+ // OPN stuff start - optimized
+ // fix missing nulls and decode blobs automatically
+
+ global $ADODB_ANSI_PADDING_OFF;
+ //$ADODB_ANSI_PADDING_OFF=1;
+ $rtrim = !empty($ADODB_ANSI_PADDING_OFF);
+
+ for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
+ if ($this->_cacheType[$i]=="BLOB") {
+ if (isset($f[$i])) {
+ $f[$i] = $this->connection->_BlobDecode($f[$i]);
+ } else {
+ $f[$i] = null;
+ }
+ } else {
+ if (!isset($f[$i])) {
+ $f[$i] = null;
+ } else if ($rtrim && is_string($f[$i])) {
+ $f[$i] = rtrim($f[$i]);
+ }
+ }
+ }
+ // OPN stuff end
+
+ $this->fields = $f;
+ if ($this->fetchMode == ADODB_FETCH_ASSOC) {
+ $this->fields = $this->GetRowAssoc();
+ } else if ($this->fetchMode == ADODB_FETCH_BOTH) {
+ $this->fields = array_merge($this->fields,$this->GetRowAssoc());
+ }
+ return true;
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+
+ }
+
+
+ function _close()
+ {
+ return @ibase_free_result($this->_queryID);
+ }
+
+ function MetaType($t,$len=-1,$fieldobj=false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+ switch (strtoupper($t)) {
+ case 'CHAR':
+ return 'C';
+
+ case 'TEXT':
+ case 'VARCHAR':
+ case 'VARYING':
+ if ($len <= $this->blobSize) return 'C';
+ return 'X';
+ case 'BLOB':
+ return 'B';
+
+ case 'TIMESTAMP':
+ case 'DATE': return 'D';
+ case 'TIME': return 'T';
+ //case 'T': return 'T';
+
+ //case 'L': return 'L';
+ case 'INT':
+ case 'SHORT':
+ case 'INTEGER': return 'I';
+ default: return 'N';
+ }
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-informix.inc.php b/vendor/adodb/adodb-php/drivers/adodb-informix.inc.php
new file mode 100644
index 0000000..84661e2
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-informix.inc.php
@@ -0,0 +1,41 @@
+<?php
+/**
+* @version v5.20.14 06-Jan-2019
+* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+* Released under both BSD license and Lesser GPL library license.
+* Whenever there is any discrepancy between the two licenses,
+* the BSD license will take precedence.
+*
+* Set tabs to 4 for best viewing.
+*
+* Latest version is available at http://adodb.org/
+*
+* Informix 9 driver that supports SELECT FIRST
+*
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR.'/drivers/adodb-informix72.inc.php');
+
+class ADODB_informix extends ADODB_informix72 {
+ var $databaseType = "informix";
+ var $hasTop = 'FIRST';
+ var $ansiOuter = true;
+
+ function IfNull( $field, $ifNull )
+ {
+ return " NVL($field, $ifNull) "; // if Informix 9.X or 10.X
+ }
+}
+
+class ADORecordset_informix extends ADORecordset_informix72 {
+ var $databaseType = "informix";
+
+ function __construct($id,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-informix72.inc.php b/vendor/adodb/adodb-php/drivers/adodb-informix72.inc.php
new file mode 100644
index 0000000..c8bdd1a
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-informix72.inc.php
@@ -0,0 +1,525 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim. All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Informix port by Mitchell T. Young (mitch@youngfamily.org)
+
+ Further mods by "Samuel CARRIERE" <samuel_carriere@hotmail.com>
+
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (!defined('IFX_SCROLL')) define('IFX_SCROLL',1);
+
+class ADODB_informix72 extends ADOConnection {
+ var $databaseType = "informix72";
+ var $dataProvider = "informix";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $fmtDate = "'Y-m-d'";
+ var $fmtTimeStamp = "'Y-m-d H:i:s'";
+ var $hasInsertID = true;
+ var $hasAffectedRows = true;
+ var $substr = 'substr';
+ var $metaTablesSQL="select tabname,tabtype from systables where tabtype in ('T','V') and owner!='informix'"; //Don't get informix tables and pseudo-tables
+
+
+ var $metaColumnsSQL =
+ "select c.colname, c.coltype, c.collength, d.default,c.colno
+ from syscolumns c, systables t,outer sysdefaults d
+ where c.tabid=t.tabid and d.tabid=t.tabid and d.colno=c.colno
+ and tabname='%s' order by c.colno";
+
+ var $metaPrimaryKeySQL =
+ "select part1,part2,part3,part4,part5,part6,part7,part8 from
+ systables t,sysconstraints s,sysindexes i where t.tabname='%s'
+ and s.tabid=t.tabid and s.constrtype='P'
+ and i.idxname=s.idxname";
+
+ var $concat_operator = '||';
+
+ var $lastQuery = false;
+ var $has_insertid = true;
+
+ var $_autocommit = true;
+ var $_bindInputArray = true; // set to true if ADOConnection.Execute() permits binding of array parameters.
+ var $sysDate = 'TODAY';
+ var $sysTimeStamp = 'CURRENT';
+ var $cursorType = IFX_SCROLL; // IFX_SCROLL or IFX_HOLD or 0
+
+ function __construct()
+ {
+ // alternatively, use older method:
+ //putenv("DBDATE=Y4MD-");
+
+ // force ISO date format
+ putenv('GL_DATE=%Y-%m-%d');
+
+ if (function_exists('ifx_byteasvarchar')) {
+ ifx_byteasvarchar(1); // Mode "0" will return a blob id, and mode "1" will return a varchar with text content.
+ ifx_textasvarchar(1); // Mode "0" will return a blob id, and mode "1" will return a varchar with text content.
+ ifx_blobinfile_mode(0); // Mode "0" means save Byte-Blobs in memory, and mode "1" means save Byte-Blobs in a file.
+ }
+ }
+
+ function ServerInfo()
+ {
+ if (isset($this->version)) return $this->version;
+
+ $arr['description'] = $this->GetOne("select DBINFO('version','full') from systables where tabid = 1");
+ $arr['version'] = $this->GetOne("select DBINFO('version','major') || DBINFO('version','minor') from systables where tabid = 1");
+ $this->version = $arr;
+ return $arr;
+ }
+
+
+
+ function _insertid()
+ {
+ $sqlca =ifx_getsqlca($this->lastQuery);
+ return @$sqlca["sqlerrd1"];
+ }
+
+ function _affectedrows()
+ {
+ if ($this->lastQuery) {
+ return @ifx_affected_rows ($this->lastQuery);
+ }
+ return 0;
+ }
+
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ $this->Execute('BEGIN');
+ $this->_autocommit = false;
+ return true;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if (!$ok) return $this->RollbackTrans();
+ if ($this->transOff) return true;
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->Execute('COMMIT');
+ $this->_autocommit = true;
+ return true;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->Execute('ROLLBACK');
+ $this->_autocommit = true;
+ return true;
+ }
+
+ function RowLock($tables,$where,$col='1 as adodbignore')
+ {
+ if ($this->_autocommit) $this->BeginTrans();
+ return $this->GetOne("select $col from $tables where $where for update");
+ }
+
+ /* Returns: the last error message from previous database operation
+ Note: This function is NOT available for Microsoft SQL Server. */
+
+ function ErrorMsg()
+ {
+ if (!empty($this->_logsql)) return $this->_errorMsg;
+ $this->_errorMsg = ifx_errormsg();
+ return $this->_errorMsg;
+ }
+
+ function ErrorNo()
+ {
+ preg_match("/.*SQLCODE=([^\]]*)/",ifx_error(),$parse);
+ if (is_array($parse) && isset($parse[1])) return (int)$parse[1];
+ return 0;
+ }
+
+
+ function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null)
+ {
+ // save old fetch mode
+ global $ADODB_FETCH_MODE;
+
+ $false = false;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+
+ }
+ $procedures = array ();
+
+ // get index details
+
+ $likepattern = '';
+ if ($NamePattern) {
+ $likepattern = " WHERE procname LIKE '".$NamePattern."'";
+ }
+
+ $rs = $this->Execute('SELECT procname, isproc FROM sysprocedures'.$likepattern);
+
+ if (is_object($rs)) {
+ // parse index data into array
+
+ while ($row = $rs->FetchRow()) {
+ $procedures[$row[0]] = array(
+ 'type' => ($row[1] == 'f' ? 'FUNCTION' : 'PROCEDURE'),
+ 'catalog' => '',
+ 'schema' => '',
+ 'remarks' => ''
+ );
+ }
+ }
+
+ // restore fetchmode
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ return $procedures;
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $false = false;
+ if (!empty($this->metaColumnsSQL)) {
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ if ($rs === false) return $false;
+ $rspkey = $this->Execute(sprintf($this->metaPrimaryKeySQL,$table)); //Added to get primary key colno items
+
+ $retarr = array();
+ while (!$rs->EOF) { //print_r($rs->fields);
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+/* //!eos.
+ $rs->fields[1] is not the correct adodb type
+ $rs->fields[2] is not correct max_length, because can include not-null bit
+
+ $fld->type = $rs->fields[1];
+ $fld->primary_key=$rspkey->fields && array_search($rs->fields[4],$rspkey->fields); //Added to set primary key flag
+ $fld->max_length = $rs->fields[2];*/
+ $pr=ifx_props($rs->fields[1],$rs->fields[2]); //!eos
+ $fld->type = $pr[0] ;//!eos
+ $fld->primary_key=$rspkey->fields && array_search($rs->fields[4],$rspkey->fields);
+ $fld->max_length = $pr[1]; //!eos
+ $fld->precision = $pr[2] ;//!eos
+ $fld->not_null = $pr[3]=="N"; //!eos
+
+ if (trim($rs->fields[3]) != "AAAAAA 0") {
+ $fld->has_default = 1;
+ $fld->default_value = $rs->fields[3];
+ } else {
+ $fld->has_default = 0;
+ }
+
+ $retarr[strtolower($fld->name)] = $fld;
+ $rs->MoveNext();
+ }
+
+ $rs->Close();
+ $rspkey->Close(); //!eos
+ return $retarr;
+ }
+
+ return $false;
+ }
+
+ function xMetaColumns($table)
+ {
+ return ADOConnection::MetaColumns($table,false);
+ }
+
+ function MetaForeignKeys($table, $owner=false, $upper=false) //!Eos
+ {
+ $sql = "
+ select tr.tabname,updrule,delrule,
+ i.part1 o1,i2.part1 d1,i.part2 o2,i2.part2 d2,i.part3 o3,i2.part3 d3,i.part4 o4,i2.part4 d4,
+ i.part5 o5,i2.part5 d5,i.part6 o6,i2.part6 d6,i.part7 o7,i2.part7 d7,i.part8 o8,i2.part8 d8
+ from systables t,sysconstraints s,sysindexes i,
+ sysreferences r,systables tr,sysconstraints s2,sysindexes i2
+ where t.tabname='$table'
+ and s.tabid=t.tabid and s.constrtype='R' and r.constrid=s.constrid
+ and i.idxname=s.idxname and tr.tabid=r.ptabid
+ and s2.constrid=r.primary and i2.idxname=s2.idxname";
+
+ $rs = $this->Execute($sql);
+ if (!$rs || $rs->EOF) return false;
+ $arr = $rs->GetArray();
+ $a = array();
+ foreach($arr as $v) {
+ $coldest=$this->metaColumnNames($v["tabname"]);
+ $colorig=$this->metaColumnNames($table);
+ $colnames=array();
+ for($i=1;$i<=8 && $v["o$i"] ;$i++) {
+ $colnames[]=$coldest[$v["d$i"]-1]."=".$colorig[$v["o$i"]-1];
+ }
+ if($upper)
+ $a[strtoupper($v["tabname"])] = $colnames;
+ else
+ $a[$v["tabname"]] = $colnames;
+ }
+ return $a;
+ }
+
+ function UpdateBlob($table, $column, $val, $where, $blobtype = 'BLOB')
+ {
+ $type = ($blobtype == 'TEXT') ? 1 : 0;
+ $blobid = ifx_create_blob($type,0,$val);
+ return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blobid));
+ }
+
+ function BlobDecode($blobid)
+ {
+ return function_exists('ifx_byteasvarchar') ? $blobid : @ifx_get_blob($blobid);
+ }
+
+ // returns true or false
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('ifx_connect')) return null;
+
+ $dbs = $argDatabasename . "@" . $argHostname;
+ if ($argHostname) putenv("INFORMIXSERVER=$argHostname");
+ putenv("INFORMIXSERVER=".trim($argHostname));
+ $this->_connectionID = ifx_connect($dbs,$argUsername,$argPassword);
+ if ($this->_connectionID === false) return false;
+ #if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ return true;
+ }
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('ifx_connect')) return null;
+
+ $dbs = $argDatabasename . "@" . $argHostname;
+ putenv("INFORMIXSERVER=".trim($argHostname));
+ $this->_connectionID = ifx_pconnect($dbs,$argUsername,$argPassword);
+ if ($this->_connectionID === false) return false;
+ #if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ return true;
+ }
+/*
+ // ifx_do does not accept bind parameters - weird ???
+ function Prepare($sql)
+ {
+ $stmt = ifx_prepare($sql);
+ if (!$stmt) return $sql;
+ else return array($sql,$stmt);
+ }
+*/
+ // returns query ID if successful, otherwise false
+ function _query($sql,$inputarr=false)
+ {
+ global $ADODB_COUNTRECS;
+
+ // String parameters have to be converted using ifx_create_char
+ if ($inputarr) {
+ foreach($inputarr as $v) {
+ if (gettype($v) == 'string') {
+ $tab[] = ifx_create_char($v);
+ }
+ else {
+ $tab[] = $v;
+ }
+ }
+ }
+
+ // In case of select statement, we use a scroll cursor in order
+ // to be able to call "move", or "movefirst" statements
+ if (!$ADODB_COUNTRECS && preg_match("/^\s*select/is", $sql)) {
+ if ($inputarr) {
+ $this->lastQuery = ifx_query($sql,$this->_connectionID, $this->cursorType, $tab);
+ }
+ else {
+ $this->lastQuery = ifx_query($sql,$this->_connectionID, $this->cursorType);
+ }
+ }
+ else {
+ if ($inputarr) {
+ $this->lastQuery = ifx_query($sql,$this->_connectionID, $tab);
+ }
+ else {
+ $this->lastQuery = ifx_query($sql,$this->_connectionID);
+ }
+ }
+
+ // Following line have been commented because autocommit mode is
+ // not supported by informix SE 7.2
+
+ //if ($this->_autocommit) ifx_query('COMMIT',$this->_connectionID);
+
+ return $this->lastQuery;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ $this->lastQuery = false;
+ if($this->_connectionID) {
+ return ifx_close($this->_connectionID);
+ }
+ return true;
+ }
+}
+
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordset_informix72 extends ADORecordSet {
+
+ var $databaseType = "informix72";
+ var $canSeek = true;
+ var $_fieldprops = false;
+
+ function __construct($id,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ $this->fetchMode = $mode;
+ return parent::__construct($id);
+ }
+
+
+
+ /* Returns: an object containing field information.
+ Get column information in the Recordset object. fetchField() can be used in order to obtain information about
+ fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
+ fetchField() is retrieved. */
+ function FetchField($fieldOffset = -1)
+ {
+ if (empty($this->_fieldprops)) {
+ $fp = ifx_fieldproperties($this->_queryID);
+ foreach($fp as $k => $v) {
+ $o = new ADOFieldObject;
+ $o->name = $k;
+ $arr = explode(';',$v); //"SQLTYPE;length;precision;scale;ISNULLABLE"
+ $o->type = $arr[0];
+ $o->max_length = $arr[1];
+ $this->_fieldprops[] = $o;
+ $o->not_null = $arr[4]=="N";
+ }
+ }
+ $ret = $this->_fieldprops[$fieldOffset];
+ return $ret;
+ }
+
+ function _initrs()
+ {
+ $this->_numOfRows = -1; // ifx_affected_rows not reliable, only returns estimate -- ($ADODB_COUNTRECS)? ifx_affected_rows($this->_queryID):-1;
+ $this->_numOfFields = ifx_num_fields($this->_queryID);
+ }
+
+ function _seek($row)
+ {
+ return @ifx_fetch_row($this->_queryID, (int) $row);
+ }
+
+ function MoveLast()
+ {
+ $this->fields = @ifx_fetch_row($this->_queryID, "LAST");
+ if ($this->fields) $this->EOF = false;
+ $this->_currentRow = -1;
+
+ if ($this->fetchMode == ADODB_FETCH_NUM) {
+ foreach($this->fields as $v) {
+ $arr[] = $v;
+ }
+ $this->fields = $arr;
+ }
+
+ return true;
+ }
+
+ function MoveFirst()
+ {
+ $this->fields = @ifx_fetch_row($this->_queryID, "FIRST");
+ if ($this->fields) $this->EOF = false;
+ $this->_currentRow = 0;
+
+ if ($this->fetchMode == ADODB_FETCH_NUM) {
+ foreach($this->fields as $v) {
+ $arr[] = $v;
+ }
+ $this->fields = $arr;
+ }
+
+ return true;
+ }
+
+ function _fetch($ignore_fields=false)
+ {
+
+ $this->fields = @ifx_fetch_row($this->_queryID);
+
+ if (!is_array($this->fields)) return false;
+
+ if ($this->fetchMode == ADODB_FETCH_NUM) {
+ foreach($this->fields as $v) {
+ $arr[] = $v;
+ }
+ $this->fields = $arr;
+ }
+ return true;
+ }
+
+ /* close() only needs to be called if you are worried about using too much memory while your script
+ is running. All associated result memory for the specified result identifier will automatically be freed. */
+ function _close()
+ {
+ if($this->_queryID) {
+ return ifx_free_result($this->_queryID);
+ }
+ return true;
+ }
+
+}
+/** !Eos
+* Auxiliar function to Parse coltype,collength. Used by Metacolumns
+* return: array ($mtype,$length,$precision,$nullable) (similar to ifx_fieldpropierties)
+*/
+function ifx_props($coltype,$collength){
+ $itype=fmod($coltype+1,256);
+ $nullable=floor(($coltype+1) /256) ?"N":"Y";
+ $mtype=substr(" CIIFFNNDN TBXCC ",$itype,1);
+ switch ($itype){
+ case 2:
+ $length=4;
+ case 6:
+ case 9:
+ case 14:
+ $length=floor($collength/256);
+ $precision=fmod($collength,256);
+ break;
+ default:
+ $precision=0;
+ $length=$collength;
+ }
+ return array($mtype,$length,$precision,$nullable);
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-ldap.inc.php b/vendor/adodb/adodb-php/drivers/adodb-ldap.inc.php
new file mode 100644
index 0000000..42b286c
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-ldap.inc.php
@@ -0,0 +1,428 @@
+<?php
+/*
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 8.
+
+ Revision 1: (02/25/2005) Updated codebase to include the _inject_bind_options function. This allows
+ users to access the options in the ldap_set_option function appropriately. Most importantly
+ LDAP Version 3 is now supported. See the examples for more information. Also fixed some minor
+ bugs that surfaced when PHP error levels were set high.
+
+ Joshua Eldridge (joshuae74#hotmail.com)
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (!defined('LDAP_ASSOC')) {
+ define('LDAP_ASSOC',ADODB_FETCH_ASSOC);
+ define('LDAP_NUM',ADODB_FETCH_NUM);
+ define('LDAP_BOTH',ADODB_FETCH_BOTH);
+}
+
+class ADODB_ldap extends ADOConnection {
+ var $databaseType = 'ldap';
+ var $dataProvider = 'ldap';
+
+ # Connection information
+ var $username = false;
+ var $password = false;
+
+ # Used during searches
+ var $filter;
+ var $dn;
+ var $version;
+ var $port = 389;
+
+ # Options configuration information
+ var $LDAP_CONNECT_OPTIONS;
+
+ # error on binding, eg. "Binding: invalid credentials"
+ var $_bind_errmsg = "Binding: %s";
+
+ function __construct()
+ {
+ }
+
+ // returns true or false
+
+ function _connect( $host, $username, $password, $ldapbase)
+ {
+ global $LDAP_CONNECT_OPTIONS;
+
+ if ( !function_exists( 'ldap_connect' ) ) return null;
+
+ if (strpos($host,'ldap://') === 0 || strpos($host,'ldaps://') === 0) {
+ $this->_connectionID = @ldap_connect($host);
+ } else {
+ $conn_info = array( $host,$this->port);
+
+ if ( strstr( $host, ':' ) ) {
+ $conn_info = explode( ':', $host );
+ }
+
+ $this->_connectionID = @ldap_connect( $conn_info[0], $conn_info[1] );
+ }
+ if (!$this->_connectionID) {
+ $e = 'Could not connect to ' . $conn_info[0];
+ $this->_errorMsg = $e;
+ if ($this->debug) ADOConnection::outp($e);
+ return false;
+ }
+ if( count( $LDAP_CONNECT_OPTIONS ) > 0 ) {
+ $this->_inject_bind_options( $LDAP_CONNECT_OPTIONS );
+ }
+
+ if ($username) {
+ $bind = @ldap_bind( $this->_connectionID, $username, $password );
+ } else {
+ $username = 'anonymous';
+ $bind = @ldap_bind( $this->_connectionID );
+ }
+
+ if (!$bind) {
+ $e = sprintf($this->_bind_errmsg,ldap_error($this->_connectionID));
+ $this->_errorMsg = $e;
+ if ($this->debug) ADOConnection::outp($e);
+ return false;
+ }
+ $this->_errorMsg = '';
+ $this->database = $ldapbase;
+ return $this->_connectionID;
+ }
+
+/*
+ Valid Domain Values for LDAP Options:
+
+ LDAP_OPT_DEREF (integer)
+ LDAP_OPT_SIZELIMIT (integer)
+ LDAP_OPT_TIMELIMIT (integer)
+ LDAP_OPT_PROTOCOL_VERSION (integer)
+ LDAP_OPT_ERROR_NUMBER (integer)
+ LDAP_OPT_REFERRALS (boolean)
+ LDAP_OPT_RESTART (boolean)
+ LDAP_OPT_HOST_NAME (string)
+ LDAP_OPT_ERROR_STRING (string)
+ LDAP_OPT_MATCHED_DN (string)
+ LDAP_OPT_SERVER_CONTROLS (array)
+ LDAP_OPT_CLIENT_CONTROLS (array)
+
+ Make sure to set this BEFORE calling Connect()
+
+ Example:
+
+ $LDAP_CONNECT_OPTIONS = Array(
+ Array (
+ "OPTION_NAME"=>LDAP_OPT_DEREF,
+ "OPTION_VALUE"=>2
+ ),
+ Array (
+ "OPTION_NAME"=>LDAP_OPT_SIZELIMIT,
+ "OPTION_VALUE"=>100
+ ),
+ Array (
+ "OPTION_NAME"=>LDAP_OPT_TIMELIMIT,
+ "OPTION_VALUE"=>30
+ ),
+ Array (
+ "OPTION_NAME"=>LDAP_OPT_PROTOCOL_VERSION,
+ "OPTION_VALUE"=>3
+ ),
+ Array (
+ "OPTION_NAME"=>LDAP_OPT_ERROR_NUMBER,
+ "OPTION_VALUE"=>13
+ ),
+ Array (
+ "OPTION_NAME"=>LDAP_OPT_REFERRALS,
+ "OPTION_VALUE"=>FALSE
+ ),
+ Array (
+ "OPTION_NAME"=>LDAP_OPT_RESTART,
+ "OPTION_VALUE"=>FALSE
+ )
+ );
+*/
+
+ function _inject_bind_options( $options ) {
+ foreach( $options as $option ) {
+ ldap_set_option( $this->_connectionID, $option["OPTION_NAME"], $option["OPTION_VALUE"] )
+ or die( "Unable to set server option: " . $option["OPTION_NAME"] );
+ }
+ }
+
+ /* returns _queryID or false */
+ function _query($sql,$inputarr=false)
+ {
+ $rs = @ldap_search( $this->_connectionID, $this->database, $sql );
+ $this->_errorMsg = ($rs) ? '' : 'Search error on '.$sql.': '.ldap_error($this->_connectionID);
+ return $rs;
+ }
+
+ function ErrorMsg()
+ {
+ return $this->_errorMsg;
+ }
+
+ function ErrorNo()
+ {
+ return @ldap_errno($this->_connectionID);
+ }
+
+ /* closes the LDAP connection */
+ function _close()
+ {
+ @ldap_close( $this->_connectionID );
+ $this->_connectionID = false;
+ }
+
+ function SelectDB($db) {
+ $this->database = $db;
+ return true;
+ } // SelectDB
+
+ function ServerInfo()
+ {
+ if( !empty( $this->version ) ) {
+ return $this->version;
+ }
+
+ $version = array();
+ /*
+ Determines how aliases are handled during search.
+ LDAP_DEREF_NEVER (0x00)
+ LDAP_DEREF_SEARCHING (0x01)
+ LDAP_DEREF_FINDING (0x02)
+ LDAP_DEREF_ALWAYS (0x03)
+ The LDAP_DEREF_SEARCHING value means aliases are dereferenced during the search but
+ not when locating the base object of the search. The LDAP_DEREF_FINDING value means
+ aliases are dereferenced when locating the base object but not during the search.
+ Default: LDAP_DEREF_NEVER
+ */
+ ldap_get_option( $this->_connectionID, LDAP_OPT_DEREF, $version['LDAP_OPT_DEREF'] ) ;
+ switch ( $version['LDAP_OPT_DEREF'] ) {
+ case 0:
+ $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_NEVER';
+ case 1:
+ $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_SEARCHING';
+ case 2:
+ $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_FINDING';
+ case 3:
+ $version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_ALWAYS';
+ }
+
+ /*
+ A limit on the number of entries to return from a search.
+ LDAP_NO_LIMIT (0) means no limit.
+ Default: LDAP_NO_LIMIT
+ */
+ ldap_get_option( $this->_connectionID, LDAP_OPT_SIZELIMIT, $version['LDAP_OPT_SIZELIMIT'] );
+ if ( $version['LDAP_OPT_SIZELIMIT'] == 0 ) {
+ $version['LDAP_OPT_SIZELIMIT'] = 'LDAP_NO_LIMIT';
+ }
+
+ /*
+ A limit on the number of seconds to spend on a search.
+ LDAP_NO_LIMIT (0) means no limit.
+ Default: LDAP_NO_LIMIT
+ */
+ ldap_get_option( $this->_connectionID, LDAP_OPT_TIMELIMIT, $version['LDAP_OPT_TIMELIMIT'] );
+ if ( $version['LDAP_OPT_TIMELIMIT'] == 0 ) {
+ $version['LDAP_OPT_TIMELIMIT'] = 'LDAP_NO_LIMIT';
+ }
+
+ /*
+ Determines whether the LDAP library automatically follows referrals returned by LDAP servers or not.
+ LDAP_OPT_ON
+ LDAP_OPT_OFF
+ Default: ON
+ */
+ ldap_get_option( $this->_connectionID, LDAP_OPT_REFERRALS, $version['LDAP_OPT_REFERRALS'] );
+ if ( $version['LDAP_OPT_REFERRALS'] == 0 ) {
+ $version['LDAP_OPT_REFERRALS'] = 'LDAP_OPT_OFF';
+ } else {
+ $version['LDAP_OPT_REFERRALS'] = 'LDAP_OPT_ON';
+ }
+
+ /*
+ Determines whether LDAP I/O operations are automatically restarted if they abort prematurely.
+ LDAP_OPT_ON
+ LDAP_OPT_OFF
+ Default: OFF
+ */
+ ldap_get_option( $this->_connectionID, LDAP_OPT_RESTART, $version['LDAP_OPT_RESTART'] );
+ if ( $version['LDAP_OPT_RESTART'] == 0 ) {
+ $version['LDAP_OPT_RESTART'] = 'LDAP_OPT_OFF';
+ } else {
+ $version['LDAP_OPT_RESTART'] = 'LDAP_OPT_ON';
+ }
+
+ /*
+ This option indicates the version of the LDAP protocol used when communicating with the primary LDAP server.
+ LDAP_VERSION2 (2)
+ LDAP_VERSION3 (3)
+ Default: LDAP_VERSION2 (2)
+ */
+ ldap_get_option( $this->_connectionID, LDAP_OPT_PROTOCOL_VERSION, $version['LDAP_OPT_PROTOCOL_VERSION'] );
+ if ( $version['LDAP_OPT_PROTOCOL_VERSION'] == 2 ) {
+ $version['LDAP_OPT_PROTOCOL_VERSION'] = 'LDAP_VERSION2';
+ } else {
+ $version['LDAP_OPT_PROTOCOL_VERSION'] = 'LDAP_VERSION3';
+ }
+
+ /* The host name (or list of hosts) for the primary LDAP server. */
+ ldap_get_option( $this->_connectionID, LDAP_OPT_HOST_NAME, $version['LDAP_OPT_HOST_NAME'] );
+ ldap_get_option( $this->_connectionID, LDAP_OPT_ERROR_NUMBER, $version['LDAP_OPT_ERROR_NUMBER'] );
+ ldap_get_option( $this->_connectionID, LDAP_OPT_ERROR_STRING, $version['LDAP_OPT_ERROR_STRING'] );
+ ldap_get_option( $this->_connectionID, LDAP_OPT_MATCHED_DN, $version['LDAP_OPT_MATCHED_DN'] );
+
+ return $this->version = $version;
+ }
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_ldap extends ADORecordSet{
+
+ var $databaseType = "ldap";
+ var $canSeek = false;
+ var $_entryID; /* keeps track of the entry resource identifier */
+
+ function __construct($queryID,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ switch ($mode)
+ {
+ case ADODB_FETCH_NUM:
+ $this->fetchMode = LDAP_NUM;
+ break;
+ case ADODB_FETCH_ASSOC:
+ $this->fetchMode = LDAP_ASSOC;
+ break;
+ case ADODB_FETCH_DEFAULT:
+ case ADODB_FETCH_BOTH:
+ default:
+ $this->fetchMode = LDAP_BOTH;
+ break;
+ }
+
+ parent::__construct($queryID);
+ }
+
+ function _initrs()
+ {
+ /*
+ This could be teaked to respect the $COUNTRECS directive from ADODB
+ It's currently being used in the _fetch() function and the
+ GetAssoc() function
+ */
+ $this->_numOfRows = ldap_count_entries( $this->connection->_connectionID, $this->_queryID );
+ }
+
+ /*
+ Return whole recordset as a multi-dimensional associative array
+ */
+ function GetAssoc($force_array = false, $first2cols = false)
+ {
+ $records = $this->_numOfRows;
+ $results = array();
+ for ( $i=0; $i < $records; $i++ ) {
+ foreach ( $this->fields as $k=>$v ) {
+ if ( is_array( $v ) ) {
+ if ( $v['count'] == 1 ) {
+ $results[$i][$k] = $v[0];
+ } else {
+ array_shift( $v );
+ $results[$i][$k] = $v;
+ }
+ }
+ }
+ }
+
+ return $results;
+ }
+
+ function GetRowAssoc($upper = ADODB_ASSOC_CASE)
+ {
+ $results = array();
+ foreach ( $this->fields as $k=>$v ) {
+ if ( is_array( $v ) ) {
+ if ( $v['count'] == 1 ) {
+ $results[$k] = $v[0];
+ } else {
+ array_shift( $v );
+ $results[$k] = $v;
+ }
+ }
+ }
+
+ return $results;
+ }
+
+ function GetRowNums()
+ {
+ $results = array();
+ foreach ( $this->fields as $k=>$v ) {
+ static $i = 0;
+ if (is_array( $v )) {
+ if ( $v['count'] == 1 ) {
+ $results[$i] = $v[0];
+ } else {
+ array_shift( $v );
+ $results[$i] = $v;
+ }
+ $i++;
+ }
+ }
+ return $results;
+ }
+
+ function _fetch()
+ {
+ if ( $this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0 ) {
+ return false;
+ }
+
+ if ( $this->_currentRow == 0 ) {
+ $this->_entryID = ldap_first_entry( $this->connection->_connectionID, $this->_queryID );
+ } else {
+ $this->_entryID = ldap_next_entry( $this->connection->_connectionID, $this->_entryID );
+ }
+
+ $this->fields = ldap_get_attributes( $this->connection->_connectionID, $this->_entryID );
+ $this->_numOfFields = $this->fields['count'];
+
+ switch ( $this->fetchMode ) {
+
+ case LDAP_ASSOC:
+ $this->fields = $this->GetRowAssoc();
+ break;
+
+ case LDAP_NUM:
+ $this->fields = array_merge($this->GetRowNums(),$this->GetRowAssoc());
+ break;
+
+ case LDAP_BOTH:
+ default:
+ $this->fields = $this->GetRowNums();
+ break;
+ }
+
+ return is_array( $this->fields );
+ }
+
+ function _close() {
+ @ldap_free_result( $this->_queryID );
+ $this->_queryID = false;
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-mssql.inc.php b/vendor/adodb/adodb-php/drivers/adodb-mssql.inc.php
new file mode 100644
index 0000000..b9aab8e
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-mssql.inc.php
@@ -0,0 +1,1194 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Native mssql driver. Requires mssql client. Works on Windows.
+ To configure for Unix, see
+ http://phpbuilder.com/columns/alberto20000919.php3
+
+*/
+
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+//----------------------------------------------------------------
+// MSSQL returns dates with the format Oct 13 2002 or 13 Oct 2002
+// and this causes tons of problems because localized versions of
+// MSSQL will return the dates in dmy or mdy order; and also the
+// month strings depends on what language has been configured. The
+// following two variables allow you to control the localization
+// settings - Ugh.
+//
+// MORE LOCALIZATION INFO
+// ----------------------
+// To configure datetime, look for and modify sqlcommn.loc,
+// typically found in c:\mssql\install
+// Also read :
+// http://support.microsoft.com/default.aspx?scid=kb;EN-US;q220918
+// Alternatively use:
+// CONVERT(char(12),datecol,120)
+//----------------------------------------------------------------
+
+
+// has datetime converstion to YYYY-MM-DD format, and also mssql_fetch_assoc
+if (ADODB_PHPVER >= 0x4300) {
+// docs say 4.2.0, but testing shows only since 4.3.0 does it work!
+ ini_set('mssql.datetimeconvert',0);
+} else {
+global $ADODB_mssql_mths; // array, months must be upper-case
+
+
+ $ADODB_mssql_date_order = 'mdy';
+ $ADODB_mssql_mths = array(
+ 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,
+ 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
+}
+
+//---------------------------------------------------------------------------
+// Call this to autoset $ADODB_mssql_date_order at the beginning of your code,
+// just after you connect to the database. Supports mdy and dmy only.
+// Not required for PHP 4.2.0 and above.
+function AutoDetect_MSSQL_Date_Order($conn)
+{
+global $ADODB_mssql_date_order;
+ $adate = $conn->GetOne('select getdate()');
+ if ($adate) {
+ $anum = (int) $adate;
+ if ($anum > 0) {
+ if ($anum > 31) {
+ //ADOConnection::outp( "MSSQL: YYYY-MM-DD date format not supported currently");
+ } else
+ $ADODB_mssql_date_order = 'dmy';
+ } else
+ $ADODB_mssql_date_order = 'mdy';
+ }
+}
+
+class ADODB_mssql extends ADOConnection {
+ var $databaseType = "mssql";
+ var $dataProvider = "mssql";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $fmtDate = "'Y-m-d'";
+ var $fmtTimeStamp = "'Y-m-d\TH:i:s'";
+ var $hasInsertID = true;
+ var $substr = "substring";
+ var $length = 'len';
+ var $hasAffectedRows = true;
+ var $metaDatabasesSQL = "select name from sysdatabases where name <> 'master'";
+ var $metaTablesSQL="select name,case when type='U' then 'T' else 'V' end from sysobjects where (type='U' or type='V') and (name not in ('sysallocations','syscolumns','syscomments','sysdepends','sysfilegroups','sysfiles','sysfiles1','sysforeignkeys','sysfulltextcatalogs','sysindexes','sysindexkeys','sysmembers','sysobjects','syspermissions','sysprotects','sysreferences','systypes','sysusers','sysalternates','sysconstraints','syssegments','REFERENTIAL_CONSTRAINTS','CHECK_CONSTRAINTS','CONSTRAINT_TABLE_USAGE','CONSTRAINT_COLUMN_USAGE','VIEWS','VIEW_TABLE_USAGE','VIEW_COLUMN_USAGE','SCHEMATA','TABLES','TABLE_CONSTRAINTS','TABLE_PRIVILEGES','COLUMNS','COLUMN_DOMAIN_USAGE','COLUMN_PRIVILEGES','DOMAINS','DOMAIN_CONSTRAINTS','KEY_COLUMN_USAGE','dtproperties'))";
+ var $metaColumnsSQL = # xtype==61 is datetime
+ "select c.name,t.name,c.length,c.isnullable, c.status,
+ (case when c.xusertype=61 then 0 else c.xprec end),
+ (case when c.xusertype=61 then 0 else c.xscale end)
+ from syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id where o.name='%s'";
+ var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE
+ var $hasGenID = true;
+ var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
+ var $sysTimeStamp = 'GetDate()';
+ var $_has_mssql_init;
+ var $maxParameterLen = 4000;
+ var $arrayClass = 'ADORecordSet_array_mssql';
+ var $uniqueSort = true;
+ var $leftOuter = '*=';
+ var $rightOuter = '=*';
+ var $ansiOuter = true; // for mssql7 or later
+ var $poorAffectedRows = true;
+ var $identitySQL = 'select SCOPE_IDENTITY()'; // 'select SCOPE_IDENTITY'; # for mssql 2000
+ var $uniqueOrderBy = true;
+ var $_bindInputArray = true;
+ var $forceNewConnect = false;
+
+ function __construct()
+ {
+ $this->_has_mssql_init = (strnatcmp(PHP_VERSION,'4.1.0')>=0);
+ }
+
+ function ServerInfo()
+ {
+ global $ADODB_FETCH_MODE;
+
+
+ if ($this->fetchMode === false) {
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ } else
+ $savem = $this->SetFetchMode(ADODB_FETCH_NUM);
+
+ if (0) {
+ $stmt = $this->PrepareSP('sp_server_info');
+ $val = 2;
+ $this->Parameter($stmt,$val,'attribute_id');
+ $row = $this->GetRow($stmt);
+ }
+
+ $row = $this->GetRow("execute sp_server_info 2");
+
+
+ if ($this->fetchMode === false) {
+ $ADODB_FETCH_MODE = $savem;
+ } else
+ $this->SetFetchMode($savem);
+
+ $arr['description'] = $row[2];
+ $arr['version'] = ADOConnection::_findvers($arr['description']);
+ return $arr;
+ }
+
+ function IfNull( $field, $ifNull )
+ {
+ return " ISNULL($field, $ifNull) "; // if MS SQL Server
+ }
+
+ function _insertid()
+ {
+ // SCOPE_IDENTITY()
+ // Returns the last IDENTITY value inserted into an IDENTITY column in
+ // the same scope. A scope is a module -- a stored procedure, trigger,
+ // function, or batch. Thus, two statements are in the same scope if
+ // they are in the same stored procedure, function, or batch.
+ if ($this->lastInsID !== false) {
+ return $this->lastInsID; // InsID from sp_executesql call
+ } else {
+ return $this->GetOne($this->identitySQL);
+ }
+ }
+
+
+
+ /**
+ * Correctly quotes a string so that all strings are escaped. We prefix and append
+ * to the string single-quotes.
+ * An example is $db->qstr("Don't bother",magic_quotes_runtime());
+ *
+ * @param s the string to quote
+ * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc().
+ * This undoes the stupidity of magic quotes for GPC.
+ *
+ * @return quoted string to be sent back to database
+ */
+ function qstr($s,$magic_quotes=false)
+ {
+ if (!$magic_quotes) {
+ return "'".str_replace("'",$this->replaceQuote,$s)."'";
+ }
+
+ // undo magic quotes for " unless sybase is on
+ $sybase = ini_get('magic_quotes_sybase');
+ if (!$sybase) {
+ $s = str_replace('\\"','"',$s);
+ if ($this->replaceQuote == "\\'") // ' already quoted, no need to change anything
+ return "'$s'";
+ else {// change \' to '' for sybase/mssql
+ $s = str_replace('\\\\','\\',$s);
+ return "'".str_replace("\\'",$this->replaceQuote,$s)."'";
+ }
+ } else {
+ return "'".$s."'";
+ }
+ }
+// moodle change end - see readme_moodle.txt
+
+ function _affectedrows()
+ {
+ return $this->GetOne('select @@rowcount');
+ }
+
+ var $_dropSeqSQL = "drop table %s";
+
+ function CreateSequence($seq='adodbseq',$start=1)
+ {
+
+ $this->Execute('BEGIN TRANSACTION adodbseq');
+ $start -= 1;
+ $this->Execute("create table $seq (id float(53))");
+ $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
+ if (!$ok) {
+ $this->Execute('ROLLBACK TRANSACTION adodbseq');
+ return false;
+ }
+ $this->Execute('COMMIT TRANSACTION adodbseq');
+ return true;
+ }
+
+ function GenID($seq='adodbseq',$start=1)
+ {
+ //$this->debug=1;
+ $this->Execute('BEGIN TRANSACTION adodbseq');
+ $ok = $this->Execute("update $seq with (tablock,holdlock) set id = id + 1");
+ if (!$ok) {
+ $this->Execute("create table $seq (id float(53))");
+ $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
+ if (!$ok) {
+ $this->Execute('ROLLBACK TRANSACTION adodbseq');
+ return false;
+ }
+ $this->Execute('COMMIT TRANSACTION adodbseq');
+ return $start;
+ }
+ $num = $this->GetOne("select id from $seq");
+ $this->Execute('COMMIT TRANSACTION adodbseq');
+ return $num;
+
+ // in old implementation, pre 1.90, we returned GUID...
+ //return $this->GetOne("SELECT CONVERT(varchar(255), NEWID()) AS 'Char'");
+ }
+
+
+ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ if ($nrows > 0 && $offset <= 0) {
+ $sql = preg_replace(
+ '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql);
+
+ if ($secs2cache)
+ $rs = $this->CacheExecute($secs2cache, $sql, $inputarr);
+ else
+ $rs = $this->Execute($sql,$inputarr);
+ } else
+ $rs = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
+
+ return $rs;
+ }
+
+
+ // Format date column in sql string given an input format that understands Y M D
+ function SQLDate($fmt, $col=false)
+ {
+ if (!$col) $col = $this->sysTimeStamp;
+ $s = '';
+
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ if ($s) $s .= '+';
+ $ch = $fmt[$i];
+ switch($ch) {
+ case 'Y':
+ case 'y':
+ $s .= "datename(yyyy,$col)";
+ break;
+ case 'M':
+ $s .= "convert(char(3),$col,0)";
+ break;
+ case 'm':
+ $s .= "replace(str(month($col),2),' ','0')";
+ break;
+ case 'Q':
+ case 'q':
+ $s .= "datename(quarter,$col)";
+ break;
+ case 'D':
+ case 'd':
+ $s .= "replace(str(day($col),2),' ','0')";
+ break;
+ case 'h':
+ $s .= "substring(convert(char(14),$col,0),13,2)";
+ break;
+
+ case 'H':
+ $s .= "replace(str(datepart(hh,$col),2),' ','0')";
+ break;
+
+ case 'i':
+ $s .= "replace(str(datepart(mi,$col),2),' ','0')";
+ break;
+ case 's':
+ $s .= "replace(str(datepart(ss,$col),2),' ','0')";
+ break;
+ case 'a':
+ case 'A':
+ $s .= "substring(convert(char(19),$col,0),18,2)";
+ break;
+
+ default:
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ $s .= $this->qstr($ch);
+ break;
+ }
+ }
+ return $s;
+ }
+
+
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ $ok = $this->Execute('BEGIN TRAN');
+ return $ok;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) return true;
+ if (!$ok) return $this->RollbackTrans();
+ if ($this->transCnt) $this->transCnt -= 1;
+ $ok = $this->Execute('COMMIT TRAN');
+ return $ok;
+ }
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ if ($this->transCnt) $this->transCnt -= 1;
+ $ok = $this->Execute('ROLLBACK TRAN');
+ return $ok;
+ }
+
+ function SetTransactionMode( $transaction_mode )
+ {
+ $this->_transmode = $transaction_mode;
+ if (empty($transaction_mode)) {
+ $this->Execute('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
+ return;
+ }
+ if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
+ $this->Execute("SET TRANSACTION ".$transaction_mode);
+ }
+
+ /*
+ Usage:
+
+ $this->BeginTrans();
+ $this->RowLock('table1,table2','table1.id=33 and table2.id=table1.id'); # lock row 33 for both tables
+
+ # some operation on both tables table1 and table2
+
+ $this->CommitTrans();
+
+ See http://www.swynk.com/friends/achigrik/SQL70Locks.asp
+ */
+ function RowLock($tables,$where,$col='1 as adodbignore')
+ {
+ if ($col == '1 as adodbignore') $col = 'top 1 null as ignore';
+ if (!$this->transCnt) $this->BeginTrans();
+ return $this->GetOne("select $col from $tables with (ROWLOCK,HOLDLOCK) where $where");
+ }
+
+
+ function MetaColumns($table, $normalize=true)
+ {
+// $arr = ADOConnection::MetaColumns($table);
+// return $arr;
+
+ $this->_findschema($table,$schema);
+ if ($schema) {
+ $dbName = $this->database;
+ $this->SelectDB($schema);
+ }
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
+
+ if ($schema) {
+ $this->SelectDB($dbName);
+ }
+
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ if (!is_object($rs)) {
+ $false = false;
+ return $false;
+ }
+
+ $retarr = array();
+ while (!$rs->EOF){
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $fld->type = $rs->fields[1];
+
+ $fld->not_null = (!$rs->fields[3]);
+ $fld->auto_increment = ($rs->fields[4] == 128); // sys.syscolumns status field. 0x80 = 128 ref: http://msdn.microsoft.com/en-us/library/ms186816.aspx
+
+ if (isset($rs->fields[5]) && $rs->fields[5]) {
+ if ($rs->fields[5]>0) $fld->max_length = $rs->fields[5];
+ $fld->scale = $rs->fields[6];
+ if ($fld->scale>0) $fld->max_length += 1;
+ } else
+ $fld->max_length = $rs->fields[2];
+
+ if ($save == ADODB_FETCH_NUM) {
+ $retarr[] = $fld;
+ } else {
+ $retarr[strtoupper($fld->name)] = $fld;
+ }
+ $rs->MoveNext();
+ }
+
+ $rs->Close();
+ return $retarr;
+
+ }
+
+
+ function MetaIndexes($table,$primary=false, $owner=false)
+ {
+ $table = $this->qstr($table);
+
+ $sql = "SELECT i.name AS ind_name, C.name AS col_name, USER_NAME(O.uid) AS Owner, c.colid, k.Keyno,
+ CASE WHEN I.indid BETWEEN 1 AND 254 AND (I.status & 2048 = 2048 OR I.Status = 16402 AND O.XType = 'V') THEN 1 ELSE 0 END AS IsPK,
+ CASE WHEN I.status & 2 = 2 THEN 1 ELSE 0 END AS IsUnique
+ FROM dbo.sysobjects o INNER JOIN dbo.sysindexes I ON o.id = i.id
+ INNER JOIN dbo.sysindexkeys K ON I.id = K.id AND I.Indid = K.Indid
+ INNER JOIN dbo.syscolumns c ON K.id = C.id AND K.colid = C.Colid
+ WHERE LEFT(i.name, 8) <> '_WA_Sys_' AND o.status >= 0 AND O.Name LIKE $table
+ ORDER BY O.name, I.Name, K.keyno";
+
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+
+ $rs = $this->Execute($sql);
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ if (!is_object($rs)) {
+ return FALSE;
+ }
+
+ $indexes = array();
+ while ($row = $rs->FetchRow()) {
+ if ($primary && !$row[5]) continue;
+
+ $indexes[$row[0]]['unique'] = $row[6];
+ $indexes[$row[0]]['columns'][] = $row[1];
+ }
+ return $indexes;
+ }
+
+ function MetaForeignKeys($table, $owner=false, $upper=false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $table = $this->qstr(strtoupper($table));
+
+ $sql =
+"select object_name(constid) as constraint_name,
+ col_name(fkeyid, fkey) as column_name,
+ object_name(rkeyid) as referenced_table_name,
+ col_name(rkeyid, rkey) as referenced_column_name
+from sysforeignkeys
+where upper(object_name(fkeyid)) = $table
+order by constraint_name, referenced_table_name, keyno";
+
+ $constraints = $this->GetArray($sql);
+
+ $ADODB_FETCH_MODE = $save;
+
+ $arr = false;
+ foreach($constraints as $constr) {
+ //print_r($constr);
+ $arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3];
+ }
+ if (!$arr) return false;
+
+ $arr2 = false;
+
+ foreach($arr as $k => $v) {
+ foreach($v as $a => $b) {
+ if ($upper) $a = strtoupper($a);
+ $arr2[$a] = $b;
+ }
+ }
+ return $arr2;
+ }
+
+ //From: Fernando Moreira <FMoreira@imediata.pt>
+ function MetaDatabases()
+ {
+ if(@mssql_select_db("master")) {
+ $qry=$this->metaDatabasesSQL;
+ if($rs=@mssql_query($qry,$this->_connectionID)){
+ $tmpAr=$ar=array();
+ while($tmpAr=@mssql_fetch_row($rs))
+ $ar[]=$tmpAr[0];
+ @mssql_select_db($this->database);
+ if(sizeof($ar))
+ return($ar);
+ else
+ return(false);
+ } else {
+ @mssql_select_db($this->database);
+ return(false);
+ }
+ }
+ return(false);
+ }
+
+ // "Stein-Aksel Basma" <basma@accelero.no>
+ // tested with MSSQL 2000
+ function MetaPrimaryKeys($table, $owner=false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $schema = '';
+ $this->_findschema($table,$schema);
+ if (!$schema) $schema = $this->database;
+ if ($schema) $schema = "and k.table_catalog like '$schema%'";
+
+ $sql = "select distinct k.column_name,ordinal_position from information_schema.key_column_usage k,
+ information_schema.table_constraints tc
+ where tc.constraint_name = k.constraint_name and tc.constraint_type =
+ 'PRIMARY KEY' and k.table_name = '$table' $schema order by ordinal_position ";
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $a = $this->GetCol($sql);
+ $ADODB_FETCH_MODE = $savem;
+
+ if ($a && sizeof($a)>0) return $a;
+ $false = false;
+ return $false;
+ }
+
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ if ($mask) {
+ $save = $this->metaTablesSQL;
+ $mask = $this->qstr(($mask));
+ $this->metaTablesSQL .= " AND name like $mask";
+ }
+ $ret = ADOConnection::MetaTables($ttype,$showSchema);
+
+ if ($mask) {
+ $this->metaTablesSQL = $save;
+ }
+ return $ret;
+ }
+
+ function SelectDB($dbName)
+ {
+ $this->database = $dbName;
+ $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
+ if ($this->_connectionID) {
+ return @mssql_select_db($dbName);
+ }
+ else return false;
+ }
+
+ function ErrorMsg()
+ {
+ if (empty($this->_errorMsg)){
+ $this->_errorMsg = mssql_get_last_message();
+ }
+ return $this->_errorMsg;
+ }
+
+ function ErrorNo()
+ {
+ if ($this->_logsql && $this->_errorCode !== false) return $this->_errorCode;
+ if (empty($this->_errorMsg)) {
+ $this->_errorMsg = mssql_get_last_message();
+ }
+ $id = @mssql_query("select @@ERROR",$this->_connectionID);
+ if (!$id) return false;
+ $arr = mssql_fetch_array($id);
+ @mssql_free_result($id);
+ if (is_array($arr)) return $arr[0];
+ else return -1;
+ }
+
+ // returns true or false, newconnect supported since php 5.1.0.
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$newconnect=false)
+ {
+ if (!function_exists('mssql_pconnect')) return null;
+ $this->_connectionID = mssql_connect($argHostname,$argUsername,$argPassword,$newconnect);
+ if ($this->_connectionID === false) return false;
+ if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ return true;
+ }
+
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('mssql_pconnect')) return null;
+ $this->_connectionID = mssql_pconnect($argHostname,$argUsername,$argPassword);
+ if ($this->_connectionID === false) return false;
+
+ // persistent connections can forget to rollback on crash, so we do it here.
+ if ($this->autoRollback) {
+ $cnt = $this->GetOne('select @@TRANCOUNT');
+ while (--$cnt >= 0) $this->Execute('ROLLBACK TRAN');
+ }
+ if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ return true;
+ }
+
+ function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true);
+ }
+
+ function Prepare($sql)
+ {
+ $sqlarr = explode('?',$sql);
+ if (sizeof($sqlarr) <= 1) return $sql;
+ $sql2 = $sqlarr[0];
+ for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++) {
+ $sql2 .= '@P'.($i-1) . $sqlarr[$i];
+ }
+ return array($sql,$this->qstr($sql2),$max,$sql2);
+ }
+
+ function PrepareSP($sql,$param=true)
+ {
+ if (!$this->_has_mssql_init) {
+ ADOConnection::outp( "PrepareSP: mssql_init only available since PHP 4.1.0");
+ return $sql;
+ }
+ $stmt = mssql_init($sql,$this->_connectionID);
+ if (!$stmt) return $sql;
+ return array($sql,$stmt);
+ }
+
+ // returns concatenated string
+ // MSSQL requires integers to be cast as strings
+ // automatically cast every datatype to VARCHAR(255)
+ // @author David Rogers (introspectshun)
+ function Concat()
+ {
+ $s = "";
+ $arr = func_get_args();
+
+ // Split single record on commas, if possible
+ if (sizeof($arr) == 1) {
+ foreach ($arr as $arg) {
+ $args = explode(',', $arg);
+ }
+ $arr = $args;
+ }
+
+ array_walk(
+ $arr,
+ function(&$value, $key) {
+ $value = "CAST(" . $value . " AS VARCHAR(255))";
+ }
+ );
+ $s = implode('+',$arr);
+ if (sizeof($arr) > 0) return "$s";
+
+ return '';
+ }
+
+ /*
+ Usage:
+ $stmt = $db->PrepareSP('SP_RUNSOMETHING'); -- takes 2 params, @myid and @group
+
+ # note that the parameter does not have @ in front!
+ $db->Parameter($stmt,$id,'myid');
+ $db->Parameter($stmt,$group,'group',false,64);
+ $db->Execute($stmt);
+
+ @param $stmt Statement returned by Prepare() or PrepareSP().
+ @param $var PHP variable to bind to. Can set to null (for isNull support).
+ @param $name Name of stored procedure variable name to bind to.
+ @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8.
+ @param [$maxLen] Holds an maximum length of the variable.
+ @param [$type] The data type of $var. Legal values depend on driver.
+
+ See mssql_bind documentation at php.net.
+ */
+ function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=false)
+ {
+ if (!$this->_has_mssql_init) {
+ ADOConnection::outp( "Parameter: mssql_bind only available since PHP 4.1.0");
+ return false;
+ }
+
+ $isNull = is_null($var); // php 4.0.4 and above...
+
+ if ($type === false)
+ switch(gettype($var)) {
+ default:
+ case 'string': $type = SQLVARCHAR; break;
+ case 'double': $type = SQLFLT8; break;
+ case 'integer': $type = SQLINT4; break;
+ case 'boolean': $type = SQLINT1; break; # SQLBIT not supported in 4.1.0
+ }
+
+ if ($this->debug) {
+ $prefix = ($isOutput) ? 'Out' : 'In';
+ $ztype = (empty($type)) ? 'false' : $type;
+ ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
+ }
+ /*
+ See http://phplens.com/lens/lensforum/msgs.php?id=7231
+
+ RETVAL is HARD CODED into php_mssql extension:
+ The return value (a long integer value) is treated like a special OUTPUT parameter,
+ called "RETVAL" (without the @). See the example at mssql_execute to
+ see how it works. - type: one of this new supported PHP constants.
+ SQLTEXT, SQLVARCHAR,SQLCHAR, SQLINT1,SQLINT2, SQLINT4, SQLBIT,SQLFLT8
+ */
+ if ($name !== 'RETVAL') $name = '@'.$name;
+ return mssql_bind($stmt[1], $name, $var, $type, $isOutput, $isNull, $maxLen);
+ }
+
+ /*
+ Unfortunately, it appears that mssql cannot handle varbinary > 255 chars
+ So all your blobs must be of type "image".
+
+ Remember to set in php.ini the following...
+
+ ; Valid range 0 - 2147483647. Default = 4096.
+ mssql.textlimit = 0 ; zero to pass through
+
+ ; Valid range 0 - 2147483647. Default = 4096.
+ mssql.textsize = 0 ; zero to pass through
+ */
+ function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ {
+
+ if (strtoupper($blobtype) == 'CLOB') {
+ $sql = "UPDATE $table SET $column='" . $val . "' WHERE $where";
+ return $this->Execute($sql) != false;
+ }
+ $sql = "UPDATE $table SET $column=0x".bin2hex($val)." WHERE $where";
+ return $this->Execute($sql) != false;
+ }
+
+ // returns query ID if successful, otherwise false
+ function _query($sql,$inputarr=false)
+ {
+ $this->_errorMsg = false;
+ if (is_array($inputarr)) {
+
+ # bind input params with sp_executesql:
+ # see http://www.quest-pipelines.com/newsletter-v3/0402_F.htm
+ # works only with sql server 7 and newer
+ $getIdentity = false;
+ if (!is_array($sql) && preg_match('/^\\s*insert/i', $sql)) {
+ $getIdentity = true;
+ $sql .= (preg_match('/;\\s*$/i', $sql) ? ' ' : '; ') . $this->identitySQL;
+ }
+ if (!is_array($sql)) $sql = $this->Prepare($sql);
+ $params = '';
+ $decl = '';
+ $i = 0;
+ foreach($inputarr as $v) {
+ if ($decl) {
+ $decl .= ', ';
+ $params .= ', ';
+ }
+ if (is_string($v)) {
+ $len = strlen($v);
+ if ($len == 0) $len = 1;
+
+ if ($len > 4000 ) {
+ // NVARCHAR is max 4000 chars. Let's use NTEXT
+ $decl .= "@P$i NTEXT";
+ } else {
+ $decl .= "@P$i NVARCHAR($len)";
+ }
+
+
+ if (substr($v,0,1) == "'" && substr($v,-1,1) == "'")
+ /*
+ * String is already fully quoted
+ */
+ $inputVar = $v;
+ else
+ $inputVar = $this->qstr($v);
+
+ $params .= "@P$i=N" . $inputVar;
+ } else if (is_integer($v)) {
+ $decl .= "@P$i INT";
+ $params .= "@P$i=".$v;
+ } else if (is_float($v)) {
+ $decl .= "@P$i FLOAT";
+ $params .= "@P$i=".$v;
+ } else if (is_bool($v)) {
+ $decl .= "@P$i INT"; # Used INT just in case BIT in not supported on the user's MSSQL version. It will cast appropriately.
+ $params .= "@P$i=".(($v)?'1':'0'); # True == 1 in MSSQL BIT fields and acceptable for storing logical true in an int field
+ } else {
+ $decl .= "@P$i CHAR"; # Used char because a type is required even when the value is to be NULL.
+ $params .= "@P$i=NULL";
+ }
+ $i += 1;
+ }
+ $decl = $this->qstr($decl);
+ if ($this->debug) ADOConnection::outp("<font size=-1>sp_executesql N{$sql[1]},N$decl,$params</font>");
+ $rez = mssql_query("sp_executesql N{$sql[1]},N$decl,$params", $this->_connectionID);
+ if ($getIdentity) {
+ $arr = @mssql_fetch_row($rez);
+ $this->lastInsID = isset($arr[0]) ? $arr[0] : false;
+ @mssql_data_seek($rez, 0);
+ }
+
+ } else if (is_array($sql)) {
+ # PrepareSP()
+ $rez = mssql_execute($sql[1]);
+ $this->lastInsID = false;
+
+ } else {
+ $rez = mssql_query($sql,$this->_connectionID);
+ $this->lastInsID = false;
+ }
+ return $rez;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ if ($this->transCnt) $this->RollbackTrans();
+ $rez = @mssql_close($this->_connectionID);
+ $this->_connectionID = false;
+ return $rez;
+ }
+
+ // mssql uses a default date like Dec 30 2000 12:00AM
+ static function UnixDate($v)
+ {
+ return ADORecordSet_array_mssql::UnixDate($v);
+ }
+
+ static function UnixTimeStamp($v)
+ {
+ return ADORecordSet_array_mssql::UnixTimeStamp($v);
+ }
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordset_mssql extends ADORecordSet {
+
+ var $databaseType = "mssql";
+ var $canSeek = true;
+ var $hasFetchAssoc; // see http://phplens.com/lens/lensforum/msgs.php?id=6083
+ // _mths works only in non-localised system
+
+ function __construct($id,$mode=false)
+ {
+ // freedts check...
+ $this->hasFetchAssoc = function_exists('mssql_fetch_assoc');
+
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+
+ }
+ $this->fetchMode = $mode;
+ return parent::__construct($id,$mode);
+ }
+
+
+ function _initrs()
+ {
+ GLOBAL $ADODB_COUNTRECS;
+ $this->_numOfRows = ($ADODB_COUNTRECS)? @mssql_num_rows($this->_queryID):-1;
+ $this->_numOfFields = @mssql_num_fields($this->_queryID);
+ }
+
+
+ //Contributed by "Sven Axelsson" <sven.axelsson@bokochwebb.se>
+ // get next resultset - requires PHP 4.0.5 or later
+ function NextRecordSet()
+ {
+ if (!mssql_next_result($this->_queryID)) return false;
+ $this->_inited = false;
+ $this->bind = false;
+ $this->_currentRow = -1;
+ $this->Init();
+ return true;
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode != ADODB_FETCH_NUM) return $this->fields[$colname];
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+ /* Returns: an object containing field information.
+ Get column information in the Recordset object. fetchField() can be used in order to obtain information about
+ fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
+ fetchField() is retrieved. */
+
+ function FetchField($fieldOffset = -1)
+ {
+ if ($fieldOffset != -1) {
+ $f = @mssql_fetch_field($this->_queryID, $fieldOffset);
+ }
+ else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */
+ $f = @mssql_fetch_field($this->_queryID);
+ }
+ $false = false;
+ if (empty($f)) return $false;
+ return $f;
+ }
+
+ function _seek($row)
+ {
+ return @mssql_data_seek($this->_queryID, $row);
+ }
+
+ // speedup
+ function MoveNext()
+ {
+ if ($this->EOF) return false;
+
+ $this->_currentRow++;
+
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ if ($this->fetchMode & ADODB_FETCH_NUM) {
+ //ADODB_FETCH_BOTH mode
+ $this->fields = @mssql_fetch_array($this->_queryID);
+ }
+ else {
+ if ($this->hasFetchAssoc) {// only for PHP 4.2.0 or later
+ $this->fields = @mssql_fetch_assoc($this->_queryID);
+ } else {
+ $flds = @mssql_fetch_array($this->_queryID);
+ if (is_array($flds)) {
+ $fassoc = array();
+ foreach($flds as $k => $v) {
+ if (is_numeric($k)) continue;
+ $fassoc[$k] = $v;
+ }
+ $this->fields = $fassoc;
+ } else
+ $this->fields = false;
+ }
+ }
+
+ if (is_array($this->fields)) {
+ if (ADODB_ASSOC_CASE == 0) {
+ foreach($this->fields as $k=>$v) {
+ $kn = strtolower($k);
+ if ($kn <> $k) {
+ unset($this->fields[$k]);
+ $this->fields[$kn] = $v;
+ }
+ }
+ } else if (ADODB_ASSOC_CASE == 1) {
+ foreach($this->fields as $k=>$v) {
+ $kn = strtoupper($k);
+ if ($kn <> $k) {
+ unset($this->fields[$k]);
+ $this->fields[$kn] = $v;
+ }
+ }
+ }
+ }
+ } else {
+ $this->fields = @mssql_fetch_row($this->_queryID);
+ }
+ if ($this->fields) return true;
+ $this->EOF = true;
+
+ return false;
+ }
+
+
+ // INSERT UPDATE DELETE returns false even if no error occurs in 4.0.4
+ // also the date format has been changed from YYYY-mm-dd to dd MMM YYYY in 4.0.4. Idiot!
+ function _fetch($ignore_fields=false)
+ {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ if ($this->fetchMode & ADODB_FETCH_NUM) {
+ //ADODB_FETCH_BOTH mode
+ $this->fields = @mssql_fetch_array($this->_queryID);
+ } else {
+ if ($this->hasFetchAssoc) // only for PHP 4.2.0 or later
+ $this->fields = @mssql_fetch_assoc($this->_queryID);
+ else {
+ $this->fields = @mssql_fetch_array($this->_queryID);
+ if (@is_array($$this->fields)) {
+ $fassoc = array();
+ foreach($$this->fields as $k => $v) {
+ if (is_integer($k)) continue;
+ $fassoc[$k] = $v;
+ }
+ $this->fields = $fassoc;
+ }
+ }
+ }
+
+ if (!$this->fields) {
+ } else if (ADODB_ASSOC_CASE == 0) {
+ foreach($this->fields as $k=>$v) {
+ $kn = strtolower($k);
+ if ($kn <> $k) {
+ unset($this->fields[$k]);
+ $this->fields[$kn] = $v;
+ }
+ }
+ } else if (ADODB_ASSOC_CASE == 1) {
+ foreach($this->fields as $k=>$v) {
+ $kn = strtoupper($k);
+ if ($kn <> $k) {
+ unset($this->fields[$k]);
+ $this->fields[$kn] = $v;
+ }
+ }
+ }
+ } else {
+ $this->fields = @mssql_fetch_row($this->_queryID);
+ }
+ return $this->fields;
+ }
+
+ /* close() only needs to be called if you are worried about using too much memory while your script
+ is running. All associated result memory for the specified result identifier will automatically be freed. */
+
+ function _close()
+ {
+ if($this->_queryID) {
+ $rez = mssql_free_result($this->_queryID);
+ $this->_queryID = false;
+ return $rez;
+ }
+ return true;
+ }
+
+ // mssql uses a default date like Dec 30 2000 12:00AM
+ static function UnixDate($v)
+ {
+ return ADORecordSet_array_mssql::UnixDate($v);
+ }
+
+ static function UnixTimeStamp($v)
+ {
+ return ADORecordSet_array_mssql::UnixTimeStamp($v);
+ }
+
+}
+
+
+class ADORecordSet_array_mssql extends ADORecordSet_array {
+ function __construct($id=-1,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+
+ // mssql uses a default date like Dec 30 2000 12:00AM
+ static function UnixDate($v)
+ {
+
+ if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixDate($v);
+
+ global $ADODB_mssql_mths,$ADODB_mssql_date_order;
+
+ //Dec 30 2000 12:00AM
+ if ($ADODB_mssql_date_order == 'dmy') {
+ if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
+ return parent::UnixDate($v);
+ }
+ if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
+
+ $theday = $rr[1];
+ $themth = substr(strtoupper($rr[2]),0,3);
+ } else {
+ if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
+ return parent::UnixDate($v);
+ }
+ if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
+
+ $theday = $rr[2];
+ $themth = substr(strtoupper($rr[1]),0,3);
+ }
+ $themth = $ADODB_mssql_mths[$themth];
+ if ($themth <= 0) return false;
+ // h-m-s-MM-DD-YY
+ return mktime(0,0,0,$themth,$theday,$rr[3]);
+ }
+
+ static function UnixTimeStamp($v)
+ {
+
+ if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixTimeStamp($v);
+
+ global $ADODB_mssql_mths,$ADODB_mssql_date_order;
+
+ //Dec 30 2000 12:00AM
+ if ($ADODB_mssql_date_order == 'dmy') {
+ if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|"
+ ,$v, $rr)) return parent::UnixTimeStamp($v);
+ if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
+
+ $theday = $rr[1];
+ $themth = substr(strtoupper($rr[2]),0,3);
+ } else {
+ if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|"
+ ,$v, $rr)) return parent::UnixTimeStamp($v);
+ if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
+
+ $theday = $rr[2];
+ $themth = substr(strtoupper($rr[1]),0,3);
+ }
+
+ $themth = $ADODB_mssql_mths[$themth];
+ if ($themth <= 0) return false;
+
+ switch (strtoupper($rr[6])) {
+ case 'P':
+ if ($rr[4]<12) $rr[4] += 12;
+ break;
+ case 'A':
+ if ($rr[4]==12) $rr[4] = 0;
+ break;
+ default:
+ break;
+ }
+ // h-m-s-MM-DD-YY
+ return mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]);
+ }
+}
+
+/*
+Code Example 1:
+
+select object_name(constid) as constraint_name,
+ object_name(fkeyid) as table_name,
+ col_name(fkeyid, fkey) as column_name,
+ object_name(rkeyid) as referenced_table_name,
+ col_name(rkeyid, rkey) as referenced_column_name
+from sysforeignkeys
+where object_name(fkeyid) = x
+order by constraint_name, table_name, referenced_table_name, keyno
+
+Code Example 2:
+select constraint_name,
+ column_name,
+ ordinal_position
+from information_schema.key_column_usage
+where constraint_catalog = db_name()
+and table_name = x
+order by constraint_name, ordinal_position
+
+http://www.databasejournal.com/scripts/article.php/1440551
+*/
diff --git a/vendor/adodb/adodb-php/drivers/adodb-mssql_n.inc.php b/vendor/adodb/adodb-php/drivers/adodb-mssql_n.inc.php
new file mode 100644
index 0000000..28b29bb
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-mssql_n.inc.php
@@ -0,0 +1,250 @@
+<?php
+
+/// $Id $
+
+///////////////////////////////////////////////////////////////////////////
+// //
+// NOTICE OF COPYRIGHT //
+// //
+// ADOdb - Database Abstraction Library for PHP //
+// //
+// Latest version is available at http://adodb.org //
+// //
+// Copyright (c) 2000-2014 John Lim (jlim\@natsoft.com.my) //
+// All rights reserved. //
+// Released under both BSD license and LGPL library license. //
+// Whenever there is any discrepancy between the two licenses, //
+// the BSD license will take precedence //
+// //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment //
+// http://moodle.com //
+// //
+// Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
+// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation; either version 2 of the License, or //
+// (at your option) any later version. //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License for more details: //
+// //
+// http://www.gnu.org/copyleft/gpl.html //
+// //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+* MSSQL Driver with auto-prepended "N" for correct unicode storage
+* of SQL literal strings. Intended to be used with MSSQL drivers that
+* are sending UCS-2 data to MSSQL (FreeTDS and ODBTP) in order to get
+* true cross-db compatibility from the application point of view.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+// one useful constant
+if (!defined('SINGLEQUOTE')) define('SINGLEQUOTE', "'");
+
+include_once(ADODB_DIR.'/drivers/adodb-mssql.inc.php');
+
+class ADODB_mssql_n extends ADODB_mssql {
+ var $databaseType = "mssql_n";
+
+ function _query($sql,$inputarr=false)
+ {
+ $sql = $this->_appendN($sql);
+ return ADODB_mssql::_query($sql,$inputarr);
+ }
+
+ /**
+ * This function will intercept all the literals used in the SQL, prepending the "N" char to them
+ * in order to allow mssql to store properly data sent in the correct UCS-2 encoding (by freeTDS
+ * and ODBTP) keeping SQL compatibility at ADOdb level (instead of hacking every project to add
+ * the "N" notation when working against MSSQL.
+ *
+ * The orginal note indicated that this hack should only be used if ALL the char-based columns
+ * in your DB are of type nchar, nvarchar and ntext, but testing seems to indicate that SQL server
+ * doesn't seem to care if the statement is used against char etc fields.
+ *
+ * @todo This function should raise an ADOdb error if one of the transformations fail
+ *
+ * @param mixed $inboundData Either a string containing an SQL statement
+ * or an array with resources from prepared statements
+ *
+ * @return mixed
+ */
+ function _appendN($inboundData) {
+
+ $inboundIsArray = false;
+
+ if (is_array($inboundData))
+ {
+ $inboundIsArray = true;
+ $inboundArray = $inboundData;
+ } else
+ $inboundArray = (array)$inboundData;
+
+ /*
+ * All changes will be placed here
+ */
+ $outboundArray = $inboundArray;
+
+ foreach($inboundArray as $inboundKey=>$inboundValue)
+ {
+
+ if (is_resource($inboundValue))
+ {
+ /*
+ * Prepared statement resource
+ */
+ if ($this->debug)
+ ADOConnection::outp("{$this->databaseType} index $inboundKey value is resource, continue");
+
+ continue;
+ }
+
+ if (strpos($inboundValue, SINGLEQUOTE) === false)
+ {
+ /*
+ * Check we have something to manipulate
+ */
+ if ($this->debug)
+ ADOConnection::outp("{$this->databaseType} index $inboundKey value $inboundValue has no single quotes, continue");
+ continue;
+ }
+
+ /*
+ * Check we haven't an odd number of single quotes (this can cause problems below
+ * and should be considered one wrong SQL). Exit with debug info.
+ */
+ if ((substr_count($inboundValue, SINGLEQUOTE) & 1))
+ {
+ if ($this->debug)
+ ADOConnection::outp("{$this->databaseType} internal transformation: not converted. Wrong number of quotes (odd)");
+
+ break;
+ }
+
+ /*
+ * Check we haven't any backslash + single quote combination. It should mean wrong
+ * backslashes use (bad magic_quotes_sybase?). Exit with debug info.
+ */
+ $regexp = '/(\\\\' . SINGLEQUOTE . '[^' . SINGLEQUOTE . '])/';
+ if (preg_match($regexp, $inboundValue))
+ {
+ if ($this->debug)
+ ADOConnection::outp("{$this->databaseType} internal transformation: not converted. Found bad use of backslash + single quote");
+
+ break;
+ }
+
+ /*
+ * Remove pairs of single-quotes
+ */
+ $pairs = array();
+ $regexp = '/(' . SINGLEQUOTE . SINGLEQUOTE . ')/';
+ preg_match_all($regexp, $inboundValue, $list_of_pairs);
+
+ if ($list_of_pairs)
+ {
+ foreach (array_unique($list_of_pairs[0]) as $key=>$value)
+ $pairs['<@#@#@PAIR-'.$key.'@#@#@>'] = $value;
+
+
+ if (!empty($pairs))
+ $inboundValue = str_replace($pairs, array_keys($pairs), $inboundValue);
+
+ }
+
+ /*
+ * Remove the rest of literals present in the query
+ */
+ $literals = array();
+ $regexp = '/(N?' . SINGLEQUOTE . '.*?' . SINGLEQUOTE . ')/is';
+ preg_match_all($regexp, $inboundValue, $list_of_literals);
+
+ if ($list_of_literals)
+ {
+ foreach (array_unique($list_of_literals[0]) as $key=>$value)
+ $literals['<#@#@#LITERAL-'.$key.'#@#@#>'] = $value;
+
+
+ if (!empty($literals))
+ $inboundValue = str_replace($literals, array_keys($literals), $inboundValue);
+ }
+
+ /*
+ * Analyse literals to prepend the N char to them if their contents aren't numeric
+ */
+ if (!empty($literals))
+ {
+ foreach ($literals as $key=>$value) {
+ if (!is_numeric(trim($value, SINGLEQUOTE)))
+ /*
+ * Non numeric string, prepend our dear N, whilst
+ * Trimming potentially existing previous "N"
+ */
+ $literals[$key] = 'N' . trim($value, 'N');
+
+ }
+ }
+
+ /*
+ * Re-apply literals to the text
+ */
+ if (!empty($literals))
+ $inboundValue = str_replace(array_keys($literals), $literals, $inboundValue);
+
+
+ /*
+ * Any pairs followed by N' must be switched to N' followed by those pairs
+ * (or strings beginning with single quotes will fail)
+ */
+ $inboundValue = preg_replace("/((<@#@#@PAIR-(\d+)@#@#@>)+)N'/", "N'$1", $inboundValue);
+
+ /*
+ * Re-apply pairs of single-quotes to the text
+ */
+ if (!empty($pairs))
+ $inboundValue = str_replace(array_keys($pairs), $pairs, $inboundValue);
+
+
+ /*
+ * Print transformation if debug = on
+ */
+ if (strcmp($inboundValue,$inboundArray[$inboundKey]) <> 0 && $this->debug)
+ ADOConnection::outp("{$this->databaseType} internal transformation: {$inboundArray[$inboundKey]} to {$inboundValue}");
+
+ if (strcmp($inboundValue,$inboundArray[$inboundKey]) <> 0)
+ /*
+ * Place the transformed value into the outbound array
+ */
+ $outboundArray[$inboundKey] = $inboundValue;
+ }
+
+ /*
+ * Any transformations are in the $outboundArray
+ */
+ if ($inboundIsArray)
+ return $outboundArray;
+
+ /*
+ * We passed a string in originally
+ */
+ return $outboundArray[0];
+
+ }
+
+}
+
+class ADORecordset_mssql_n extends ADORecordset_mssql {
+ var $databaseType = "mssql_n";
+ function __construct($id,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-mssqlnative.inc.php b/vendor/adodb/adodb-php/drivers/adodb-mssqlnative.inc.php
new file mode 100644
index 0000000..d5e412f
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-mssqlnative.inc.php
@@ -0,0 +1,1200 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Native mssql driver. Requires mssql client. Works on Windows.
+ http://www.microsoft.com/sql/technologies/php/default.mspx
+ To configure for Unix, see
+ http://phpbuilder.com/columns/alberto20000919.php3
+
+ $stream = sqlsrv_get_field($stmt, $index, SQLSRV_SQLTYPE_STREAM(SQLSRV_ENC_BINARY));
+ stream_filter_append($stream, "convert.iconv.ucs-2/utf-8"); // Voila, UTF-8 can be read directly from $stream
+
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (!function_exists('sqlsrv_configure')) {
+ die("mssqlnative extension not installed");
+}
+
+if (!function_exists('sqlsrv_set_error_handling')) {
+ function sqlsrv_set_error_handling($constant) {
+ sqlsrv_configure("WarningsReturnAsErrors", $constant);
+ }
+}
+if (!function_exists('sqlsrv_log_set_severity')) {
+ function sqlsrv_log_set_severity($constant) {
+ sqlsrv_configure("LogSeverity", $constant);
+ }
+}
+if (!function_exists('sqlsrv_log_set_subsystems')) {
+ function sqlsrv_log_set_subsystems($constant) {
+ sqlsrv_configure("LogSubsystems", $constant);
+ }
+}
+
+
+//----------------------------------------------------------------
+// MSSQL returns dates with the format Oct 13 2002 or 13 Oct 2002
+// and this causes tons of problems because localized versions of
+// MSSQL will return the dates in dmy or mdy order; and also the
+// month strings depends on what language has been configured. The
+// following two variables allow you to control the localization
+// settings - Ugh.
+//
+// MORE LOCALIZATION INFO
+// ----------------------
+// To configure datetime, look for and modify sqlcommn.loc,
+// typically found in c:\mssql\install
+// Also read :
+// http://support.microsoft.com/default.aspx?scid=kb;EN-US;q220918
+// Alternatively use:
+// CONVERT(char(12),datecol,120)
+//
+// Also if your month is showing as month-1,
+// e.g. Jan 13, 2002 is showing as 13/0/2002, then see
+// http://phplens.com/lens/lensforum/msgs.php?id=7048&x=1
+// it's a localisation problem.
+//----------------------------------------------------------------
+
+
+// has datetime converstion to YYYY-MM-DD format, and also mssql_fetch_assoc
+if (ADODB_PHPVER >= 0x4300) {
+// docs say 4.2.0, but testing shows only since 4.3.0 does it work!
+ ini_set('mssql.datetimeconvert',0);
+} else {
+ global $ADODB_mssql_mths; // array, months must be upper-case
+ $ADODB_mssql_date_order = 'mdy';
+ $ADODB_mssql_mths = array(
+ 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,
+ 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
+}
+
+class ADODB_mssqlnative extends ADOConnection {
+ var $databaseType = "mssqlnative";
+ var $dataProvider = "mssqlnative";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $fmtDate = "'Y-m-d'";
+ var $fmtTimeStamp = "'Y-m-d\TH:i:s'";
+ var $hasInsertID = true;
+ var $substr = "substring";
+ var $length = 'len';
+ var $hasAffectedRows = true;
+ var $poorAffectedRows = false;
+ var $metaDatabasesSQL = "select name from sys.sysdatabases where name <> 'master'";
+ var $metaTablesSQL="select name,case when type='U' then 'T' else 'V' end from sysobjects where (type='U' or type='V') and (name not in ('sysallocations','syscolumns','syscomments','sysdepends','sysfilegroups','sysfiles','sysfiles1','sysforeignkeys','sysfulltextcatalogs','sysindexes','sysindexkeys','sysmembers','sysobjects','syspermissions','sysprotects','sysreferences','systypes','sysusers','sysalternates','sysconstraints','syssegments','REFERENTIAL_CONSTRAINTS','CHECK_CONSTRAINTS','CONSTRAINT_TABLE_USAGE','CONSTRAINT_COLUMN_USAGE','VIEWS','VIEW_TABLE_USAGE','VIEW_COLUMN_USAGE','SCHEMATA','TABLES','TABLE_CONSTRAINTS','TABLE_PRIVILEGES','COLUMNS','COLUMN_DOMAIN_USAGE','COLUMN_PRIVILEGES','DOMAINS','DOMAIN_CONSTRAINTS','KEY_COLUMN_USAGE','dtproperties'))";
+ var $metaColumnsSQL =
+ "select c.name,
+ t.name as type,
+ c.length,
+ c.xprec as precision,
+ c.xscale as scale,
+ c.isnullable as nullable,
+ c.cdefault as default_value,
+ c.xtype,
+ t.length as type_length,
+ sc.is_identity
+ from syscolumns c
+ join systypes t on t.xusertype=c.xusertype
+ join sysobjects o on o.id=c.id
+ join sys.tables st on st.name=o.name
+ join sys.columns sc on sc.object_id = st.object_id and sc.name=c.name
+ where o.name='%s'";
+ var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE
+ var $hasGenID = true;
+ var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
+ var $sysTimeStamp = 'GetDate()';
+ var $maxParameterLen = 4000;
+ var $arrayClass = 'ADORecordSet_array_mssqlnative';
+ var $uniqueSort = true;
+ var $leftOuter = '*=';
+ var $rightOuter = '=*';
+ var $ansiOuter = true; // for mssql7 or later
+ var $identitySQL = 'select SCOPE_IDENTITY()'; // 'select SCOPE_IDENTITY'; # for mssql 2000
+ var $uniqueOrderBy = true;
+ var $_bindInputArray = true;
+ var $_dropSeqSQL = "drop table %s";
+ var $connectionInfo = array();
+ var $cachedSchemaFlush = false;
+ var $sequences = false;
+ var $mssql_version = '';
+
+ function __construct()
+ {
+ if ($this->debug) {
+ ADOConnection::outp("<pre>");
+ sqlsrv_set_error_handling( SQLSRV_ERRORS_LOG_ALL );
+ sqlsrv_log_set_severity( SQLSRV_LOG_SEVERITY_ALL );
+ sqlsrv_log_set_subsystems(SQLSRV_LOG_SYSTEM_ALL);
+ sqlsrv_configure('WarningsReturnAsErrors', 0);
+ } else {
+ sqlsrv_set_error_handling(0);
+ sqlsrv_log_set_severity(0);
+ sqlsrv_log_set_subsystems(SQLSRV_LOG_SYSTEM_ALL);
+ sqlsrv_configure('WarningsReturnAsErrors', 0);
+ }
+ }
+
+ /**
+ * Initializes the SQL Server version.
+ * Dies if connected to a non-supported version (2000 and older)
+ */
+ function ServerVersion() {
+ $data = $this->ServerInfo();
+ preg_match('/^\d{2}/', $data['version'], $matches);
+ $version = (int)reset($matches);
+
+ // We only support SQL Server 2005 and up
+ if($version < 9) {
+ die("SQL SERVER VERSION {$data['version']} NOT SUPPORTED IN mssqlnative DRIVER");
+ }
+
+ $this->mssql_version = $version;
+ }
+
+ function ServerInfo() {
+ global $ADODB_FETCH_MODE;
+ static $arr = false;
+ if (is_array($arr))
+ return $arr;
+ if ($this->fetchMode === false) {
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ } elseif ($this->fetchMode >=0 && $this->fetchMode <=2) {
+ $savem = $this->fetchMode;
+ } else
+ $savem = $this->SetFetchMode(ADODB_FETCH_NUM);
+
+ $arrServerInfo = sqlsrv_server_info($this->_connectionID);
+ $ADODB_FETCH_MODE = $savem;
+ $arr['description'] = $arrServerInfo['SQLServerName'].' connected to '.$arrServerInfo['CurrentDatabase'];
+ $arr['version'] = $arrServerInfo['SQLServerVersion'];//ADOConnection::_findvers($arr['description']);
+ return $arr;
+ }
+
+ function IfNull( $field, $ifNull )
+ {
+ return " ISNULL($field, $ifNull) "; // if MS SQL Server
+ }
+
+ function _insertid()
+ {
+ // SCOPE_IDENTITY()
+ // Returns the last IDENTITY value inserted into an IDENTITY column in
+ // the same scope. A scope is a module -- a stored procedure, trigger,
+ // function, or batch. Thus, two statements are in the same scope if
+ // they are in the same stored procedure, function, or batch.
+ return $this->lastInsertID;
+ }
+
+ function _affectedrows()
+ {
+ if ($this->_queryID)
+ return sqlsrv_rows_affected($this->_queryID);
+ }
+
+ function GenID($seq='adodbseq',$start=1) {
+ if (!$this->mssql_version)
+ $this->ServerVersion();
+ switch($this->mssql_version){
+ case 9:
+ case 10:
+ return $this->GenID2008($seq, $start);
+ break;
+ default:
+ return $this->GenID2012($seq, $start);
+ break;
+ }
+ }
+
+ function CreateSequence($seq='adodbseq',$start=1)
+ {
+ if (!$this->mssql_version)
+ $this->ServerVersion();
+
+ switch($this->mssql_version){
+ case 9:
+ case 10:
+ return $this->CreateSequence2008($seq, $start);
+ break;
+ default:
+ return $this->CreateSequence2012($seq, $start);
+ break;
+ }
+
+ }
+
+ /**
+ * For Server 2005,2008, duplicate a sequence with an identity table
+ */
+ function CreateSequence2008($seq='adodbseq',$start=1)
+ {
+ if($this->debug) ADOConnection::outp("<hr>CreateSequence($seq,$start)");
+ sqlsrv_begin_transaction($this->_connectionID);
+ $start -= 1;
+ $this->Execute("create table $seq (id int)");//was float(53)
+ $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
+ if (!$ok) {
+ if($this->debug) ADOConnection::outp("<hr>Error: ROLLBACK");
+ sqlsrv_rollback($this->_connectionID);
+ return false;
+ }
+ sqlsrv_commit($this->_connectionID);
+ return true;
+ }
+
+ /**
+ * Proper Sequences Only available to Server 2012 and up
+ */
+ function CreateSequence2012($seq='adodbseq',$start=1){
+ if (!$this->sequences){
+ $sql = "SELECT name FROM sys.sequences";
+ $this->sequences = $this->GetCol($sql);
+ }
+ $ok = $this->Execute("CREATE SEQUENCE $seq START WITH $start INCREMENT BY 1");
+ if (!$ok)
+ die("CANNOT CREATE SEQUENCE" . print_r(sqlsrv_errors(),true));
+ $this->sequences[] = $seq;
+ }
+
+ /**
+ * For Server 2005,2008, duplicate a sequence with an identity table
+ */
+ function GenID2008($seq='adodbseq',$start=1)
+ {
+ if($this->debug) ADOConnection::outp("<hr>CreateSequence($seq,$start)");
+ sqlsrv_begin_transaction($this->_connectionID);
+ $ok = $this->Execute("update $seq with (tablock,holdlock) set id = id + 1");
+ if (!$ok) {
+ $start -= 1;
+ $this->Execute("create table $seq (id int)");//was float(53)
+ $ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
+ if (!$ok) {
+ if($this->debug) ADOConnection::outp("<hr>Error: ROLLBACK");
+ sqlsrv_rollback($this->_connectionID);
+ return false;
+ }
+ }
+ $num = $this->GetOne("select id from $seq");
+ sqlsrv_commit($this->_connectionID);
+ return $num;
+ }
+ /**
+ * Only available to Server 2012 and up
+ * Cannot do this the normal adodb way by trapping an error if the
+ * sequence does not exist because sql server will auto create a
+ * sequence with the starting number of -9223372036854775808
+ */
+ function GenID2012($seq='adodbseq',$start=1)
+ {
+
+ /*
+ * First time in create an array of sequence names that we
+ * can use in later requests to see if the sequence exists
+ * the overhead is creating a list of sequences every time
+ * we need access to at least 1. If we really care about
+ * performance, we could maybe flag a 'nocheck' class variable
+ */
+ if (!$this->sequences){
+ $sql = "SELECT name FROM sys.sequences";
+ $this->sequences = $this->GetCol($sql);
+ }
+ if (!is_array($this->sequences)
+ || is_array($this->sequences) && !in_array($seq,$this->sequences)){
+ $this->CreateSequence2012($seq, $start);
+
+ }
+ $num = $this->GetOne("SELECT NEXT VALUE FOR $seq");
+ return $num;
+ }
+
+ // Format date column in sql string given an input format that understands Y M D
+ function SQLDate($fmt, $col=false)
+ {
+ if (!$col) $col = $this->sysTimeStamp;
+ $s = '';
+
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ if ($s) $s .= '+';
+ $ch = $fmt[$i];
+ switch($ch) {
+ case 'Y':
+ case 'y':
+ $s .= "datename(yyyy,$col)";
+ break;
+ case 'M':
+ $s .= "convert(char(3),$col,0)";
+ break;
+ case 'm':
+ $s .= "replace(str(month($col),2),' ','0')";
+ break;
+ case 'Q':
+ case 'q':
+ $s .= "datename(quarter,$col)";
+ break;
+ case 'D':
+ case 'd':
+ $s .= "replace(str(day($col),2),' ','0')";
+ break;
+ case 'h':
+ $s .= "substring(convert(char(14),$col,0),13,2)";
+ break;
+
+ case 'H':
+ $s .= "replace(str(datepart(hh,$col),2),' ','0')";
+ break;
+
+ case 'i':
+ $s .= "replace(str(datepart(mi,$col),2),' ','0')";
+ break;
+ case 's':
+ $s .= "replace(str(datepart(ss,$col),2),' ','0')";
+ break;
+ case 'a':
+ case 'A':
+ $s .= "substring(convert(char(19),$col,0),18,2)";
+ break;
+
+ default:
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ $s .= $this->qstr($ch);
+ break;
+ }
+ }
+ return $s;
+ }
+
+
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ if ($this->debug) ADOConnection::outp('<hr>begin transaction');
+ sqlsrv_begin_transaction($this->_connectionID);
+ return true;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) return true;
+ if ($this->debug) ADOConnection::outp('<hr>commit transaction');
+ if (!$ok) return $this->RollbackTrans();
+ if ($this->transCnt) $this->transCnt -= 1;
+ sqlsrv_commit($this->_connectionID);
+ return true;
+ }
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ if ($this->debug) ADOConnection::outp('<hr>rollback transaction');
+ if ($this->transCnt) $this->transCnt -= 1;
+ sqlsrv_rollback($this->_connectionID);
+ return true;
+ }
+
+ function SetTransactionMode( $transaction_mode )
+ {
+ $this->_transmode = $transaction_mode;
+ if (empty($transaction_mode)) {
+ $this->Execute('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
+ return;
+ }
+ if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
+ $this->Execute("SET TRANSACTION ".$transaction_mode);
+ }
+
+ /*
+ Usage:
+
+ $this->BeginTrans();
+ $this->RowLock('table1,table2','table1.id=33 and table2.id=table1.id'); # lock row 33 for both tables
+
+ # some operation on both tables table1 and table2
+
+ $this->CommitTrans();
+
+ See http://www.swynk.com/friends/achigrik/SQL70Locks.asp
+ */
+ function RowLock($tables,$where,$col='1 as adodbignore')
+ {
+ if ($col == '1 as adodbignore') $col = 'top 1 null as ignore';
+ if (!$this->transCnt) $this->BeginTrans();
+ return $this->GetOne("select $col from $tables with (ROWLOCK,HOLDLOCK) where $where");
+ }
+
+ function SelectDB($dbName)
+ {
+ $this->database = $dbName;
+ $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
+ if ($this->_connectionID) {
+ $rs = $this->Execute('USE '.$dbName);
+ if($rs) {
+ return true;
+ } else return false;
+ }
+ else return false;
+ }
+
+ function ErrorMsg()
+ {
+ $retErrors = sqlsrv_errors(SQLSRV_ERR_ALL);
+ if($retErrors != null) {
+ foreach($retErrors as $arrError) {
+ $this->_errorMsg .= "SQLState: ".$arrError[ 'SQLSTATE']."\n";
+ $this->_errorMsg .= "Error Code: ".$arrError[ 'code']."\n";
+ $this->_errorMsg .= "Message: ".$arrError[ 'message']."\n";
+ }
+ }
+ return $this->_errorMsg;
+ }
+
+ function ErrorNo()
+ {
+ $err = sqlsrv_errors(SQLSRV_ERR_ALL);
+ if($err[0]) return $err[0]['code'];
+ else return 0;
+ }
+
+ // returns true or false
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('sqlsrv_connect')) return null;
+ $connectionInfo = $this->connectionInfo;
+ $connectionInfo["Database"]=$argDatabasename;
+ $connectionInfo["UID"]=$argUsername;
+ $connectionInfo["PWD"]=$argPassword;
+
+ foreach ($this->connectionParameters as $parameter=>$value)
+ $connectionInfo[$parameter] = $value;
+
+ if ($this->debug) ADOConnection::outp("<hr>connecting... hostname: $argHostname params: ".var_export($connectionInfo,true));
+ //if ($this->debug) ADOConnection::outp("<hr>_connectionID before: ".serialize($this->_connectionID));
+ if(!($this->_connectionID = sqlsrv_connect($argHostname,$connectionInfo))) {
+ if ($this->debug) ADOConnection::outp( "<hr><b>errors</b>: ".print_r( sqlsrv_errors(), true));
+ return false;
+ }
+ //if ($this->debug) ADOConnection::outp(" _connectionID after: ".serialize($this->_connectionID));
+ //if ($this->debug) ADOConnection::outp("<hr>defined functions: <pre>".var_export(get_defined_functions(),true)."</pre>");
+ return true;
+ }
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ //return null;//not implemented. NOTE: Persistent connections have no effect if PHP is used as a CGI program. (FastCGI!)
+ return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
+ }
+
+ function Prepare($sql)
+ {
+ return $sql; // prepare does not work properly with bind parameters as bind parameters are managed by sqlsrv_prepare!
+
+ $stmt = sqlsrv_prepare( $this->_connectionID, $sql);
+ if (!$stmt) return $sql;
+ return array($sql,$stmt);
+ }
+
+ // returns concatenated string
+ // MSSQL requires integers to be cast as strings
+ // automatically cast every datatype to VARCHAR(255)
+ // @author David Rogers (introspectshun)
+ function Concat()
+ {
+ $s = "";
+ $arr = func_get_args();
+
+ // Split single record on commas, if possible
+ if (sizeof($arr) == 1) {
+ foreach ($arr as $arg) {
+ $args = explode(',', $arg);
+ }
+ $arr = $args;
+ }
+
+ array_walk(
+ $arr,
+ function(&$value, $key) {
+ $value = "CAST(" . $value . " AS VARCHAR(255))";
+ }
+ );
+ $s = implode('+',$arr);
+ if (sizeof($arr) > 0) return "$s";
+
+ return '';
+ }
+
+ /*
+ Unfortunately, it appears that mssql cannot handle varbinary > 255 chars
+ So all your blobs must be of type "image".
+
+ Remember to set in php.ini the following...
+
+ ; Valid range 0 - 2147483647. Default = 4096.
+ mssql.textlimit = 0 ; zero to pass through
+
+ ; Valid range 0 - 2147483647. Default = 4096.
+ mssql.textsize = 0 ; zero to pass through
+ */
+ function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ {
+
+ if (strtoupper($blobtype) == 'CLOB') {
+ $sql = "UPDATE $table SET $column='" . $val . "' WHERE $where";
+ return $this->Execute($sql) != false;
+ }
+ $sql = "UPDATE $table SET $column=0x".bin2hex($val)." WHERE $where";
+ return $this->Execute($sql) != false;
+ }
+
+ // returns query ID if successful, otherwise false
+ function _query($sql,$inputarr=false)
+ {
+ $this->_errorMsg = false;
+
+ if (is_array($sql)) $sql = $sql[1];
+
+ $insert = false;
+ // handle native driver flaw for retrieving the last insert ID
+ if(preg_match('/^\W*insert[\s\w()[\]",.]+values\s*\((?:[^;\']|\'\'|(?:(?:\'\')*\'[^\']+\'(?:\'\')*))*;?$/i', $sql)) {
+ $insert = true;
+ $sql .= '; '.$this->identitySQL; // select scope_identity()
+ }
+ if($inputarr) {
+ $rez = sqlsrv_query($this->_connectionID, $sql, $inputarr);
+ } else {
+ $rez = sqlsrv_query($this->_connectionID,$sql);
+ }
+
+ if ($this->debug) ADOConnection::outp("<hr>running query: ".var_export($sql,true)."<hr>input array: ".var_export($inputarr,true)."<hr>result: ".var_export($rez,true));
+
+ if(!$rez) {
+ $rez = false;
+ } else if ($insert) {
+ // retrieve the last insert ID (where applicable)
+ while ( sqlsrv_next_result($rez) ) {
+ sqlsrv_fetch($rez);
+ $this->lastInsertID = sqlsrv_get_field($rez, 0);
+ }
+ }
+ return $rez;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ if ($this->transCnt) $this->RollbackTrans();
+ $rez = @sqlsrv_close($this->_connectionID);
+ $this->_connectionID = false;
+ return $rez;
+ }
+
+ // mssql uses a default date like Dec 30 2000 12:00AM
+ static function UnixDate($v)
+ {
+ return ADORecordSet_array_mssqlnative::UnixDate($v);
+ }
+
+ static function UnixTimeStamp($v)
+ {
+ return ADORecordSet_array_mssqlnative::UnixTimeStamp($v);
+ }
+
+ function MetaIndexes($table,$primary=false, $owner = false)
+ {
+ $table = $this->qstr($table);
+
+ $sql = "SELECT i.name AS ind_name, C.name AS col_name, USER_NAME(O.uid) AS Owner, c.colid, k.Keyno,
+ CASE WHEN I.indid BETWEEN 1 AND 254 AND (I.status & 2048 = 2048 OR I.Status = 16402 AND O.XType = 'V') THEN 1 ELSE 0 END AS IsPK,
+ CASE WHEN I.status & 2 = 2 THEN 1 ELSE 0 END AS IsUnique
+ FROM dbo.sysobjects o INNER JOIN dbo.sysindexes I ON o.id = i.id
+ INNER JOIN dbo.sysindexkeys K ON I.id = K.id AND I.Indid = K.Indid
+ INNER JOIN dbo.syscolumns c ON K.id = C.id AND K.colid = C.Colid
+ WHERE LEFT(i.name, 8) <> '_WA_Sys_' AND o.status >= 0 AND O.Name LIKE $table
+ ORDER BY O.name, I.Name, K.keyno";
+
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+
+ $rs = $this->Execute($sql);
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ if (!is_object($rs)) {
+ return FALSE;
+ }
+
+ $indexes = array();
+ while ($row = $rs->FetchRow()) {
+ if (!$primary && $row[5]) continue;
+
+ $indexes[$row[0]]['unique'] = $row[6];
+ $indexes[$row[0]]['columns'][] = $row[1];
+ }
+ return $indexes;
+ }
+
+ function MetaForeignKeys($table, $owner=false, $upper=false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $table = $this->qstr(strtoupper($table));
+
+ $sql =
+ "select object_name(constid) as constraint_name,
+ col_name(fkeyid, fkey) as column_name,
+ object_name(rkeyid) as referenced_table_name,
+ col_name(rkeyid, rkey) as referenced_column_name
+ from sysforeignkeys
+ where upper(object_name(fkeyid)) = $table
+ order by constraint_name, referenced_table_name, keyno";
+
+ $constraints =& $this->GetArray($sql);
+
+ $ADODB_FETCH_MODE = $save;
+
+ $arr = false;
+ foreach($constraints as $constr) {
+ //print_r($constr);
+ $arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3];
+ }
+ if (!$arr) return false;
+
+ $arr2 = false;
+
+ foreach($arr as $k => $v) {
+ foreach($v as $a => $b) {
+ if ($upper) $a = strtoupper($a);
+ $arr2[$a] = $b;
+ }
+ }
+ return $arr2;
+ }
+
+ //From: Fernando Moreira <FMoreira@imediata.pt>
+ function MetaDatabases()
+ {
+ $this->SelectDB("master");
+ $rs =& $this->Execute($this->metaDatabasesSQL);
+ $rows = $rs->GetRows();
+ $ret = array();
+ for($i=0;$i<count($rows);$i++) {
+ $ret[] = $rows[$i][0];
+ }
+ $this->SelectDB($this->database);
+ if($ret)
+ return $ret;
+ else
+ return false;
+ }
+
+ // "Stein-Aksel Basma" <basma@accelero.no>
+ // tested with MSSQL 2000
+ function MetaPrimaryKeys($table, $owner=false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $schema = '';
+ $this->_findschema($table,$schema);
+ if (!$schema) $schema = $this->database;
+ if ($schema) $schema = "and k.table_catalog like '$schema%'";
+
+ $sql = "select distinct k.column_name,ordinal_position from information_schema.key_column_usage k,
+ information_schema.table_constraints tc
+ where tc.constraint_name = k.constraint_name and tc.constraint_type =
+ 'PRIMARY KEY' and k.table_name = '$table' $schema order by ordinal_position ";
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $a = $this->GetCol($sql);
+ $ADODB_FETCH_MODE = $savem;
+
+ if ($a && sizeof($a)>0) return $a;
+ $false = false;
+ return $false;
+ }
+
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ if ($mask) {
+ $save = $this->metaTablesSQL;
+ $mask = $this->qstr(($mask));
+ $this->metaTablesSQL .= " AND name like $mask";
+ }
+ $ret = ADOConnection::MetaTables($ttype,$showSchema);
+
+ if ($mask) {
+ $this->metaTablesSQL = $save;
+ }
+ return $ret;
+ }
+ function MetaColumns($table, $upper=true, $schema=false){
+
+ # start adg
+ static $cached_columns = array();
+ if ($this->cachedSchemaFlush)
+ $cached_columns = array();
+
+ if (array_key_exists($table,$cached_columns)){
+ return $cached_columns[$table];
+ }
+ # end adg
+
+ if (!$this->mssql_version)
+ $this->ServerVersion();
+
+ $this->_findschema($table,$schema);
+ if ($schema) {
+ $dbName = $this->database;
+ $this->SelectDB($schema);
+ }
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
+
+ if ($schema) {
+ $this->SelectDB($dbName);
+ }
+
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ if (!is_object($rs)) {
+ $false = false;
+ return $false;
+ }
+
+ $retarr = array();
+ while (!$rs->EOF){
+
+ $fld = new ADOFieldObject();
+ if (array_key_exists(0,$rs->fields)) {
+ $fld->name = $rs->fields[0];
+ $fld->type = $rs->fields[1];
+ $fld->max_length = $rs->fields[2];
+ $fld->precision = $rs->fields[3];
+ $fld->scale = $rs->fields[4];
+ $fld->not_null =!$rs->fields[5];
+ $fld->has_default = $rs->fields[6];
+ $fld->xtype = $rs->fields[7];
+ $fld->type_length = $rs->fields[8];
+ $fld->auto_increment= $rs->fields[9];
+ } else {
+ $fld->name = $rs->fields['name'];
+ $fld->type = $rs->fields['type'];
+ $fld->max_length = $rs->fields['length'];
+ $fld->precision = $rs->fields['precision'];
+ $fld->scale = $rs->fields['scale'];
+ $fld->not_null =!$rs->fields['nullable'];
+ $fld->has_default = $rs->fields['default_value'];
+ $fld->xtype = $rs->fields['xtype'];
+ $fld->type_length = $rs->fields['type_length'];
+ $fld->auto_increment= $rs->fields['is_identity'];
+ }
+
+ if ($save == ADODB_FETCH_NUM)
+ $retarr[] = $fld;
+ else
+ $retarr[strtoupper($fld->name)] = $fld;
+
+ $rs->MoveNext();
+
+ }
+ $rs->Close();
+ # start adg
+ $cached_columns[$table] = $retarr;
+ # end adg
+ return $retarr;
+ }
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordset_mssqlnative extends ADORecordSet {
+
+ var $databaseType = "mssqlnative";
+ var $canSeek = false;
+ var $fieldOffset = 0;
+ // _mths works only in non-localised system
+
+ function __construct($id,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+
+ }
+ $this->fetchMode = $mode;
+ return parent::__construct($id,$mode);
+ }
+
+
+ function _initrs()
+ {
+ global $ADODB_COUNTRECS;
+ # KMN # if ($this->connection->debug) ADOConnection::outp("(before) ADODB_COUNTRECS: {$ADODB_COUNTRECS} _numOfRows: {$this->_numOfRows} _numOfFields: {$this->_numOfFields}");
+ /*$retRowsAff = sqlsrv_rows_affected($this->_queryID);//"If you need to determine the number of rows a query will return before retrieving the actual results, appending a SELECT COUNT ... query would let you get that information, and then a call to next_result would move you to the "real" results."
+ ADOConnection::outp("rowsaff: ".serialize($retRowsAff));
+ $this->_numOfRows = ($ADODB_COUNTRECS)? $retRowsAff:-1;*/
+ $this->_numOfRows = -1;//not supported
+ $fieldmeta = sqlsrv_field_metadata($this->_queryID);
+ $this->_numOfFields = ($fieldmeta)? count($fieldmeta):-1;
+ # KMN # if ($this->connection->debug) ADOConnection::outp("(after) _numOfRows: {$this->_numOfRows} _numOfFields: {$this->_numOfFields}");
+ /*
+ * Copy the oracle method and cache the metadata at init time
+ */
+ if ($this->_numOfFields>0) {
+ $this->_fieldobjs = array();
+ $max = $this->_numOfFields;
+ for ($i=0;$i<$max; $i++) $this->_fieldobjs[] = $this->_FetchField($i);
+ }
+
+ }
+
+
+ //Contributed by "Sven Axelsson" <sven.axelsson@bokochwebb.se>
+ // get next resultset - requires PHP 4.0.5 or later
+ function NextRecordSet()
+ {
+ if (!sqlsrv_next_result($this->_queryID)) return false;
+ $this->_inited = false;
+ $this->bind = false;
+ $this->_currentRow = -1;
+ $this->Init();
+ return true;
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode != ADODB_FETCH_NUM) return $this->fields[$colname];
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+ /* Returns: an object containing field information.
+ Get column information in the Recordset object. fetchField() can be used in order to obtain information about
+ fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
+ fetchField() is retrieved.
+ Designed By jcortinap#jc.com.mx
+ */
+ function _FetchField($fieldOffset = -1)
+ {
+ $_typeConversion = array(
+ -155 => 'datetimeoffset',
+ -154 => 'char',
+ -152 => 'xml',
+ -151 => 'udt',
+ -11 => 'uniqueidentifier',
+ -10 => 'ntext',
+ -9 => 'nvarchar',
+ -8 => 'nchar',
+ -7 => 'bit',
+ -6 => 'tinyint',
+ -5 => 'bigint',
+ -4 => 'image',
+ -3 => 'varbinary',
+ -2 => 'timestamp',
+ -1 => 'text',
+ 1 => 'char',
+ 2 => 'numeric',
+ 3 => 'decimal',
+ 4 => 'int',
+ 5 => 'smallint',
+ 6 => 'float',
+ 7 => 'real',
+ 12 => 'varchar',
+ 91 => 'date',
+ 93 => 'datetime'
+ );
+
+ $fa = @sqlsrv_field_metadata($this->_queryID);
+ if ($fieldOffset != -1) {
+ $fa = $fa[$fieldOffset];
+ }
+ $false = false;
+ if (empty($fa)) {
+ $f = false;//PHP Notice: Only variable references should be returned by reference
+ }
+ else
+ {
+ // Convert to an object
+ $fa = array_change_key_case($fa, CASE_LOWER);
+ $fb = array();
+ if ($fieldOffset != -1)
+ {
+ $fb = array(
+ 'name' => $fa['name'],
+ 'max_length' => $fa['size'],
+ 'column_source' => $fa['name'],
+ 'type' => $_typeConversion[$fa['type']]
+ );
+ }
+ else
+ {
+ foreach ($fa as $key => $value)
+ {
+ $fb[] = array(
+ 'name' => $value['name'],
+ 'max_length' => $value['size'],
+ 'column_source' => $value['name'],
+ 'type' => $_typeConversion[$value['type']]
+ );
+ }
+ }
+ $f = (object) $fb;
+ }
+ return $f;
+ }
+
+ /*
+ * Fetchfield copies the oracle method, it loads the field information
+ * into the _fieldobjs array once, to save multiple calls to the
+ * sqlsrv_field_metadata function
+ *
+ * @author KM Newnham
+ * @date 02/20/2013
+ */
+ function FetchField($fieldOffset = -1)
+ {
+ return $this->_fieldobjs[$fieldOffset];
+ }
+
+ function _seek($row)
+ {
+ return false;//There is no support for cursors in the driver at this time. All data is returned via forward-only streams.
+ }
+
+ // speedup
+ function MoveNext()
+ {
+ //# KMN # if ($this->connection->debug) ADOConnection::outp("movenext()");
+ //# KMN # if ($this->connection->debug) ADOConnection::outp("eof (beginning): ".$this->EOF);
+ if ($this->EOF) return false;
+
+ $this->_currentRow++;
+ // # KMN # if ($this->connection->debug) ADOConnection::outp("_currentRow: ".$this->_currentRow);
+
+ if ($this->_fetch()) return true;
+ $this->EOF = true;
+ //# KMN # if ($this->connection->debug) ADOConnection::outp("eof (end): ".$this->EOF);
+
+ return false;
+ }
+
+
+ // INSERT UPDATE DELETE returns false even if no error occurs in 4.0.4
+ // also the date format has been changed from YYYY-mm-dd to dd MMM YYYY in 4.0.4. Idiot!
+ function _fetch($ignore_fields=false)
+ {
+ # KMN # if ($this->connection->debug) ADOConnection::outp("_fetch()");
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ if ($this->fetchMode & ADODB_FETCH_NUM) {
+ //# KMN # if ($this->connection->debug) ADOConnection::outp("fetch mode: both");
+ $this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_BOTH);
+ } else {
+ //# KMN # if ($this->connection->debug) ADOConnection::outp("fetch mode: assoc");
+ $this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_ASSOC);
+ }
+
+ if (is_array($this->fields)) {
+ if (ADODB_ASSOC_CASE == 0) {
+ foreach($this->fields as $k=>$v) {
+ $this->fields[strtolower($k)] = $v;
+ }
+ } else if (ADODB_ASSOC_CASE == 1) {
+ foreach($this->fields as $k=>$v) {
+ $this->fields[strtoupper($k)] = $v;
+ }
+ }
+ }
+ } else {
+ //# KMN # if ($this->connection->debug) ADOConnection::outp("fetch mode: num");
+ $this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_NUMERIC);
+ }
+ if(is_array($this->fields) && array_key_exists(1,$this->fields) && !array_key_exists(0,$this->fields)) {//fix fetch numeric keys since they're not 0 based
+ $arrFixed = array();
+ foreach($this->fields as $key=>$value) {
+ if(is_numeric($key)) {
+ $arrFixed[$key-1] = $value;
+ } else {
+ $arrFixed[$key] = $value;
+ }
+ }
+ //if($this->connection->debug) ADOConnection::outp("<hr>fixing non 0 based return array, old: ".print_r($this->fields,true)." new: ".print_r($arrFixed,true));
+ $this->fields = $arrFixed;
+ }
+ if(is_array($this->fields)) {
+ foreach($this->fields as $key=>$value) {
+ if (is_object($value) && method_exists($value, 'format')) {//is DateTime object
+ $this->fields[$key] = $value->format("Y-m-d\TH:i:s\Z");
+ }
+ }
+ }
+ if($this->fields === null) $this->fields = false;
+ # KMN # if ($this->connection->debug) ADOConnection::outp("<hr>after _fetch, fields: <pre>".print_r($this->fields,true)." backtrace: ".adodb_backtrace(false));
+ return $this->fields;
+ }
+
+ /* close() only needs to be called if you are worried about using too much memory while your script
+ is running. All associated result memory for the specified result identifier will automatically be freed. */
+ function _close()
+ {
+ if(is_object($this->_queryID)) {
+ $rez = sqlsrv_free_stmt($this->_queryID);
+ $this->_queryID = false;
+ return $rez;
+ }
+ return true;
+ }
+
+ // mssql uses a default date like Dec 30 2000 12:00AM
+ static function UnixDate($v)
+ {
+ return ADORecordSet_array_mssqlnative::UnixDate($v);
+ }
+
+ static function UnixTimeStamp($v)
+ {
+ return ADORecordSet_array_mssqlnative::UnixTimeStamp($v);
+ }
+}
+
+
+class ADORecordSet_array_mssqlnative extends ADORecordSet_array {
+ function __construct($id=-1,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+
+ // mssql uses a default date like Dec 30 2000 12:00AM
+ static function UnixDate($v)
+ {
+
+ if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixDate($v);
+
+ global $ADODB_mssql_mths,$ADODB_mssql_date_order;
+
+ //Dec 30 2000 12:00AM
+ if ($ADODB_mssql_date_order == 'dmy') {
+ if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
+ return parent::UnixDate($v);
+ }
+ if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
+
+ $theday = $rr[1];
+ $themth = substr(strtoupper($rr[2]),0,3);
+ } else {
+ if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
+ return parent::UnixDate($v);
+ }
+ if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
+
+ $theday = $rr[2];
+ $themth = substr(strtoupper($rr[1]),0,3);
+ }
+ $themth = $ADODB_mssql_mths[$themth];
+ if ($themth <= 0) return false;
+ // h-m-s-MM-DD-YY
+ return adodb_mktime(0,0,0,$themth,$theday,$rr[3]);
+ }
+
+ static function UnixTimeStamp($v)
+ {
+
+ if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixTimeStamp($v);
+
+ global $ADODB_mssql_mths,$ADODB_mssql_date_order;
+
+ //Dec 30 2000 12:00AM
+ if ($ADODB_mssql_date_order == 'dmy') {
+ if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|"
+ ,$v, $rr)) return parent::UnixTimeStamp($v);
+ if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
+
+ $theday = $rr[1];
+ $themth = substr(strtoupper($rr[2]),0,3);
+ } else {
+ if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|"
+ ,$v, $rr)) return parent::UnixTimeStamp($v);
+ if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
+
+ $theday = $rr[2];
+ $themth = substr(strtoupper($rr[1]),0,3);
+ }
+
+ $themth = $ADODB_mssql_mths[$themth];
+ if ($themth <= 0) return false;
+
+ switch (strtoupper($rr[6])) {
+ case 'P':
+ if ($rr[4]<12) $rr[4] += 12;
+ break;
+ case 'A':
+ if ($rr[4]==12) $rr[4] = 0;
+ break;
+ default:
+ break;
+ }
+ // h-m-s-MM-DD-YY
+ return adodb_mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]);
+ }
+}
+
+/*
+Code Example 1:
+
+select object_name(constid) as constraint_name,
+ object_name(fkeyid) as table_name,
+ col_name(fkeyid, fkey) as column_name,
+ object_name(rkeyid) as referenced_table_name,
+ col_name(rkeyid, rkey) as referenced_column_name
+from sysforeignkeys
+where object_name(fkeyid) = x
+order by constraint_name, table_name, referenced_table_name, keyno
+
+Code Example 2:
+select constraint_name,
+ column_name,
+ ordinal_position
+from information_schema.key_column_usage
+where constraint_catalog = db_name()
+and table_name = x
+order by constraint_name, ordinal_position
+
+http://www.databasejournal.com/scripts/article.php/1440551
+*/
diff --git a/vendor/adodb/adodb-php/drivers/adodb-mssqlpo.inc.php b/vendor/adodb/adodb-php/drivers/adodb-mssqlpo.inc.php
new file mode 100644
index 0000000..6168849
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-mssqlpo.inc.php
@@ -0,0 +1,58 @@
+<?php
+/**
+* @version v5.20.14 06-Jan-2019
+* @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+* @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+* Released under both BSD license and Lesser GPL library license.
+* Whenever there is any discrepancy between the two licenses,
+* the BSD license will take precedence.
+*
+* Set tabs to 4 for best viewing.
+*
+* Latest version is available at http://adodb.org/
+*
+* Portable MSSQL Driver that supports || instead of +
+*
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+
+/*
+ The big difference between mssqlpo and it's parent mssql is that mssqlpo supports
+ the more standard || string concatenation operator.
+*/
+
+include_once(ADODB_DIR.'/drivers/adodb-mssql.inc.php');
+
+class ADODB_mssqlpo extends ADODB_mssql {
+ var $databaseType = "mssqlpo";
+ var $concat_operator = '||';
+
+ function PrepareSP($sql, $param = true)
+ {
+ if (!$this->_has_mssql_init) {
+ ADOConnection::outp( "PrepareSP: mssql_init only available since PHP 4.1.0");
+ return $sql;
+ }
+ if (is_string($sql)) $sql = str_replace('||','+',$sql);
+ $stmt = mssql_init($sql,$this->_connectionID);
+ if (!$stmt) return $sql;
+ return array($sql,$stmt);
+ }
+
+ function _query($sql,$inputarr=false)
+ {
+ if (is_string($sql)) $sql = str_replace('||','+',$sql);
+ return ADODB_mssql::_query($sql,$inputarr);
+ }
+}
+
+class ADORecordset_mssqlpo extends ADORecordset_mssql {
+ var $databaseType = "mssqlpo";
+ function __construct($id,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-mysql.inc.php b/vendor/adodb/adodb-php/drivers/adodb-mysql.inc.php
new file mode 100644
index 0000000..f839d85
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-mysql.inc.php
@@ -0,0 +1,893 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 8.
+
+ This driver only supports the original non-transactional MySQL driver. It
+ is deprected in PHP version 5.5 and removed in PHP version 7. It is deprecated
+ as of ADOdb version 5.20.0. Use the mysqli driver instead, which supports both
+ transactional and non-transactional updates
+
+ Requires mysql client. Works on Windows and Unix.
+
+ 28 Feb 2001: MetaColumns bug fix - suggested by Freek Dijkstra (phpeverywhere@macfreek.com)
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (! defined("_ADODB_MYSQL_LAYER")) {
+ define("_ADODB_MYSQL_LAYER", 1 );
+
+class ADODB_mysql extends ADOConnection {
+ var $databaseType = 'mysql';
+ var $dataProvider = 'mysql';
+ var $hasInsertID = true;
+ var $hasAffectedRows = true;
+ var $metaTablesSQL = "SELECT
+ TABLE_NAME,
+ CASE WHEN TABLE_TYPE = 'VIEW' THEN 'V' ELSE 'T' END
+ FROM INFORMATION_SCHEMA.TABLES
+ WHERE TABLE_SCHEMA=";
+ var $metaColumnsSQL = "SHOW COLUMNS FROM `%s`";
+ var $fmtTimeStamp = "'Y-m-d H:i:s'";
+ var $hasLimit = true;
+ var $hasMoveFirst = true;
+ var $hasGenID = true;
+ var $isoDates = true; // accepts dates in ISO format
+ var $sysDate = 'CURDATE()';
+ var $sysTimeStamp = 'NOW()';
+ var $hasTransactions = false;
+ var $forceNewConnect = false;
+ var $poorAffectedRows = true;
+ var $clientFlags = 0;
+ var $charSet = '';
+ var $substr = "substring";
+ var $nameQuote = '`'; /// string to use to quote identifiers and names
+ var $compat323 = false; // true if compat with mysql 3.23
+
+ function __construct()
+ {
+ if (defined('ADODB_EXTENSION')) $this->rsPrefix .= 'ext_';
+ }
+
+
+ // SetCharSet - switch the client encoding
+ function SetCharSet($charset_name)
+ {
+ if (!function_exists('mysql_set_charset')) {
+ return false;
+ }
+
+ if ($this->charSet !== $charset_name) {
+ $ok = @mysql_set_charset($charset_name,$this->_connectionID);
+ if ($ok) {
+ $this->charSet = $charset_name;
+ return true;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ function ServerInfo()
+ {
+ $arr['description'] = ADOConnection::GetOne("select version()");
+ $arr['version'] = ADOConnection::_findvers($arr['description']);
+ return $arr;
+ }
+
+ function IfNull( $field, $ifNull )
+ {
+ return " IFNULL($field, $ifNull) "; // if MySQL
+ }
+
+ function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null)
+ {
+ // save old fetch mode
+ global $ADODB_FETCH_MODE;
+
+ $false = false;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+
+ $procedures = array ();
+
+ // get index details
+
+ $likepattern = '';
+ if ($NamePattern) {
+ $likepattern = " LIKE '".$NamePattern."'";
+ }
+ $rs = $this->Execute('SHOW PROCEDURE STATUS'.$likepattern);
+ if (is_object($rs)) {
+
+ // parse index data into array
+ while ($row = $rs->FetchRow()) {
+ $procedures[$row[1]] = array(
+ 'type' => 'PROCEDURE',
+ 'catalog' => '',
+ 'schema' => '',
+ 'remarks' => $row[7],
+ );
+ }
+ }
+
+ $rs = $this->Execute('SHOW FUNCTION STATUS'.$likepattern);
+ if (is_object($rs)) {
+ // parse index data into array
+ while ($row = $rs->FetchRow()) {
+ $procedures[$row[1]] = array(
+ 'type' => 'FUNCTION',
+ 'catalog' => '',
+ 'schema' => '',
+ 'remarks' => $row[7]
+ );
+ }
+ }
+
+ // restore fetchmode
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ return $procedures;
+ }
+
+ /**
+ * Retrieves a list of tables based on given criteria
+ *
+ * @param string $ttype Table type = 'TABLE', 'VIEW' or false=both (default)
+ * @param string $showSchema schema name, false = current schema (default)
+ * @param string $mask filters the table by name
+ *
+ * @return array list of tables
+ */
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ $save = $this->metaTablesSQL;
+ if ($showSchema && is_string($showSchema)) {
+ $this->metaTablesSQL .= $this->qstr($showSchema);
+ } else {
+ $this->metaTablesSQL .= "schema()";
+ }
+
+ if ($mask) {
+ $mask = $this->qstr($mask);
+ $this->metaTablesSQL .= " AND table_name LIKE $mask";
+ }
+ $ret = ADOConnection::MetaTables($ttype,$showSchema);
+
+ $this->metaTablesSQL = $save;
+ return $ret;
+ }
+
+
+ function MetaIndexes ($table, $primary = FALSE, $owner=false)
+ {
+ // save old fetch mode
+ global $ADODB_FETCH_MODE;
+
+ $false = false;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+
+ // get index details
+ $rs = $this->Execute(sprintf('SHOW INDEX FROM %s',$table));
+
+ // restore fetchmode
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ if (!is_object($rs)) {
+ return $false;
+ }
+
+ $indexes = array ();
+
+ // parse index data into array
+ while ($row = $rs->FetchRow()) {
+ if ($primary == FALSE AND $row[2] == 'PRIMARY') {
+ continue;
+ }
+
+ if (!isset($indexes[$row[2]])) {
+ $indexes[$row[2]] = array(
+ 'unique' => ($row[1] == 0),
+ 'columns' => array()
+ );
+ }
+
+ $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
+ }
+
+ // sort columns by order in the index
+ foreach ( array_keys ($indexes) as $index )
+ {
+ ksort ($indexes[$index]['columns']);
+ }
+
+ return $indexes;
+ }
+
+
+ // if magic quotes disabled, use mysql_real_escape_string()
+ function qstr($s,$magic_quotes=false)
+ {
+ if (is_null($s)) return 'NULL';
+ if (!$magic_quotes) {
+
+ if (ADODB_PHPVER >= 0x4300) {
+ if (is_resource($this->_connectionID))
+ return "'".mysql_real_escape_string($s,$this->_connectionID)."'";
+ }
+ if ($this->replaceQuote[0] == '\\'){
+ $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
+ }
+ return "'".str_replace("'",$this->replaceQuote,$s)."'";
+ }
+
+ // undo magic quotes for "
+ $s = str_replace('\\"','"',$s);
+ return "'$s'";
+ }
+
+ function _insertid()
+ {
+ return ADOConnection::GetOne('SELECT LAST_INSERT_ID()');
+ //return mysql_insert_id($this->_connectionID);
+ }
+
+ function GetOne($sql,$inputarr=false)
+ {
+ global $ADODB_GETONE_EOF;
+ if ($this->compat323 == false && strncasecmp($sql,'sele',4) == 0) {
+ $rs = $this->SelectLimit($sql,1,-1,$inputarr);
+ if ($rs) {
+ $rs->Close();
+ if ($rs->EOF) return $ADODB_GETONE_EOF;
+ return reset($rs->fields);
+ }
+ } else {
+ return ADOConnection::GetOne($sql,$inputarr);
+ }
+ return false;
+ }
+
+ function BeginTrans()
+ {
+ if ($this->debug) ADOConnection::outp("Transactions not supported in 'mysql' driver. Use 'mysqlt' or 'mysqli' driver");
+ }
+
+ function _affectedrows()
+ {
+ return mysql_affected_rows($this->_connectionID);
+ }
+
+ // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
+ // Reference on Last_Insert_ID on the recommended way to simulate sequences
+ var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
+ var $_genSeqSQL = "create table if not exists %s (id int not null)";
+ var $_genSeqCountSQL = "select count(*) from %s";
+ var $_genSeq2SQL = "insert into %s values (%s)";
+ var $_dropSeqSQL = "drop table if exists %s";
+
+ function CreateSequence($seqname='adodbseq',$startID=1)
+ {
+ if (empty($this->_genSeqSQL)) return false;
+ $u = strtoupper($seqname);
+
+ $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
+ if (!$ok) return false;
+ return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
+ }
+
+
+ function GenID($seqname='adodbseq',$startID=1)
+ {
+ // post-nuke sets hasGenID to false
+ if (!$this->hasGenID) return false;
+
+ $savelog = $this->_logsql;
+ $this->_logsql = false;
+ $getnext = sprintf($this->_genIDSQL,$seqname);
+ $holdtransOK = $this->_transOK; // save the current status
+ $rs = @$this->Execute($getnext);
+ if (!$rs) {
+ if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
+ $u = strtoupper($seqname);
+ $this->Execute(sprintf($this->_genSeqSQL,$seqname));
+ $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname));
+ if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
+ $rs = $this->Execute($getnext);
+ }
+
+ if ($rs) {
+ $this->genID = mysql_insert_id($this->_connectionID);
+ $rs->Close();
+ } else
+ $this->genID = 0;
+
+ $this->_logsql = $savelog;
+ return $this->genID;
+ }
+
+ function MetaDatabases()
+ {
+ $qid = mysql_list_dbs($this->_connectionID);
+ $arr = array();
+ $i = 0;
+ $max = mysql_num_rows($qid);
+ while ($i < $max) {
+ $db = mysql_tablename($qid,$i);
+ if ($db != 'mysql') $arr[] = $db;
+ $i += 1;
+ }
+ return $arr;
+ }
+
+
+ // Format date column in sql string given an input format that understands Y M D
+ function SQLDate($fmt, $col=false)
+ {
+ if (!$col) $col = $this->sysTimeStamp;
+ $s = 'DATE_FORMAT('.$col.",'";
+ $concat = false;
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ $ch = $fmt[$i];
+ switch($ch) {
+
+ default:
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ /** FALL THROUGH */
+ case '-':
+ case '/':
+ $s .= $ch;
+ break;
+
+ case 'Y':
+ case 'y':
+ $s .= '%Y';
+ break;
+ case 'M':
+ $s .= '%b';
+ break;
+
+ case 'm':
+ $s .= '%m';
+ break;
+ case 'D':
+ case 'd':
+ $s .= '%d';
+ break;
+
+ case 'Q':
+ case 'q':
+ $s .= "'),Quarter($col)";
+
+ if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
+ else $s .= ",('";
+ $concat = true;
+ break;
+
+ case 'H':
+ $s .= '%H';
+ break;
+
+ case 'h':
+ $s .= '%I';
+ break;
+
+ case 'i':
+ $s .= '%i';
+ break;
+
+ case 's':
+ $s .= '%s';
+ break;
+
+ case 'a':
+ case 'A':
+ $s .= '%p';
+ break;
+
+ case 'w':
+ $s .= '%w';
+ break;
+
+ case 'W':
+ $s .= '%U';
+ break;
+
+ case 'l':
+ $s .= '%W';
+ break;
+ }
+ }
+ $s.="')";
+ if ($concat) $s = "CONCAT($s)";
+ return $s;
+ }
+
+
+ // returns concatenated string
+ // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
+ function Concat()
+ {
+ $s = "";
+ $arr = func_get_args();
+
+ // suggestion by andrew005@mnogo.ru
+ $s = implode(',',$arr);
+ if (strlen($s) > 0) return "CONCAT($s)";
+ else return '';
+ }
+
+ function OffsetDate($dayFraction,$date=false)
+ {
+ if (!$date) $date = $this->sysDate;
+
+ $fraction = $dayFraction * 24 * 3600;
+ return '('. $date . ' + INTERVAL ' . $fraction.' SECOND)';
+
+// return "from_unixtime(unix_timestamp($date)+$fraction)";
+ }
+
+ // returns true or false
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!empty($this->port)) $argHostname .= ":".$this->port;
+
+ if (ADODB_PHPVER >= 0x4300)
+ $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword,
+ $this->forceNewConnect,$this->clientFlags);
+ else if (ADODB_PHPVER >= 0x4200)
+ $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword,
+ $this->forceNewConnect);
+ else
+ $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword);
+
+ if ($this->_connectionID === false) return false;
+ if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ return true;
+ }
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!empty($this->port)) $argHostname .= ":".$this->port;
+
+ if (ADODB_PHPVER >= 0x4300)
+ $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword,$this->clientFlags);
+ else
+ $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword);
+ if ($this->_connectionID === false) return false;
+ if ($this->autoRollback) $this->RollbackTrans();
+ if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ return true;
+ }
+
+ function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ $this->forceNewConnect = true;
+ return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ $this->_findschema($table,$schema);
+ if ($schema) {
+ $dbName = $this->database;
+ $this->SelectDB($schema);
+ }
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
+
+ if ($schema) {
+ $this->SelectDB($dbName);
+ }
+
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ if (!is_object($rs)) {
+ $false = false;
+ return $false;
+ }
+
+ $retarr = array();
+ while (!$rs->EOF){
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $type = $rs->fields[1];
+
+ // split type into type(length):
+ $fld->scale = null;
+ if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
+ $fld->type = $query_array[1];
+ $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
+ $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
+ } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
+ $fld->type = $query_array[1];
+ $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
+ } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
+ $fld->type = $query_array[1];
+ $arr = explode(",",$query_array[2]);
+ $fld->enums = $arr;
+ $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
+ $fld->max_length = ($zlen > 0) ? $zlen : 1;
+ } else {
+ $fld->type = $type;
+ $fld->max_length = -1;
+ }
+ $fld->not_null = ($rs->fields[2] != 'YES');
+ $fld->primary_key = ($rs->fields[3] == 'PRI');
+ $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
+ $fld->binary = (strpos($type,'blob') !== false || strpos($type,'binary') !== false);
+ $fld->unsigned = (strpos($type,'unsigned') !== false);
+ $fld->zerofill = (strpos($type,'zerofill') !== false);
+
+ if (!$fld->binary) {
+ $d = $rs->fields[4];
+ if ($d != '' && $d != 'NULL') {
+ $fld->has_default = true;
+ $fld->default_value = $d;
+ } else {
+ $fld->has_default = false;
+ }
+ }
+
+ if ($save == ADODB_FETCH_NUM) {
+ $retarr[] = $fld;
+ } else {
+ $retarr[strtoupper($fld->name)] = $fld;
+ }
+ $rs->MoveNext();
+ }
+
+ $rs->Close();
+ return $retarr;
+ }
+
+ // returns true or false
+ function SelectDB($dbName)
+ {
+ $this->database = $dbName;
+ $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
+ if ($this->_connectionID) {
+ return @mysql_select_db($dbName,$this->_connectionID);
+ }
+ else return false;
+ }
+
+ // parameters use PostgreSQL convention, not MySQL
+ function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs=0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ $offsetStr =($offset>=0) ? ((integer)$offset)."," : '';
+ // jason judge, see http://phplens.com/lens/lensforum/msgs.php?id=9220
+ if ($nrows < 0) $nrows = '18446744073709551615';
+
+ if ($secs)
+ $rs = $this->CacheExecute($secs,$sql." LIMIT $offsetStr".((integer)$nrows),$inputarr);
+ else
+ $rs = $this->Execute($sql." LIMIT $offsetStr".((integer)$nrows),$inputarr);
+ return $rs;
+ }
+
+ // returns queryID or false
+ function _query($sql,$inputarr=false)
+ {
+
+ return mysql_query($sql,$this->_connectionID);
+ /*
+ global $ADODB_COUNTRECS;
+ if($ADODB_COUNTRECS)
+ return mysql_query($sql,$this->_connectionID);
+ else
+ return @mysql_unbuffered_query($sql,$this->_connectionID); // requires PHP >= 4.0.6
+ */
+ }
+
+ /* Returns: the last error message from previous database operation */
+ function ErrorMsg()
+ {
+
+ if ($this->_logsql) return $this->_errorMsg;
+ if (empty($this->_connectionID)) $this->_errorMsg = @mysql_error();
+ else $this->_errorMsg = @mysql_error($this->_connectionID);
+ return $this->_errorMsg;
+ }
+
+ /* Returns: the last error number from previous database operation */
+ function ErrorNo()
+ {
+ if ($this->_logsql) return $this->_errorCode;
+ if (empty($this->_connectionID)) return @mysql_errno();
+ else return @mysql_errno($this->_connectionID);
+ }
+
+ // returns true or false
+ function _close()
+ {
+ @mysql_close($this->_connectionID);
+
+ $this->charSet = '';
+ $this->_connectionID = false;
+ }
+
+
+ /*
+ * Maximum size of C field
+ */
+ function CharMax()
+ {
+ return 255;
+ }
+
+ /*
+ * Maximum size of X field
+ */
+ function TextMax()
+ {
+ return 4294967295;
+ }
+
+ // "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx>
+ function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
+ {
+ global $ADODB_FETCH_MODE;
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true;
+
+ if ( !empty($owner) ) {
+ $table = "$owner.$table";
+ }
+ $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
+ if ($associative) {
+ $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"];
+ } else {
+ $create_sql = $a_create_table[1];
+ }
+
+ $matches = array();
+
+ if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
+ $foreign_keys = array();
+ $num_keys = count($matches[0]);
+ for ( $i = 0; $i < $num_keys; $i ++ ) {
+ $my_field = explode('`, `', $matches[1][$i]);
+ $ref_table = $matches[2][$i];
+ $ref_field = explode('`, `', $matches[3][$i]);
+
+ if ( $upper ) {
+ $ref_table = strtoupper($ref_table);
+ }
+
+ // see https://sourceforge.net/p/adodb/bugs/100/
+ if (!isset($foreign_keys[$ref_table])) {
+ $foreign_keys[$ref_table] = array();
+ }
+ $num_fields = count($my_field);
+ for ( $j = 0; $j < $num_fields; $j ++ ) {
+ if ( $associative ) {
+ $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
+ } else {
+ $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
+ }
+ }
+ }
+
+ return $foreign_keys;
+ }
+
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+
+class ADORecordSet_mysql extends ADORecordSet{
+
+ var $databaseType = "mysql";
+ var $canSeek = true;
+
+ function __construct($queryID,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ switch ($mode)
+ {
+ case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
+ case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
+ case ADODB_FETCH_DEFAULT:
+ case ADODB_FETCH_BOTH:
+ default:
+ $this->fetchMode = MYSQL_BOTH; break;
+ }
+ $this->adodbFetchMode = $mode;
+ parent::__construct($queryID);
+ }
+
+ function _initrs()
+ {
+ //GLOBAL $ADODB_COUNTRECS;
+ // $this->_numOfRows = ($ADODB_COUNTRECS) ? @mysql_num_rows($this->_queryID):-1;
+ $this->_numOfRows = @mysql_num_rows($this->_queryID);
+ $this->_numOfFields = @mysql_num_fields($this->_queryID);
+ }
+
+ function FetchField($fieldOffset = -1)
+ {
+ if ($fieldOffset != -1) {
+ $o = @mysql_fetch_field($this->_queryID, $fieldOffset);
+ $f = @mysql_field_flags($this->_queryID,$fieldOffset);
+ if ($o) $o->max_length = @mysql_field_len($this->_queryID,$fieldOffset); // suggested by: Jim Nicholson (jnich#att.com)
+ //$o->max_length = -1; // mysql returns the max length less spaces -- so it is unrealiable
+ if ($o) $o->binary = (strpos($f,'binary')!== false);
+ }
+ else { /* The $fieldOffset argument is not provided thus its -1 */
+ $o = @mysql_fetch_field($this->_queryID);
+ //if ($o) $o->max_length = @mysql_field_len($this->_queryID); // suggested by: Jim Nicholson (jnich#att.com)
+ $o->max_length = -1; // mysql returns the max length less spaces -- so it is unrealiable
+ }
+
+ return $o;
+ }
+
+ function GetRowAssoc($upper = ADODB_ASSOC_CASE)
+ {
+ if ($this->fetchMode == MYSQL_ASSOC && $upper == ADODB_ASSOC_CASE_LOWER) {
+ $row = $this->fields;
+ }
+ else {
+ $row = ADORecordSet::GetRowAssoc($upper);
+ }
+ return $row;
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ // added @ by "Michael William Miller" <mille562@pilot.msu.edu>
+ if ($this->fetchMode != MYSQL_NUM) return @$this->fields[$colname];
+
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+ function _seek($row)
+ {
+ if ($this->_numOfRows == 0) return false;
+ return @mysql_data_seek($this->_queryID,$row);
+ }
+
+ function MoveNext()
+ {
+ //return adodb_movenext($this);
+ //if (defined('ADODB_EXTENSION')) return adodb_movenext($this);
+ if (@$this->fields = mysql_fetch_array($this->_queryID,$this->fetchMode)) {
+ $this->_updatefields();
+ $this->_currentRow += 1;
+ return true;
+ }
+ if (!$this->EOF) {
+ $this->_currentRow += 1;
+ $this->EOF = true;
+ }
+ return false;
+ }
+
+ function _fetch()
+ {
+ $this->fields = @mysql_fetch_array($this->_queryID,$this->fetchMode);
+ $this->_updatefields();
+ return is_array($this->fields);
+ }
+
+ function _close() {
+ @mysql_free_result($this->_queryID);
+ $this->_queryID = false;
+ }
+
+ function MetaType($t,$len=-1,$fieldobj=false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+
+ $len = -1; // mysql max_length is not accurate
+ switch (strtoupper($t)) {
+ case 'STRING':
+ case 'CHAR':
+ case 'VARCHAR':
+ case 'TINYBLOB':
+ case 'TINYTEXT':
+ case 'ENUM':
+ case 'SET':
+ if ($len <= $this->blobSize) return 'C';
+
+ case 'TEXT':
+ case 'LONGTEXT':
+ case 'MEDIUMTEXT':
+ return 'X';
+
+ // php_mysql extension always returns 'blob' even if 'text'
+ // so we have to check whether binary...
+ case 'IMAGE':
+ case 'LONGBLOB':
+ case 'BLOB':
+ case 'MEDIUMBLOB':
+ case 'BINARY':
+ return !empty($fieldobj->binary) ? 'B' : 'X';
+
+ case 'YEAR':
+ case 'DATE': return 'D';
+
+ case 'TIME':
+ case 'DATETIME':
+ case 'TIMESTAMP': return 'T';
+
+ case 'INT':
+ case 'INTEGER':
+ case 'BIGINT':
+ case 'TINYINT':
+ case 'MEDIUMINT':
+ case 'SMALLINT':
+
+ if (!empty($fieldobj->primary_key)) return 'R';
+ else return 'I';
+
+ default: return 'N';
+ }
+ }
+
+}
+
+class ADORecordSet_ext_mysql extends ADORecordSet_mysql {
+ function __construct($queryID,$mode=false)
+ {
+ parent::__construct($queryID,$mode);
+ }
+
+ function MoveNext()
+ {
+ return @adodb_movenext($this);
+ }
+}
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-mysqli.inc.php b/vendor/adodb/adodb-php/drivers/adodb-mysqli.inc.php
new file mode 100644
index 0000000..37b8448
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-mysqli.inc.php
@@ -0,0 +1,1295 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 8.
+
+ This is the preferred driver for MySQL connections, and supports both transactional
+ and non-transactional table types. You can use this as a drop-in replacement for both
+ the mysql and mysqlt drivers. As of ADOdb Version 5.20.0, all other native MySQL drivers
+ are deprecated
+
+ Requires mysql client. Works on Windows and Unix.
+
+21 October 2003: MySQLi extension implementation by Arjen de Rijke (a.de.rijke@xs4all.nl)
+Based on adodb 3.40
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (! defined("_ADODB_MYSQLI_LAYER")) {
+ define("_ADODB_MYSQLI_LAYER", 1 );
+
+ // PHP5 compat...
+ if (! defined("MYSQLI_BINARY_FLAG")) define("MYSQLI_BINARY_FLAG", 128);
+ if (!defined('MYSQLI_READ_DEFAULT_GROUP')) define('MYSQLI_READ_DEFAULT_GROUP',1);
+
+ // disable adodb extension - currently incompatible.
+ global $ADODB_EXTENSION; $ADODB_EXTENSION = false;
+
+class ADODB_mysqli extends ADOConnection {
+ var $databaseType = 'mysqli';
+ var $dataProvider = 'mysql';
+ var $hasInsertID = true;
+ var $hasAffectedRows = true;
+ var $metaTablesSQL = "SELECT
+ TABLE_NAME,
+ CASE WHEN TABLE_TYPE = 'VIEW' THEN 'V' ELSE 'T' END
+ FROM INFORMATION_SCHEMA.TABLES
+ WHERE TABLE_SCHEMA=";
+ var $metaColumnsSQL = "SHOW COLUMNS FROM `%s`";
+ var $fmtTimeStamp = "'Y-m-d H:i:s'";
+ var $hasLimit = true;
+ var $hasMoveFirst = true;
+ var $hasGenID = true;
+ var $isoDates = true; // accepts dates in ISO format
+ var $sysDate = 'CURDATE()';
+ var $sysTimeStamp = 'NOW()';
+ var $hasTransactions = true;
+ var $forceNewConnect = false;
+ var $poorAffectedRows = true;
+ var $clientFlags = 0;
+ var $substr = "substring";
+ var $port = 3306; //Default to 3306 to fix HHVM bug
+ var $socket = ''; //Default to empty string to fix HHVM bug
+ var $_bindInputArray = false;
+ var $nameQuote = '`'; /// string to use to quote identifiers and names
+ var $optionFlags = array(array(MYSQLI_READ_DEFAULT_GROUP,0));
+ var $arrayClass = 'ADORecordSet_array_mysqli';
+ var $multiQuery = false;
+
+ function __construct()
+ {
+ // if(!extension_loaded("mysqli"))
+ //trigger_error("You must have the mysqli extension installed.", E_USER_ERROR);
+ }
+
+ function SetTransactionMode( $transaction_mode )
+ {
+ $this->_transmode = $transaction_mode;
+ if (empty($transaction_mode)) {
+ $this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ');
+ return;
+ }
+ if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
+ $this->Execute("SET SESSION TRANSACTION ".$transaction_mode);
+ }
+
+ // returns true or false
+ // To add: parameter int $port,
+ // parameter string $socket
+ function _connect($argHostname = NULL,
+ $argUsername = NULL,
+ $argPassword = NULL,
+ $argDatabasename = NULL, $persist=false)
+ {
+ if(!extension_loaded("mysqli")) {
+ return null;
+ }
+ $this->_connectionID = @mysqli_init();
+
+ if (is_null($this->_connectionID)) {
+ // mysqli_init only fails if insufficient memory
+ if ($this->debug) {
+ ADOConnection::outp("mysqli_init() failed : " . $this->ErrorMsg());
+ }
+ return false;
+ }
+ /*
+ I suggest a simple fix which would enable adodb and mysqli driver to
+ read connection options from the standard mysql configuration file
+ /etc/my.cnf - "Bastien Duclaux" <bduclaux#yahoo.com>
+ */
+ foreach($this->optionFlags as $arr) {
+ mysqli_options($this->_connectionID,$arr[0],$arr[1]);
+ }
+
+ //http ://php.net/manual/en/mysqli.persistconns.php
+ if ($persist && PHP_VERSION > 5.2 && strncmp($argHostname,'p:',2) != 0) $argHostname = 'p:'.$argHostname;
+
+ #if (!empty($this->port)) $argHostname .= ":".$this->port;
+ $ok = @mysqli_real_connect($this->_connectionID,
+ $argHostname,
+ $argUsername,
+ $argPassword,
+ $argDatabasename,
+ # PHP7 compat: port must be int. Use default port if cast yields zero
+ (int)$this->port != 0 ? (int)$this->port : 3306,
+ $this->socket,
+ $this->clientFlags);
+
+ if ($ok) {
+ if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ return true;
+ } else {
+ if ($this->debug) {
+ ADOConnection::outp("Could not connect : " . $this->ErrorMsg());
+ }
+ $this->_connectionID = null;
+ return false;
+ }
+ }
+
+ // returns true or false
+ // How to force a persistent connection
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true);
+ }
+
+ // When is this used? Close old connection first?
+ // In _connect(), check $this->forceNewConnect?
+ function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ $this->forceNewConnect = true;
+ return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
+ }
+
+ function IfNull( $field, $ifNull )
+ {
+ return " IFNULL($field, $ifNull) "; // if MySQL
+ }
+
+ // do not use $ADODB_COUNTRECS
+ function GetOne($sql,$inputarr=false)
+ {
+ global $ADODB_GETONE_EOF;
+
+ $ret = false;
+ $rs = $this->Execute($sql,$inputarr);
+ if ($rs) {
+ if ($rs->EOF) $ret = $ADODB_GETONE_EOF;
+ else $ret = reset($rs->fields);
+ $rs->Close();
+ }
+ return $ret;
+ }
+
+ function ServerInfo()
+ {
+ $arr['description'] = $this->GetOne("select version()");
+ $arr['version'] = ADOConnection::_findvers($arr['description']);
+ return $arr;
+ }
+
+
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+
+ //$this->Execute('SET AUTOCOMMIT=0');
+ mysqli_autocommit($this->_connectionID, false);
+ $this->Execute('BEGIN');
+ return true;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) return true;
+ if (!$ok) return $this->RollbackTrans();
+
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->Execute('COMMIT');
+
+ //$this->Execute('SET AUTOCOMMIT=1');
+ mysqli_autocommit($this->_connectionID, true);
+ return true;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->Execute('ROLLBACK');
+ //$this->Execute('SET AUTOCOMMIT=1');
+ mysqli_autocommit($this->_connectionID, true);
+ return true;
+ }
+
+ function RowLock($tables,$where='',$col='1 as adodbignore')
+ {
+ if ($this->transCnt==0) $this->BeginTrans();
+ if ($where) $where = ' where '.$where;
+ $rs = $this->Execute("select $col from $tables $where for update");
+ return !empty($rs);
+ }
+
+ /**
+ * Quotes a string to be sent to the database
+ * When there is no active connection,
+ * @param string $s The string to quote
+ * @param boolean $magic_quotes If false, use mysqli_real_escape_string()
+ * if you are quoting a string extracted from a POST/GET variable,
+ * then pass get_magic_quotes_gpc() as the second parameter. This will
+ * ensure that the variable is not quoted twice, once by qstr() and
+ * once by the magic_quotes_gpc.
+ * Eg. $s = $db->qstr(_GET['name'],get_magic_quotes_gpc());
+ * @return string Quoted string
+ */
+ function qstr($s, $magic_quotes = false)
+ {
+ if (is_null($s)) return 'NULL';
+ if (!$magic_quotes) {
+ // mysqli_real_escape_string() throws a warning when the given
+ // connection is invalid
+ if (PHP_VERSION >= 5 && $this->_connectionID) {
+ return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'";
+ }
+
+ if ($this->replaceQuote[0] == '\\') {
+ $s = adodb_str_replace(array('\\',"\0"), array('\\\\',"\\\0") ,$s);
+ }
+ return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
+ }
+ // undo magic quotes for "
+ $s = str_replace('\\"','"',$s);
+ return "'$s'";
+ }
+
+ function _insertid()
+ {
+ $result = @mysqli_insert_id($this->_connectionID);
+ if ($result == -1) {
+ if ($this->debug) ADOConnection::outp("mysqli_insert_id() failed : " . $this->ErrorMsg());
+ }
+ return $result;
+ }
+
+ // Only works for INSERT, UPDATE and DELETE query's
+ function _affectedrows()
+ {
+ $result = @mysqli_affected_rows($this->_connectionID);
+ if ($result == -1) {
+ if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : " . $this->ErrorMsg());
+ }
+ return $result;
+ }
+
+ // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
+ // Reference on Last_Insert_ID on the recommended way to simulate sequences
+ var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
+ var $_genSeqSQL = "create table if not exists %s (id int not null)";
+ var $_genSeqCountSQL = "select count(*) from %s";
+ var $_genSeq2SQL = "insert into %s values (%s)";
+ var $_dropSeqSQL = "drop table if exists %s";
+
+ function CreateSequence($seqname='adodbseq',$startID=1)
+ {
+ if (empty($this->_genSeqSQL)) return false;
+ $u = strtoupper($seqname);
+
+ $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
+ if (!$ok) return false;
+ return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
+ }
+
+ function GenID($seqname='adodbseq',$startID=1)
+ {
+ // post-nuke sets hasGenID to false
+ if (!$this->hasGenID) return false;
+
+ $getnext = sprintf($this->_genIDSQL,$seqname);
+ $holdtransOK = $this->_transOK; // save the current status
+ $rs = @$this->Execute($getnext);
+ if (!$rs) {
+ if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
+ $u = strtoupper($seqname);
+ $this->Execute(sprintf($this->_genSeqSQL,$seqname));
+ $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname));
+ if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
+ $rs = $this->Execute($getnext);
+ }
+
+ if ($rs) {
+ $this->genID = mysqli_insert_id($this->_connectionID);
+ $rs->Close();
+ } else
+ $this->genID = 0;
+
+ return $this->genID;
+ }
+
+ function MetaDatabases()
+ {
+ $query = "SHOW DATABASES";
+ $ret = $this->Execute($query);
+ if ($ret && is_object($ret)){
+ $arr = array();
+ while (!$ret->EOF){
+ $db = $ret->Fields('Database');
+ if ($db != 'mysql') $arr[] = $db;
+ $ret->MoveNext();
+ }
+ return $arr;
+ }
+ return $ret;
+ }
+
+
+ function MetaIndexes ($table, $primary = FALSE, $owner = false)
+ {
+ // save old fetch mode
+ global $ADODB_FETCH_MODE;
+
+ $false = false;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+
+ // get index details
+ $rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table));
+
+ // restore fetchmode
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ if (!is_object($rs)) {
+ return $false;
+ }
+
+ $indexes = array ();
+
+ // parse index data into array
+ while ($row = $rs->FetchRow()) {
+ if ($primary == FALSE AND $row[2] == 'PRIMARY') {
+ continue;
+ }
+
+ if (!isset($indexes[$row[2]])) {
+ $indexes[$row[2]] = array(
+ 'unique' => ($row[1] == 0),
+ 'columns' => array()
+ );
+ }
+
+ $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
+ }
+
+ // sort columns by order in the index
+ foreach ( array_keys ($indexes) as $index )
+ {
+ ksort ($indexes[$index]['columns']);
+ }
+
+ return $indexes;
+ }
+
+
+ // Format date column in sql string given an input format that understands Y M D
+ function SQLDate($fmt, $col=false)
+ {
+ if (!$col) $col = $this->sysTimeStamp;
+ $s = 'DATE_FORMAT('.$col.",'";
+ $concat = false;
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ $ch = $fmt[$i];
+ switch($ch) {
+ case 'Y':
+ case 'y':
+ $s .= '%Y';
+ break;
+ case 'Q':
+ case 'q':
+ $s .= "'),Quarter($col)";
+
+ if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
+ else $s .= ",('";
+ $concat = true;
+ break;
+ case 'M':
+ $s .= '%b';
+ break;
+
+ case 'm':
+ $s .= '%m';
+ break;
+ case 'D':
+ case 'd':
+ $s .= '%d';
+ break;
+
+ case 'H':
+ $s .= '%H';
+ break;
+
+ case 'h':
+ $s .= '%I';
+ break;
+
+ case 'i':
+ $s .= '%i';
+ break;
+
+ case 's':
+ $s .= '%s';
+ break;
+
+ case 'a':
+ case 'A':
+ $s .= '%p';
+ break;
+
+ case 'w':
+ $s .= '%w';
+ break;
+
+ case 'l':
+ $s .= '%W';
+ break;
+
+ default:
+
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ $s .= $ch;
+ break;
+ }
+ }
+ $s.="')";
+ if ($concat) $s = "CONCAT($s)";
+ return $s;
+ }
+
+ // returns concatenated string
+ // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
+ function Concat()
+ {
+ $s = "";
+ $arr = func_get_args();
+
+ // suggestion by andrew005@mnogo.ru
+ $s = implode(',',$arr);
+ if (strlen($s) > 0) return "CONCAT($s)";
+ else return '';
+ }
+
+ // dayFraction is a day in floating point
+ function OffsetDate($dayFraction,$date=false)
+ {
+ if (!$date) $date = $this->sysDate;
+
+ $fraction = $dayFraction * 24 * 3600;
+ return $date . ' + INTERVAL ' . $fraction.' SECOND';
+
+// return "from_unixtime(unix_timestamp($date)+$fraction)";
+ }
+
+ function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null)
+ {
+ // save old fetch mode
+ global $ADODB_FETCH_MODE;
+
+ $false = false;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+
+ $procedures = array ();
+
+ // get index details
+
+ $likepattern = '';
+ if ($NamePattern) {
+ $likepattern = " LIKE '".$NamePattern."'";
+ }
+ $rs = $this->Execute('SHOW PROCEDURE STATUS'.$likepattern);
+ if (is_object($rs)) {
+
+ // parse index data into array
+ while ($row = $rs->FetchRow()) {
+ $procedures[$row[1]] = array(
+ 'type' => 'PROCEDURE',
+ 'catalog' => '',
+ 'schema' => '',
+ 'remarks' => $row[7],
+ );
+ }
+ }
+
+ $rs = $this->Execute('SHOW FUNCTION STATUS'.$likepattern);
+ if (is_object($rs)) {
+ // parse index data into array
+ while ($row = $rs->FetchRow()) {
+ $procedures[$row[1]] = array(
+ 'type' => 'FUNCTION',
+ 'catalog' => '',
+ 'schema' => '',
+ 'remarks' => $row[7]
+ );
+ }
+ }
+
+ // restore fetchmode
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ return $procedures;
+ }
+
+ /**
+ * Retrieves a list of tables based on given criteria
+ *
+ * @param string $ttype Table type = 'TABLE', 'VIEW' or false=both (default)
+ * @param string $showSchema schema name, false = current schema (default)
+ * @param string $mask filters the table by name
+ *
+ * @return array list of tables
+ */
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ $save = $this->metaTablesSQL;
+ if ($showSchema && is_string($showSchema)) {
+ $this->metaTablesSQL .= $this->qstr($showSchema);
+ } else {
+ $this->metaTablesSQL .= "schema()";
+ }
+
+ if ($mask) {
+ $mask = $this->qstr($mask);
+ $this->metaTablesSQL .= " AND table_name LIKE $mask";
+ }
+ $ret = ADOConnection::MetaTables($ttype,$showSchema);
+
+ $this->metaTablesSQL = $save;
+ return $ret;
+ }
+
+ // "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx>
+ function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
+ {
+ global $ADODB_FETCH_MODE;
+
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true;
+
+ if ( !empty($owner) ) {
+ $table = "$owner.$table";
+ }
+ $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
+ if ($associative) {
+ $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"];
+ } else $create_sql = $a_create_table[1];
+
+ $matches = array();
+
+ if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
+ $foreign_keys = array();
+ $num_keys = count($matches[0]);
+ for ( $i = 0; $i < $num_keys; $i ++ ) {
+ $my_field = explode('`, `', $matches[1][$i]);
+ $ref_table = $matches[2][$i];
+ $ref_field = explode('`, `', $matches[3][$i]);
+
+ if ( $upper ) {
+ $ref_table = strtoupper($ref_table);
+ }
+
+ // see https://sourceforge.net/p/adodb/bugs/100/
+ if (!isset($foreign_keys[$ref_table])) {
+ $foreign_keys[$ref_table] = array();
+ }
+ $num_fields = count($my_field);
+ for ( $j = 0; $j < $num_fields; $j ++ ) {
+ if ( $associative ) {
+ $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
+ } else {
+ $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
+ }
+ }
+ }
+
+ return $foreign_keys;
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ $false = false;
+ if (!$this->metaColumnsSQL)
+ return $false;
+
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== false)
+ $savem = $this->SetFetchMode(false);
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ if (!is_object($rs))
+ return $false;
+
+ $retarr = array();
+ while (!$rs->EOF) {
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $type = $rs->fields[1];
+
+ // split type into type(length):
+ $fld->scale = null;
+ if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
+ $fld->type = $query_array[1];
+ $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
+ $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
+ } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
+ $fld->type = $query_array[1];
+ $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
+ } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
+ $fld->type = $query_array[1];
+ $arr = explode(",",$query_array[2]);
+ $fld->enums = $arr;
+ $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
+ $fld->max_length = ($zlen > 0) ? $zlen : 1;
+ } else {
+ $fld->type = $type;
+ $fld->max_length = -1;
+ }
+ $fld->not_null = ($rs->fields[2] != 'YES');
+ $fld->primary_key = ($rs->fields[3] == 'PRI');
+ $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
+ $fld->binary = (strpos($type,'blob') !== false);
+ $fld->unsigned = (strpos($type,'unsigned') !== false);
+ $fld->zerofill = (strpos($type,'zerofill') !== false);
+
+ if (!$fld->binary) {
+ $d = $rs->fields[4];
+ if ($d != '' && $d != 'NULL') {
+ $fld->has_default = true;
+ $fld->default_value = $d;
+ } else {
+ $fld->has_default = false;
+ }
+ }
+
+ if ($save == ADODB_FETCH_NUM) {
+ $retarr[] = $fld;
+ } else {
+ $retarr[strtoupper($fld->name)] = $fld;
+ }
+ $rs->MoveNext();
+ }
+
+ $rs->Close();
+ return $retarr;
+ }
+
+ // returns true or false
+ function SelectDB($dbName)
+ {
+// $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);
+ $this->database = $dbName;
+ $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
+
+ if ($this->_connectionID) {
+ $result = @mysqli_select_db($this->_connectionID, $dbName);
+ if (!$result) {
+ ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg());
+ }
+ return $result;
+ }
+ return false;
+ }
+
+ // parameters use PostgreSQL convention, not MySQL
+ function SelectLimit($sql,
+ $nrows = -1,
+ $offset = -1,
+ $inputarr = false,
+ $secs = 0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ $offsetStr = ($offset >= 0) ? "$offset," : '';
+ if ($nrows < 0) $nrows = '18446744073709551615';
+
+ if ($secs)
+ $rs = $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr );
+ else
+ $rs = $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr );
+
+ return $rs;
+ }
+
+
+ function Prepare($sql)
+ {
+ return $sql;
+ $stmt = $this->_connectionID->prepare($sql);
+ if (!$stmt) {
+ echo $this->ErrorMsg();
+ return $sql;
+ }
+ return array($sql,$stmt);
+ }
+
+
+ // returns queryID or false
+ function _query($sql, $inputarr)
+ {
+ global $ADODB_COUNTRECS;
+ // Move to the next recordset, or return false if there is none. In a stored proc
+ // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
+ // returns false. I think this is because the last "recordset" is actually just the
+ // return value of the stored proc (ie the number of rows affected).
+ // Commented out for reasons of performance. You should retrieve every recordset yourself.
+ // if (!mysqli_next_result($this->connection->_connectionID)) return false;
+
+ if (is_array($sql)) {
+
+ // Prepare() not supported because mysqli_stmt_execute does not return a recordset, but
+ // returns as bound variables.
+
+ $stmt = $sql[1];
+ $a = '';
+ foreach($inputarr as $k => $v) {
+ if (is_string($v)) $a .= 's';
+ else if (is_integer($v)) $a .= 'i';
+ else $a .= 'd';
+ }
+
+ $fnarr = array_merge( array($stmt,$a) , $inputarr);
+ $ret = call_user_func_array('mysqli_stmt_bind_param',$fnarr);
+ $ret = mysqli_stmt_execute($stmt);
+ return $ret;
+ }
+
+ /*
+ if (!$mysql_res = mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) {
+ if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
+ return false;
+ }
+
+ return $mysql_res;
+ */
+
+ if ($this->multiQuery) {
+ $rs = mysqli_multi_query($this->_connectionID, $sql.';');
+ if ($rs) {
+ $rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID );
+ return $rs ? $rs : true; // mysqli_more_results( $this->_connectionID )
+ }
+ } else {
+ $rs = mysqli_query($this->_connectionID, $sql, $ADODB_COUNTRECS ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT);
+
+ if ($rs) return $rs;
+ }
+
+ if($this->debug)
+ ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
+
+ return false;
+
+ }
+
+ /* Returns: the last error message from previous database operation */
+ function ErrorMsg()
+ {
+ if (empty($this->_connectionID))
+ $this->_errorMsg = @mysqli_connect_error();
+ else
+ $this->_errorMsg = @mysqli_error($this->_connectionID);
+ return $this->_errorMsg;
+ }
+
+ /* Returns: the last error number from previous database operation */
+ function ErrorNo()
+ {
+ if (empty($this->_connectionID))
+ return @mysqli_connect_errno();
+ else
+ return @mysqli_errno($this->_connectionID);
+ }
+
+ // returns true or false
+ function _close()
+ {
+ @mysqli_close($this->_connectionID);
+ $this->_connectionID = false;
+ }
+
+ /*
+ * Maximum size of C field
+ */
+ function CharMax()
+ {
+ return 255;
+ }
+
+ /*
+ * Maximum size of X field
+ */
+ function TextMax()
+ {
+ return 4294967295;
+ }
+
+
+ // this is a set of functions for managing client encoding - very important if the encodings
+ // of your database and your output target (i.e. HTML) don't match
+ // for instance, you may have UTF8 database and server it on-site as latin1 etc.
+ // GetCharSet - get the name of the character set the client is using now
+ // Under Windows, the functions should work with MySQL 4.1.11 and above, the set of charsets supported
+ // depends on compile flags of mysql distribution
+
+ function GetCharSet()
+ {
+ //we will use ADO's builtin property charSet
+ if (!method_exists($this->_connectionID,'character_set_name'))
+ return false;
+
+ $this->charSet = @$this->_connectionID->character_set_name();
+ if (!$this->charSet) {
+ return false;
+ } else {
+ return $this->charSet;
+ }
+ }
+
+ // SetCharSet - switch the client encoding
+ function SetCharSet($charset_name)
+ {
+ if (!method_exists($this->_connectionID,'set_charset')) {
+ return false;
+ }
+
+ if ($this->charSet !== $charset_name) {
+ $if = @$this->_connectionID->set_charset($charset_name);
+ return ($if === true & $this->GetCharSet() == $charset_name);
+ } else {
+ return true;
+ }
+ }
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_mysqli extends ADORecordSet{
+
+ var $databaseType = "mysqli";
+ var $canSeek = true;
+
+ function __construct($queryID, $mode = false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+
+ switch ($mode) {
+ case ADODB_FETCH_NUM:
+ $this->fetchMode = MYSQLI_NUM;
+ break;
+ case ADODB_FETCH_ASSOC:
+ $this->fetchMode = MYSQLI_ASSOC;
+ break;
+ case ADODB_FETCH_DEFAULT:
+ case ADODB_FETCH_BOTH:
+ default:
+ $this->fetchMode = MYSQLI_BOTH;
+ break;
+ }
+ $this->adodbFetchMode = $mode;
+ parent::__construct($queryID);
+ }
+
+ function _initrs()
+ {
+ global $ADODB_COUNTRECS;
+
+ $this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1;
+ $this->_numOfFields = @mysqli_num_fields($this->_queryID);
+ }
+
+/*
+1 = MYSQLI_NOT_NULL_FLAG
+2 = MYSQLI_PRI_KEY_FLAG
+4 = MYSQLI_UNIQUE_KEY_FLAG
+8 = MYSQLI_MULTIPLE_KEY_FLAG
+16 = MYSQLI_BLOB_FLAG
+32 = MYSQLI_UNSIGNED_FLAG
+64 = MYSQLI_ZEROFILL_FLAG
+128 = MYSQLI_BINARY_FLAG
+256 = MYSQLI_ENUM_FLAG
+512 = MYSQLI_AUTO_INCREMENT_FLAG
+1024 = MYSQLI_TIMESTAMP_FLAG
+2048 = MYSQLI_SET_FLAG
+32768 = MYSQLI_NUM_FLAG
+16384 = MYSQLI_PART_KEY_FLAG
+32768 = MYSQLI_GROUP_FLAG
+65536 = MYSQLI_UNIQUE_FLAG
+131072 = MYSQLI_BINCMP_FLAG
+*/
+
+ function FetchField($fieldOffset = -1)
+ {
+ $fieldnr = $fieldOffset;
+ if ($fieldOffset != -1) {
+ $fieldOffset = @mysqli_field_seek($this->_queryID, $fieldnr);
+ }
+ $o = @mysqli_fetch_field($this->_queryID);
+ if (!$o) return false;
+
+ //Fix for HHVM
+ if ( !isset($o->flags) ) {
+ $o->flags = 0;
+ }
+ /* Properties of an ADOFieldObject as set by MetaColumns */
+ $o->primary_key = $o->flags & MYSQLI_PRI_KEY_FLAG;
+ $o->not_null = $o->flags & MYSQLI_NOT_NULL_FLAG;
+ $o->auto_increment = $o->flags & MYSQLI_AUTO_INCREMENT_FLAG;
+ $o->binary = $o->flags & MYSQLI_BINARY_FLAG;
+ // $o->blob = $o->flags & MYSQLI_BLOB_FLAG; /* not returned by MetaColumns */
+ $o->unsigned = $o->flags & MYSQLI_UNSIGNED_FLAG;
+
+ return $o;
+ }
+
+ function GetRowAssoc($upper = ADODB_ASSOC_CASE)
+ {
+ if ($this->fetchMode == MYSQLI_ASSOC && $upper == ADODB_ASSOC_CASE_LOWER) {
+ return $this->fields;
+ }
+ $row = ADORecordSet::GetRowAssoc($upper);
+ return $row;
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode != MYSQLI_NUM) {
+ return @$this->fields[$colname];
+ }
+
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i = 0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+ function _seek($row)
+ {
+ if ($this->_numOfRows == 0 || $row < 0) {
+ return false;
+ }
+
+ mysqli_data_seek($this->_queryID, $row);
+ $this->EOF = false;
+ return true;
+ }
+
+
+ function NextRecordSet()
+ {
+ global $ADODB_COUNTRECS;
+
+ mysqli_free_result($this->_queryID);
+ $this->_queryID = -1;
+ // Move to the next recordset, or return false if there is none. In a stored proc
+ // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
+ // returns false. I think this is because the last "recordset" is actually just the
+ // return value of the stored proc (ie the number of rows affected).
+ if(!mysqli_next_result($this->connection->_connectionID)) {
+ return false;
+ }
+ // CD: There is no $this->_connectionID variable, at least in the ADO version I'm using
+ $this->_queryID = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->connection->_connectionID )
+ : @mysqli_use_result( $this->connection->_connectionID );
+ if(!$this->_queryID) {
+ return false;
+ }
+ $this->_inited = false;
+ $this->bind = false;
+ $this->_currentRow = -1;
+ $this->Init();
+ return true;
+ }
+
+ // 10% speedup to move MoveNext to child class
+ // This is the only implementation that works now (23-10-2003).
+ // Other functions return no or the wrong results.
+ function MoveNext()
+ {
+ if ($this->EOF) return false;
+ $this->_currentRow++;
+ $this->fields = @mysqli_fetch_array($this->_queryID,$this->fetchMode);
+
+ if (is_array($this->fields)) {
+ $this->_updatefields();
+ return true;
+ }
+ $this->EOF = true;
+ return false;
+ }
+
+ function _fetch()
+ {
+ $this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode);
+ $this->_updatefields();
+ return is_array($this->fields);
+ }
+
+ function _close()
+ {
+ //if results are attached to this pointer from Stored Proceedure calls, the next standard query will die 2014
+ //only a problem with persistant connections
+
+ if(isset($this->connection->_connectionID) && $this->connection->_connectionID) {
+ while(mysqli_more_results($this->connection->_connectionID)){
+ mysqli_next_result($this->connection->_connectionID);
+ }
+ }
+
+ if($this->_queryID instanceof mysqli_result) {
+ mysqli_free_result($this->_queryID);
+ }
+ $this->_queryID = false;
+ }
+
+/*
+
+0 = MYSQLI_TYPE_DECIMAL
+1 = MYSQLI_TYPE_CHAR
+1 = MYSQLI_TYPE_TINY
+2 = MYSQLI_TYPE_SHORT
+3 = MYSQLI_TYPE_LONG
+4 = MYSQLI_TYPE_FLOAT
+5 = MYSQLI_TYPE_DOUBLE
+6 = MYSQLI_TYPE_NULL
+7 = MYSQLI_TYPE_TIMESTAMP
+8 = MYSQLI_TYPE_LONGLONG
+9 = MYSQLI_TYPE_INT24
+10 = MYSQLI_TYPE_DATE
+11 = MYSQLI_TYPE_TIME
+12 = MYSQLI_TYPE_DATETIME
+13 = MYSQLI_TYPE_YEAR
+14 = MYSQLI_TYPE_NEWDATE
+247 = MYSQLI_TYPE_ENUM
+248 = MYSQLI_TYPE_SET
+249 = MYSQLI_TYPE_TINY_BLOB
+250 = MYSQLI_TYPE_MEDIUM_BLOB
+251 = MYSQLI_TYPE_LONG_BLOB
+252 = MYSQLI_TYPE_BLOB
+253 = MYSQLI_TYPE_VAR_STRING
+254 = MYSQLI_TYPE_STRING
+255 = MYSQLI_TYPE_GEOMETRY
+*/
+
+ function MetaType($t, $len = -1, $fieldobj = false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+
+
+ $len = -1; // mysql max_length is not accurate
+ switch (strtoupper($t)) {
+ case 'STRING':
+ case 'CHAR':
+ case 'VARCHAR':
+ case 'TINYBLOB':
+ case 'TINYTEXT':
+ case 'ENUM':
+ case 'SET':
+
+ case MYSQLI_TYPE_TINY_BLOB :
+ #case MYSQLI_TYPE_CHAR :
+ case MYSQLI_TYPE_STRING :
+ case MYSQLI_TYPE_ENUM :
+ case MYSQLI_TYPE_SET :
+ case 253 :
+ if ($len <= $this->blobSize) return 'C';
+
+ case 'TEXT':
+ case 'LONGTEXT':
+ case 'MEDIUMTEXT':
+ return 'X';
+
+ // php_mysql extension always returns 'blob' even if 'text'
+ // so we have to check whether binary...
+ case 'IMAGE':
+ case 'LONGBLOB':
+ case 'BLOB':
+ case 'MEDIUMBLOB':
+
+ case MYSQLI_TYPE_BLOB :
+ case MYSQLI_TYPE_LONG_BLOB :
+ case MYSQLI_TYPE_MEDIUM_BLOB :
+ return !empty($fieldobj->binary) ? 'B' : 'X';
+
+ case 'YEAR':
+ case 'DATE':
+ case MYSQLI_TYPE_DATE :
+ case MYSQLI_TYPE_YEAR :
+ return 'D';
+
+ case 'TIME':
+ case 'DATETIME':
+ case 'TIMESTAMP':
+
+ case MYSQLI_TYPE_DATETIME :
+ case MYSQLI_TYPE_NEWDATE :
+ case MYSQLI_TYPE_TIME :
+ case MYSQLI_TYPE_TIMESTAMP :
+ return 'T';
+
+ case 'INT':
+ case 'INTEGER':
+ case 'BIGINT':
+ case 'TINYINT':
+ case 'MEDIUMINT':
+ case 'SMALLINT':
+
+ case MYSQLI_TYPE_INT24 :
+ case MYSQLI_TYPE_LONG :
+ case MYSQLI_TYPE_LONGLONG :
+ case MYSQLI_TYPE_SHORT :
+ case MYSQLI_TYPE_TINY :
+ if (!empty($fieldobj->primary_key)) return 'R';
+ return 'I';
+
+ // Added floating-point types
+ // Maybe not necessery.
+ case 'FLOAT':
+ case 'DOUBLE':
+// case 'DOUBLE PRECISION':
+ case 'DECIMAL':
+ case 'DEC':
+ case 'FIXED':
+ default:
+ //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>";
+ return 'N';
+ }
+ } // function
+
+
+} // rs class
+
+}
+
+class ADORecordSet_array_mysqli extends ADORecordSet_array {
+
+ function __construct($id=-1,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+
+ function MetaType($t, $len = -1, $fieldobj = false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+
+
+ $len = -1; // mysql max_length is not accurate
+ switch (strtoupper($t)) {
+ case 'STRING':
+ case 'CHAR':
+ case 'VARCHAR':
+ case 'TINYBLOB':
+ case 'TINYTEXT':
+ case 'ENUM':
+ case 'SET':
+
+ case MYSQLI_TYPE_TINY_BLOB :
+ #case MYSQLI_TYPE_CHAR :
+ case MYSQLI_TYPE_STRING :
+ case MYSQLI_TYPE_ENUM :
+ case MYSQLI_TYPE_SET :
+ case 253 :
+ if ($len <= $this->blobSize) return 'C';
+
+ case 'TEXT':
+ case 'LONGTEXT':
+ case 'MEDIUMTEXT':
+ return 'X';
+
+ // php_mysql extension always returns 'blob' even if 'text'
+ // so we have to check whether binary...
+ case 'IMAGE':
+ case 'LONGBLOB':
+ case 'BLOB':
+ case 'MEDIUMBLOB':
+
+ case MYSQLI_TYPE_BLOB :
+ case MYSQLI_TYPE_LONG_BLOB :
+ case MYSQLI_TYPE_MEDIUM_BLOB :
+
+ return !empty($fieldobj->binary) ? 'B' : 'X';
+ case 'YEAR':
+ case 'DATE':
+ case MYSQLI_TYPE_DATE :
+ case MYSQLI_TYPE_YEAR :
+
+ return 'D';
+
+ case 'TIME':
+ case 'DATETIME':
+ case 'TIMESTAMP':
+
+ case MYSQLI_TYPE_DATETIME :
+ case MYSQLI_TYPE_NEWDATE :
+ case MYSQLI_TYPE_TIME :
+ case MYSQLI_TYPE_TIMESTAMP :
+
+ return 'T';
+
+ case 'INT':
+ case 'INTEGER':
+ case 'BIGINT':
+ case 'TINYINT':
+ case 'MEDIUMINT':
+ case 'SMALLINT':
+
+ case MYSQLI_TYPE_INT24 :
+ case MYSQLI_TYPE_LONG :
+ case MYSQLI_TYPE_LONGLONG :
+ case MYSQLI_TYPE_SHORT :
+ case MYSQLI_TYPE_TINY :
+
+ if (!empty($fieldobj->primary_key)) return 'R';
+
+ return 'I';
+
+
+ // Added floating-point types
+ // Maybe not necessery.
+ case 'FLOAT':
+ case 'DOUBLE':
+// case 'DOUBLE PRECISION':
+ case 'DECIMAL':
+ case 'DEC':
+ case 'FIXED':
+ default:
+ //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>";
+ return 'N';
+ }
+ } // function
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-mysqlpo.inc.php b/vendor/adodb/adodb-php/drivers/adodb-mysqlpo.inc.php
new file mode 100644
index 0000000..1cc7a91
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-mysqlpo.inc.php
@@ -0,0 +1,128 @@
+<?php
+
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 8.
+
+ MySQL code that supports transactions. For MySQL 3.23 or later.
+ Code from James Poon <jpoon88@yahoo.com>
+
+ This driver extends the deprecated mysql driver, and was originally designed to be a
+ portable driver in the same manner as oci8po and mssqlpo. Its functionality
+ is exactly duplicated in the mysqlt driver, which is itself deprecated.
+ This driver will be removed in ADOdb version 6.0.0.
+
+ Requires mysql client. Works on Windows and Unix.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR."/drivers/adodb-mysql.inc.php");
+
+
+class ADODB_mysqlt extends ADODB_mysql {
+ var $databaseType = 'mysqlt';
+ var $ansiOuter = true; // for Version 3.23.17 or later
+ var $hasTransactions = true;
+ var $autoRollback = true; // apparently mysql does not autorollback properly
+
+ function __construct()
+ {
+ global $ADODB_EXTENSION; if ($ADODB_EXTENSION) $this->rsPrefix .= 'ext_';
+ }
+
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ $this->Execute('SET AUTOCOMMIT=0');
+ $this->Execute('BEGIN');
+ return true;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) return true;
+ if (!$ok) return $this->RollbackTrans();
+
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->Execute('COMMIT');
+ $this->Execute('SET AUTOCOMMIT=1');
+ return true;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->Execute('ROLLBACK');
+ $this->Execute('SET AUTOCOMMIT=1');
+ return true;
+ }
+
+ function RowLock($tables,$where='',$col='1 as adodbignore')
+ {
+ if ($this->transCnt==0) $this->BeginTrans();
+ if ($where) $where = ' where '.$where;
+ $rs = $this->Execute("select $col from $tables $where for update");
+ return !empty($rs);
+ }
+
+}
+
+class ADORecordSet_mysqlt extends ADORecordSet_mysql{
+ var $databaseType = "mysqlt";
+
+ function __construct($queryID,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+
+ switch ($mode)
+ {
+ case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
+ case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
+
+ case ADODB_FETCH_DEFAULT:
+ case ADODB_FETCH_BOTH:
+ default: $this->fetchMode = MYSQL_BOTH; break;
+ }
+
+ $this->adodbFetchMode = $mode;
+ parent::__construct($queryID);
+ }
+
+ function MoveNext()
+ {
+ if (@$this->fields = mysql_fetch_array($this->_queryID,$this->fetchMode)) {
+ $this->_currentRow += 1;
+ return true;
+ }
+ if (!$this->EOF) {
+ $this->_currentRow += 1;
+ $this->EOF = true;
+ }
+ return false;
+ }
+}
+
+class ADORecordSet_ext_mysqlt extends ADORecordSet_mysqlt {
+
+ function __construct($queryID,$mode=false)
+ {
+ parent::__construct($queryID,$mode);
+ }
+
+ function MoveNext()
+ {
+ return adodb_movenext($this);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-mysqlt.inc.php b/vendor/adodb/adodb-php/drivers/adodb-mysqlt.inc.php
new file mode 100644
index 0000000..0e31926
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-mysqlt.inc.php
@@ -0,0 +1,137 @@
+<?php
+
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 8.
+
+ This driver only supports the original MySQL driver in transactional mode. It
+ is deprected in PHP version 5.5 and removed in PHP version 7. It is deprecated
+ as of ADOdb version 5.20.0. Use the mysqli driver instead, which supports both
+ transactional and non-transactional updates
+
+ Requires mysql client. Works on Windows and Unix.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR."/drivers/adodb-mysql.inc.php");
+
+
+class ADODB_mysqlt extends ADODB_mysql {
+ var $databaseType = 'mysqlt';
+ var $ansiOuter = true; // for Version 3.23.17 or later
+ var $hasTransactions = true;
+ var $autoRollback = true; // apparently mysql does not autorollback properly
+
+ function __construct()
+ {
+ global $ADODB_EXTENSION; if ($ADODB_EXTENSION) $this->rsPrefix .= 'ext_';
+ }
+
+ /* set transaction mode
+
+ SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
+{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
+
+ */
+ function SetTransactionMode( $transaction_mode )
+ {
+ $this->_transmode = $transaction_mode;
+ if (empty($transaction_mode)) {
+ $this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ');
+ return;
+ }
+ if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
+ $this->Execute("SET SESSION TRANSACTION ".$transaction_mode);
+ }
+
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ $this->Execute('SET AUTOCOMMIT=0');
+ $this->Execute('BEGIN');
+ return true;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) return true;
+ if (!$ok) return $this->RollbackTrans();
+
+ if ($this->transCnt) $this->transCnt -= 1;
+ $ok = $this->Execute('COMMIT');
+ $this->Execute('SET AUTOCOMMIT=1');
+ return $ok ? true : false;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ if ($this->transCnt) $this->transCnt -= 1;
+ $ok = $this->Execute('ROLLBACK');
+ $this->Execute('SET AUTOCOMMIT=1');
+ return $ok ? true : false;
+ }
+
+ function RowLock($tables,$where='',$col='1 as adodbignore')
+ {
+ if ($this->transCnt==0) $this->BeginTrans();
+ if ($where) $where = ' where '.$where;
+ $rs = $this->Execute("select $col from $tables $where for update");
+ return !empty($rs);
+ }
+
+}
+
+class ADORecordSet_mysqlt extends ADORecordSet_mysql{
+ var $databaseType = "mysqlt";
+
+ function __construct($queryID,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+
+ switch ($mode)
+ {
+ case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
+ case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
+
+ case ADODB_FETCH_DEFAULT:
+ case ADODB_FETCH_BOTH:
+ default: $this->fetchMode = MYSQL_BOTH; break;
+ }
+
+ $this->adodbFetchMode = $mode;
+ parent::__construct($queryID);
+ }
+
+ function MoveNext()
+ {
+ if (@$this->fields = mysql_fetch_array($this->_queryID,$this->fetchMode)) {
+ $this->_currentRow += 1;
+ return true;
+ }
+ if (!$this->EOF) {
+ $this->_currentRow += 1;
+ $this->EOF = true;
+ }
+ return false;
+ }
+}
+
+class ADORecordSet_ext_mysqlt extends ADORecordSet_mysqlt {
+
+ function MoveNext()
+ {
+ return adodb_movenext($this);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-netezza.inc.php b/vendor/adodb/adodb-php/drivers/adodb-netezza.inc.php
new file mode 100644
index 0000000..7a1b63c
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-netezza.inc.php
@@ -0,0 +1,157 @@
+<?php
+/*
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+
+ First cut at the Netezza Driver by Josh Eldridge joshuae74#hotmail.com
+ Based on the previous postgres drivers.
+ http://www.netezza.com/
+ Major Additions/Changes:
+ MetaDatabasesSQL, MetaTablesSQL, MetaColumnsSQL
+ Note: You have to have admin privileges to access the system tables
+ Removed non-working keys code (Netezza has no concept of keys)
+ Fixed the way data types and lengths are returned in MetaColumns()
+ as well as added the default lengths for certain types
+ Updated public variables for Netezza
+ Still need to remove blob functions, as Netezza doesn't suppport blob
+*/
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR.'/drivers/adodb-postgres64.inc.php');
+
+class ADODB_netezza extends ADODB_postgres64 {
+ var $databaseType = 'netezza';
+ var $dataProvider = 'netezza';
+ var $hasInsertID = false;
+ var $_resultid = false;
+ var $concat_operator='||';
+ var $random = 'random';
+ var $metaDatabasesSQL = "select objname from _v_object_data where objtype='database' order by 1";
+ var $metaTablesSQL = "select objname from _v_object_data where objtype='table' order by 1";
+ var $isoDates = true; // accepts dates in ISO format
+ var $sysDate = "CURRENT_DATE";
+ var $sysTimeStamp = "CURRENT_TIMESTAMP";
+ var $blobEncodeType = 'C';
+ var $metaColumnsSQL = "SELECT attname, atttype FROM _v_relation_column_def WHERE name = '%s' AND attnum > 0 ORDER BY attnum";
+ var $metaColumnsSQL1 = "SELECT attname, atttype FROM _v_relation_column_def WHERE name = '%s' AND attnum > 0 ORDER BY attnum";
+ // netezza doesn't have keys. it does have distributions, so maybe this is
+ // something that can be pulled from the system tables
+ var $metaKeySQL = "";
+ var $hasAffectedRows = true;
+ var $hasLimit = true;
+ var $true = 't'; // string that represents TRUE for a database
+ var $false = 'f'; // string that represents FALSE for a database
+ var $fmtDate = "'Y-m-d'"; // used by DBDate() as the default date format used by the database
+ var $fmtTimeStamp = "'Y-m-d G:i:s'"; // used by DBTimeStamp as the default timestamp fmt.
+ var $ansiOuter = true;
+ var $autoRollback = true; // apparently pgsql does not autorollback properly before 4.3.4
+ // http://bugs.php.net/bug.php?id=25404
+
+
+ function __construct()
+ {
+
+ }
+
+ function MetaColumns($table,$upper=true)
+ {
+
+ // Changed this function to support Netezza which has no concept of keys
+ // could posisbly work on other things from the system table later.
+
+ global $ADODB_FETCH_MODE;
+
+ $table = strtolower($table);
+
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
+
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table,$table));
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+
+ if ($rs === false) return false;
+
+ $retarr = array();
+ while (!$rs->EOF) {
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+
+ // since we're returning type and length as one string,
+ // split them out here.
+
+ if ($first = strstr($rs->fields[1], "(")) {
+ $fld->max_length = trim($first, "()");
+ } else {
+ $fld->max_length = -1;
+ }
+
+ if ($first = strpos($rs->fields[1], "(")) {
+ $fld->type = substr($rs->fields[1], 0, $first);
+ } else {
+ $fld->type = $rs->fields[1];
+ }
+
+ switch ($fld->type) {
+ case "byteint":
+ case "boolean":
+ $fld->max_length = 1;
+ break;
+ case "smallint":
+ $fld->max_length = 2;
+ break;
+ case "integer":
+ case "numeric":
+ case "date":
+ $fld->max_length = 4;
+ break;
+ case "bigint":
+ case "time":
+ case "timestamp":
+ $fld->max_length = 8;
+ break;
+ case "timetz":
+ case "time with time zone":
+ $fld->max_length = 12;
+ break;
+ }
+
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
+ else $retarr[($upper) ? strtoupper($fld->name) : $fld->name] = $fld;
+
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ return $retarr;
+
+ }
+
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_netezza extends ADORecordSet_postgres64
+{
+ var $databaseType = "netezza";
+ var $canSeek = true;
+
+ function __construct($queryID,$mode=false)
+ {
+ parent::__construct($queryID,$mode);
+ }
+
+ // _initrs modified to disable blob handling
+ function _initrs()
+ {
+ global $ADODB_COUNTRECS;
+ $this->_numOfRows = ($ADODB_COUNTRECS)? @pg_num_rows($this->_queryID):-1;
+ $this->_numOfFields = @pg_num_fields($this->_queryID);
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-oci8.inc.php b/vendor/adodb/adodb-php/drivers/adodb-oci8.inc.php
new file mode 100644
index 0000000..66847ed
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-oci8.inc.php
@@ -0,0 +1,1826 @@
+<?php
+/*
+
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim. All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+
+ Latest version is available at http://adodb.org/
+
+ Code contributed by George Fourlanos <fou@infomap.gr>
+
+ 13 Nov 2000 jlim - removed all ora_* references.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+/*
+NLS_Date_Format
+Allows you to use a date format other than the Oracle Lite default. When a literal
+character string appears where a date value is expected, the Oracle Lite database
+tests the string to see if it matches the formats of Oracle, SQL-92, or the value
+specified for this parameter in the POLITE.INI file. Setting this parameter also
+defines the default format used in the TO_CHAR or TO_DATE functions when no
+other format string is supplied.
+
+For Oracle the default is dd-mon-yy or dd-mon-yyyy, and for SQL-92 the default is
+yy-mm-dd or yyyy-mm-dd.
+
+Using 'RR' in the format forces two-digit years less than or equal to 49 to be
+interpreted as years in the 21st century (2000-2049), and years over 50 as years in
+the 20th century (1950-1999). Setting the RR format as the default for all two-digit
+year entries allows you to become year-2000 compliant. For example:
+NLS_DATE_FORMAT='RR-MM-DD'
+
+You can also modify the date format using the ALTER SESSION command.
+*/
+
+# define the LOB descriptor type for the given type
+# returns false if no LOB descriptor
+function oci_lob_desc($type) {
+ switch ($type) {
+ case OCI_B_BFILE: return OCI_D_FILE;
+ case OCI_B_CFILEE: return OCI_D_FILE;
+ case OCI_B_CLOB: return OCI_D_LOB;
+ case OCI_B_BLOB: return OCI_D_LOB;
+ case OCI_B_ROWID: return OCI_D_ROWID;
+ }
+ return false;
+}
+
+class ADODB_oci8 extends ADOConnection {
+ var $databaseType = 'oci8';
+ var $dataProvider = 'oci8';
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $concat_operator='||';
+ var $sysDate = "TRUNC(SYSDATE)";
+ var $sysTimeStamp = 'SYSDATE'; // requires oracle 9 or later, otherwise use SYSDATE
+ var $metaDatabasesSQL = "SELECT USERNAME FROM ALL_USERS WHERE USERNAME NOT IN ('SYS','SYSTEM','DBSNMP','OUTLN') ORDER BY 1";
+ var $_stmt;
+ var $_commit = OCI_COMMIT_ON_SUCCESS;
+ var $_initdate = true; // init date to YYYY-MM-DD
+ var $metaTablesSQL = "select table_name,table_type from cat where table_type in ('TABLE','VIEW') and table_name not like 'BIN\$%'"; // bin$ tables are recycle bin tables
+ var $metaColumnsSQL = "select cname,coltype,width, SCALE, PRECISION, NULLS, DEFAULTVAL from col where tname='%s' order by colno"; //changed by smondino@users.sourceforge. net
+ var $metaColumnsSQL2 = "select column_name,data_type,data_length, data_scale, data_precision,
+ case when nullable = 'Y' then 'NULL'
+ else 'NOT NULL' end as nulls,
+ data_default from all_tab_cols
+ where owner='%s' and table_name='%s' order by column_id"; // when there is a schema
+ var $_bindInputArray = true;
+ var $hasGenID = true;
+ var $_genIDSQL = "SELECT (%s.nextval) FROM DUAL";
+ var $_genSeqSQL = "
+DECLARE
+ PRAGMA AUTONOMOUS_TRANSACTION;
+BEGIN
+ execute immediate 'CREATE SEQUENCE %s START WITH %s';
+END;
+";
+
+ var $_dropSeqSQL = "DROP SEQUENCE %s";
+ var $hasAffectedRows = true;
+ var $random = "abs(mod(DBMS_RANDOM.RANDOM,10000001)/10000000)";
+ var $noNullStrings = false;
+ var $connectSID = false;
+ var $_bind = false;
+ var $_nestedSQL = true;
+ var $_hasOciFetchStatement = false;
+ var $_getarray = false; // currently not working
+ var $leftOuter = ''; // oracle wierdness, $col = $value (+) for LEFT OUTER, $col (+)= $value for RIGHT OUTER
+ var $session_sharing_force_blob = false; // alter session on updateblob if set to true
+ var $firstrows = true; // enable first rows optimization on SelectLimit()
+ var $selectOffsetAlg1 = 1000; // when to use 1st algorithm of selectlimit.
+ var $NLS_DATE_FORMAT = 'YYYY-MM-DD'; // To include time, use 'RRRR-MM-DD HH24:MI:SS'
+ var $dateformat = 'YYYY-MM-DD'; // DBDate format
+ var $useDBDateFormatForTextInput=false;
+ var $datetime = false; // MetaType('DATE') returns 'D' (datetime==false) or 'T' (datetime == true)
+ var $_refLOBs = array();
+
+ // var $ansiOuter = true; // if oracle9
+
+ function __construct()
+ {
+ $this->_hasOciFetchStatement = ADODB_PHPVER >= 0x4200;
+ if (defined('ADODB_EXTENSION')) {
+ $this->rsPrefix .= 'ext_';
+ }
+ }
+
+ /* function MetaColumns($table, $normalize=true) added by smondino@users.sourceforge.net*/
+ function MetaColumns($table, $normalize=true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $schema = '';
+ $this->_findschema($table, $schema);
+
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== false) {
+ $savem = $this->SetFetchMode(false);
+ }
+
+ if ($schema){
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL2, strtoupper($schema), strtoupper($table)));
+ }
+ else {
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table)));
+ }
+
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+ if (!$rs) {
+ return false;
+ }
+ $retarr = array();
+ while (!$rs->EOF) {
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $fld->type = $rs->fields[1];
+ $fld->max_length = $rs->fields[2];
+ $fld->scale = $rs->fields[3];
+ if ($rs->fields[1] == 'NUMBER') {
+ if ($rs->fields[3] == 0) {
+ $fld->type = 'INT';
+ }
+ $fld->max_length = $rs->fields[4];
+ }
+ $fld->not_null = (strncmp($rs->fields[5], 'NOT',3) === 0);
+ $fld->binary = (strpos($fld->type,'BLOB') !== false);
+ $fld->default_value = $rs->fields[6];
+
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) {
+ $retarr[] = $fld;
+ }
+ else {
+ $retarr[strtoupper($fld->name)] = $fld;
+ }
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ if (empty($retarr)) {
+ return false;
+ }
+ return $retarr;
+ }
+
+ function Time()
+ {
+ $rs = $this->Execute("select TO_CHAR($this->sysTimeStamp,'YYYY-MM-DD HH24:MI:SS') from dual");
+ if ($rs && !$rs->EOF) {
+ return $this->UnixTimeStamp(reset($rs->fields));
+ }
+
+ return false;
+ }
+
+ /**
+ * Multiple modes of connection are supported:
+ *
+ * a. Local Database
+ * $conn->Connect(false,'scott','tiger');
+ *
+ * b. From tnsnames.ora
+ * $conn->Connect($tnsname,'scott','tiger');
+ * $conn->Connect(false,'scott','tiger',$tnsname);
+ *
+ * c. Server + service name
+ * $conn->Connect($serveraddress,'scott,'tiger',$service_name);
+ *
+ * d. Server + SID
+ * $conn->connectSID = true;
+ * $conn->Connect($serveraddress,'scott,'tiger',$SID);
+ *
+ * @param string|false $argHostname DB server hostname or TNS name
+ * @param string $argUsername
+ * @param string $argPassword
+ * @param string $argDatabasename Service name, SID (defaults to null)
+ * @param int $mode Connection mode, defaults to 0
+ * (0 = non-persistent, 1 = persistent, 2 = force new connection)
+ *
+ * @return bool
+ */
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename=null, $mode=0)
+ {
+ if (!function_exists('oci_pconnect')) {
+ return null;
+ }
+ #adodb_backtrace();
+
+ $this->_errorMsg = false;
+ $this->_errorCode = false;
+
+ if($argHostname) { // added by Jorma Tuomainen <jorma.tuomainen@ppoy.fi>
+ if (empty($argDatabasename)) {
+ $argDatabasename = $argHostname;
+ }
+ else {
+ if(strpos($argHostname,":")) {
+ $argHostinfo=explode(":",$argHostname);
+ $argHostname=$argHostinfo[0];
+ $argHostport=$argHostinfo[1];
+ } else {
+ $argHostport = empty($this->port)? "1521" : $this->port;
+ }
+
+ if (strncasecmp($argDatabasename,'SID=',4) == 0) {
+ $argDatabasename = substr($argDatabasename,4);
+ $this->connectSID = true;
+ }
+
+ if ($this->connectSID) {
+ $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
+ .")(PORT=$argHostport))(CONNECT_DATA=(SID=$argDatabasename)))";
+ } else
+ $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
+ .")(PORT=$argHostport))(CONNECT_DATA=(SERVICE_NAME=$argDatabasename)))";
+ }
+ }
+
+ //if ($argHostname) print "<p>Connect: 1st argument should be left blank for $this->databaseType</p>";
+ if ($mode==1) {
+ $this->_connectionID = ($this->charSet)
+ ? oci_pconnect($argUsername,$argPassword, $argDatabasename,$this->charSet)
+ : oci_pconnect($argUsername,$argPassword, $argDatabasename);
+ if ($this->_connectionID && $this->autoRollback) {
+ oci_rollback($this->_connectionID);
+ }
+ } else if ($mode==2) {
+ $this->_connectionID = ($this->charSet)
+ ? oci_new_connect($argUsername,$argPassword, $argDatabasename,$this->charSet)
+ : oci_new_connect($argUsername,$argPassword, $argDatabasename);
+ } else {
+ $this->_connectionID = ($this->charSet)
+ ? oci_connect($argUsername,$argPassword, $argDatabasename,$this->charSet)
+ : oci_connect($argUsername,$argPassword, $argDatabasename);
+ }
+ if (!$this->_connectionID) {
+ return false;
+ }
+
+ if ($this->_initdate) {
+ $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='".$this->NLS_DATE_FORMAT."'");
+ }
+
+ // looks like:
+ // Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production With the Partitioning option JServer Release 8.1.7.0.0 - Production
+ // $vers = oci_server_version($this->_connectionID);
+ // if (strpos($vers,'8i') !== false) $this->ansiOuter = true;
+ return true;
+ }
+
+ function ServerInfo()
+ {
+ $arr['compat'] = $this->GetOne('select value from sys.database_compatible_level');
+ $arr['description'] = @oci_server_version($this->_connectionID);
+ $arr['version'] = ADOConnection::_findvers($arr['description']);
+ return $arr;
+ }
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,1);
+ }
+
+ // returns true or false
+ function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,2);
+ }
+
+ function _affectedrows()
+ {
+ if (is_resource($this->_stmt)) {
+ return @oci_num_rows($this->_stmt);
+ }
+ return 0;
+ }
+
+ function IfNull( $field, $ifNull )
+ {
+ return " NVL($field, $ifNull) "; // if Oracle
+ }
+
+ // format and return date string in database date format
+ function DBDate($d,$isfld=false)
+ {
+ if (empty($d) && $d !== 0) {
+ return 'null';
+ }
+
+ if ($isfld) {
+ $d = _adodb_safedate($d);
+ return 'TO_DATE('.$d.",'".$this->dateformat."')";
+ }
+
+ if (is_string($d)) {
+ $d = ADORecordSet::UnixDate($d);
+ }
+
+ if (is_object($d)) {
+ $ds = $d->format($this->fmtDate);
+ }
+ else {
+ $ds = adodb_date($this->fmtDate,$d);
+ }
+
+ return "TO_DATE(".$ds.",'".$this->dateformat."')";
+ }
+
+ function BindDate($d)
+ {
+ $d = ADOConnection::DBDate($d);
+ if (strncmp($d, "'", 1)) {
+ return $d;
+ }
+
+ return substr($d, 1, strlen($d)-2);
+ }
+
+ function BindTimeStamp($ts)
+ {
+ if (empty($ts) && $ts !== 0) {
+ return 'null';
+ }
+ if (is_string($ts)) {
+ $ts = ADORecordSet::UnixTimeStamp($ts);
+ }
+
+ if (is_object($ts)) {
+ $tss = $ts->format("'Y-m-d H:i:s'");
+ }
+ else {
+ $tss = adodb_date("'Y-m-d H:i:s'",$ts);
+ }
+
+ return $tss;
+ }
+
+ // format and return date string in database timestamp format
+ function DBTimeStamp($ts,$isfld=false)
+ {
+ if (empty($ts) && $ts !== 0) {
+ return 'null';
+ }
+ if ($isfld) {
+ return 'TO_DATE(substr('.$ts.",1,19),'RRRR-MM-DD, HH24:MI:SS')";
+ }
+ if (is_string($ts)) {
+ $ts = ADORecordSet::UnixTimeStamp($ts);
+ }
+
+ if (is_object($ts)) {
+ $tss = $ts->format("'Y-m-d H:i:s'");
+ }
+ else {
+ $tss = date("'Y-m-d H:i:s'",$ts);
+ }
+
+ return 'TO_DATE('.$tss.",'RRRR-MM-DD, HH24:MI:SS')";
+ }
+
+ function RowLock($tables,$where,$col='1 as adodbignore')
+ {
+ if ($this->autoCommit) {
+ $this->BeginTrans();
+ }
+ return $this->GetOne("select $col from $tables where $where for update");
+ }
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ if ($mask) {
+ $save = $this->metaTablesSQL;
+ $mask = $this->qstr(strtoupper($mask));
+ $this->metaTablesSQL .= " AND upper(table_name) like $mask";
+ }
+ $ret = ADOConnection::MetaTables($ttype,$showSchema);
+
+ if ($mask) {
+ $this->metaTablesSQL = $save;
+ }
+ return $ret;
+ }
+
+ // Mark Newnham
+ function MetaIndexes ($table, $primary = FALSE, $owner=false)
+ {
+ // save old fetch mode
+ global $ADODB_FETCH_MODE;
+
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+
+ // get index details
+ $table = strtoupper($table);
+
+ // get Primary index
+ $primary_key = '';
+
+ $rs = $this->Execute(sprintf("SELECT * FROM ALL_CONSTRAINTS WHERE UPPER(TABLE_NAME)='%s' AND CONSTRAINT_TYPE='P'",$table));
+ if (!is_object($rs)) {
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+ return false;
+ }
+
+ if ($row = $rs->FetchRow()) {
+ $primary_key = $row[1]; //constraint_name
+ }
+
+ if ($primary==TRUE && $primary_key=='') {
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+ return false; //There is no primary key
+ }
+
+ $rs = $this->Execute(sprintf("SELECT ALL_INDEXES.INDEX_NAME, ALL_INDEXES.UNIQUENESS, ALL_IND_COLUMNS.COLUMN_POSITION, ALL_IND_COLUMNS.COLUMN_NAME FROM ALL_INDEXES,ALL_IND_COLUMNS WHERE UPPER(ALL_INDEXES.TABLE_NAME)='%s' AND ALL_IND_COLUMNS.INDEX_NAME=ALL_INDEXES.INDEX_NAME",$table));
+
+
+ if (!is_object($rs)) {
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+ return false;
+ }
+
+ $indexes = array ();
+ // parse index data into array
+
+ while ($row = $rs->FetchRow()) {
+ if ($primary && $row[0] != $primary_key) {
+ continue;
+ }
+ if (!isset($indexes[$row[0]])) {
+ $indexes[$row[0]] = array(
+ 'unique' => ($row[1] == 'UNIQUE'),
+ 'columns' => array()
+ );
+ }
+ $indexes[$row[0]]['columns'][$row[2] - 1] = $row[3];
+ }
+
+ // sort columns by order in the index
+ foreach ( array_keys ($indexes) as $index ) {
+ ksort ($indexes[$index]['columns']);
+ }
+
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ }
+ return $indexes;
+ }
+
+ function BeginTrans()
+ {
+ if ($this->transOff) {
+ return true;
+ }
+ $this->transCnt += 1;
+ $this->autoCommit = false;
+ $this->_commit = OCI_DEFAULT;
+
+ if ($this->_transmode) {
+ $ok = $this->Execute("SET TRANSACTION ".$this->_transmode);
+ }
+ else {
+ $ok = true;
+ }
+
+ return $ok ? true : false;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) {
+ return true;
+ }
+ if (!$ok) {
+ return $this->RollbackTrans();
+ }
+
+ if ($this->transCnt) {
+ $this->transCnt -= 1;
+ }
+ $ret = oci_commit($this->_connectionID);
+ $this->_commit = OCI_COMMIT_ON_SUCCESS;
+ $this->autoCommit = true;
+ return $ret;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) {
+ return true;
+ }
+ if ($this->transCnt) {
+ $this->transCnt -= 1;
+ }
+ $ret = oci_rollback($this->_connectionID);
+ $this->_commit = OCI_COMMIT_ON_SUCCESS;
+ $this->autoCommit = true;
+ return $ret;
+ }
+
+
+ function SelectDB($dbName)
+ {
+ return false;
+ }
+
+ function ErrorMsg()
+ {
+ if ($this->_errorMsg !== false) {
+ return $this->_errorMsg;
+ }
+
+ if (is_resource($this->_stmt)) {
+ $arr = @oci_error($this->_stmt);
+ }
+ if (empty($arr)) {
+ if (is_resource($this->_connectionID)) {
+ $arr = @oci_error($this->_connectionID);
+ }
+ else {
+ $arr = @oci_error();
+ }
+ if ($arr === false) {
+ return '';
+ }
+ }
+ $this->_errorMsg = $arr['message'];
+ $this->_errorCode = $arr['code'];
+ return $this->_errorMsg;
+ }
+
+ function ErrorNo()
+ {
+ if ($this->_errorCode !== false) {
+ return $this->_errorCode;
+ }
+
+ if (is_resource($this->_stmt)) {
+ $arr = @oci_error($this->_stmt);
+ }
+ if (empty($arr)) {
+ $arr = @oci_error($this->_connectionID);
+ if ($arr == false) {
+ $arr = @oci_error();
+ }
+ if ($arr == false) {
+ return '';
+ }
+ }
+
+ $this->_errorMsg = $arr['message'];
+ $this->_errorCode = $arr['code'];
+
+ return $arr['code'];
+ }
+
+ /**
+ * Format date column in sql string given an input format that understands Y M D
+ */
+ function SQLDate($fmt, $col=false)
+ {
+ if (!$col) {
+ $col = $this->sysTimeStamp;
+ }
+ $s = 'TO_CHAR('.$col.",'";
+
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ $ch = $fmt[$i];
+ switch($ch) {
+ case 'Y':
+ case 'y':
+ $s .= 'YYYY';
+ break;
+ case 'Q':
+ case 'q':
+ $s .= 'Q';
+ break;
+
+ case 'M':
+ $s .= 'Mon';
+ break;
+
+ case 'm':
+ $s .= 'MM';
+ break;
+ case 'D':
+ case 'd':
+ $s .= 'DD';
+ break;
+
+ case 'H':
+ $s.= 'HH24';
+ break;
+
+ case 'h':
+ $s .= 'HH';
+ break;
+
+ case 'i':
+ $s .= 'MI';
+ break;
+
+ case 's':
+ $s .= 'SS';
+ break;
+
+ case 'a':
+ case 'A':
+ $s .= 'AM';
+ break;
+
+ case 'w':
+ $s .= 'D';
+ break;
+
+ case 'l':
+ $s .= 'DAY';
+ break;
+
+ case 'W':
+ $s .= 'WW';
+ break;
+
+ default:
+ // handle escape characters...
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ if (strpos('-/.:;, ',$ch) !== false) {
+ $s .= $ch;
+ }
+ else {
+ $s .= '"'.$ch.'"';
+ }
+
+ }
+ }
+ return $s. "')";
+ }
+
+ function GetRandRow($sql, $arr = false)
+ {
+ $sql = "SELECT * FROM ($sql ORDER BY dbms_random.value) WHERE rownum = 1";
+
+ return $this->GetRow($sql,$arr);
+ }
+
+ /**
+ * This algorithm makes use of
+ *
+ * a. FIRST_ROWS hint
+ * The FIRST_ROWS hint explicitly chooses the approach to optimize response
+ * time, that is, minimum resource usage to return the first row. Results
+ * will be returned as soon as they are identified.
+ *
+ * b. Uses rownum tricks to obtain only the required rows from a given offset.
+ * As this uses complicated sql statements, we only use this if $offset >= 100.
+ * This idea by Tomas V V Cox.
+ *
+ * This implementation does not appear to work with oracle 8.0.5 or earlier.
+ * Comment out this function then, and the slower SelectLimit() in the base
+ * class will be used.
+ *
+ * Note: FIRST_ROWS hinting is only used if $sql is a string; when
+ * processing a prepared statement's handle, no hinting is performed.
+ */
+ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ // Since the methods used to limit the number of returned rows rely
+ // on modifying the provided SQL query, we can't work with prepared
+ // statements so we just extract the SQL string.
+ if(is_array($sql)) {
+ $sql = $sql[0];
+ }
+
+ // seems that oracle only supports 1 hint comment in 8i
+ if ($this->firstrows) {
+ if ($nrows > 500 && $nrows < 1000) {
+ $hint = "FIRST_ROWS($nrows)";
+ }
+ else {
+ $hint = 'FIRST_ROWS';
+ }
+
+ if (strpos($sql,'/*+') !== false) {
+ $sql = str_replace('/*+ ',"/*+$hint ",$sql);
+ }
+ else {
+ $sql = preg_replace('/^[ \t\n]*select/i',"SELECT /*+$hint*/",$sql);
+ }
+ $hint = "/*+ $hint */";
+ } else {
+ $hint = '';
+ }
+
+ if ($offset == -1 || ($offset < $this->selectOffsetAlg1 && 0 < $nrows && $nrows < 1000)) {
+ if ($nrows > 0) {
+ if ($offset > 0) {
+ $nrows += $offset;
+ }
+ $sql = "select * from (".$sql.") where rownum <= :adodb_offset";
+ $inputarr['adodb_offset'] = $nrows;
+ $nrows = -1;
+ }
+ // note that $nrows = 0 still has to work ==> no rows returned
+
+ return ADOConnection::SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
+ } else {
+ // Algorithm by Tomas V V Cox, from PEAR DB oci8.php
+
+ // Let Oracle return the name of the columns
+ $q_fields = "SELECT * FROM (".$sql.") WHERE NULL = NULL";
+
+ if (! $stmt_arr = $this->Prepare($q_fields)) {
+ return false;
+ }
+ $stmt = $stmt_arr[1];
+
+ if (is_array($inputarr)) {
+ foreach($inputarr as $k => $v) {
+ $i=0;
+ if ($this->databaseType == 'oci8po') {
+ $bv_name = ":".$i++;
+ } else {
+ $bv_name = ":".$k;
+ }
+ if (is_array($v)) {
+ // suggested by g.giunta@libero.
+ if (sizeof($v) == 2) {
+ oci_bind_by_name($stmt,$bv_name,$inputarr[$k][0],$v[1]);
+ }
+ else {
+ oci_bind_by_name($stmt,$bv_name,$inputarr[$k][0],$v[1],$v[2]);
+ }
+ } else {
+ $len = -1;
+ if ($v === ' ') {
+ $len = 1;
+ }
+ if (isset($bindarr)) { // is prepared sql, so no need to oci_bind_by_name again
+ $bindarr[$k] = $v;
+ } else { // dynamic sql, so rebind every time
+ oci_bind_by_name($stmt,$bv_name,$inputarr[$k],$len);
+ }
+ }
+ }
+ }
+
+ if (!oci_execute($stmt, OCI_DEFAULT)) {
+ oci_free_statement($stmt);
+ return false;
+ }
+
+ $ncols = oci_num_fields($stmt);
+ for ( $i = 1; $i <= $ncols; $i++ ) {
+ $cols[] = '"'.oci_field_name($stmt, $i).'"';
+ }
+ $result = false;
+
+ oci_free_statement($stmt);
+ $fields = implode(',', $cols);
+ if ($nrows <= 0) {
+ $nrows = 999999999999;
+ }
+ else {
+ $nrows += $offset;
+ }
+ $offset += 1; // in Oracle rownum starts at 1
+
+ $sql = "SELECT $hint $fields FROM".
+ "(SELECT rownum as adodb_rownum, $fields FROM".
+ " ($sql) WHERE rownum <= :adodb_nrows".
+ ") WHERE adodb_rownum >= :adodb_offset";
+ $inputarr['adodb_nrows'] = $nrows;
+ $inputarr['adodb_offset'] = $offset;
+
+ if ($secs2cache > 0) {
+ $rs = $this->CacheExecute($secs2cache, $sql,$inputarr);
+ }
+ else {
+ $rs = $this->Execute($sql, $inputarr);
+ }
+ return $rs;
+ }
+ }
+
+ /**
+ * Usage:
+ * Store BLOBs and CLOBs
+ *
+ * Example: to store $var in a blob
+ * $conn->Execute('insert into TABLE (id,ablob) values(12,empty_blob())');
+ * $conn->UpdateBlob('TABLE', 'ablob', $varHoldingBlob, 'ID=12', 'BLOB');
+ *
+ * $blobtype supports 'BLOB' and 'CLOB', but you need to change to 'empty_clob()'.
+ *
+ * to get length of LOB:
+ * select DBMS_LOB.GETLENGTH(ablob) from TABLE
+ *
+ * If you are using CURSOR_SHARING = force, it appears this will case a segfault
+ * under oracle 8.1.7.0. Run:
+ * $db->Execute('ALTER SESSION SET CURSOR_SHARING=EXACT');
+ * before UpdateBlob() then...
+ */
+ function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ {
+
+ //if (strlen($val) < 4000) return $this->Execute("UPDATE $table SET $column=:blob WHERE $where",array('blob'=>$val)) != false;
+
+ switch(strtoupper($blobtype)) {
+ default: ADOConnection::outp("<b>UpdateBlob</b>: Unknown blobtype=$blobtype"); return false;
+ case 'BLOB': $type = OCI_B_BLOB; break;
+ case 'CLOB': $type = OCI_B_CLOB; break;
+ }
+
+ if ($this->databaseType == 'oci8po')
+ $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?";
+ else
+ $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob";
+
+ $desc = oci_new_descriptor($this->_connectionID, OCI_D_LOB);
+ $arr['blob'] = array($desc,-1,$type);
+ if ($this->session_sharing_force_blob) {
+ $this->Execute('ALTER SESSION SET CURSOR_SHARING=EXACT');
+ }
+ $commit = $this->autoCommit;
+ if ($commit) {
+ $this->BeginTrans();
+ }
+ $rs = $this->_Execute($sql,$arr);
+ if ($rez = !empty($rs)) {
+ $desc->save($val);
+ }
+ $desc->free();
+ if ($commit) {
+ $this->CommitTrans();
+ }
+ if ($this->session_sharing_force_blob) {
+ $this->Execute('ALTER SESSION SET CURSOR_SHARING=FORCE');
+ }
+
+ if ($rez) {
+ $rs->Close();
+ }
+ return $rez;
+ }
+
+ /**
+ * Usage: store file pointed to by $val in a blob
+ */
+ function UpdateBlobFile($table,$column,$val,$where,$blobtype='BLOB')
+ {
+ switch(strtoupper($blobtype)) {
+ default: ADOConnection::outp( "<b>UpdateBlob</b>: Unknown blobtype=$blobtype"); return false;
+ case 'BLOB': $type = OCI_B_BLOB; break;
+ case 'CLOB': $type = OCI_B_CLOB; break;
+ }
+
+ if ($this->databaseType == 'oci8po')
+ $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?";
+ else
+ $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob";
+
+ $desc = oci_new_descriptor($this->_connectionID, OCI_D_LOB);
+ $arr['blob'] = array($desc,-1,$type);
+
+ $this->BeginTrans();
+ $rs = ADODB_oci8::Execute($sql,$arr);
+ if ($rez = !empty($rs)) {
+ $desc->savefile($val);
+ }
+ $desc->free();
+ $this->CommitTrans();
+
+ if ($rez) {
+ $rs->Close();
+ }
+ return $rez;
+ }
+
+ /**
+ * Execute SQL
+ *
+ * @param sql SQL statement to execute, or possibly an array holding prepared statement ($sql[0] will hold sql text)
+ * @param [inputarr] holds the input data to bind to. Null elements will be set to null.
+ * @return RecordSet or false
+ */
+ function Execute($sql,$inputarr=false)
+ {
+ if ($this->fnExecute) {
+ $fn = $this->fnExecute;
+ $ret = $fn($this,$sql,$inputarr);
+ if (isset($ret)) {
+ return $ret;
+ }
+ }
+ if ($inputarr !== false) {
+ if (!is_array($inputarr)) {
+ $inputarr = array($inputarr);
+ }
+
+ $element0 = reset($inputarr);
+ $array2d = $this->bulkBind && is_array($element0) && !is_object(reset($element0));
+
+ # see http://phplens.com/lens/lensforum/msgs.php?id=18786
+ if ($array2d || !$this->_bindInputArray) {
+
+ # is_object check because oci8 descriptors can be passed in
+ if ($array2d && $this->_bindInputArray) {
+ if (is_string($sql)) {
+ $stmt = $this->Prepare($sql);
+ } else {
+ $stmt = $sql;
+ }
+
+ foreach($inputarr as $arr) {
+ $ret = $this->_Execute($stmt,$arr);
+ if (!$ret) {
+ return $ret;
+ }
+ }
+ return $ret;
+ } else {
+ $sqlarr = explode(':', $sql);
+ $sql = '';
+ $lastnomatch = -2;
+ #var_dump($sqlarr);echo "<hr>";var_dump($inputarr);echo"<hr>";
+ foreach($sqlarr as $k => $str) {
+ if ($k == 0) {
+ $sql = $str;
+ continue;
+ }
+ // we need $lastnomatch because of the following datetime,
+ // eg. '10:10:01', which causes code to think that there is bind param :10 and :1
+ $ok = preg_match('/^([0-9]*)/', $str, $arr);
+
+ if (!$ok) {
+ $sql .= $str;
+ } else {
+ $at = $arr[1];
+ if (isset($inputarr[$at]) || is_null($inputarr[$at])) {
+ if ((strlen($at) == strlen($str) && $k < sizeof($arr)-1)) {
+ $sql .= ':'.$str;
+ $lastnomatch = $k;
+ } else if ($lastnomatch == $k-1) {
+ $sql .= ':'.$str;
+ } else {
+ if (is_null($inputarr[$at])) {
+ $sql .= 'null';
+ }
+ else {
+ $sql .= $this->qstr($inputarr[$at]);
+ }
+ $sql .= substr($str, strlen($at));
+ }
+ } else {
+ $sql .= ':'.$str;
+ }
+ }
+ }
+ $inputarr = false;
+ }
+ }
+ $ret = $this->_Execute($sql,$inputarr);
+
+ } else {
+ $ret = $this->_Execute($sql,false);
+ }
+
+ return $ret;
+ }
+
+ /*
+ * Example of usage:
+ * $stmt = $this->Prepare('insert into emp (empno, ename) values (:empno, :ename)');
+ */
+ function Prepare($sql,$cursor=false)
+ {
+ static $BINDNUM = 0;
+
+ $stmt = oci_parse($this->_connectionID,$sql);
+
+ if (!$stmt) {
+ $this->_errorMsg = false;
+ $this->_errorCode = false;
+ $arr = @oci_error($this->_connectionID);
+ if ($arr === false) {
+ return false;
+ }
+
+ $this->_errorMsg = $arr['message'];
+ $this->_errorCode = $arr['code'];
+ return false;
+ }
+
+ $BINDNUM += 1;
+
+ $sttype = @oci_statement_type($stmt);
+ if ($sttype == 'BEGIN' || $sttype == 'DECLARE') {
+ return array($sql,$stmt,0,$BINDNUM, ($cursor) ? oci_new_cursor($this->_connectionID) : false);
+ }
+ return array($sql,$stmt,0,$BINDNUM);
+ }
+
+ /*
+ Call an oracle stored procedure and returns a cursor variable as a recordset.
+ Concept by Robert Tuttle robert@ud.com
+
+ Example:
+ Note: we return a cursor variable in :RS2
+ $rs = $db->ExecuteCursor("BEGIN adodb.open_tab(:RS2); END;",'RS2');
+
+ $rs = $db->ExecuteCursor(
+ "BEGIN :RS2 = adodb.getdata(:VAR1); END;",
+ 'RS2',
+ array('VAR1' => 'Mr Bean'));
+
+ */
+ function ExecuteCursor($sql,$cursorName='rs',$params=false)
+ {
+ if (is_array($sql)) {
+ $stmt = $sql;
+ }
+ else $stmt = ADODB_oci8::Prepare($sql,true); # true to allocate oci_new_cursor
+
+ if (is_array($stmt) && sizeof($stmt) >= 5) {
+ $hasref = true;
+ $ignoreCur = false;
+ $this->Parameter($stmt, $ignoreCur, $cursorName, false, -1, OCI_B_CURSOR);
+ if ($params) {
+ foreach($params as $k => $v) {
+ $this->Parameter($stmt,$params[$k], $k);
+ }
+ }
+ } else
+ $hasref = false;
+
+ $rs = $this->Execute($stmt);
+ if ($rs) {
+ if ($rs->databaseType == 'array') {
+ oci_free_cursor($stmt[4]);
+ }
+ elseif ($hasref) {
+ $rs->_refcursor = $stmt[4];
+ }
+ }
+ return $rs;
+ }
+
+ /**
+ * Bind a variable -- very, very fast for executing repeated statements in oracle.
+ *
+ * Better than using
+ * for ($i = 0; $i < $max; $i++) {
+ * $p1 = ?; $p2 = ?; $p3 = ?;
+ * $this->Execute("insert into table (col0, col1, col2) values (:0, :1, :2)", array($p1,$p2,$p3));
+ * }
+ *
+ * Usage:
+ * $stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:0, :1, :2)");
+ * $DB->Bind($stmt, $p1);
+ * $DB->Bind($stmt, $p2);
+ * $DB->Bind($stmt, $p3);
+ * for ($i = 0; $i < $max; $i++) {
+ * $p1 = ?; $p2 = ?; $p3 = ?;
+ * $DB->Execute($stmt);
+ * }
+ *
+ * Some timings to insert 1000 records, test table has 3 cols, and 1 index.
+ * - Time 0.6081s (1644.60 inserts/sec) with direct oci_parse/oci_execute
+ * - Time 0.6341s (1577.16 inserts/sec) with ADOdb Prepare/Bind/Execute
+ * - Time 1.5533s ( 643.77 inserts/sec) with pure SQL using Execute
+ *
+ * Now if PHP only had batch/bulk updating like Java or PL/SQL...
+ *
+ * Note that the order of parameters differs from oci_bind_by_name,
+ * because we default the names to :0, :1, :2
+ */
+ function Bind(&$stmt,&$var,$size=4000,$type=false,$name=false,$isOutput=false)
+ {
+
+ if (!is_array($stmt)) {
+ return false;
+ }
+
+ if (($type == OCI_B_CURSOR) && sizeof($stmt) >= 5) {
+ return oci_bind_by_name($stmt[1],":".$name,$stmt[4],$size,$type);
+ }
+
+ if ($name == false) {
+ if ($type !== false) {
+ $rez = oci_bind_by_name($stmt[1],":".$stmt[2],$var,$size,$type);
+ }
+ else {
+ $rez = oci_bind_by_name($stmt[1],":".$stmt[2],$var,$size); // +1 byte for null terminator
+ }
+ $stmt[2] += 1;
+ } else if (oci_lob_desc($type)) {
+ if ($this->debug) {
+ ADOConnection::outp("<b>Bind</b>: name = $name");
+ }
+ //we have to create a new Descriptor here
+ $numlob = count($this->_refLOBs);
+ $this->_refLOBs[$numlob]['LOB'] = oci_new_descriptor($this->_connectionID, oci_lob_desc($type));
+ $this->_refLOBs[$numlob]['TYPE'] = $isOutput;
+
+ $tmp = $this->_refLOBs[$numlob]['LOB'];
+ $rez = oci_bind_by_name($stmt[1], ":".$name, $tmp, -1, $type);
+ if ($this->debug) {
+ ADOConnection::outp("<b>Bind</b>: descriptor has been allocated, var (".$name.") binded");
+ }
+
+ // if type is input then write data to lob now
+ if ($isOutput == false) {
+ $var = $this->BlobEncode($var);
+ $tmp->WriteTemporary($var);
+ $this->_refLOBs[$numlob]['VAR'] = &$var;
+ if ($this->debug) {
+ ADOConnection::outp("<b>Bind</b>: LOB has been written to temp");
+ }
+ } else {
+ $this->_refLOBs[$numlob]['VAR'] = &$var;
+ }
+ $rez = $tmp;
+ } else {
+ if ($this->debug)
+ ADOConnection::outp("<b>Bind</b>: name = $name");
+
+ if ($type !== false) {
+ $rez = oci_bind_by_name($stmt[1],":".$name,$var,$size,$type);
+ }
+ else {
+ $rez = oci_bind_by_name($stmt[1],":".$name,$var,$size); // +1 byte for null terminator
+ }
+ }
+
+ return $rez;
+ }
+
+ function Param($name,$type='C')
+ {
+ return ':'.$name;
+ }
+
+ /**
+ * Usage:
+ * $stmt = $db->Prepare('select * from table where id =:myid and group=:group');
+ * $db->Parameter($stmt,$id,'myid');
+ * $db->Parameter($stmt,$group,'group');
+ * $db->Execute($stmt);
+ *
+ * @param $stmt Statement returned by Prepare() or PrepareSP().
+ * @param $var PHP variable to bind to
+ * @param $name Name of stored procedure variable name to bind to.
+ * @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8.
+ * @param [$maxLen] Holds an maximum length of the variable.
+ * @param [$type] The data type of $var. Legal values depend on driver.
+ *
+ * @link http://php.net/oci_bind_by_name
+ */
+ function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false)
+ {
+ if ($this->debug) {
+ $prefix = ($isOutput) ? 'Out' : 'In';
+ $ztype = (empty($type)) ? 'false' : $type;
+ ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
+ }
+ return $this->Bind($stmt,$var,$maxLen,$type,$name,$isOutput);
+ }
+
+ /**
+ * returns query ID if successful, otherwise false
+ * this version supports:
+ *
+ * 1. $db->execute('select * from table');
+ *
+ * 2. $db->prepare('insert into table (a,b,c) values (:0,:1,:2)');
+ * $db->execute($prepared_statement, array(1,2,3));
+ *
+ * 3. $db->execute('insert into table (a,b,c) values (:a,:b,:c)',array('a'=>1,'b'=>2,'c'=>3));
+ *
+ * 4. $db->prepare('insert into table (a,b,c) values (:0,:1,:2)');
+ * $db->bind($stmt,1); $db->bind($stmt,2); $db->bind($stmt,3);
+ * $db->execute($stmt);
+ */
+ function _query($sql,$inputarr=false)
+ {
+ if (is_array($sql)) { // is prepared sql
+ $stmt = $sql[1];
+
+ // we try to bind to permanent array, so that oci_bind_by_name is persistent
+ // and carried out once only - note that max array element size is 4000 chars
+ if (is_array($inputarr)) {
+ $bindpos = $sql[3];
+ if (isset($this->_bind[$bindpos])) {
+ // all tied up already
+ $bindarr = $this->_bind[$bindpos];
+ } else {
+ // one statement to bind them all
+ $bindarr = array();
+ foreach($inputarr as $k => $v) {
+ $bindarr[$k] = $v;
+ oci_bind_by_name($stmt,":$k",$bindarr[$k],is_string($v) && strlen($v)>4000 ? -1 : 4000);
+ }
+ $this->_bind[$bindpos] = $bindarr;
+ }
+ }
+ } else {
+ $stmt=oci_parse($this->_connectionID,$sql);
+ }
+
+ $this->_stmt = $stmt;
+ if (!$stmt) {
+ return false;
+ }
+
+ if (defined('ADODB_PREFETCH_ROWS')) {
+ @oci_set_prefetch($stmt,ADODB_PREFETCH_ROWS);
+ }
+
+ if (is_array($inputarr)) {
+ foreach($inputarr as $k => $v) {
+ if (is_array($v)) {
+ // suggested by g.giunta@libero.
+ if (sizeof($v) == 2) {
+ oci_bind_by_name($stmt,":$k",$inputarr[$k][0],$v[1]);
+ }
+ else {
+ oci_bind_by_name($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]);
+ }
+
+ if ($this->debug==99) {
+ if (is_object($v[0])) {
+ echo "name=:$k",' len='.$v[1],' type='.$v[2],'<br>';
+ }
+ else {
+ echo "name=:$k",' var='.$inputarr[$k][0],' len='.$v[1],' type='.$v[2],'<br>';
+ }
+
+ }
+ } else {
+ $len = -1;
+ if ($v === ' ') {
+ $len = 1;
+ }
+ if (isset($bindarr)) { // is prepared sql, so no need to oci_bind_by_name again
+ $bindarr[$k] = $v;
+ } else { // dynamic sql, so rebind every time
+ oci_bind_by_name($stmt,":$k",$inputarr[$k],$len);
+ }
+ }
+ }
+ }
+
+ $this->_errorMsg = false;
+ $this->_errorCode = false;
+ if (oci_execute($stmt,$this->_commit)) {
+
+ if (count($this -> _refLOBs) > 0) {
+
+ foreach ($this -> _refLOBs as $key => $value) {
+ if ($this -> _refLOBs[$key]['TYPE'] == true) {
+ $tmp = $this -> _refLOBs[$key]['LOB'] -> load();
+ if ($this -> debug) {
+ ADOConnection::outp("<b>OUT LOB</b>: LOB has been loaded. <br>");
+ }
+ //$_GLOBALS[$this -> _refLOBs[$key]['VAR']] = $tmp;
+ $this -> _refLOBs[$key]['VAR'] = $tmp;
+ } else {
+ $this->_refLOBs[$key]['LOB']->save($this->_refLOBs[$key]['VAR']);
+ $this -> _refLOBs[$key]['LOB']->free();
+ unset($this -> _refLOBs[$key]);
+ if ($this->debug) {
+ ADOConnection::outp("<b>IN LOB</b>: LOB has been saved. <br>");
+ }
+ }
+ }
+ }
+
+ switch (@oci_statement_type($stmt)) {
+ case "SELECT":
+ return $stmt;
+
+ case 'DECLARE':
+ case "BEGIN":
+ if (is_array($sql) && !empty($sql[4])) {
+ $cursor = $sql[4];
+ if (is_resource($cursor)) {
+ $ok = oci_execute($cursor);
+ return $cursor;
+ }
+ return $stmt;
+ } else {
+ if (is_resource($stmt)) {
+ oci_free_statement($stmt);
+ return true;
+ }
+ return $stmt;
+ }
+ break;
+ default :
+
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // From Oracle Whitepaper: PHP Scalability and High Availability
+ function IsConnectionError($err)
+ {
+ switch($err) {
+ case 378: /* buffer pool param incorrect */
+ case 602: /* core dump */
+ case 603: /* fatal error */
+ case 609: /* attach failed */
+ case 1012: /* not logged in */
+ case 1033: /* init or shutdown in progress */
+ case 1043: /* Oracle not available */
+ case 1089: /* immediate shutdown in progress */
+ case 1090: /* shutdown in progress */
+ case 1092: /* instance terminated */
+ case 3113: /* disconnect */
+ case 3114: /* not connected */
+ case 3122: /* closing window */
+ case 3135: /* lost contact */
+ case 12153: /* TNS: not connected */
+ case 27146: /* fatal or instance terminated */
+ case 28511: /* Lost RPC */
+ return true;
+ }
+ return false;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ if (!$this->_connectionID) {
+ return;
+ }
+
+
+ if (!$this->autoCommit) {
+ oci_rollback($this->_connectionID);
+ }
+ if (count($this->_refLOBs) > 0) {
+ foreach ($this ->_refLOBs as $key => $value) {
+ $this->_refLOBs[$key]['LOB']->free();
+ unset($this->_refLOBs[$key]);
+ }
+ }
+ oci_close($this->_connectionID);
+
+ $this->_stmt = false;
+ $this->_connectionID = false;
+ }
+
+ function MetaPrimaryKeys($table, $owner=false,$internalKey=false)
+ {
+ if ($internalKey) {
+ return array('ROWID');
+ }
+
+ // tested with oracle 8.1.7
+ $table = strtoupper($table);
+ if ($owner) {
+ $owner_clause = "AND ((a.OWNER = b.OWNER) AND (a.OWNER = UPPER('$owner')))";
+ $ptab = 'ALL_';
+ } else {
+ $owner_clause = '';
+ $ptab = 'USER_';
+ }
+ $sql = "
+SELECT /*+ RULE */ distinct b.column_name
+ FROM {$ptab}CONSTRAINTS a
+ , {$ptab}CONS_COLUMNS b
+ WHERE ( UPPER(b.table_name) = ('$table'))
+ AND (UPPER(a.table_name) = ('$table') and a.constraint_type = 'P')
+ $owner_clause
+ AND (a.constraint_name = b.constraint_name)";
+
+ $rs = $this->Execute($sql);
+ if ($rs && !$rs->EOF) {
+ $arr = $rs->GetArray();
+ $a = array();
+ foreach($arr as $v) {
+ $a[] = reset($v);
+ }
+ return $a;
+ }
+ else return false;
+ }
+
+ /**
+ * returns assoc array where keys are tables, and values are foreign keys
+ *
+ * @param str $table
+ * @param str $owner [optional][default=NULL]
+ * @param bool $upper [optional][discarded]
+ * @return mixed[] Array of foreign key information
+ *
+ * @link http://gis.mit.edu/classes/11.521/sqlnotes/referential_integrity.html
+ */
+ function MetaForeignKeys($table, $owner=false, $upper=false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $table = $this->qstr(strtoupper($table));
+ if (!$owner) {
+ $owner = $this->user;
+ $tabp = 'user_';
+ } else
+ $tabp = 'all_';
+
+ $owner = ' and owner='.$this->qstr(strtoupper($owner));
+
+ $sql =
+"select constraint_name,r_owner,r_constraint_name
+ from {$tabp}constraints
+ where constraint_type = 'R' and table_name = $table $owner";
+
+ $constraints = $this->GetArray($sql);
+ $arr = false;
+ foreach($constraints as $constr) {
+ $cons = $this->qstr($constr[0]);
+ $rowner = $this->qstr($constr[1]);
+ $rcons = $this->qstr($constr[2]);
+ $cols = $this->GetArray("select column_name from {$tabp}cons_columns where constraint_name=$cons $owner order by position");
+ $tabcol = $this->GetArray("select table_name,column_name from {$tabp}cons_columns where owner=$rowner and constraint_name=$rcons order by position");
+
+ if ($cols && $tabcol)
+ for ($i=0, $max=sizeof($cols); $i < $max; $i++) {
+ $arr[$tabcol[$i][0]] = $cols[$i][0].'='.$tabcol[$i][1];
+ }
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ return $arr;
+ }
+
+
+ function CharMax()
+ {
+ return 4000;
+ }
+
+ function TextMax()
+ {
+ return 4000;
+ }
+
+ /**
+ * Quotes a string.
+ * An example is $db->qstr("Don't bother",magic_quotes_runtime());
+ *
+ * @param string $s the string to quote
+ * @param bool $magic_quotes if $s is GET/POST var, set to get_magic_quotes_gpc().
+ * This undoes the stupidity of magic quotes for GPC.
+ *
+ * @return string quoted string to be sent back to database
+ */
+ function qstr($s,$magic_quotes=false)
+ {
+ //$nofixquotes=false;
+
+ if ($this->noNullStrings && strlen($s)==0) {
+ $s = ' ';
+ }
+ if (!$magic_quotes) {
+ if ($this->replaceQuote[0] == '\\'){
+ $s = str_replace('\\','\\\\',$s);
+ }
+ return "'".str_replace("'",$this->replaceQuote,$s)."'";
+ }
+
+ // undo magic quotes for " unless sybase is on
+ if (!ini_get('magic_quotes_sybase')) {
+ $s = str_replace('\\"','"',$s);
+ $s = str_replace('\\\\','\\',$s);
+ return "'".str_replace("\\'",$this->replaceQuote,$s)."'";
+ } else {
+ return "'".$s."'";
+ }
+ }
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordset_oci8 extends ADORecordSet {
+
+ var $databaseType = 'oci8';
+ var $bind=false;
+ var $_fieldobjs;
+
+ function __construct($queryID,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ switch ($mode) {
+ case ADODB_FETCH_ASSOC:
+ $this->fetchMode = OCI_ASSOC;
+ break;
+ case ADODB_FETCH_DEFAULT:
+ case ADODB_FETCH_BOTH:
+ $this->fetchMode = OCI_NUM + OCI_ASSOC;
+ break;
+ case ADODB_FETCH_NUM:
+ default:
+ $this->fetchMode = OCI_NUM;
+ break;
+ }
+ $this->fetchMode += OCI_RETURN_NULLS + OCI_RETURN_LOBS;
+ $this->adodbFetchMode = $mode;
+ $this->_queryID = $queryID;
+ }
+
+ /**
+ * Overrides the core destructor method as that causes problems here
+ *
+ * @return void
+ */
+ function __destruct() {}
+
+ function Init()
+ {
+ if ($this->_inited) {
+ return;
+ }
+
+ $this->_inited = true;
+ if ($this->_queryID) {
+
+ $this->_currentRow = 0;
+ @$this->_initrs();
+ if ($this->_numOfFields) {
+ $this->EOF = !$this->_fetch();
+ }
+ else $this->EOF = true;
+
+ /*
+ // based on idea by Gaetano Giunta to detect unusual oracle errors
+ // see http://phplens.com/lens/lensforum/msgs.php?id=6771
+ $err = oci_error($this->_queryID);
+ if ($err && $this->connection->debug) {
+ ADOConnection::outp($err);
+ }
+ */
+
+ if (!is_array($this->fields)) {
+ $this->_numOfRows = 0;
+ $this->fields = array();
+ }
+ } else {
+ $this->fields = array();
+ $this->_numOfRows = 0;
+ $this->_numOfFields = 0;
+ $this->EOF = true;
+ }
+ }
+
+ function _initrs()
+ {
+ $this->_numOfRows = -1;
+ $this->_numOfFields = oci_num_fields($this->_queryID);
+ if ($this->_numOfFields>0) {
+ $this->_fieldobjs = array();
+ $max = $this->_numOfFields;
+ for ($i=0;$i<$max; $i++) $this->_fieldobjs[] = $this->_FetchField($i);
+ }
+ }
+
+ /**
+ * Get column information in the Recordset object.
+ * fetchField() can be used in order to obtain information about fields
+ * in a certain query result. If the field offset isn't specified, the next
+ * field that wasn't yet retrieved by fetchField() is retrieved
+ *
+ * @return object containing field information
+ */
+ function _FetchField($fieldOffset = -1)
+ {
+ $fld = new ADOFieldObject;
+ $fieldOffset += 1;
+ $fld->name =oci_field_name($this->_queryID, $fieldOffset);
+ if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_LOWER) {
+ $fld->name = strtolower($fld->name);
+ }
+ $fld->type = oci_field_type($this->_queryID, $fieldOffset);
+ $fld->max_length = oci_field_size($this->_queryID, $fieldOffset);
+
+ switch($fld->type) {
+ case 'NUMBER':
+ $p = oci_field_precision($this->_queryID, $fieldOffset);
+ $sc = oci_field_scale($this->_queryID, $fieldOffset);
+ if ($p != 0 && $sc == 0) {
+ $fld->type = 'INT';
+ }
+ $fld->scale = $p;
+ break;
+
+ case 'CLOB':
+ case 'NCLOB':
+ case 'BLOB':
+ $fld->max_length = -1;
+ break;
+ }
+ return $fld;
+ }
+
+ /* For some reason, oci_field_name fails when called after _initrs() so we cache it */
+ function FetchField($fieldOffset = -1)
+ {
+ return $this->_fieldobjs[$fieldOffset];
+ }
+
+
+ function MoveNext()
+ {
+ if ($this->fields = @oci_fetch_array($this->_queryID,$this->fetchMode)) {
+ $this->_currentRow += 1;
+ $this->_updatefields();
+ return true;
+ }
+ if (!$this->EOF) {
+ $this->_currentRow += 1;
+ $this->EOF = true;
+ }
+ return false;
+ }
+
+ // Optimize SelectLimit() by using oci_fetch()
+ function GetArrayLimit($nrows,$offset=-1)
+ {
+ if ($offset <= 0) {
+ $arr = $this->GetArray($nrows);
+ return $arr;
+ }
+ $arr = array();
+ for ($i=1; $i < $offset; $i++) {
+ if (!@oci_fetch($this->_queryID)) {
+ return $arr;
+ }
+ }
+
+ if (!$this->fields = @oci_fetch_array($this->_queryID,$this->fetchMode)) {
+ return $arr;
+ }
+ $this->_updatefields();
+ $results = array();
+ $cnt = 0;
+ while (!$this->EOF && $nrows != $cnt) {
+ $results[$cnt++] = $this->fields;
+ $this->MoveNext();
+ }
+
+ return $results;
+ }
+
+
+ // Use associative array to get fields array
+ function Fields($colname)
+ {
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+
+ function _seek($row)
+ {
+ return false;
+ }
+
+ function _fetch()
+ {
+ $this->fields = @oci_fetch_array($this->_queryID,$this->fetchMode);
+ $this->_updatefields();
+
+ return $this->fields;
+ }
+
+ /**
+ * close() only needs to be called if you are worried about using too much
+ * memory while your script is running. All associated result memory for the
+ * specified result identifier will automatically be freed.
+ */
+ function _close()
+ {
+ if ($this->connection->_stmt === $this->_queryID) {
+ $this->connection->_stmt = false;
+ }
+ if (!empty($this->_refcursor)) {
+ oci_free_cursor($this->_refcursor);
+ $this->_refcursor = false;
+ }
+ @oci_free_statement($this->_queryID);
+ $this->_queryID = false;
+ }
+
+ /**
+ * not the fastest implementation - quick and dirty - jlim
+ * for best performance, use the actual $rs->MetaType().
+ *
+ * @param mixed $t
+ * @param int $len [optional] Length of blobsize
+ * @param bool $fieldobj [optional][discarded]
+ * @return str The metatype of the field
+ */
+ function MetaType($t, $len=-1, $fieldobj=false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+
+ switch (strtoupper($t)) {
+ case 'VARCHAR':
+ case 'VARCHAR2':
+ case 'CHAR':
+ case 'VARBINARY':
+ case 'BINARY':
+ case 'NCHAR':
+ case 'NVARCHAR':
+ case 'NVARCHAR2':
+ if ($len <= $this->blobSize) {
+ return 'C';
+ }
+
+ case 'NCLOB':
+ case 'LONG':
+ case 'LONG VARCHAR':
+ case 'CLOB':
+ return 'X';
+
+ case 'LONG RAW':
+ case 'LONG VARBINARY':
+ case 'BLOB':
+ return 'B';
+
+ case 'DATE':
+ return ($this->connection->datetime) ? 'T' : 'D';
+
+
+ case 'TIMESTAMP': return 'T';
+
+ case 'INT':
+ case 'SMALLINT':
+ case 'INTEGER':
+ return 'I';
+
+ default:
+ return 'N';
+ }
+ }
+}
+
+class ADORecordSet_ext_oci8 extends ADORecordSet_oci8 {
+ function __construct($queryID,$mode=false)
+ {
+ parent::__construct($queryID, $mode);
+ }
+
+ function MoveNext()
+ {
+ return adodb_movenext($this);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-oci805.inc.php b/vendor/adodb/adodb-php/drivers/adodb-oci805.inc.php
new file mode 100644
index 0000000..b729ab8
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-oci805.inc.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * @version v5.20.14 06-Jan-2019
+ * @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ * @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ * Released under both BSD license and Lesser GPL library license.
+ * Whenever there is any discrepancy between the two licenses,
+ * the BSD license will take precedence.
+ *
+ * Set tabs to 4 for best viewing.
+ *
+ * Latest version is available at http://adodb.org/
+ *
+ * Oracle 8.0.5 driver
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR.'/drivers/adodb-oci8.inc.php');
+
+class ADODB_oci805 extends ADODB_oci8 {
+ var $databaseType = "oci805";
+ var $connectSID = true;
+
+ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
+ {
+ // seems that oracle only supports 1 hint comment in 8i
+ if (strpos($sql,'/*+') !== false)
+ $sql = str_replace('/*+ ','/*+FIRST_ROWS ',$sql);
+ else
+ $sql = preg_replace('/^[ \t\n]*select/i','SELECT /*+FIRST_ROWS*/',$sql);
+
+ /*
+ The following is only available from 8.1.5 because order by in inline views not
+ available before then...
+ http://www.jlcomp.demon.co.uk/faq/top_sql.html
+ if ($nrows > 0) {
+ if ($offset > 0) $nrows += $offset;
+ $sql = "select * from ($sql) where rownum <= $nrows";
+ $nrows = -1;
+ }
+ */
+
+ return ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
+ }
+}
+
+class ADORecordset_oci805 extends ADORecordset_oci8 {
+ var $databaseType = "oci805";
+ function __construct($id,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-oci8po.inc.php b/vendor/adodb/adodb-php/drivers/adodb-oci8po.inc.php
new file mode 100644
index 0000000..7687760
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-oci8po.inc.php
@@ -0,0 +1,286 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim. All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+
+ Latest version is available at http://adodb.org/
+
+ Portable version of oci8 driver, to make it more similar to other database drivers.
+ The main differences are
+
+ 1. that the OCI_ASSOC names are in lowercase instead of uppercase.
+ 2. bind variables are mapped using ? instead of :<bindvar>
+
+ Should some emulation of RecordCount() be implemented?
+
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR.'/drivers/adodb-oci8.inc.php');
+
+class ADODB_oci8po extends ADODB_oci8 {
+ var $databaseType = 'oci8po';
+ var $dataProvider = 'oci8';
+ var $metaColumnsSQL = "select lower(cname),coltype,width, SCALE, PRECISION, NULLS, DEFAULTVAL from col where tname='%s' order by colno"; //changed by smondino@users.sourceforge. net
+ var $metaTablesSQL = "select lower(table_name),table_type from cat where table_type in ('TABLE','VIEW')";
+
+ function __construct()
+ {
+ $this->_hasOCIFetchStatement = ADODB_PHPVER >= 0x4200;
+ # oci8po does not support adodb extension: adodb_movenext()
+ }
+
+ function Param($name,$type='C')
+ {
+ return '?';
+ }
+
+ function Prepare($sql,$cursor=false)
+ {
+ $sqlarr = explode('?',$sql);
+ $sql = $sqlarr[0];
+ for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++) {
+ $sql .= ':'.($i-1) . $sqlarr[$i];
+ }
+ return ADODB_oci8::Prepare($sql,$cursor);
+ }
+
+ function Execute($sql,$inputarr=false)
+ {
+ return ADOConnection::Execute($sql,$inputarr);
+ }
+
+ /**
+ * The optimizations performed by ADODB_oci8::SelectLimit() are not
+ * compatible with the oci8po driver, so we rely on the slower method
+ * from the base class.
+ * We can't properly handle prepared statements either due to preprocessing
+ * of query parameters, so we treat them as regular SQL statements.
+ */
+ function SelectLimit($sql, $nrows=-1, $offset=-1, $inputarr=false, $secs2cache=0)
+ {
+ if(is_array($sql)) {
+// $sql = $sql[0];
+ }
+ return ADOConnection::SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
+ }
+
+ // emulate handling of parameters ? ?, replacing with :bind0 :bind1
+ function _query($sql,$inputarr=false)
+ {
+ if (is_array($inputarr)) {
+ $i = 0;
+ if (is_array($sql)) {
+ foreach($inputarr as $v) {
+ $arr['bind'.$i++] = $v;
+ }
+ } else {
+ $sql = $this->extractBinds($sql,$inputarr);
+ }
+ }
+ return ADODB_oci8::_query($sql,$inputarr);
+ }
+ /**
+ * Replaces compatibility bind markers with oracle ones and returns a
+ * valid sql statement
+ *
+ * This replaces a regexp based section of code that has been subject
+ * to numerous tweaks, as more extreme test cases have appeared. This
+ * is now done this like this to help maintainability and avoid the
+ * need to rely on regexp experienced maintainers
+ *
+ * @param string $sql The sql statement
+ * @param string[] $inputarr The bind array
+ *
+ * @return string The modified statement
+ */
+ final private function extractBinds($sql,$inputarr)
+ {
+ $inString = false;
+ $escaped = 0;
+ $sqlLength = strlen($sql) - 1;
+ $newSql = '';
+ $bindCount = 0;
+
+ /*
+ * inputarr is the passed in bind list, which is associative, but
+ * we only want the keys here
+ */
+ $inputKeys = array_keys($inputarr);
+
+
+ for ($i=0;$i<=$sqlLength;$i++)
+ {
+ /*
+ * find the next character of the string
+ */
+ $c = $sql{$i};
+
+ if ($c == "'" && !$inString && $escaped==0)
+ /*
+ * Found the start of a string inside the statement
+ */
+ $inString = true;
+ elseif ($c == "\\" && $escaped==0)
+ /*
+ * The next character will be escaped
+ */
+ $escaped = 1;
+ elseif ($c == "'" && $inString && $escaped==0)
+ /*
+ * We found the end of the string
+ */
+ $inString = false;
+
+ if ($escaped == 2)
+ $escaped = 0;
+
+ if ($escaped==0 && !$inString && $c == '?')
+ /*
+ * We found a bind symbol, replace it with the oracle equivalent
+ */
+ $newSql .= ':' . $inputKeys[$bindCount++];
+ else
+ /*
+ * Add the current character the pile
+ */
+ $newSql .= $c;
+
+ if ($escaped == 1)
+ /*
+ * We have just found an escape character, make sure we ignore the
+ * next one that comes along, it might be a ' character
+ */
+ $escaped = 2;
+ }
+
+ return $newSql;
+
+ }
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordset_oci8po extends ADORecordset_oci8 {
+
+ var $databaseType = 'oci8po';
+
+ function __construct($queryID,$mode=false)
+ {
+ parent::__construct($queryID,$mode);
+ }
+
+ function Fields($colname)
+ {
+ if ($this->fetchMode & OCI_ASSOC) return $this->fields[$colname];
+
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+ // lowercase field names...
+ function _FetchField($fieldOffset = -1)
+ {
+ $fld = new ADOFieldObject;
+ $fieldOffset += 1;
+ $fld->name = OCIcolumnname($this->_queryID, $fieldOffset);
+ if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_LOWER) {
+ $fld->name = strtolower($fld->name);
+ }
+ $fld->type = OCIcolumntype($this->_queryID, $fieldOffset);
+ $fld->max_length = OCIcolumnsize($this->_queryID, $fieldOffset);
+ if ($fld->type == 'NUMBER') {
+ $sc = OCIColumnScale($this->_queryID, $fieldOffset);
+ if ($sc == 0) {
+ $fld->type = 'INT';
+ }
+ }
+ return $fld;
+ }
+
+ // 10% speedup to move MoveNext to child class
+ function MoveNext()
+ {
+ $ret = @oci_fetch_array($this->_queryID,$this->fetchMode);
+ if($ret !== false) {
+ global $ADODB_ANSI_PADDING_OFF;
+ $this->fields = $ret;
+ $this->_currentRow++;
+ $this->_updatefields();
+
+ if (!empty($ADODB_ANSI_PADDING_OFF)) {
+ foreach($this->fields as $k => $v) {
+ if (is_string($v)) $this->fields[$k] = rtrim($v);
+ }
+ }
+ return true;
+ }
+ if (!$this->EOF) {
+ $this->EOF = true;
+ $this->_currentRow++;
+ }
+ return false;
+ }
+
+ /* Optimize SelectLimit() by using OCIFetch() instead of OCIFetchInto() */
+ function GetArrayLimit($nrows,$offset=-1)
+ {
+ if ($offset <= 0) {
+ $arr = $this->GetArray($nrows);
+ return $arr;
+ }
+ for ($i=1; $i < $offset; $i++)
+ if (!@OCIFetch($this->_queryID)) {
+ $arr = array();
+ return $arr;
+ }
+ $ret = @oci_fetch_array($this->_queryID,$this->fetchMode);
+ if ($ret === false) {
+ $arr = array();
+ return $arr;
+ }
+ $this->fields = $ret;
+ $this->_updatefields();
+ $results = array();
+ $cnt = 0;
+ while (!$this->EOF && $nrows != $cnt) {
+ $results[$cnt++] = $this->fields;
+ $this->MoveNext();
+ }
+
+ return $results;
+ }
+
+ function _fetch()
+ {
+ global $ADODB_ANSI_PADDING_OFF;
+
+ $ret = @oci_fetch_array($this->_queryID,$this->fetchMode);
+ if ($ret) {
+ $this->fields = $ret;
+ $this->_updatefields();
+
+ if (!empty($ADODB_ANSI_PADDING_OFF)) {
+ foreach($this->fields as $k => $v) {
+ if (is_string($v)) $this->fields[$k] = rtrim($v);
+ }
+ }
+ }
+ return $ret !== false;
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-oci8quercus.inc.php b/vendor/adodb/adodb-php/drivers/adodb-oci8quercus.inc.php
new file mode 100644
index 0000000..62601b7
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-oci8quercus.inc.php
@@ -0,0 +1,89 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim. All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+
+ Latest version is available at http://adodb.org/
+
+ Portable version of oci8 driver, to make it more similar to other database drivers.
+ The main differences are
+
+ 1. that the OCI_ASSOC names are in lowercase instead of uppercase.
+ 2. bind variables are mapped using ? instead of :<bindvar>
+
+ Should some emulation of RecordCount() be implemented?
+
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR.'/drivers/adodb-oci8.inc.php');
+
+class ADODB_oci8quercus extends ADODB_oci8 {
+ var $databaseType = 'oci8quercus';
+ var $dataProvider = 'oci8';
+
+ function __construct()
+ {
+ }
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordset_oci8quercus extends ADORecordset_oci8 {
+
+ var $databaseType = 'oci8quercus';
+
+ function __construct($queryID,$mode=false)
+ {
+ parent::__construct($queryID,$mode);
+ }
+
+ function _FetchField($fieldOffset = -1)
+ {
+ global $QUERCUS;
+ $fld = new ADOFieldObject;
+
+ if (!empty($QUERCUS)) {
+ $fld->name = oci_field_name($this->_queryID, $fieldOffset);
+ $fld->type = oci_field_type($this->_queryID, $fieldOffset);
+ $fld->max_length = oci_field_size($this->_queryID, $fieldOffset);
+
+ //if ($fld->name == 'VAL6_NUM_12_4') $fld->type = 'NUMBER';
+ switch($fld->type) {
+ case 'string': $fld->type = 'VARCHAR'; break;
+ case 'real': $fld->type = 'NUMBER'; break;
+ }
+ } else {
+ $fieldOffset += 1;
+ $fld->name = oci_field_name($this->_queryID, $fieldOffset);
+ $fld->type = oci_field_type($this->_queryID, $fieldOffset);
+ $fld->max_length = oci_field_size($this->_queryID, $fieldOffset);
+ }
+ switch($fld->type) {
+ case 'NUMBER':
+ $p = oci_field_precision($this->_queryID, $fieldOffset);
+ $sc = oci_field_scale($this->_queryID, $fieldOffset);
+ if ($p != 0 && $sc == 0) $fld->type = 'INT';
+ $fld->scale = $p;
+ break;
+
+ case 'CLOB':
+ case 'NCLOB':
+ case 'BLOB':
+ $fld->max_length = -1;
+ break;
+ }
+
+ return $fld;
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-odbc.inc.php b/vendor/adodb/adodb-php/drivers/adodb-odbc.inc.php
new file mode 100644
index 0000000..8a7e370
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-odbc.inc.php
@@ -0,0 +1,735 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Requires ODBC. Works on Windows and Unix.
+*/
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+ define("_ADODB_ODBC_LAYER", 2 );
+
+/*--------------------------------------------------------------------------------------
+--------------------------------------------------------------------------------------*/
+
+
+class ADODB_odbc extends ADOConnection {
+ var $databaseType = "odbc";
+ var $fmtDate = "'Y-m-d'";
+ var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $dataProvider = "odbc";
+ var $hasAffectedRows = true;
+ var $binmode = ODBC_BINMODE_RETURN;
+ var $useFetchArray = false; // setting this to true will make array elements in FETCH_ASSOC mode case-sensitive
+ // breaking backward-compat
+ //var $longreadlen = 8000; // default number of chars to return for a Blob/Long field
+ var $_bindInputArray = false;
+ var $curmode = SQL_CUR_USE_DRIVER; // See sqlext.h, SQL_CUR_DEFAULT == SQL_CUR_USE_DRIVER == 2L
+ var $_genSeqSQL = "create table %s (id integer)";
+ var $_autocommit = true;
+ var $_haserrorfunctions = true;
+ var $_has_stupid_odbc_fetch_api_change = true;
+ var $_lastAffectedRows = 0;
+ var $uCaseTables = true; // for meta* functions, uppercase table names
+
+ function __construct()
+ {
+ $this->_haserrorfunctions = ADODB_PHPVER >= 0x4050;
+ $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
+ }
+
+ // returns true or false
+ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('odbc_connect')) return null;
+
+ if (!empty($argDatabasename) && stristr($argDSN, 'Database=') === false) {
+ $argDSN = trim($argDSN);
+ $endDSN = substr($argDSN, strlen($argDSN) - 1);
+ if ($endDSN != ';') $argDSN .= ';';
+ $argDSN .= 'Database='.$argDatabasename;
+ }
+
+ $last_php_error = $this->resetLastError();
+ if ($this->curmode === false) $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword);
+ else $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword,$this->curmode);
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
+
+ return $this->_connectionID != false;
+ }
+
+ // returns true or false
+ function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('odbc_connect')) return null;
+
+ $last_php_error = $this->resetLastError();
+ $this->_errorMsg = '';
+ if ($this->debug && $argDatabasename) {
+ ADOConnection::outp("For odbc PConnect(), $argDatabasename is not used. Place dsn in 1st parameter.");
+ }
+ // print "dsn=$argDSN u=$argUsername p=$argPassword<br>"; flush();
+ if ($this->curmode === false) $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword);
+ else $this->_connectionID = odbc_pconnect($argDSN,$argUsername,$argPassword,$this->curmode);
+
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ if ($this->_connectionID && $this->autoRollback) @odbc_rollback($this->_connectionID);
+ if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
+
+ return $this->_connectionID != false;
+ }
+
+
+ function ServerInfo()
+ {
+
+ if (!empty($this->host) && ADODB_PHPVER >= 0x4300) {
+ $dsn = strtoupper($this->host);
+ $first = true;
+ $found = false;
+
+ if (!function_exists('odbc_data_source')) return false;
+
+ while(true) {
+
+ $rez = @odbc_data_source($this->_connectionID,
+ $first ? SQL_FETCH_FIRST : SQL_FETCH_NEXT);
+ $first = false;
+ if (!is_array($rez)) break;
+ if (strtoupper($rez['server']) == $dsn) {
+ $found = true;
+ break;
+ }
+ }
+ if (!$found) return ADOConnection::ServerInfo();
+ if (!isset($rez['version'])) $rez['version'] = '';
+ return $rez;
+ } else {
+ return ADOConnection::ServerInfo();
+ }
+ }
+
+
+ function CreateSequence($seqname='adodbseq',$start=1)
+ {
+ if (empty($this->_genSeqSQL)) return false;
+ $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
+ if (!$ok) return false;
+ $start -= 1;
+ return $this->Execute("insert into $seqname values($start)");
+ }
+
+ var $_dropSeqSQL = 'drop table %s';
+ function DropSequence($seqname = 'adodbseq')
+ {
+ if (empty($this->_dropSeqSQL)) return false;
+ return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
+ }
+
+ /*
+ This algorithm is not very efficient, but works even if table locking
+ is not available.
+
+ Will return false if unable to generate an ID after $MAXLOOPS attempts.
+ */
+ function GenID($seq='adodbseq',$start=1)
+ {
+ // if you have to modify the parameter below, your database is overloaded,
+ // or you need to implement generation of id's yourself!
+ $MAXLOOPS = 100;
+ //$this->debug=1;
+ while (--$MAXLOOPS>=0) {
+ $num = $this->GetOne("select id from $seq");
+ if ($num === false) {
+ $this->Execute(sprintf($this->_genSeqSQL ,$seq));
+ $start -= 1;
+ $num = '0';
+ $ok = $this->Execute("insert into $seq values($start)");
+ if (!$ok) return false;
+ }
+ $this->Execute("update $seq set id=id+1 where id=$num");
+
+ if ($this->affected_rows() > 0) {
+ $num += 1;
+ $this->genID = $num;
+ return $num;
+ } elseif ($this->affected_rows() == 0) {
+ // some drivers do not return a valid value => try with another method
+ $value = $this->GetOne("select id from $seq");
+ if ($value == $num + 1) {
+ return $value;
+ }
+ }
+ }
+ if ($fn = $this->raiseErrorFn) {
+ $fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
+ }
+ return false;
+ }
+
+
+ function ErrorMsg()
+ {
+ if ($this->_haserrorfunctions) {
+ if ($this->_errorMsg !== false) return $this->_errorMsg;
+ if (empty($this->_connectionID)) return @odbc_errormsg();
+ return @odbc_errormsg($this->_connectionID);
+ } else return ADOConnection::ErrorMsg();
+ }
+
+ function ErrorNo()
+ {
+
+ if ($this->_haserrorfunctions) {
+ if ($this->_errorCode !== false) {
+ // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
+ return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode;
+ }
+
+ if (empty($this->_connectionID)) $e = @odbc_error();
+ else $e = @odbc_error($this->_connectionID);
+
+ // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
+ // so we check and patch
+ if (strlen($e)<=2) return 0;
+ return $e;
+ } else return ADOConnection::ErrorNo();
+ }
+
+
+
+ function BeginTrans()
+ {
+ if (!$this->hasTransactions) return false;
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ $this->_autocommit = false;
+ return odbc_autocommit($this->_connectionID,false);
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) return true;
+ if (!$ok) return $this->RollbackTrans();
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->_autocommit = true;
+ $ret = odbc_commit($this->_connectionID);
+ odbc_autocommit($this->_connectionID,true);
+ return $ret;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->_autocommit = true;
+ $ret = odbc_rollback($this->_connectionID);
+ odbc_autocommit($this->_connectionID,true);
+ return $ret;
+ }
+
+ function MetaPrimaryKeys($table,$owner=false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ if ($this->uCaseTables) $table = strtoupper($table);
+ $schema = '';
+ $this->_findschema($table,$schema);
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $qid = @odbc_primarykeys($this->_connectionID,'',$schema,$table);
+
+ if (!$qid) {
+ $ADODB_FETCH_MODE = $savem;
+ return false;
+ }
+ $rs = new ADORecordSet_odbc($qid);
+ $ADODB_FETCH_MODE = $savem;
+
+ if (!$rs) return false;
+ $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
+
+ $arr = $rs->GetArray();
+ $rs->Close();
+ //print_r($arr);
+ $arr2 = array();
+ for ($i=0; $i < sizeof($arr); $i++) {
+ if ($arr[$i][3]) $arr2[] = $arr[$i][3];
+ }
+ return $arr2;
+ }
+
+
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $qid = odbc_tables($this->_connectionID);
+
+ $rs = new ADORecordSet_odbc($qid);
+
+ $ADODB_FETCH_MODE = $savem;
+ if (!$rs) {
+ $false = false;
+ return $false;
+ }
+ $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
+
+ $arr = $rs->GetArray();
+ //print_r($arr);
+
+ $rs->Close();
+ $arr2 = array();
+
+ if ($ttype) {
+ $isview = strncmp($ttype,'V',1) === 0;
+ }
+ for ($i=0; $i < sizeof($arr); $i++) {
+ if (!$arr[$i][2]) continue;
+ $type = $arr[$i][3];
+ if ($ttype) {
+ if ($isview) {
+ if (strncmp($type,'V',1) === 0) $arr2[] = $arr[$i][2];
+ } else if (strncmp($type,'SYS',3) !== 0) $arr2[] = $arr[$i][2];
+ } else if (strncmp($type,'SYS',3) !== 0) $arr2[] = $arr[$i][2];
+ }
+ return $arr2;
+ }
+
+/*
+See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcdatetime_data_type_changes.asp
+/ SQL data type codes /
+#define SQL_UNKNOWN_TYPE 0
+#define SQL_CHAR 1
+#define SQL_NUMERIC 2
+#define SQL_DECIMAL 3
+#define SQL_INTEGER 4
+#define SQL_SMALLINT 5
+#define SQL_FLOAT 6
+#define SQL_REAL 7
+#define SQL_DOUBLE 8
+#if (ODBCVER >= 0x0300)
+#define SQL_DATETIME 9
+#endif
+#define SQL_VARCHAR 12
+
+
+/ One-parameter shortcuts for date/time data types /
+#if (ODBCVER >= 0x0300)
+#define SQL_TYPE_DATE 91
+#define SQL_TYPE_TIME 92
+#define SQL_TYPE_TIMESTAMP 93
+
+#define SQL_UNICODE (-95)
+#define SQL_UNICODE_VARCHAR (-96)
+#define SQL_UNICODE_LONGVARCHAR (-97)
+*/
+ function ODBCTypes($t)
+ {
+ switch ((integer)$t) {
+ case 1:
+ case 12:
+ case 0:
+ case -95:
+ case -96:
+ return 'C';
+ case -97:
+ case -1: //text
+ return 'X';
+ case -4: //image
+ return 'B';
+
+ case 9:
+ case 91:
+ return 'D';
+
+ case 10:
+ case 11:
+ case 92:
+ case 93:
+ return 'T';
+
+ case 4:
+ case 5:
+ case -6:
+ return 'I';
+
+ case -11: // uniqidentifier
+ return 'R';
+ case -7: //bit
+ return 'L';
+
+ default:
+ return 'N';
+ }
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $false = false;
+ if ($this->uCaseTables) $table = strtoupper($table);
+ $schema = '';
+ $this->_findschema($table,$schema);
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ /*if (false) { // after testing, confirmed that the following does not work becoz of a bug
+ $qid2 = odbc_tables($this->_connectionID);
+ $rs = new ADORecordSet_odbc($qid2);
+ $ADODB_FETCH_MODE = $savem;
+ if (!$rs) return false;
+ $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
+ $rs->_fetch();
+
+ while (!$rs->EOF) {
+ if ($table == strtoupper($rs->fields[2])) {
+ $q = $rs->fields[0];
+ $o = $rs->fields[1];
+ break;
+ }
+ $rs->MoveNext();
+ }
+ $rs->Close();
+
+ $qid = odbc_columns($this->_connectionID,$q,$o,strtoupper($table),'%');
+ } */
+
+ switch ($this->databaseType) {
+ case 'access':
+ case 'vfp':
+ $qid = odbc_columns($this->_connectionID);#,'%','',strtoupper($table),'%');
+ break;
+
+
+ case 'db2':
+ $colname = "%";
+ $qid = odbc_columns($this->_connectionID, "", $schema, $table, $colname);
+ break;
+
+ default:
+ $qid = @odbc_columns($this->_connectionID,'%','%',strtoupper($table),'%');
+ if (empty($qid)) $qid = odbc_columns($this->_connectionID);
+ break;
+ }
+ if (empty($qid)) return $false;
+
+ $rs = new ADORecordSet_odbc($qid);
+ $ADODB_FETCH_MODE = $savem;
+
+ if (!$rs) return $false;
+ $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
+ $rs->_fetch();
+
+ $retarr = array();
+
+ /*
+ $rs->fields indices
+ 0 TABLE_QUALIFIER
+ 1 TABLE_SCHEM
+ 2 TABLE_NAME
+ 3 COLUMN_NAME
+ 4 DATA_TYPE
+ 5 TYPE_NAME
+ 6 PRECISION
+ 7 LENGTH
+ 8 SCALE
+ 9 RADIX
+ 10 NULLABLE
+ 11 REMARKS
+ */
+ while (!$rs->EOF) {
+ // adodb_pr($rs->fields);
+ if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[3];
+ $fld->type = $this->ODBCTypes($rs->fields[4]);
+
+ // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp
+ // access uses precision to store length for char/varchar
+ if ($fld->type == 'C' or $fld->type == 'X') {
+ if ($this->databaseType == 'access')
+ $fld->max_length = $rs->fields[6];
+ else if ($rs->fields[4] <= -95) // UNICODE
+ $fld->max_length = $rs->fields[7]/2;
+ else
+ $fld->max_length = $rs->fields[7];
+ } else
+ $fld->max_length = $rs->fields[7];
+ $fld->not_null = !empty($rs->fields[10]);
+ $fld->scale = $rs->fields[8];
+ $retarr[strtoupper($fld->name)] = $fld;
+ } else if (sizeof($retarr)>0)
+ break;
+ $rs->MoveNext();
+ }
+ $rs->Close(); //-- crashes 4.03pl1 -- why?
+
+ if (empty($retarr)) $retarr = false;
+ return $retarr;
+ }
+
+ function Prepare($sql)
+ {
+ if (! $this->_bindInputArray) return $sql; // no binding
+ $stmt = odbc_prepare($this->_connectionID,$sql);
+ if (!$stmt) {
+ // we don't know whether odbc driver is parsing prepared stmts, so just return sql
+ return $sql;
+ }
+ return array($sql,$stmt,false);
+ }
+
+ /* returns queryID or false */
+ function _query($sql,$inputarr=false)
+ {
+ $last_php_error = $this->resetLastError();
+ $this->_errorMsg = '';
+
+ if ($inputarr) {
+ if (is_array($sql)) {
+ $stmtid = $sql[1];
+ } else {
+ $stmtid = odbc_prepare($this->_connectionID,$sql);
+
+ if ($stmtid == false) {
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ return false;
+ }
+ }
+
+ if (! odbc_execute($stmtid,$inputarr)) {
+ //@odbc_free_result($stmtid);
+ if ($this->_haserrorfunctions) {
+ $this->_errorMsg = odbc_errormsg();
+ $this->_errorCode = odbc_error();
+ }
+ return false;
+ }
+
+ } else if (is_array($sql)) {
+ $stmtid = $sql[1];
+ if (!odbc_execute($stmtid)) {
+ //@odbc_free_result($stmtid);
+ if ($this->_haserrorfunctions) {
+ $this->_errorMsg = odbc_errormsg();
+ $this->_errorCode = odbc_error();
+ }
+ return false;
+ }
+ } else
+ $stmtid = odbc_exec($this->_connectionID,$sql);
+
+ $this->_lastAffectedRows = 0;
+ if ($stmtid) {
+ if (@odbc_num_fields($stmtid) == 0) {
+ $this->_lastAffectedRows = odbc_num_rows($stmtid);
+ $stmtid = true;
+ } else {
+ $this->_lastAffectedRows = 0;
+ odbc_binmode($stmtid,$this->binmode);
+ odbc_longreadlen($stmtid,$this->maxblobsize);
+ }
+
+ if ($this->_haserrorfunctions) {
+ $this->_errorMsg = '';
+ $this->_errorCode = 0;
+ } else {
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ }
+ } else {
+ if ($this->_haserrorfunctions) {
+ $this->_errorMsg = odbc_errormsg();
+ $this->_errorCode = odbc_error();
+ } else {
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ }
+ }
+ return $stmtid;
+ }
+
+ /*
+ Insert a null into the blob field of the table first.
+ Then use UpdateBlob to store the blob.
+
+ Usage:
+
+ $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
+ $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
+ */
+ function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ {
+ return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ $ret = @odbc_close($this->_connectionID);
+ $this->_connectionID = false;
+ return $ret;
+ }
+
+ function _affectedrows()
+ {
+ return $this->_lastAffectedRows;
+ }
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_odbc extends ADORecordSet {
+
+ var $bind = false;
+ var $databaseType = "odbc";
+ var $dataProvider = "odbc";
+ var $useFetchArray;
+ var $_has_stupid_odbc_fetch_api_change;
+
+ function __construct($id,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ $this->fetchMode = $mode;
+
+ $this->_queryID = $id;
+
+ // the following is required for mysql odbc driver in 4.3.1 -- why?
+ $this->EOF = false;
+ $this->_currentRow = -1;
+ //parent::__construct($id);
+ }
+
+
+ // returns the field object
+ function FetchField($fieldOffset = -1)
+ {
+
+ $off=$fieldOffset+1; // offsets begin at 1
+
+ $o= new ADOFieldObject();
+ $o->name = @odbc_field_name($this->_queryID,$off);
+ $o->type = @odbc_field_type($this->_queryID,$off);
+ $o->max_length = @odbc_field_len($this->_queryID,$off);
+ if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
+ else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
+ return $o;
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+
+ function _initrs()
+ {
+ global $ADODB_COUNTRECS;
+ $this->_numOfRows = ($ADODB_COUNTRECS) ? @odbc_num_rows($this->_queryID) : -1;
+ $this->_numOfFields = @odbc_num_fields($this->_queryID);
+ // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0
+ if ($this->_numOfRows == 0) $this->_numOfRows = -1;
+ //$this->useFetchArray = $this->connection->useFetchArray;
+ $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
+ }
+
+ function _seek($row)
+ {
+ return false;
+ }
+
+ // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated
+ function GetArrayLimit($nrows,$offset=-1)
+ {
+ if ($offset <= 0) {
+ $rs = $this->GetArray($nrows);
+ return $rs;
+ }
+ $savem = $this->fetchMode;
+ $this->fetchMode = ADODB_FETCH_NUM;
+ $this->Move($offset);
+ $this->fetchMode = $savem;
+
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ $this->fields = $this->GetRowAssoc();
+ }
+
+ $results = array();
+ $cnt = 0;
+ while (!$this->EOF && $nrows != $cnt) {
+ $results[$cnt++] = $this->fields;
+ $this->MoveNext();
+ }
+
+ return $results;
+ }
+
+
+ function MoveNext()
+ {
+ if ($this->_numOfRows != 0 && !$this->EOF) {
+ $this->_currentRow++;
+ if( $this->_fetch() ) {
+ return true;
+ }
+ }
+ $this->fields = false;
+ $this->EOF = true;
+ return false;
+ }
+
+ function _fetch()
+ {
+ $this->fields = false;
+ if ($this->_has_stupid_odbc_fetch_api_change)
+ $rez = @odbc_fetch_into($this->_queryID,$this->fields);
+ else {
+ $row = 0;
+ $rez = @odbc_fetch_into($this->_queryID,$row,$this->fields);
+ }
+ if ($rez) {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ $this->fields = $this->GetRowAssoc();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ function _close()
+ {
+ return @odbc_free_result($this->_queryID);
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-odbc_db2.inc.php b/vendor/adodb/adodb-php/drivers/adodb-odbc_db2.inc.php
new file mode 100644
index 0000000..20fcccd
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-odbc_db2.inc.php
@@ -0,0 +1,369 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ DB2 data driver. Requires ODBC.
+
+From phpdb list:
+
+Hi Andrew,
+
+thanks a lot for your help. Today we discovered what
+our real problem was:
+
+After "playing" a little bit with the php-scripts that try
+to connect to the IBM DB2, we set the optional parameter
+Cursortype when calling odbc_pconnect(....).
+
+And the exciting thing: When we set the cursor type
+to SQL_CUR_USE_ODBC Cursor Type, then
+the whole query speed up from 1 till 10 seconds
+to 0.2 till 0.3 seconds for 100 records. Amazing!!!
+
+Therfore, PHP is just almost fast as calling the DB2
+from Servlets using JDBC (don't take too much care
+about the speed at whole: the database was on a
+completely other location, so the whole connection
+was made over a slow network connection).
+
+I hope this helps when other encounter the same
+problem when trying to connect to DB2 from
+PHP.
+
+Kind regards,
+Christian Szardenings
+
+2 Oct 2001
+Mark Newnham has discovered that the SQL_CUR_USE_ODBC is not supported by
+IBM's DB2 ODBC driver, so this must be a 3rd party ODBC driver.
+
+From the IBM CLI Reference:
+
+SQL_ATTR_ODBC_CURSORS (DB2 CLI v5)
+This connection attribute is defined by ODBC, but is not supported by DB2
+CLI. Any attempt to set or get this attribute will result in an SQLSTATE of
+HYC00 (Driver not capable).
+
+A 32-bit option specifying how the Driver Manager uses the ODBC cursor
+library.
+
+So I guess this means the message [above] was related to using a 3rd party
+odbc driver.
+
+Setting SQL_CUR_USE_ODBC
+========================
+To set SQL_CUR_USE_ODBC for drivers that require it, do this:
+
+$db = NewADOConnection('odbc_db2');
+$db->curMode = SQL_CUR_USE_ODBC;
+$db->Connect($dsn, $userid, $pwd);
+
+
+
+USING CLI INTERFACE
+===================
+
+I have had reports that the $host and $database params have to be reversed in
+Connect() when using the CLI interface. From Halmai Csongor csongor.halmai#nexum.hu:
+
+> The symptom is that if I change the database engine from postgres or any other to DB2 then the following
+> connection command becomes wrong despite being described this version to be correct in the docs.
+>
+> $connection_object->Connect( $DATABASE_HOST, $DATABASE_AUTH_USER_NAME, $DATABASE_AUTH_PASSWORD, $DATABASE_NAME )
+>
+> In case of DB2 I had to swap the first and last arguments in order to connect properly.
+
+
+System Error 5
+==============
+IF you get a System Error 5 when trying to Connect/Load, it could be a permission problem. Give the user connecting
+to DB2 full rights to the DB2 SQLLIB directory, and place the user in the DBUSERS group.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (!defined('_ADODB_ODBC_LAYER')) {
+ include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
+}
+if (!defined('ADODB_ODBC_DB2')){
+define('ADODB_ODBC_DB2',1);
+
+class ADODB_ODBC_DB2 extends ADODB_odbc {
+ var $databaseType = "db2";
+ var $concat_operator = '||';
+ var $sysTime = 'CURRENT TIME';
+ var $sysDate = 'CURRENT DATE';
+ var $sysTimeStamp = 'CURRENT TIMESTAMP';
+ // The complete string representation of a timestamp has the form
+ // yyyy-mm-dd-hh.mm.ss.nnnnnn.
+ var $fmtTimeStamp = "'Y-m-d-H.i.s'";
+ var $ansiOuter = true;
+ var $identitySQL = 'values IDENTITY_VAL_LOCAL()';
+ var $_bindInputArray = true;
+ var $hasInsertID = true;
+ var $rsPrefix = 'ADORecordset_odbc_';
+
+ function __construct()
+ {
+ if (strncmp(PHP_OS,'WIN',3) === 0) $this->curmode = SQL_CUR_USE_ODBC;
+ parent::__construct();
+ }
+
+ function IfNull( $field, $ifNull )
+ {
+ return " COALESCE($field, $ifNull) "; // if DB2 UDB
+ }
+
+ function ServerInfo()
+ {
+ //odbc_setoption($this->_connectionID,1,101 /*SQL_ATTR_ACCESS_MODE*/, 1 /*SQL_MODE_READ_ONLY*/);
+ $vers = $this->GetOne('select versionnumber from sysibm.sysversions');
+ //odbc_setoption($this->_connectionID,1,101, 0 /*SQL_MODE_READ_WRITE*/);
+ return array('description'=>'DB2 ODBC driver', 'version'=>$vers);
+ }
+
+ function _insertid()
+ {
+ return $this->GetOne($this->identitySQL);
+ }
+
+ function RowLock($tables,$where,$col='1 as adodbignore')
+ {
+ if ($this->_autocommit) $this->BeginTrans();
+ return $this->GetOne("select $col from $tables where $where for update");
+ }
+
+ function MetaTables($ttype=false,$showSchema=false, $qtable="%", $qschema="%")
+ {
+ global $ADODB_FETCH_MODE;
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $qid = odbc_tables($this->_connectionID, "", $qschema, $qtable, "");
+
+ $rs = new ADORecordSet_odbc($qid);
+
+ $ADODB_FETCH_MODE = $savem;
+ if (!$rs) {
+ $false = false;
+ return $false;
+ }
+ $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
+
+ $arr = $rs->GetArray();
+ //print_r($arr);
+
+ $rs->Close();
+ $arr2 = array();
+
+ if ($ttype) {
+ $isview = strncmp($ttype,'V',1) === 0;
+ }
+ for ($i=0; $i < sizeof($arr); $i++) {
+
+ if (!$arr[$i][2]) continue;
+ if (strncmp($arr[$i][1],'SYS',3) === 0) continue;
+
+ $type = $arr[$i][3];
+
+ if ($showSchema) $arr[$i][2] = $arr[$i][1].'.'.$arr[$i][2];
+
+ if ($ttype) {
+ if ($isview) {
+ if (strncmp($type,'V',1) === 0) $arr2[] = $arr[$i][2];
+ } else if (strncmp($type,'T',1) === 0) $arr2[] = $arr[$i][2];
+ } else if (strncmp($type,'S',1) !== 0) $arr2[] = $arr[$i][2];
+ }
+ return $arr2;
+ }
+
+ function MetaIndexes ($table, $primary = FALSE, $owner=false)
+ {
+ // save old fetch mode
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+ $false = false;
+ // get index details
+ $table = strtoupper($table);
+ $SQL="SELECT NAME, UNIQUERULE, COLNAMES FROM SYSIBM.SYSINDEXES WHERE TBNAME='$table'";
+ if ($primary)
+ $SQL.= " AND UNIQUERULE='P'";
+ $rs = $this->Execute($SQL);
+ if (!is_object($rs)) {
+ if (isset($savem))
+ $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ return $false;
+ }
+ $indexes = array ();
+ // parse index data into array
+ while ($row = $rs->FetchRow()) {
+ $indexes[$row[0]] = array(
+ 'unique' => ($row[1] == 'U' || $row[1] == 'P'),
+ 'columns' => array()
+ );
+ $cols = ltrim($row[2],'+');
+ $indexes[$row[0]]['columns'] = explode('+', $cols);
+ }
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ }
+ return $indexes;
+ }
+
+ // Format date column in sql string given an input format that understands Y M D
+ function SQLDate($fmt, $col=false)
+ {
+ // use right() and replace() ?
+ if (!$col) $col = $this->sysDate;
+ $s = '';
+
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ if ($s) $s .= '||';
+ $ch = $fmt[$i];
+ switch($ch) {
+ case 'Y':
+ case 'y':
+ $s .= "char(year($col))";
+ break;
+ case 'M':
+ $s .= "substr(monthname($col),1,3)";
+ break;
+ case 'm':
+ $s .= "right(digits(month($col)),2)";
+ break;
+ case 'D':
+ case 'd':
+ $s .= "right(digits(day($col)),2)";
+ break;
+ case 'H':
+ case 'h':
+ if ($col != $this->sysDate) $s .= "right(digits(hour($col)),2)";
+ else $s .= "''";
+ break;
+ case 'i':
+ case 'I':
+ if ($col != $this->sysDate)
+ $s .= "right(digits(minute($col)),2)";
+ else $s .= "''";
+ break;
+ case 'S':
+ case 's':
+ if ($col != $this->sysDate)
+ $s .= "right(digits(second($col)),2)";
+ else $s .= "''";
+ break;
+ default:
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ $s .= $this->qstr($ch);
+ }
+ }
+ return $s;
+ }
+
+
+ function SelectLimit($sql, $nrows = -1, $offset = -1, $inputArr = false, $secs2cache = 0)
+ {
+ $nrows = (integer) $nrows;
+ if ($offset <= 0) {
+ // could also use " OPTIMIZE FOR $nrows ROWS "
+ if ($nrows >= 0) $sql .= " FETCH FIRST $nrows ROWS ONLY ";
+ $rs = $this->Execute($sql,$inputArr);
+ } else {
+ if ($offset > 0 && $nrows < 0);
+ else {
+ $nrows += $offset;
+ $sql .= " FETCH FIRST $nrows ROWS ONLY ";
+ }
+ $rs = ADOConnection::SelectLimit($sql,-1,$offset,$inputArr);
+ }
+
+ return $rs;
+ }
+
+};
+
+
+class ADORecordSet_odbc_db2 extends ADORecordSet_odbc {
+
+ var $databaseType = "db2";
+
+ function __construct($id,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+
+ function MetaType($t,$len=-1,$fieldobj=false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+
+ switch (strtoupper($t)) {
+ case 'VARCHAR':
+ case 'CHAR':
+ case 'CHARACTER':
+ case 'C':
+ if ($len <= $this->blobSize) return 'C';
+
+ case 'LONGCHAR':
+ case 'TEXT':
+ case 'CLOB':
+ case 'DBCLOB': // double-byte
+ case 'X':
+ return 'X';
+
+ case 'BLOB':
+ case 'GRAPHIC':
+ case 'VARGRAPHIC':
+ return 'B';
+
+ case 'DATE':
+ case 'D':
+ return 'D';
+
+ case 'TIME':
+ case 'TIMESTAMP':
+ case 'T':
+ return 'T';
+
+ //case 'BOOLEAN':
+ //case 'BIT':
+ // return 'L';
+
+ //case 'COUNTER':
+ // return 'R';
+
+ case 'INT':
+ case 'INTEGER':
+ case 'BIGINT':
+ case 'SMALLINT':
+ case 'I':
+ return 'I';
+
+ default: return 'N';
+ }
+ }
+}
+
+} //define
diff --git a/vendor/adodb/adodb-php/drivers/adodb-odbc_mssql.inc.php b/vendor/adodb/adodb-php/drivers/adodb-odbc_mssql.inc.php
new file mode 100644
index 0000000..367964c
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-odbc_mssql.inc.php
@@ -0,0 +1,365 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ MSSQL support via ODBC. Requires ODBC. Works on Windows and Unix.
+ For Unix configuration, see http://phpbuilder.com/columns/alberto20000919.php3
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (!defined('_ADODB_ODBC_LAYER')) {
+ include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
+}
+
+
+class ADODB_odbc_mssql extends ADODB_odbc {
+ var $databaseType = 'odbc_mssql';
+ var $fmtDate = "'Y-m-d'";
+ var $fmtTimeStamp = "'Y-m-d\TH:i:s'";
+ var $_bindInputArray = true;
+ var $metaDatabasesSQL = "select name from sysdatabases where name <> 'master'";
+ var $metaTablesSQL="select name,case when type='U' then 'T' else 'V' end from sysobjects where (type='U' or type='V') and (name not in ('sysallocations','syscolumns','syscomments','sysdepends','sysfilegroups','sysfiles','sysfiles1','sysforeignkeys','sysfulltextcatalogs','sysindexes','sysindexkeys','sysmembers','sysobjects','syspermissions','sysprotects','sysreferences','systypes','sysusers','sysalternates','sysconstraints','syssegments','REFERENTIAL_CONSTRAINTS','CHECK_CONSTRAINTS','CONSTRAINT_TABLE_USAGE','CONSTRAINT_COLUMN_USAGE','VIEWS','VIEW_TABLE_USAGE','VIEW_COLUMN_USAGE','SCHEMATA','TABLES','TABLE_CONSTRAINTS','TABLE_PRIVILEGES','COLUMNS','COLUMN_DOMAIN_USAGE','COLUMN_PRIVILEGES','DOMAINS','DOMAIN_CONSTRAINTS','KEY_COLUMN_USAGE'))";
+ var $metaColumnsSQL = # xtype==61 is datetime
+ "select c.name,t.name,c.length,c.isnullable, c.status,
+ (case when c.xusertype=61 then 0 else c.xprec end),
+ (case when c.xusertype=61 then 0 else c.xscale end)
+ from syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id where o.name='%s'";
+ var $hasTop = 'top'; // support mssql/interbase SELECT TOP 10 * FROM TABLE
+ var $sysDate = 'GetDate()';
+ var $sysTimeStamp = 'GetDate()';
+ var $leftOuter = '*=';
+ var $rightOuter = '=*';
+ var $substr = 'substring';
+ var $length = 'len';
+ var $ansiOuter = true; // for mssql7 or later
+ var $identitySQL = 'select SCOPE_IDENTITY()'; // 'select SCOPE_IDENTITY'; # for mssql 2000
+ var $hasInsertID = true;
+ var $connectStmt = 'SET CONCAT_NULL_YIELDS_NULL OFF'; # When SET CONCAT_NULL_YIELDS_NULL is ON,
+ # concatenating a null value with a string yields a NULL result
+
+ function __construct()
+ {
+ parent::__construct();
+ //$this->curmode = SQL_CUR_USE_ODBC;
+ }
+
+ // crashes php...
+ function ServerInfo()
+ {
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $row = $this->GetRow("execute sp_server_info 2");
+ $ADODB_FETCH_MODE = $save;
+ if (!is_array($row)) return false;
+ $arr['description'] = $row[2];
+ $arr['version'] = ADOConnection::_findvers($arr['description']);
+ return $arr;
+ }
+
+ function IfNull( $field, $ifNull )
+ {
+ return " ISNULL($field, $ifNull) "; // if MS SQL Server
+ }
+
+ function _insertid()
+ {
+ // SCOPE_IDENTITY()
+ // Returns the last IDENTITY value inserted into an IDENTITY column in
+ // the same scope. A scope is a module -- a stored procedure, trigger,
+ // function, or batch. Thus, two statements are in the same scope if
+ // they are in the same stored procedure, function, or batch.
+ return $this->GetOne($this->identitySQL);
+ }
+
+
+ function MetaForeignKeys($table, $owner=false, $upper=false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $table = $this->qstr(strtoupper($table));
+
+ $sql =
+"select object_name(constid) as constraint_name,
+ col_name(fkeyid, fkey) as column_name,
+ object_name(rkeyid) as referenced_table_name,
+ col_name(rkeyid, rkey) as referenced_column_name
+from sysforeignkeys
+where upper(object_name(fkeyid)) = $table
+order by constraint_name, referenced_table_name, keyno";
+
+ $constraints = $this->GetArray($sql);
+
+ $ADODB_FETCH_MODE = $save;
+
+ $arr = false;
+ foreach($constraints as $constr) {
+ //print_r($constr);
+ $arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3];
+ }
+ if (!$arr) return false;
+
+ $arr2 = false;
+
+ foreach($arr as $k => $v) {
+ foreach($v as $a => $b) {
+ if ($upper) $a = strtoupper($a);
+ $arr2[$a] = $b;
+ }
+ }
+ return $arr2;
+ }
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ if ($mask) {//$this->debug=1;
+ $save = $this->metaTablesSQL;
+ $mask = $this->qstr($mask);
+ $this->metaTablesSQL .= " AND name like $mask";
+ }
+ $ret = ADOConnection::MetaTables($ttype,$showSchema);
+
+ if ($mask) {
+ $this->metaTablesSQL = $save;
+ }
+ return $ret;
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+
+ $this->_findschema($table,$schema);
+ if ($schema) {
+ $dbName = $this->database;
+ $this->SelectDB($schema);
+ }
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
+
+ if ($schema) {
+ $this->SelectDB($dbName);
+ }
+
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ if (!is_object($rs)) {
+ $false = false;
+ return $false;
+ }
+
+ $retarr = array();
+ while (!$rs->EOF){
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $fld->type = $rs->fields[1];
+
+ $fld->not_null = (!$rs->fields[3]);
+ $fld->auto_increment = ($rs->fields[4] == 128); // sys.syscolumns status field. 0x80 = 128 ref: http://msdn.microsoft.com/en-us/library/ms186816.aspx
+
+
+ if (isset($rs->fields[5]) && $rs->fields[5]) {
+ if ($rs->fields[5]>0) $fld->max_length = $rs->fields[5];
+ $fld->scale = $rs->fields[6];
+ if ($fld->scale>0) $fld->max_length += 1;
+ } else
+ $fld->max_length = $rs->fields[2];
+
+
+ if ($save == ADODB_FETCH_NUM) {
+ $retarr[] = $fld;
+ } else {
+ $retarr[strtoupper($fld->name)] = $fld;
+ }
+ $rs->MoveNext();
+ }
+
+ $rs->Close();
+ return $retarr;
+
+ }
+
+
+ function MetaIndexes($table,$primary=false, $owner=false)
+ {
+ $table = $this->qstr($table);
+
+ $sql = "SELECT i.name AS ind_name, C.name AS col_name, USER_NAME(O.uid) AS Owner, c.colid, k.Keyno,
+ CASE WHEN I.indid BETWEEN 1 AND 254 AND (I.status & 2048 = 2048 OR I.Status = 16402 AND O.XType = 'V') THEN 1 ELSE 0 END AS IsPK,
+ CASE WHEN I.status & 2 = 2 THEN 1 ELSE 0 END AS IsUnique
+ FROM dbo.sysobjects o INNER JOIN dbo.sysindexes I ON o.id = i.id
+ INNER JOIN dbo.sysindexkeys K ON I.id = K.id AND I.Indid = K.Indid
+ INNER JOIN dbo.syscolumns c ON K.id = C.id AND K.colid = C.Colid
+ WHERE LEFT(i.name, 8) <> '_WA_Sys_' AND o.status >= 0 AND O.Name LIKE $table
+ ORDER BY O.name, I.Name, K.keyno";
+
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+
+ $rs = $this->Execute($sql);
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ if (!is_object($rs)) {
+ return FALSE;
+ }
+
+ $indexes = array();
+ while ($row = $rs->FetchRow()) {
+ if (!$primary && $row[5]) continue;
+
+ $indexes[$row[0]]['unique'] = $row[6];
+ $indexes[$row[0]]['columns'][] = $row[1];
+ }
+ return $indexes;
+ }
+
+ function _query($sql,$inputarr=false)
+ {
+ if (is_string($sql)) $sql = str_replace('||','+',$sql);
+ return ADODB_odbc::_query($sql,$inputarr);
+ }
+
+ function SetTransactionMode( $transaction_mode )
+ {
+ $this->_transmode = $transaction_mode;
+ if (empty($transaction_mode)) {
+ $this->Execute('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
+ return;
+ }
+ if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
+ $this->Execute("SET TRANSACTION ".$transaction_mode);
+ }
+
+ // "Stein-Aksel Basma" <basma@accelero.no>
+ // tested with MSSQL 2000
+ function MetaPrimaryKeys($table, $owner = false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $schema = '';
+ $this->_findschema($table,$schema);
+ //if (!$schema) $schema = $this->database;
+ if ($schema) $schema = "and k.table_catalog like '$schema%'";
+
+ $sql = "select distinct k.column_name,ordinal_position from information_schema.key_column_usage k,
+ information_schema.table_constraints tc
+ where tc.constraint_name = k.constraint_name and tc.constraint_type =
+ 'PRIMARY KEY' and k.table_name = '$table' $schema order by ordinal_position ";
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+ $a = $this->GetCol($sql);
+ $ADODB_FETCH_MODE = $savem;
+
+ if ($a && sizeof($a)>0) return $a;
+ $false = false;
+ return $false;
+ }
+
+ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ if ($nrows > 0 && $offset <= 0) {
+ $sql = preg_replace(
+ '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql);
+ $rs = $this->Execute($sql,$inputarr);
+ } else
+ $rs = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
+
+ return $rs;
+ }
+
+ // Format date column in sql string given an input format that understands Y M D
+ function SQLDate($fmt, $col=false)
+ {
+ if (!$col) $col = $this->sysTimeStamp;
+ $s = '';
+
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ if ($s) $s .= '+';
+ $ch = $fmt[$i];
+ switch($ch) {
+ case 'Y':
+ case 'y':
+ $s .= "datename(yyyy,$col)";
+ break;
+ case 'M':
+ $s .= "convert(char(3),$col,0)";
+ break;
+ case 'm':
+ $s .= "replace(str(month($col),2),' ','0')";
+ break;
+ case 'Q':
+ case 'q':
+ $s .= "datename(quarter,$col)";
+ break;
+ case 'D':
+ case 'd':
+ $s .= "replace(str(day($col),2),' ','0')";
+ break;
+ case 'h':
+ $s .= "substring(convert(char(14),$col,0),13,2)";
+ break;
+
+ case 'H':
+ $s .= "replace(str(datepart(hh,$col),2),' ','0')";
+ break;
+
+ case 'i':
+ $s .= "replace(str(datepart(mi,$col),2),' ','0')";
+ break;
+ case 's':
+ $s .= "replace(str(datepart(ss,$col),2),' ','0')";
+ break;
+ case 'a':
+ case 'A':
+ $s .= "substring(convert(char(19),$col,0),18,2)";
+ break;
+
+ default:
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ $s .= $this->qstr($ch);
+ break;
+ }
+ }
+ return $s;
+ }
+
+}
+
+class ADORecordSet_odbc_mssql extends ADORecordSet_odbc {
+
+ var $databaseType = 'odbc_mssql';
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-odbc_oracle.inc.php b/vendor/adodb/adodb-php/drivers/adodb-odbc_oracle.inc.php
new file mode 100644
index 0000000..d1badca
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-odbc_oracle.inc.php
@@ -0,0 +1,108 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Oracle support via ODBC. Requires ODBC. Works on Windows.
+*/
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (!defined('_ADODB_ODBC_LAYER')) {
+ include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
+}
+
+
+class ADODB_odbc_oracle extends ADODB_odbc {
+ var $databaseType = 'odbc_oracle';
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $concat_operator='||';
+ var $fmtDate = "'Y-m-d 00:00:00'";
+ var $fmtTimeStamp = "'Y-m-d h:i:sA'";
+ var $metaTablesSQL = 'select table_name from cat';
+ var $metaColumnsSQL = "select cname,coltype,width from col where tname='%s' order by colno";
+ var $sysDate = "TRUNC(SYSDATE)";
+ var $sysTimeStamp = 'SYSDATE';
+
+ //var $_bindInputArray = false;
+
+ function MetaTables($ttype = false, $showSchema = false, $mask = false)
+ {
+ $false = false;
+ $rs = $this->Execute($this->metaTablesSQL);
+ if ($rs === false) return $false;
+ $arr = $rs->GetArray();
+ $arr2 = array();
+ for ($i=0; $i < sizeof($arr); $i++) {
+ $arr2[] = $arr[$i][0];
+ }
+ $rs->Close();
+ return $arr2;
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table)));
+ if ($rs === false) {
+ $false = false;
+ return $false;
+ }
+ $retarr = array();
+ while (!$rs->EOF) { //print_r($rs->fields);
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $fld->type = $rs->fields[1];
+ $fld->max_length = $rs->fields[2];
+
+
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
+ else $retarr[strtoupper($fld->name)] = $fld;
+
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ return $retarr;
+ }
+
+ // returns true or false
+ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
+ {
+ $last_php_error = $this->resetLastError();
+ $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword,SQL_CUR_USE_ODBC );
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+
+ $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'");
+ //if ($this->_connectionID) odbc_autocommit($this->_connectionID,true);
+ return $this->_connectionID != false;
+ }
+ // returns true or false
+ function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
+ {
+ $last_php_error = $this->resetLastError();
+ $this->_connectionID = odbc_pconnect($argDSN,$argUsername,$argPassword,SQL_CUR_USE_ODBC );
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+
+ $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'");
+ //if ($this->_connectionID) odbc_autocommit($this->_connectionID,true);
+ return $this->_connectionID != false;
+ }
+}
+
+class ADORecordSet_odbc_oracle extends ADORecordSet_odbc {
+
+ var $databaseType = 'odbc_oracle';
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-odbtp.inc.php b/vendor/adodb/adodb-php/drivers/adodb-odbtp.inc.php
new file mode 100644
index 0000000..6dfb5d0
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-odbtp.inc.php
@@ -0,0 +1,839 @@
+<?php
+/*
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence. See License.txt.
+ Set tabs to 4 for best viewing.
+ Latest version is available at http://adodb.org/
+*/
+// Code contributed by "stefan bogdan" <sbogdan#rsb.ro>
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+define("_ADODB_ODBTP_LAYER", 2 );
+
+class ADODB_odbtp extends ADOConnection{
+ var $databaseType = "odbtp";
+ var $dataProvider = "odbtp";
+ var $fmtDate = "'Y-m-d'";
+ var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $odbc_driver = 0;
+ var $hasAffectedRows = true;
+ var $hasInsertID = false;
+ var $hasGenID = true;
+ var $hasMoveFirst = true;
+
+ var $_genSeqSQL = "create table %s (seq_name char(30) not null unique , seq_value integer not null)";
+ var $_dropSeqSQL = "delete from adodb_seq where seq_name = '%s'";
+ var $_bindInputArray = false;
+ var $_useUnicodeSQL = false;
+ var $_canPrepareSP = false;
+ var $_dontPoolDBC = true;
+
+ function __construct()
+ {
+ }
+
+ function ServerInfo()
+ {
+ return array('description' => @odbtp_get_attr( ODB_ATTR_DBMSNAME, $this->_connectionID),
+ 'version' => @odbtp_get_attr( ODB_ATTR_DBMSVER, $this->_connectionID));
+ }
+
+ function ErrorMsg()
+ {
+ if ($this->_errorMsg !== false) return $this->_errorMsg;
+ if (empty($this->_connectionID)) return @odbtp_last_error();
+ return @odbtp_last_error($this->_connectionID);
+ }
+
+ function ErrorNo()
+ {
+ if ($this->_errorCode !== false) return $this->_errorCode;
+ if (empty($this->_connectionID)) return @odbtp_last_error_state();
+ return @odbtp_last_error_state($this->_connectionID);
+ }
+/*
+ function DBDate($d,$isfld=false)
+ {
+ if (empty($d) && $d !== 0) return 'null';
+ if ($isfld) return "convert(date, $d, 120)";
+
+ if (is_string($d)) $d = ADORecordSet::UnixDate($d);
+ $d = adodb_date($this->fmtDate,$d);
+ return "convert(date, $d, 120)";
+ }
+
+ function DBTimeStamp($d,$isfld=false)
+ {
+ if (empty($d) && $d !== 0) return 'null';
+ if ($isfld) return "convert(datetime, $d, 120)";
+
+ if (is_string($d)) $d = ADORecordSet::UnixDate($d);
+ $d = adodb_date($this->fmtDate,$d);
+ return "convert(datetime, $d, 120)";
+ }
+*/
+
+ function _insertid()
+ {
+ // SCOPE_IDENTITY()
+ // Returns the last IDENTITY value inserted into an IDENTITY column in
+ // the same scope. A scope is a module -- a stored procedure, trigger,
+ // function, or batch. Thus, two statements are in the same scope if
+ // they are in the same stored procedure, function, or batch.
+ return $this->GetOne($this->identitySQL);
+ }
+
+ function _affectedrows()
+ {
+ if ($this->_queryID) {
+ return @odbtp_affected_rows ($this->_queryID);
+ } else
+ return 0;
+ }
+
+ function CreateSequence($seqname='adodbseq',$start=1)
+ {
+ //verify existence
+ $num = $this->GetOne("select seq_value from adodb_seq");
+ $seqtab='adodb_seq';
+ if( $this->odbc_driver == ODB_DRIVER_FOXPRO ) {
+ $path = @odbtp_get_attr( ODB_ATTR_DATABASENAME, $this->_connectionID );
+ //if using vfp dbc file
+ if( !strcasecmp(strrchr($path, '.'), '.dbc') )
+ $path = substr($path,0,strrpos($path,'\/'));
+ $seqtab = $path . '/' . $seqtab;
+ }
+ if($num == false) {
+ if (empty($this->_genSeqSQL)) return false;
+ $ok = $this->Execute(sprintf($this->_genSeqSQL ,$seqtab));
+ }
+ $num = $this->GetOne("select seq_value from adodb_seq where seq_name='$seqname'");
+ if ($num) {
+ return false;
+ }
+ $start -= 1;
+ return $this->Execute("insert into adodb_seq values('$seqname',$start)");
+ }
+
+ function DropSequence($seqname = 'adodbseq')
+ {
+ if (empty($this->_dropSeqSQL)) return false;
+ return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
+ }
+
+ function GenID($seq='adodbseq',$start=1)
+ {
+ $seqtab='adodb_seq';
+ if( $this->odbc_driver == ODB_DRIVER_FOXPRO) {
+ $path = @odbtp_get_attr( ODB_ATTR_DATABASENAME, $this->_connectionID );
+ //if using vfp dbc file
+ if( !strcasecmp(strrchr($path, '.'), '.dbc') )
+ $path = substr($path,0,strrpos($path,'\/'));
+ $seqtab = $path . '/' . $seqtab;
+ }
+ $MAXLOOPS = 100;
+ while (--$MAXLOOPS>=0) {
+ $num = $this->GetOne("select seq_value from adodb_seq where seq_name='$seq'");
+ if ($num === false) {
+ //verify if abodb_seq table exist
+ $ok = $this->GetOne("select seq_value from adodb_seq ");
+ if(!$ok) {
+ //creating the sequence table adodb_seq
+ $this->Execute(sprintf($this->_genSeqSQL ,$seqtab));
+ }
+ $start -= 1;
+ $num = '0';
+ $ok = $this->Execute("insert into adodb_seq values('$seq',$start)");
+ if (!$ok) return false;
+ }
+ $ok = $this->Execute("update adodb_seq set seq_value=seq_value+1 where seq_name='$seq'");
+ if($ok) {
+ $num += 1;
+ $this->genID = $num;
+ return $num;
+ }
+ }
+ if ($fn = $this->raiseErrorFn) {
+ $fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
+ }
+ return false;
+ }
+
+ //example for $UserOrDSN
+ //for visual fox : DRIVER={Microsoft Visual FoxPro Driver};SOURCETYPE=DBF;SOURCEDB=c:\YourDbfFileDir;EXCLUSIVE=NO;
+ //for visual fox dbc: DRIVER={Microsoft Visual FoxPro Driver};SOURCETYPE=DBC;SOURCEDB=c:\YourDbcFileDir\mydb.dbc;EXCLUSIVE=NO;
+ //for access : DRIVER={Microsoft Access Driver (*.mdb)};DBQ=c:\path_to_access_db\base_test.mdb;UID=root;PWD=;
+ //for mssql : DRIVER={SQL Server};SERVER=myserver;UID=myuid;PWD=mypwd;DATABASE=OdbtpTest;
+ //if uid & pwd can be separate
+ function _connect($HostOrInterface, $UserOrDSN='', $argPassword='', $argDatabase='')
+ {
+ if ($argPassword && stripos($UserOrDSN,'DRIVER=') !== false) {
+ $this->_connectionID = odbtp_connect($HostOrInterface,$UserOrDSN.';PWD='.$argPassword);
+ } else
+ $this->_connectionID = odbtp_connect($HostOrInterface,$UserOrDSN,$argPassword,$argDatabase);
+ if ($this->_connectionID === false) {
+ $this->_errorMsg = $this->ErrorMsg() ;
+ return false;
+ }
+
+ odbtp_convert_datetime($this->_connectionID,true);
+
+ if ($this->_dontPoolDBC) {
+ if (function_exists('odbtp_dont_pool_dbc'))
+ @odbtp_dont_pool_dbc($this->_connectionID);
+ }
+ else {
+ $this->_dontPoolDBC = true;
+ }
+ $this->odbc_driver = @odbtp_get_attr(ODB_ATTR_DRIVER, $this->_connectionID);
+ $dbms = strtolower(@odbtp_get_attr(ODB_ATTR_DBMSNAME, $this->_connectionID));
+ $this->odbc_name = $dbms;
+
+ // Account for inconsistent DBMS names
+ if( $this->odbc_driver == ODB_DRIVER_ORACLE )
+ $dbms = 'oracle';
+ else if( $this->odbc_driver == ODB_DRIVER_SYBASE )
+ $dbms = 'sybase';
+
+ // Set DBMS specific attributes
+ switch( $dbms ) {
+ case 'microsoft sql server':
+ $this->databaseType = 'odbtp_mssql';
+ $this->fmtDate = "'Y-m-d'";
+ $this->fmtTimeStamp = "'Y-m-d h:i:sA'";
+ $this->sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
+ $this->sysTimeStamp = 'GetDate()';
+ $this->ansiOuter = true;
+ $this->leftOuter = '*=';
+ $this->rightOuter = '=*';
+ $this->hasTop = 'top';
+ $this->hasInsertID = true;
+ $this->hasTransactions = true;
+ $this->_bindInputArray = true;
+ $this->_canSelectDb = true;
+ $this->substr = "substring";
+ $this->length = 'len';
+ $this->identitySQL = 'select SCOPE_IDENTITY()';
+ $this->metaDatabasesSQL = "select name from master..sysdatabases where name <> 'master'";
+ $this->_canPrepareSP = true;
+ break;
+ case 'access':
+ $this->databaseType = 'odbtp_access';
+ $this->fmtDate = "#Y-m-d#";
+ $this->fmtTimeStamp = "#Y-m-d h:i:sA#";
+ $this->sysDate = "FORMAT(NOW,'yyyy-mm-dd')";
+ $this->sysTimeStamp = 'NOW';
+ $this->hasTop = 'top';
+ $this->hasTransactions = false;
+ $this->_canPrepareSP = true; // For MS Access only.
+ break;
+ case 'visual foxpro':
+ $this->databaseType = 'odbtp_vfp';
+ $this->fmtDate = "{^Y-m-d}";
+ $this->fmtTimeStamp = "{^Y-m-d, h:i:sA}";
+ $this->sysDate = 'date()';
+ $this->sysTimeStamp = 'datetime()';
+ $this->ansiOuter = true;
+ $this->hasTop = 'top';
+ $this->hasTransactions = false;
+ $this->replaceQuote = "'+chr(39)+'";
+ $this->true = '.T.';
+ $this->false = '.F.';
+
+ break;
+ case 'oracle':
+ $this->databaseType = 'odbtp_oci8';
+ $this->fmtDate = "'Y-m-d 00:00:00'";
+ $this->fmtTimeStamp = "'Y-m-d h:i:sA'";
+ $this->sysDate = 'TRUNC(SYSDATE)';
+ $this->sysTimeStamp = 'SYSDATE';
+ $this->hasTransactions = true;
+ $this->_bindInputArray = true;
+ $this->concat_operator = '||';
+ break;
+ case 'sybase':
+ $this->databaseType = 'odbtp_sybase';
+ $this->fmtDate = "'Y-m-d'";
+ $this->fmtTimeStamp = "'Y-m-d H:i:s'";
+ $this->sysDate = 'GetDate()';
+ $this->sysTimeStamp = 'GetDate()';
+ $this->leftOuter = '*=';
+ $this->rightOuter = '=*';
+ $this->hasInsertID = true;
+ $this->hasTransactions = true;
+ $this->identitySQL = 'select SCOPE_IDENTITY()';
+ break;
+ default:
+ $this->databaseType = 'odbtp';
+ if( @odbtp_get_attr(ODB_ATTR_TXNCAPABLE, $this->_connectionID) )
+ $this->hasTransactions = true;
+ else
+ $this->hasTransactions = false;
+ }
+ @odbtp_set_attr(ODB_ATTR_FULLCOLINFO, TRUE, $this->_connectionID );
+
+ if ($this->_useUnicodeSQL )
+ @odbtp_set_attr(ODB_ATTR_UNICODESQL, TRUE, $this->_connectionID);
+
+ return true;
+ }
+
+ function _pconnect($HostOrInterface, $UserOrDSN='', $argPassword='', $argDatabase='')
+ {
+ $this->_dontPoolDBC = false;
+ return $this->_connect($HostOrInterface, $UserOrDSN, $argPassword, $argDatabase);
+ }
+
+ function SelectDB($dbName)
+ {
+ if (!@odbtp_select_db($dbName, $this->_connectionID)) {
+ return false;
+ }
+ $this->database = $dbName;
+ $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
+ return true;
+ }
+
+ function MetaTables($ttype='',$showSchema=false,$mask=false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== false) $savefm = $this->SetFetchMode(false);
+
+ $arr = $this->GetArray("||SQLTables||||$ttype");
+
+ if (isset($savefm)) $this->SetFetchMode($savefm);
+ $ADODB_FETCH_MODE = $savem;
+
+ $arr2 = array();
+ for ($i=0; $i < sizeof($arr); $i++) {
+ if ($arr[$i][3] == 'SYSTEM TABLE' ) continue;
+ if ($arr[$i][2])
+ $arr2[] = $showSchema && $arr[$i][1]? $arr[$i][1].'.'.$arr[$i][2] : $arr[$i][2];
+ }
+ return $arr2;
+ }
+
+ function MetaColumns($table,$upper=true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $schema = false;
+ $this->_findschema($table,$schema);
+ if ($upper) $table = strtoupper($table);
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== false) $savefm = $this->SetFetchMode(false);
+
+ $rs = $this->Execute( "||SQLColumns||$schema|$table" );
+
+ if (isset($savefm)) $this->SetFetchMode($savefm);
+ $ADODB_FETCH_MODE = $savem;
+
+ if (!$rs || $rs->EOF) {
+ $false = false;
+ return $false;
+ }
+ $retarr = array();
+ while (!$rs->EOF) {
+ //print_r($rs->fields);
+ if (strtoupper($rs->fields[2]) == $table) {
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[3];
+ $fld->type = $rs->fields[5];
+ $fld->max_length = $rs->fields[6];
+ $fld->not_null = !empty($rs->fields[9]);
+ $fld->scale = $rs->fields[7];
+ if (isset($rs->fields[12])) // vfp does not have field 12
+ if (!is_null($rs->fields[12])) {
+ $fld->has_default = true;
+ $fld->default_value = $rs->fields[12];
+ }
+ $retarr[strtoupper($fld->name)] = $fld;
+ } else if (!empty($retarr))
+ break;
+ $rs->MoveNext();
+ }
+ $rs->Close();
+
+ return $retarr;
+ }
+
+ function MetaPrimaryKeys($table, $owner='')
+ {
+ global $ADODB_FETCH_MODE;
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $arr = $this->GetArray("||SQLPrimaryKeys||$owner|$table");
+ $ADODB_FETCH_MODE = $savem;
+
+ //print_r($arr);
+ $arr2 = array();
+ for ($i=0; $i < sizeof($arr); $i++) {
+ if ($arr[$i][3]) $arr2[] = $arr[$i][3];
+ }
+ return $arr2;
+ }
+
+ function MetaForeignKeys($table, $owner='', $upper=false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $constraints = $this->GetArray("||SQLForeignKeys|||||$owner|$table");
+ $ADODB_FETCH_MODE = $savem;
+
+ $arr = false;
+ foreach($constraints as $constr) {
+ //print_r($constr);
+ $arr[$constr[11]][$constr[2]][] = $constr[7].'='.$constr[3];
+ }
+ if (!$arr) {
+ $false = false;
+ return $false;
+ }
+
+ $arr2 = array();
+
+ foreach($arr as $k => $v) {
+ foreach($v as $a => $b) {
+ if ($upper) $a = strtoupper($a);
+ $arr2[$a] = $b;
+ }
+ }
+ return $arr2;
+ }
+
+ function BeginTrans()
+ {
+ if (!$this->hasTransactions) return false;
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ $this->autoCommit = false;
+ if (defined('ODB_TXN_DEFAULT'))
+ $txn = ODB_TXN_DEFAULT;
+ else
+ $txn = ODB_TXN_READUNCOMMITTED;
+ $rs = @odbtp_set_attr(ODB_ATTR_TRANSACTIONS,$txn,$this->_connectionID);
+ if(!$rs) return false;
+ return true;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) return true;
+ if (!$ok) return $this->RollbackTrans();
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->autoCommit = true;
+ if( ($ret = @odbtp_commit($this->_connectionID)) )
+ $ret = @odbtp_set_attr(ODB_ATTR_TRANSACTIONS, ODB_TXN_NONE, $this->_connectionID);//set transaction off
+ return $ret;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ if ($this->transCnt) $this->transCnt -= 1;
+ $this->autoCommit = true;
+ if( ($ret = @odbtp_rollback($this->_connectionID)) )
+ $ret = @odbtp_set_attr(ODB_ATTR_TRANSACTIONS, ODB_TXN_NONE, $this->_connectionID);//set transaction off
+ return $ret;
+ }
+
+ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
+ {
+ // TOP requires ORDER BY for Visual FoxPro
+ if( $this->odbc_driver == ODB_DRIVER_FOXPRO ) {
+ if (!preg_match('/ORDER[ \t\r\n]+BY/is',$sql)) $sql .= ' ORDER BY 1';
+ }
+ $ret = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
+ return $ret;
+ }
+
+ function Prepare($sql)
+ {
+ if (! $this->_bindInputArray) return $sql; // no binding
+
+ $this->_errorMsg = false;
+ $this->_errorCode = false;
+
+ $stmt = @odbtp_prepare($sql,$this->_connectionID);
+ if (!$stmt) {
+ // print "Prepare Error for ($sql) ".$this->ErrorMsg()."<br>";
+ return $sql;
+ }
+ return array($sql,$stmt,false);
+ }
+
+ function PrepareSP($sql, $param = true)
+ {
+ if (!$this->_canPrepareSP) return $sql; // Can't prepare procedures
+
+ $this->_errorMsg = false;
+ $this->_errorCode = false;
+
+ $stmt = @odbtp_prepare_proc($sql,$this->_connectionID);
+ if (!$stmt) return false;
+ return array($sql,$stmt);
+ }
+
+ /*
+ Usage:
+ $stmt = $db->PrepareSP('SP_RUNSOMETHING'); -- takes 2 params, @myid and @group
+
+ # note that the parameter does not have @ in front!
+ $db->Parameter($stmt,$id,'myid');
+ $db->Parameter($stmt,$group,'group',false,64);
+ $db->Parameter($stmt,$group,'photo',false,100000,ODB_BINARY);
+ $db->Execute($stmt);
+
+ @param $stmt Statement returned by Prepare() or PrepareSP().
+ @param $var PHP variable to bind to. Can set to null (for isNull support).
+ @param $name Name of stored procedure variable name to bind to.
+ @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in odbtp.
+ @param [$maxLen] Holds an maximum length of the variable.
+ @param [$type] The data type of $var. Legal values depend on driver.
+
+ See odbtp_attach_param documentation at http://odbtp.sourceforge.net.
+ */
+ function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=0, $type=0)
+ {
+ if ( $this->odbc_driver == ODB_DRIVER_JET ) {
+ $name = '['.$name.']';
+ if( !$type && $this->_useUnicodeSQL
+ && @odbtp_param_bindtype($stmt[1], $name) == ODB_CHAR )
+ {
+ $type = ODB_WCHAR;
+ }
+ }
+ else {
+ $name = '@'.$name;
+ }
+ return @odbtp_attach_param($stmt[1], $name, $var, $type, $maxLen);
+ }
+
+ /*
+ Insert a null into the blob field of the table first.
+ Then use UpdateBlob to store the blob.
+
+ Usage:
+
+ $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
+ $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
+ */
+
+ function UpdateBlob($table,$column,$val,$where,$blobtype='image')
+ {
+ $sql = "UPDATE $table SET $column = ? WHERE $where";
+ if( !($stmt = @odbtp_prepare($sql, $this->_connectionID)) )
+ return false;
+ if( !@odbtp_input( $stmt, 1, ODB_BINARY, 1000000, $blobtype ) )
+ return false;
+ if( !@odbtp_set( $stmt, 1, $val ) )
+ return false;
+ return @odbtp_execute( $stmt ) != false;
+ }
+
+ function MetaIndexes($table,$primary=false, $owner=false)
+ {
+ switch ( $this->odbc_driver) {
+ case ODB_DRIVER_MSSQL:
+ return $this->MetaIndexes_mssql($table, $primary);
+ default:
+ return array();
+ }
+ }
+
+ function MetaIndexes_mssql($table,$primary=false, $owner = false)
+ {
+ $table = strtolower($this->qstr($table));
+
+ $sql = "SELECT i.name AS ind_name, C.name AS col_name, USER_NAME(O.uid) AS Owner, c.colid, k.Keyno,
+ CASE WHEN I.indid BETWEEN 1 AND 254 AND (I.status & 2048 = 2048 OR I.Status = 16402 AND O.XType = 'V') THEN 1 ELSE 0 END AS IsPK,
+ CASE WHEN I.status & 2 = 2 THEN 1 ELSE 0 END AS IsUnique
+ FROM dbo.sysobjects o INNER JOIN dbo.sysindexes I ON o.id = i.id
+ INNER JOIN dbo.sysindexkeys K ON I.id = K.id AND I.Indid = K.Indid
+ INNER JOIN dbo.syscolumns c ON K.id = C.id AND K.colid = C.Colid
+ WHERE LEFT(i.name, 8) <> '_WA_Sys_' AND o.status >= 0 AND lower(O.Name) = $table
+ ORDER BY O.name, I.Name, K.keyno";
+
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+
+ $rs = $this->Execute($sql);
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ if (!is_object($rs)) {
+ return FALSE;
+ }
+
+ $indexes = array();
+ while ($row = $rs->FetchRow()) {
+ if ($primary && !$row[5]) continue;
+
+ $indexes[$row[0]]['unique'] = $row[6];
+ $indexes[$row[0]]['columns'][] = $row[1];
+ }
+ return $indexes;
+ }
+
+ function IfNull( $field, $ifNull )
+ {
+ switch( $this->odbc_driver ) {
+ case ODB_DRIVER_MSSQL:
+ return " ISNULL($field, $ifNull) ";
+ case ODB_DRIVER_JET:
+ return " IIF(IsNull($field), $ifNull, $field) ";
+ }
+ return " CASE WHEN $field is null THEN $ifNull ELSE $field END ";
+ }
+
+ function _query($sql,$inputarr=false)
+ {
+ $last_php_error = $this->resetLastError();
+ $this->_errorMsg = false;
+ $this->_errorCode = false;
+
+ if ($inputarr) {
+ if (is_array($sql)) {
+ $stmtid = $sql[1];
+ } else {
+ $stmtid = @odbtp_prepare($sql,$this->_connectionID);
+ if ($stmtid == false) {
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ return false;
+ }
+ }
+ $num_params = @odbtp_num_params( $stmtid );
+ /*
+ for( $param = 1; $param <= $num_params; $param++ ) {
+ @odbtp_input( $stmtid, $param );
+ @odbtp_set( $stmtid, $param, $inputarr[$param-1] );
+ }*/
+
+ $param = 1;
+ foreach($inputarr as $v) {
+ @odbtp_input( $stmtid, $param );
+ @odbtp_set( $stmtid, $param, $v );
+ $param += 1;
+ if ($param > $num_params) break;
+ }
+
+ if (!@odbtp_execute($stmtid) ) {
+ return false;
+ }
+ } else if (is_array($sql)) {
+ $stmtid = $sql[1];
+ if (!@odbtp_execute($stmtid)) {
+ return false;
+ }
+ } else {
+ $stmtid = odbtp_query($sql,$this->_connectionID);
+ }
+ $this->_lastAffectedRows = 0;
+ if ($stmtid) {
+ $this->_lastAffectedRows = @odbtp_affected_rows($stmtid);
+ }
+ return $stmtid;
+ }
+
+ function _close()
+ {
+ $ret = @odbtp_close($this->_connectionID);
+ $this->_connectionID = false;
+ return $ret;
+ }
+}
+
+class ADORecordSet_odbtp extends ADORecordSet {
+
+ var $databaseType = 'odbtp';
+ var $canSeek = true;
+
+ function __construct($queryID,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ $this->fetchMode = $mode;
+ parent::__construct($queryID);
+ }
+
+ function _initrs()
+ {
+ $this->_numOfFields = @odbtp_num_fields($this->_queryID);
+ if (!($this->_numOfRows = @odbtp_num_rows($this->_queryID)))
+ $this->_numOfRows = -1;
+
+ if (!$this->connection->_useUnicodeSQL) return;
+
+ if ($this->connection->odbc_driver == ODB_DRIVER_JET) {
+ if (!@odbtp_get_attr(ODB_ATTR_MAPCHARTOWCHAR,
+ $this->connection->_connectionID))
+ {
+ for ($f = 0; $f < $this->_numOfFields; $f++) {
+ if (@odbtp_field_bindtype($this->_queryID, $f) == ODB_CHAR)
+ @odbtp_bind_field($this->_queryID, $f, ODB_WCHAR);
+ }
+ }
+ }
+ }
+
+ function FetchField($fieldOffset = 0)
+ {
+ $off=$fieldOffset; // offsets begin at 0
+ $o= new ADOFieldObject();
+ $o->name = @odbtp_field_name($this->_queryID,$off);
+ $o->type = @odbtp_field_type($this->_queryID,$off);
+ $o->max_length = @odbtp_field_length($this->_queryID,$off);
+ if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
+ else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
+ return $o;
+ }
+
+ function _seek($row)
+ {
+ return @odbtp_data_seek($this->_queryID, $row);
+ }
+
+ function fields($colname)
+ {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
+
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $name = @odbtp_field_name( $this->_queryID, $i );
+ $this->bind[strtoupper($name)] = $i;
+ }
+ }
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+ function _fetch_odbtp($type=0)
+ {
+ switch ($this->fetchMode) {
+ case ADODB_FETCH_NUM:
+ $this->fields = @odbtp_fetch_row($this->_queryID, $type);
+ break;
+ case ADODB_FETCH_ASSOC:
+ $this->fields = @odbtp_fetch_assoc($this->_queryID, $type);
+ break;
+ default:
+ $this->fields = @odbtp_fetch_array($this->_queryID, $type);
+ }
+ if ($this->databaseType = 'odbtp_vfp') {
+ if ($this->fields)
+ foreach($this->fields as $k => $v) {
+ if (strncmp($v,'1899-12-30',10) == 0) $this->fields[$k] = '';
+ }
+ }
+ return is_array($this->fields);
+ }
+
+ function _fetch()
+ {
+ return $this->_fetch_odbtp();
+ }
+
+ function MoveFirst()
+ {
+ if (!$this->_fetch_odbtp(ODB_FETCH_FIRST)) return false;
+ $this->EOF = false;
+ $this->_currentRow = 0;
+ return true;
+ }
+
+ function MoveLast()
+ {
+ if (!$this->_fetch_odbtp(ODB_FETCH_LAST)) return false;
+ $this->EOF = false;
+ $this->_currentRow = $this->_numOfRows - 1;
+ return true;
+ }
+
+ function NextRecordSet()
+ {
+ if (!@odbtp_next_result($this->_queryID)) return false;
+ $this->_inited = false;
+ $this->bind = false;
+ $this->_currentRow = -1;
+ $this->Init();
+ return true;
+ }
+
+ function _close()
+ {
+ return @odbtp_free_query($this->_queryID);
+ }
+}
+
+class ADORecordSet_odbtp_mssql extends ADORecordSet_odbtp {
+
+ var $databaseType = 'odbtp_mssql';
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+}
+
+class ADORecordSet_odbtp_access extends ADORecordSet_odbtp {
+
+ var $databaseType = 'odbtp_access';
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+}
+
+class ADORecordSet_odbtp_vfp extends ADORecordSet_odbtp {
+
+ var $databaseType = 'odbtp_vfp';
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+}
+
+class ADORecordSet_odbtp_oci8 extends ADORecordSet_odbtp {
+
+ var $databaseType = 'odbtp_oci8';
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+}
+
+class ADORecordSet_odbtp_sybase extends ADORecordSet_odbtp {
+
+ var $databaseType = 'odbtp_sybase';
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-odbtp_unicode.inc.php b/vendor/adodb/adodb-php/drivers/adodb-odbtp_unicode.inc.php
new file mode 100644
index 0000000..b41b1fd
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-odbtp_unicode.inc.php
@@ -0,0 +1,35 @@
+<?php
+/*
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence. See License.txt.
+ Set tabs to 4 for best viewing.
+ Latest version is available at http://adodb.org/
+*/
+
+// Code contributed by "Robert Twitty" <rtwitty#neutron.ushmm.org>
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+/*
+ Because the ODBTP server sends and reads UNICODE text data using UTF-8
+ encoding, the following HTML meta tag must be included within the HTML
+ head section of every HTML form and script page:
+
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+ Also, all SQL query strings must be submitted as UTF-8 encoded text.
+*/
+
+if (!defined('_ADODB_ODBTP_LAYER')) {
+ include(ADODB_DIR."/drivers/adodb-odbtp.inc.php");
+}
+
+class ADODB_odbtp_unicode extends ADODB_odbtp {
+ var $databaseType = 'odbtp';
+ var $_useUnicodeSQL = true;
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-oracle.inc.php b/vendor/adodb/adodb-php/drivers/adodb-oracle.inc.php
new file mode 100644
index 0000000..65e1050
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-oracle.inc.php
@@ -0,0 +1,343 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+
+ Latest version is available at http://adodb.org/
+
+ Oracle data driver. Requires Oracle client. Works on Windows and Unix and Oracle 7.
+
+ If you are using Oracle 8 or later, use the oci8 driver which is much better and more reliable.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+class ADODB_oracle extends ADOConnection {
+ var $databaseType = "oracle";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $concat_operator='||';
+ var $_curs;
+ var $_initdate = true; // init date to YYYY-MM-DD
+ var $metaTablesSQL = 'select table_name from cat';
+ var $metaColumnsSQL = "select cname,coltype,width from col where tname='%s' order by colno";
+ var $sysDate = "TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-DD'),'YYYY-MM-DD')";
+ var $sysTimeStamp = 'SYSDATE';
+ var $connectSID = true;
+
+ function __construct()
+ {
+ }
+
+ // format and return date string in database date format
+ function DBDate($d, $isfld = false)
+ {
+ if (is_string($d)) $d = ADORecordSet::UnixDate($d);
+ if (is_object($d)) $ds = $d->format($this->fmtDate);
+ else $ds = adodb_date($this->fmtDate,$d);
+ return 'TO_DATE('.$ds.",'YYYY-MM-DD')";
+ }
+
+ // format and return date string in database timestamp format
+ function DBTimeStamp($ts, $isfld = false)
+ {
+
+ if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts);
+ if (is_object($ts)) $ds = $ts->format($this->fmtDate);
+ else $ds = adodb_date($this->fmtTimeStamp,$ts);
+ return 'TO_DATE('.$ds.",'RRRR-MM-DD, HH:MI:SS AM')";
+ }
+
+
+ function BindDate($d)
+ {
+ $d = ADOConnection::DBDate($d);
+ if (strncmp($d,"'",1)) return $d;
+
+ return substr($d,1,strlen($d)-2);
+ }
+
+ function BindTimeStamp($d)
+ {
+ $d = ADOConnection::DBTimeStamp($d);
+ if (strncmp($d,"'",1)) return $d;
+
+ return substr($d,1,strlen($d)-2);
+ }
+
+
+
+ function BeginTrans()
+ {
+ $this->autoCommit = false;
+ ora_commitoff($this->_connectionID);
+ return true;
+ }
+
+
+ function CommitTrans($ok=true)
+ {
+ if (!$ok) return $this->RollbackTrans();
+ $ret = ora_commit($this->_connectionID);
+ ora_commiton($this->_connectionID);
+ return $ret;
+ }
+
+
+ function RollbackTrans()
+ {
+ $ret = ora_rollback($this->_connectionID);
+ ora_commiton($this->_connectionID);
+ return $ret;
+ }
+
+
+ /* there seems to be a bug in the oracle extension -- always returns ORA-00000 - no error */
+ function ErrorMsg()
+ {
+ if ($this->_errorMsg !== false) return $this->_errorMsg;
+
+ if (is_resource($this->_curs)) $this->_errorMsg = @ora_error($this->_curs);
+ if (empty($this->_errorMsg)) $this->_errorMsg = @ora_error($this->_connectionID);
+ return $this->_errorMsg;
+ }
+
+
+ function ErrorNo()
+ {
+ if ($this->_errorCode !== false) return $this->_errorCode;
+
+ if (is_resource($this->_curs)) $this->_errorCode = @ora_errorcode($this->_curs);
+ if (empty($this->_errorCode)) $this->_errorCode = @ora_errorcode($this->_connectionID);
+ return $this->_errorCode;
+ }
+
+
+
+ // returns true or false
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename, $mode=0)
+ {
+ if (!function_exists('ora_plogon')) return null;
+
+ // <G. Giunta 2003/03/03/> Reset error messages before connecting
+ $this->_errorMsg = false;
+ $this->_errorCode = false;
+
+ // G. Giunta 2003/08/13 - This looks danegrously suspicious: why should we want to set
+ // the oracle home to the host name of remote DB?
+// if ($argHostname) putenv("ORACLE_HOME=$argHostname");
+
+ if($argHostname) { // code copied from version submitted for oci8 by Jorma Tuomainen <jorma.tuomainen@ppoy.fi>
+ if (empty($argDatabasename)) $argDatabasename = $argHostname;
+ else {
+ if(strpos($argHostname,":")) {
+ $argHostinfo=explode(":",$argHostname);
+ $argHostname=$argHostinfo[0];
+ $argHostport=$argHostinfo[1];
+ } else {
+ $argHostport="1521";
+ }
+
+
+ if ($this->connectSID) {
+ $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
+ .")(PORT=$argHostport))(CONNECT_DATA=(SID=$argDatabasename)))";
+ } else
+ $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
+ .")(PORT=$argHostport))(CONNECT_DATA=(SERVICE_NAME=$argDatabasename)))";
+ }
+
+ }
+
+ if ($argDatabasename) $argUsername .= "@$argDatabasename";
+
+ //if ($argHostname) print "<p>Connect: 1st argument should be left blank for $this->databaseType</p>";
+ if ($mode == 1)
+ $this->_connectionID = ora_plogon($argUsername,$argPassword);
+ else
+ $this->_connectionID = ora_logon($argUsername,$argPassword);
+ if ($this->_connectionID === false) return false;
+ if ($this->autoCommit) ora_commiton($this->_connectionID);
+ if ($this->_initdate) {
+ $rs = $this->_query("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD'");
+ if ($rs) ora_close($rs);
+ }
+
+ return true;
+ }
+
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, 1);
+ }
+
+
+ // returns query ID if successful, otherwise false
+ function _query($sql,$inputarr=false)
+ {
+ // <G. Giunta 2003/03/03/> Reset error messages before executing
+ $this->_errorMsg = false;
+ $this->_errorCode = false;
+
+ $curs = ora_open($this->_connectionID);
+
+ if ($curs === false) return false;
+ $this->_curs = $curs;
+ if (!ora_parse($curs,$sql)) return false;
+ if (ora_exec($curs)) return $curs;
+ // <G. Giunta 2004/03/03> before we close the cursor, we have to store the error message
+ // that we can obtain ONLY from the cursor (and not from the connection)
+ $this->_errorCode = @ora_errorcode($curs);
+ $this->_errorMsg = @ora_error($curs);
+ // </G. Giunta 2004/03/03>
+ @ora_close($curs);
+ return false;
+ }
+
+
+ // returns true or false
+ function _close()
+ {
+ return @ora_logoff($this->_connectionID);
+ }
+
+
+
+}
+
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordset_oracle extends ADORecordSet {
+
+ var $databaseType = "oracle";
+ var $bind = false;
+
+ function __construct($queryID,$mode=false)
+ {
+
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ $this->fetchMode = $mode;
+
+ $this->_queryID = $queryID;
+
+ $this->_inited = true;
+ $this->fields = array();
+ if ($queryID) {
+ $this->_currentRow = 0;
+ $this->EOF = !$this->_fetch();
+ @$this->_initrs();
+ } else {
+ $this->_numOfRows = 0;
+ $this->_numOfFields = 0;
+ $this->EOF = true;
+ }
+
+ return $this->_queryID;
+ }
+
+
+
+ /* Returns: an object containing field information.
+ Get column information in the Recordset object. fetchField() can be used in order to obtain information about
+ fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
+ fetchField() is retrieved. */
+
+ function FetchField($fieldOffset = -1)
+ {
+ $fld = new ADOFieldObject;
+ $fld->name = ora_columnname($this->_queryID, $fieldOffset);
+ $fld->type = ora_columntype($this->_queryID, $fieldOffset);
+ $fld->max_length = ora_columnsize($this->_queryID, $fieldOffset);
+ return $fld;
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+ function _initrs()
+ {
+ $this->_numOfRows = -1;
+ $this->_numOfFields = @ora_numcols($this->_queryID);
+ }
+
+
+ function _seek($row)
+ {
+ return false;
+ }
+
+ function _fetch($ignore_fields=false) {
+// should remove call by reference, but ora_fetch_into requires it in 4.0.3pl1
+ if ($this->fetchMode & ADODB_FETCH_ASSOC)
+ return @ora_fetch_into($this->_queryID,$this->fields,ORA_FETCHINTO_NULLS|ORA_FETCHINTO_ASSOC);
+ else
+ return @ora_fetch_into($this->_queryID,$this->fields,ORA_FETCHINTO_NULLS);
+ }
+
+ /* close() only needs to be called if you are worried about using too much memory while your script
+ is running. All associated result memory for the specified result identifier will automatically be freed. */
+
+ function _close()
+{
+ return @ora_close($this->_queryID);
+ }
+
+ function MetaType($t, $len = -1, $fieldobj = false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+
+ switch (strtoupper($t)) {
+ case 'VARCHAR':
+ case 'VARCHAR2':
+ case 'CHAR':
+ case 'VARBINARY':
+ case 'BINARY':
+ if ($len <= $this->blobSize) return 'C';
+ case 'LONG':
+ case 'LONG VARCHAR':
+ case 'CLOB':
+ return 'X';
+ case 'LONG RAW':
+ case 'LONG VARBINARY':
+ case 'BLOB':
+ return 'B';
+
+ case 'DATE': return 'D';
+
+ //case 'T': return 'T';
+
+ case 'BIT': return 'L';
+ case 'INT':
+ case 'SMALLINT':
+ case 'INTEGER': return 'I';
+ default: return 'N';
+ }
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-pdo.inc.php b/vendor/adodb/adodb-php/drivers/adodb-pdo.inc.php
new file mode 100644
index 0000000..cb4fbc4
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-pdo.inc.php
@@ -0,0 +1,815 @@
+<?php
+/**
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+
+ Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Requires ODBC. Works on Windows and Unix.
+
+ Problems:
+ Where is float/decimal type in pdo_param_type
+ LOB handling for CLOB/BLOB differs significantly
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+
+/*
+enum pdo_param_type {
+PDO::PARAM_NULL, 0
+
+/* int as in long (the php native int type).
+ * If you mark a column as an int, PDO expects get_col to return
+ * a pointer to a long
+PDO::PARAM_INT, 1
+
+/* get_col ptr should point to start of the string buffer
+PDO::PARAM_STR, 2
+
+/* get_col: when len is 0 ptr should point to a php_stream *,
+ * otherwise it should behave like a string. Indicate a NULL field
+ * value by setting the ptr to NULL
+PDO::PARAM_LOB, 3
+
+/* get_col: will expect the ptr to point to a new PDOStatement object handle,
+ * but this isn't wired up yet
+PDO::PARAM_STMT, 4 /* hierarchical result set
+
+/* get_col ptr should point to a zend_bool
+PDO::PARAM_BOOL, 5
+
+
+/* magic flag to denote a parameter as being input/output
+PDO::PARAM_INPUT_OUTPUT = 0x80000000
+};
+*/
+
+function adodb_pdo_type($t)
+{
+ switch($t) {
+ case 2: return 'VARCHAR';
+ case 3: return 'BLOB';
+ default: return 'NUMERIC';
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
+
+class ADODB_pdo extends ADOConnection {
+ var $databaseType = "pdo";
+ var $dataProvider = "pdo";
+ var $fmtDate = "'Y-m-d'";
+ var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $hasAffectedRows = true;
+ var $_bindInputArray = true;
+ var $_genIDSQL;
+ var $_genSeqSQL = "create table %s (id integer)";
+ var $_dropSeqSQL;
+ var $_autocommit = true;
+ var $_haserrorfunctions = true;
+ var $_lastAffectedRows = 0;
+
+ var $_errormsg = false;
+ var $_errorno = false;
+
+ var $dsnType = '';
+ var $stmt = false;
+ var $_driver;
+
+ function __construct()
+ {
+ }
+
+ function _UpdatePDO()
+ {
+ $d = $this->_driver;
+ $this->fmtDate = $d->fmtDate;
+ $this->fmtTimeStamp = $d->fmtTimeStamp;
+ $this->replaceQuote = $d->replaceQuote;
+ $this->sysDate = $d->sysDate;
+ $this->sysTimeStamp = $d->sysTimeStamp;
+ $this->random = $d->random;
+ $this->concat_operator = $d->concat_operator;
+ $this->nameQuote = $d->nameQuote;
+
+ $this->hasGenID = $d->hasGenID;
+ $this->_genIDSQL = $d->_genIDSQL;
+ $this->_genSeqSQL = $d->_genSeqSQL;
+ $this->_dropSeqSQL = $d->_dropSeqSQL;
+
+ $d->_init($this);
+ }
+
+ function Time()
+ {
+ if (!empty($this->_driver->_hasdual)) {
+ $sql = "select $this->sysTimeStamp from dual";
+ }
+ else {
+ $sql = "select $this->sysTimeStamp";
+ }
+
+ $rs = $this->_Execute($sql);
+ if ($rs && !$rs->EOF) {
+ return $this->UnixTimeStamp(reset($rs->fields));
+ }
+
+ return false;
+ }
+
+ // returns true or false
+ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persist=false)
+ {
+ $at = strpos($argDSN,':');
+ $this->dsnType = substr($argDSN,0,$at);
+
+ if ($argDatabasename) {
+ switch($this->dsnType){
+ case 'sqlsrv':
+ $argDSN .= ';database='.$argDatabasename;
+ break;
+ case 'mssql':
+ case 'mysql':
+ case 'oci':
+ case 'pgsql':
+ case 'sqlite':
+ default:
+ $argDSN .= ';dbname='.$argDatabasename;
+ }
+ }
+ try {
+ $this->_connectionID = new PDO($argDSN, $argUsername, $argPassword);
+ } catch (Exception $e) {
+ $this->_connectionID = false;
+ $this->_errorno = -1;
+ //var_dump($e);
+ $this->_errormsg = 'Connection attempt failed: '.$e->getMessage();
+ return false;
+ }
+
+ if ($this->_connectionID) {
+ switch(ADODB_ASSOC_CASE){
+ case ADODB_ASSOC_CASE_LOWER:
+ $m = PDO::CASE_LOWER;
+ break;
+ case ADODB_ASSOC_CASE_UPPER:
+ $m = PDO::CASE_UPPER;
+ break;
+ default:
+ case ADODB_ASSOC_CASE_NATIVE:
+ $m = PDO::CASE_NATURAL;
+ break;
+ }
+
+ //$this->_connectionID->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_SILENT );
+ $this->_connectionID->setAttribute(PDO::ATTR_CASE,$m);
+
+ $class = 'ADODB_pdo_'.$this->dsnType;
+ //$this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT,true);
+ switch($this->dsnType) {
+ case 'mssql':
+ case 'mysql':
+ case 'oci':
+ case 'pgsql':
+ case 'sqlite':
+ case 'sqlsrv':
+ include_once(ADODB_DIR.'/drivers/adodb-pdo_'.$this->dsnType.'.inc.php');
+ break;
+ }
+ if (class_exists($class)) {
+ $this->_driver = new $class();
+ }
+ else {
+ $this->_driver = new ADODB_pdo_base();
+ }
+
+ $this->_driver->_connectionID = $this->_connectionID;
+ $this->_UpdatePDO();
+ $this->_driver->database = $this->database;
+ return true;
+ }
+ $this->_driver = new ADODB_pdo_base();
+ return false;
+ }
+
+ function Concat()
+ {
+ $args = func_get_args();
+ if(method_exists($this->_driver, 'Concat')) {
+ return call_user_func_array(array($this->_driver, 'Concat'), $args);
+ }
+
+ if (PHP_VERSION >= 5.3) {
+ return call_user_func_array('parent::Concat', $args);
+ }
+ return call_user_func_array(array($this,'parent::Concat'), $args);
+ }
+
+ // returns true or false
+ function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
+ {
+ return $this->_connect($argDSN, $argUsername, $argPassword, $argDatabasename, true);
+ }
+
+ /*------------------------------------------------------------------------------*/
+
+
+ function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
+ {
+ $save = $this->_driver->fetchMode;
+ $this->_driver->fetchMode = $this->fetchMode;
+ $this->_driver->debug = $this->debug;
+ $ret = $this->_driver->SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
+ $this->_driver->fetchMode = $save;
+ return $ret;
+ }
+
+
+ function ServerInfo()
+ {
+ return $this->_driver->ServerInfo();
+ }
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ return $this->_driver->MetaTables($ttype,$showSchema,$mask);
+ }
+
+ function MetaColumns($table,$normalize=true)
+ {
+ return $this->_driver->MetaColumns($table,$normalize);
+ }
+
+ function InParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false)
+ {
+ $obj = $stmt[1];
+ if ($type) {
+ $obj->bindParam($name, $var, $type, $maxLen);
+ }
+ else {
+ $obj->bindParam($name, $var);
+ }
+ }
+
+ function OffsetDate($dayFraction,$date=false)
+ {
+ return $this->_driver->OffsetDate($dayFraction,$date);
+ }
+
+ function SelectDB($dbName)
+ {
+ return $this->_driver->SelectDB($dbName);
+ }
+
+ function SQLDate($fmt, $col=false)
+ {
+ return $this->_driver->SQLDate($fmt, $col);
+ }
+
+ function ErrorMsg()
+ {
+ if ($this->_errormsg !== false) {
+ return $this->_errormsg;
+ }
+ if (!empty($this->_stmt)) {
+ $arr = $this->_stmt->errorInfo();
+ }
+ else if (!empty($this->_connectionID)) {
+ $arr = $this->_connectionID->errorInfo();
+ }
+ else {
+ return 'No Connection Established';
+ }
+
+ if ($arr) {
+ if (sizeof($arr)<2) {
+ return '';
+ }
+ if ((integer)$arr[0]) {
+ return $arr[2];
+ }
+ else {
+ return '';
+ }
+ }
+ else {
+ return '-1';
+ }
+ }
+
+
+ function ErrorNo()
+ {
+ if ($this->_errorno !== false) {
+ return $this->_errorno;
+ }
+ if (!empty($this->_stmt)) {
+ $err = $this->_stmt->errorCode();
+ }
+ else if (!empty($this->_connectionID)) {
+ $arr = $this->_connectionID->errorInfo();
+ if (isset($arr[0])) {
+ $err = $arr[0];
+ }
+ else {
+ $err = -1;
+ }
+ } else {
+ return 0;
+ }
+
+ if ($err == '00000') {
+ return 0; // allows empty check
+ }
+ return $err;
+ }
+
+ /**
+ * @param bool $auto_commit
+ * @return void
+ */
+ function SetAutoCommit($auto_commit)
+ {
+ if(method_exists($this->_driver, 'SetAutoCommit')) {
+ $this->_driver->SetAutoCommit($auto_commit);
+ }
+ }
+
+ function SetTransactionMode($transaction_mode)
+ {
+ if(method_exists($this->_driver, 'SetTransactionMode')) {
+ return $this->_driver->SetTransactionMode($transaction_mode);
+ }
+
+ return parent::SetTransactionMode($seqname);
+ }
+
+ function BeginTrans()
+ {
+ if(method_exists($this->_driver, 'BeginTrans')) {
+ return $this->_driver->BeginTrans();
+ }
+
+ if (!$this->hasTransactions) {
+ return false;
+ }
+ if ($this->transOff) {
+ return true;
+ }
+ $this->transCnt += 1;
+ $this->_autocommit = false;
+ $this->SetAutoCommit(false);
+
+ return $this->_connectionID->beginTransaction();
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if(method_exists($this->_driver, 'CommitTrans')) {
+ return $this->_driver->CommitTrans($ok);
+ }
+
+ if (!$this->hasTransactions) {
+ return false;
+ }
+ if ($this->transOff) {
+ return true;
+ }
+ if (!$ok) {
+ return $this->RollbackTrans();
+ }
+ if ($this->transCnt) {
+ $this->transCnt -= 1;
+ }
+ $this->_autocommit = true;
+
+ $ret = $this->_connectionID->commit();
+ $this->SetAutoCommit(true);
+ return $ret;
+ }
+
+ function RollbackTrans()
+ {
+ if(method_exists($this->_driver, 'RollbackTrans')) {
+ return $this->_driver->RollbackTrans();
+ }
+
+ if (!$this->hasTransactions) {
+ return false;
+ }
+ if ($this->transOff) {
+ return true;
+ }
+ if ($this->transCnt) {
+ $this->transCnt -= 1;
+ }
+ $this->_autocommit = true;
+
+ $ret = $this->_connectionID->rollback();
+ $this->SetAutoCommit(true);
+ return $ret;
+ }
+
+ function Prepare($sql)
+ {
+ $this->_stmt = $this->_connectionID->prepare($sql);
+ if ($this->_stmt) {
+ return array($sql,$this->_stmt);
+ }
+
+ return false;
+ }
+
+ function PrepareStmt($sql)
+ {
+ $stmt = $this->_connectionID->prepare($sql);
+ if (!$stmt) {
+ return false;
+ }
+ $obj = new ADOPDOStatement($stmt,$this);
+ return $obj;
+ }
+
+ function CreateSequence($seqname='adodbseq',$startID=1)
+ {
+ if(method_exists($this->_driver, 'CreateSequence')) {
+ return $this->_driver->CreateSequence($seqname, $startID);
+ }
+
+ return parent::CreateSequence($seqname, $startID);
+ }
+
+ function DropSequence($seqname='adodbseq')
+ {
+ if(method_exists($this->_driver, 'DropSequence')) {
+ return $this->_driver->DropSequence($seqname);
+ }
+
+ return parent::DropSequence($seqname);
+ }
+
+ function GenID($seqname='adodbseq',$startID=1)
+ {
+ if(method_exists($this->_driver, 'GenID')) {
+ return $this->_driver->GenID($seqname, $startID);
+ }
+
+ return parent::GenID($seqname, $startID);
+ }
+
+
+ /* returns queryID or false */
+ function _query($sql,$inputarr=false)
+ {
+ $ok = false;
+ if (is_array($sql)) {
+ $stmt = $sql[1];
+ } else {
+ $stmt = $this->_connectionID->prepare($sql);
+ }
+ #adodb_backtrace();
+ #var_dump($this->_bindInputArray);
+ if ($stmt) {
+ $this->_driver->debug = $this->debug;
+ if ($inputarr) {
+ $ok = $stmt->execute($inputarr);
+ }
+ else {
+ $ok = $stmt->execute();
+ }
+ }
+
+
+ $this->_errormsg = false;
+ $this->_errorno = false;
+
+ if ($ok) {
+ $this->_stmt = $stmt;
+ return $stmt;
+ }
+
+ if ($stmt) {
+
+ $arr = $stmt->errorinfo();
+ if ((integer)$arr[1]) {
+ $this->_errormsg = $arr[2];
+ $this->_errorno = $arr[1];
+ }
+
+ } else {
+ $this->_errormsg = false;
+ $this->_errorno = false;
+ }
+ return false;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ $this->_stmt = false;
+ return true;
+ }
+
+ function _affectedrows()
+ {
+ return ($this->_stmt) ? $this->_stmt->rowCount() : 0;
+ }
+
+ function _insertid()
+ {
+ return ($this->_connectionID) ? $this->_connectionID->lastInsertId() : 0;
+ }
+
+ /**
+ * Quotes a string to be sent to the database.
+ * If we have an active connection, delegates quoting to the underlying
+ * PDO object. Otherwise, replace "'" by the value of $replaceQuote (same
+ * behavior as mysqli driver)
+ * @param string $s The string to quote
+ * @param boolean $magic_quotes If false, use PDO::quote().
+ * @return string Quoted string
+ */
+ function qstr($s, $magic_quotes = false)
+ {
+ if (!$magic_quotes) {
+ if ($this->_connectionID) {
+ return $this->_connectionID->quote($s);
+ }
+ return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
+ }
+
+ // undo magic quotes for "
+ $s = str_replace('\\"', '"', $s);
+ return "'$s'";
+ }
+
+}
+
+class ADODB_pdo_base extends ADODB_pdo {
+
+ var $sysDate = "'?'";
+ var $sysTimeStamp = "'?'";
+
+
+ function _init($parentDriver)
+ {
+ $parentDriver->_bindInputArray = true;
+ #$parentDriver->_connectionID->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,true);
+ }
+
+ function ServerInfo()
+ {
+ return ADOConnection::ServerInfo();
+ }
+
+ function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
+ {
+ $ret = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
+ return $ret;
+ }
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ return false;
+ }
+
+ function MetaColumns($table,$normalize=true)
+ {
+ return false;
+ }
+}
+
+class ADOPDOStatement {
+
+ var $databaseType = "pdo";
+ var $dataProvider = "pdo";
+ var $_stmt;
+ var $_connectionID;
+
+ function __construct($stmt,$connection)
+ {
+ $this->_stmt = $stmt;
+ $this->_connectionID = $connection;
+ }
+
+ function Execute($inputArr=false)
+ {
+ $savestmt = $this->_connectionID->_stmt;
+ $rs = $this->_connectionID->Execute(array(false,$this->_stmt),$inputArr);
+ $this->_connectionID->_stmt = $savestmt;
+ return $rs;
+ }
+
+ function InParameter(&$var,$name,$maxLen=4000,$type=false)
+ {
+
+ if ($type) {
+ $this->_stmt->bindParam($name,$var,$type,$maxLen);
+ }
+ else {
+ $this->_stmt->bindParam($name, $var);
+ }
+ }
+
+ function Affected_Rows()
+ {
+ return ($this->_stmt) ? $this->_stmt->rowCount() : 0;
+ }
+
+ function ErrorMsg()
+ {
+ if ($this->_stmt) {
+ $arr = $this->_stmt->errorInfo();
+ }
+ else {
+ $arr = $this->_connectionID->errorInfo();
+ }
+
+ if (is_array($arr)) {
+ if ((integer) $arr[0] && isset($arr[2])) {
+ return $arr[2];
+ }
+ else {
+ return '';
+ }
+ } else {
+ return '-1';
+ }
+ }
+
+ function NumCols()
+ {
+ return ($this->_stmt) ? $this->_stmt->columnCount() : 0;
+ }
+
+ function ErrorNo()
+ {
+ if ($this->_stmt) {
+ return $this->_stmt->errorCode();
+ }
+ else {
+ return $this->_connectionID->errorInfo();
+ }
+ }
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_pdo extends ADORecordSet {
+
+ var $bind = false;
+ var $databaseType = "pdo";
+ var $dataProvider = "pdo";
+
+ function __construct($id,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ $this->adodbFetchMode = $mode;
+ switch($mode) {
+ case ADODB_FETCH_NUM: $mode = PDO::FETCH_NUM; break;
+ case ADODB_FETCH_ASSOC: $mode = PDO::FETCH_ASSOC; break;
+
+ case ADODB_FETCH_BOTH:
+ default: $mode = PDO::FETCH_BOTH; break;
+ }
+ $this->fetchMode = $mode;
+
+ $this->_queryID = $id;
+ parent::__construct($id);
+ }
+
+
+ function Init()
+ {
+ if ($this->_inited) {
+ return;
+ }
+ $this->_inited = true;
+ if ($this->_queryID) {
+ @$this->_initrs();
+ }
+ else {
+ $this->_numOfRows = 0;
+ $this->_numOfFields = 0;
+ }
+ if ($this->_numOfRows != 0 && $this->_currentRow == -1) {
+ $this->_currentRow = 0;
+ if ($this->EOF = ($this->_fetch() === false)) {
+ $this->_numOfRows = 0; // _numOfRows could be -1
+ }
+ } else {
+ $this->EOF = true;
+ }
+ }
+
+ function _initrs()
+ {
+ global $ADODB_COUNTRECS;
+
+ $this->_numOfRows = ($ADODB_COUNTRECS) ? @$this->_queryID->rowCount() : -1;
+ if (!$this->_numOfRows) {
+ $this->_numOfRows = -1;
+ }
+ $this->_numOfFields = $this->_queryID->columnCount();
+ }
+
+ // returns the field object
+ function FetchField($fieldOffset = -1)
+ {
+ $off=$fieldOffset+1; // offsets begin at 1
+
+ $o= new ADOFieldObject();
+ $arr = @$this->_queryID->getColumnMeta($fieldOffset);
+ if (!$arr) {
+ $o->name = 'bad getColumnMeta()';
+ $o->max_length = -1;
+ $o->type = 'VARCHAR';
+ $o->precision = 0;
+ # $false = false;
+ return $o;
+ }
+ //adodb_pr($arr);
+ $o->name = $arr['name'];
+ if (isset($arr['sqlsrv:decl_type']) && $arr['sqlsrv:decl_type'] <> "null")
+ {
+ /*
+ * If the database is SQL server, use the native built-ins
+ */
+ $o->type = $arr['sqlsrv:decl_type'];
+ }
+ elseif (isset($arr['native_type']) && $arr['native_type'] <> "null")
+ {
+ $o->type = $arr['native_type'];
+ }
+ else
+ {
+ $o->type = adodb_pdo_type($arr['pdo_type']);
+ }
+
+ $o->max_length = $arr['len'];
+ $o->precision = $arr['precision'];
+
+ switch(ADODB_ASSOC_CASE) {
+ case ADODB_ASSOC_CASE_LOWER:
+ $o->name = strtolower($o->name);
+ break;
+ case ADODB_ASSOC_CASE_UPPER:
+ $o->name = strtoupper($o->name);
+ break;
+ }
+ return $o;
+ }
+
+ function _seek($row)
+ {
+ return false;
+ }
+
+ function _fetch()
+ {
+ if (!$this->_queryID) {
+ return false;
+ }
+
+ $this->fields = $this->_queryID->fetch($this->fetchMode);
+ return !empty($this->fields);
+ }
+
+ function _close()
+ {
+ $this->_queryID = false;
+ }
+
+ function Fields($colname)
+ {
+ if ($this->adodbFetchMode != ADODB_FETCH_NUM) {
+ return @$this->fields[$colname];
+ }
+
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-pdo_mssql.inc.php b/vendor/adodb/adodb-php/drivers/adodb-pdo_mssql.inc.php
new file mode 100644
index 0000000..3f5e1d5
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-pdo_mssql.inc.php
@@ -0,0 +1,62 @@
+<?php
+
+
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 8.
+
+*/
+
+class ADODB_pdo_mssql extends ADODB_pdo {
+
+ var $hasTop = 'top';
+ var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
+ var $sysTimeStamp = 'GetDate()';
+
+
+ function _init($parentDriver)
+ {
+
+ $parentDriver->hasTransactions = false; ## <<< BUG IN PDO mssql driver
+ $parentDriver->_bindInputArray = false;
+ $parentDriver->hasInsertID = true;
+ }
+
+ function ServerInfo()
+ {
+ return ADOConnection::ServerInfo();
+ }
+
+ function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
+ {
+ $ret = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
+ return $ret;
+ }
+
+ function SetTransactionMode( $transaction_mode )
+ {
+ $this->_transmode = $transaction_mode;
+ if (empty($transaction_mode)) {
+ $this->Execute('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
+ return;
+ }
+ if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
+ $this->Execute("SET TRANSACTION ".$transaction_mode);
+ }
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ return false;
+ }
+
+ function MetaColumns($table,$normalize=true)
+ {
+ return false;
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-pdo_mysql.inc.php b/vendor/adodb/adodb-php/drivers/adodb-pdo_mysql.inc.php
new file mode 100644
index 0000000..f873e14
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-pdo_mysql.inc.php
@@ -0,0 +1,313 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 8.
+
+*/
+
+class ADODB_pdo_mysql extends ADODB_pdo {
+
+ var $metaTablesSQL = "SELECT
+ TABLE_NAME,
+ CASE WHEN TABLE_TYPE = 'VIEW' THEN 'V' ELSE 'T' END
+ FROM INFORMATION_SCHEMA.TABLES
+ WHERE TABLE_SCHEMA=";
+ var $metaColumnsSQL = "SHOW COLUMNS FROM `%s`";
+ var $sysDate = 'CURDATE()';
+ var $sysTimeStamp = 'NOW()';
+ var $hasGenID = true;
+ var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
+ var $_dropSeqSQL = "drop table %s";
+ var $fmtTimeStamp = "'Y-m-d, H:i:s'";
+ var $nameQuote = '`';
+
+ function _init($parentDriver)
+ {
+ $parentDriver->hasTransactions = false;
+ #$parentDriver->_bindInputArray = false;
+ $parentDriver->hasInsertID = true;
+ $parentDriver->_connectionID->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
+ }
+
+ // dayFraction is a day in floating point
+ function OffsetDate($dayFraction, $date=false)
+ {
+ if (!$date) {
+ $date = $this->sysDate;
+ }
+
+ $fraction = $dayFraction * 24 * 3600;
+ return $date . ' + INTERVAL ' . $fraction . ' SECOND';
+// return "from_unixtime(unix_timestamp($date)+$fraction)";
+ }
+
+ function Concat()
+ {
+ $s = '';
+ $arr = func_get_args();
+
+ // suggestion by andrew005#mnogo.ru
+ $s = implode(',', $arr);
+ if (strlen($s) > 0) {
+ return "CONCAT($s)";
+ }
+ return '';
+ }
+
+ function ServerInfo()
+ {
+ $arr['description'] = ADOConnection::GetOne('select version()');
+ $arr['version'] = ADOConnection::_findvers($arr['description']);
+ return $arr;
+ }
+
+ function MetaTables($ttype=false, $showSchema=false, $mask=false)
+ {
+ $save = $this->metaTablesSQL;
+ if ($showSchema && is_string($showSchema)) {
+ $this->metaTablesSQL .= $this->qstr($showSchema);
+ } else {
+ $this->metaTablesSQL .= 'schema()';
+ }
+
+ if ($mask) {
+ $mask = $this->qstr($mask);
+ $this->metaTablesSQL .= " like $mask";
+ }
+ $ret = ADOConnection::MetaTables($ttype, $showSchema);
+
+ $this->metaTablesSQL = $save;
+ return $ret;
+ }
+
+ /**
+ * @param bool $auto_commit
+ * @return void
+ */
+ function SetAutoCommit($auto_commit)
+ {
+ $this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT, $auto_commit);
+ }
+
+ function SetTransactionMode($transaction_mode)
+ {
+ $this->_transmode = $transaction_mode;
+ if (empty($transaction_mode)) {
+ $this->Execute('SET TRANSACTION ISOLATION LEVEL REPEATABLE READ');
+ return;
+ }
+ if (!stristr($transaction_mode, 'isolation')) {
+ $transaction_mode = 'ISOLATION LEVEL ' . $transaction_mode;
+ }
+ $this->Execute('SET SESSION TRANSACTION ' . $transaction_mode);
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ $this->_findschema($table, $schema);
+ if ($schema) {
+ $dbName = $this->database;
+ $this->SelectDB($schema);
+ }
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ if ($this->fetchMode !== false) {
+ $savem = $this->SetFetchMode(false);
+ }
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL, $table));
+
+ if ($schema) {
+ $this->SelectDB($dbName);
+ }
+
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+ if (!is_object($rs)) {
+ $false = false;
+ return $false;
+ }
+
+ $retarr = array();
+ while (!$rs->EOF){
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $type = $rs->fields[1];
+
+ // split type into type(length):
+ $fld->scale = null;
+ if (preg_match('/^(.+)\((\d+),(\d+)/', $type, $query_array)) {
+ $fld->type = $query_array[1];
+ $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
+ $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
+ } elseif (preg_match('/^(.+)\((\d+)/', $type, $query_array)) {
+ $fld->type = $query_array[1];
+ $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
+ } elseif (preg_match('/^(enum)\((.*)\)$/i', $type, $query_array)) {
+ $fld->type = $query_array[1];
+ $arr = explode(',', $query_array[2]);
+ $fld->enums = $arr;
+ $zlen = max(array_map('strlen', $arr)) - 2; // PHP >= 4.0.6
+ $fld->max_length = ($zlen > 0) ? $zlen : 1;
+ } else {
+ $fld->type = $type;
+ $fld->max_length = -1;
+ }
+ $fld->not_null = ($rs->fields[2] != 'YES');
+ $fld->primary_key = ($rs->fields[3] == 'PRI');
+ $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
+ $fld->binary = (strpos($type, 'blob') !== false);
+ $fld->unsigned = (strpos($type, 'unsigned') !== false);
+
+ if (!$fld->binary) {
+ $d = $rs->fields[4];
+ if ($d != '' && $d != 'NULL') {
+ $fld->has_default = true;
+ $fld->default_value = $d;
+ } else {
+ $fld->has_default = false;
+ }
+ }
+
+ if ($save == ADODB_FETCH_NUM) {
+ $retarr[] = $fld;
+ } else {
+ $retarr[strtoupper($fld->name)] = $fld;
+ }
+ $rs->MoveNext();
+ }
+
+ $rs->Close();
+ return $retarr;
+ }
+
+ // returns true or false
+ function SelectDB($dbName)
+ {
+ $this->database = $dbName;
+ $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
+ $try = $this->Execute('use ' . $dbName);
+ return ($try !== false);
+ }
+
+ // parameters use PostgreSQL convention, not MySQL
+ function SelectLimit($sql, $nrows=-1, $offset=-1, $inputarr=false, $secs=0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ $offsetStr =($offset>=0) ? "$offset," : '';
+ // jason judge, see http://phplens.com/lens/lensforum/msgs.php?id=9220
+ if ($nrows < 0) {
+ $nrows = '18446744073709551615';
+ }
+
+ if ($secs) {
+ $rs = $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows", $inputarr);
+ } else {
+ $rs = $this->Execute($sql . " LIMIT $offsetStr$nrows", $inputarr);
+ }
+ return $rs;
+ }
+
+ function SQLDate($fmt, $col=false)
+ {
+ if (!$col) {
+ $col = $this->sysTimeStamp;
+ }
+ $s = 'DATE_FORMAT(' . $col . ",'";
+ $concat = false;
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ $ch = $fmt[$i];
+ switch($ch) {
+
+ default:
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt, $i, 1);
+ }
+ // FALL THROUGH
+ case '-':
+ case '/':
+ $s .= $ch;
+ break;
+
+ case 'Y':
+ case 'y':
+ $s .= '%Y';
+ break;
+
+ case 'M':
+ $s .= '%b';
+ break;
+
+ case 'm':
+ $s .= '%m';
+ break;
+
+ case 'D':
+ case 'd':
+ $s .= '%d';
+ break;
+
+ case 'Q':
+ case 'q':
+ $s .= "'),Quarter($col)";
+
+ if ($len > $i+1) {
+ $s .= ",DATE_FORMAT($col,'";
+ } else {
+ $s .= ",('";
+ }
+ $concat = true;
+ break;
+
+ case 'H':
+ $s .= '%H';
+ break;
+
+ case 'h':
+ $s .= '%I';
+ break;
+
+ case 'i':
+ $s .= '%i';
+ break;
+
+ case 's':
+ $s .= '%s';
+ break;
+
+ case 'a':
+ case 'A':
+ $s .= '%p';
+ break;
+
+ case 'w':
+ $s .= '%w';
+ break;
+
+ case 'W':
+ $s .= '%U';
+ break;
+
+ case 'l':
+ $s .= '%W';
+ break;
+ }
+ }
+ $s .= "')";
+ if ($concat) {
+ $s = "CONCAT($s)";
+ }
+ return $s;
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-pdo_oci.inc.php b/vendor/adodb/adodb-php/drivers/adodb-pdo_oci.inc.php
new file mode 100644
index 0000000..ae6a1f1
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-pdo_oci.inc.php
@@ -0,0 +1,102 @@
+<?php
+
+
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 8.
+
+*/
+
+class ADODB_pdo_oci extends ADODB_pdo_base {
+
+ var $concat_operator='||';
+ var $sysDate = "TRUNC(SYSDATE)";
+ var $sysTimeStamp = 'SYSDATE';
+ var $NLS_DATE_FORMAT = 'YYYY-MM-DD'; // To include time, use 'RRRR-MM-DD HH24:MI:SS'
+ var $random = "abs(mod(DBMS_RANDOM.RANDOM,10000001)/10000000)";
+ var $metaTablesSQL = "select table_name,table_type from cat where table_type in ('TABLE','VIEW')";
+ var $metaColumnsSQL = "select cname,coltype,width, SCALE, PRECISION, NULLS, DEFAULTVAL from col where tname='%s' order by colno";
+
+ var $_initdate = true;
+ var $_hasdual = true;
+
+ function _init($parentDriver)
+ {
+ $parentDriver->_bindInputArray = true;
+ $parentDriver->_nestedSQL = true;
+ if ($this->_initdate) {
+ $parentDriver->Execute("ALTER SESSION SET NLS_DATE_FORMAT='".$this->NLS_DATE_FORMAT."'");
+ }
+ }
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ if ($mask) {
+ $save = $this->metaTablesSQL;
+ $mask = $this->qstr(strtoupper($mask));
+ $this->metaTablesSQL .= " AND table_name like $mask";
+ }
+ $ret = ADOConnection::MetaTables($ttype,$showSchema);
+
+ if ($mask) {
+ $this->metaTablesSQL = $save;
+ }
+ return $ret;
+ }
+
+ function MetaColumns($table,$normalize=true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $false = false;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
+
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table)));
+
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ if (!$rs) {
+ return $false;
+ }
+ $retarr = array();
+ while (!$rs->EOF) { //print_r($rs->fields);
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $fld->type = $rs->fields[1];
+ $fld->max_length = $rs->fields[2];
+ $fld->scale = $rs->fields[3];
+ if ($rs->fields[1] == 'NUMBER' && $rs->fields[3] == 0) {
+ $fld->type ='INT';
+ $fld->max_length = $rs->fields[4];
+ }
+ $fld->not_null = (strncmp($rs->fields[5], 'NOT',3) === 0);
+ $fld->binary = (strpos($fld->type,'BLOB') !== false);
+ $fld->default_value = $rs->fields[6];
+
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
+ else $retarr[strtoupper($fld->name)] = $fld;
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ if (empty($retarr))
+ return $false;
+ else
+ return $retarr;
+ }
+
+ /**
+ * @param bool $auto_commit
+ * @return void
+ */
+ function SetAutoCommit($auto_commit)
+ {
+ $this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT, $auto_commit);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-pdo_pgsql.inc.php b/vendor/adodb/adodb-php/drivers/adodb-pdo_pgsql.inc.php
new file mode 100644
index 0000000..1146b43
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-pdo_pgsql.inc.php
@@ -0,0 +1,232 @@
+<?php
+
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 8.
+
+*/
+
+class ADODB_pdo_pgsql extends ADODB_pdo {
+ var $metaDatabasesSQL = "select datname from pg_database where datname not in ('template0','template1') order by 1";
+ var $metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
+ and tablename not in ('sql_features', 'sql_implementation_info', 'sql_languages',
+ 'sql_packages', 'sql_sizing', 'sql_sizing_profiles')
+ union
+ select viewname,'V' from pg_views where viewname not like 'pg\_%'";
+ //"select tablename from pg_tables where tablename not like 'pg_%' order by 1";
+ var $isoDates = true; // accepts dates in ISO format
+ var $sysDate = "CURRENT_DATE";
+ var $sysTimeStamp = "CURRENT_TIMESTAMP";
+ var $blobEncodeType = 'C';
+ var $metaColumnsSQL = "SELECT a.attname,t.typname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,a.attnum
+ FROM pg_class c, pg_attribute a,pg_type t
+ WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s')) and a.attname not like '....%%'
+AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
+
+ // used when schema defined
+ var $metaColumnsSQL1 = "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum
+FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n
+WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s'))
+ and c.relnamespace=n.oid and n.nspname='%s'
+ and a.attname not like '....%%' AND a.attnum > 0
+ AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
+
+ // get primary key etc -- from Freek Dijkstra
+ var $metaKeySQL = "SELECT ic.relname AS index_name, a.attname AS column_name,i.indisunique AS unique_key, i.indisprimary AS primary_key
+ FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a WHERE bc.oid = i.indrelid AND ic.oid = i.indexrelid AND (i.indkey[0] = a.attnum OR i.indkey[1] = a.attnum OR i.indkey[2] = a.attnum OR i.indkey[3] = a.attnum OR i.indkey[4] = a.attnum OR i.indkey[5] = a.attnum OR i.indkey[6] = a.attnum OR i.indkey[7] = a.attnum) AND a.attrelid = bc.oid AND bc.relname = '%s'";
+
+ var $hasAffectedRows = true;
+ var $hasLimit = false; // set to true for pgsql 7 only. support pgsql/mysql SELECT * FROM TABLE LIMIT 10
+ // below suggested by Freek Dijkstra
+ var $true = 't'; // string that represents TRUE for a database
+ var $false = 'f'; // string that represents FALSE for a database
+ var $fmtDate = "'Y-m-d'"; // used by DBDate() as the default date format used by the database
+ var $fmtTimeStamp = "'Y-m-d G:i:s'"; // used by DBTimeStamp as the default timestamp fmt.
+ var $hasMoveFirst = true;
+ var $hasGenID = true;
+ var $_genIDSQL = "SELECT NEXTVAL('%s')";
+ var $_genSeqSQL = "CREATE SEQUENCE %s START %s";
+ var $_dropSeqSQL = "DROP SEQUENCE %s";
+ var $metaDefaultsSQL = "SELECT d.adnum as num, d.adsrc as def from pg_attrdef d, pg_class c where d.adrelid=c.oid and c.relname='%s' order by d.adnum";
+ var $random = 'random()'; /// random function
+ var $concat_operator='||';
+
+ function _init($parentDriver)
+ {
+
+ $parentDriver->hasTransactions = false; ## <<< BUG IN PDO pgsql driver
+ $parentDriver->hasInsertID = true;
+ $parentDriver->_nestedSQL = true;
+ }
+
+ function ServerInfo()
+ {
+ $arr['description'] = ADOConnection::GetOne("select version()");
+ $arr['version'] = ADOConnection::_findvers($arr['description']);
+ return $arr;
+ }
+
+ function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ $offsetStr = ($offset >= 0) ? " OFFSET $offset" : '';
+ $limitStr = ($nrows >= 0) ? " LIMIT $nrows" : '';
+ if ($secs2cache)
+ $rs = $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);
+ else
+ $rs = $this->Execute($sql."$limitStr$offsetStr",$inputarr);
+
+ return $rs;
+ }
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ $info = $this->ServerInfo();
+ if ($info['version'] >= 7.3) {
+ $this->metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
+ and schemaname not in ( 'pg_catalog','information_schema')
+ union
+ select viewname,'V' from pg_views where viewname not like 'pg\_%' and schemaname not in ( 'pg_catalog','information_schema') ";
+ }
+ if ($mask) {
+ $save = $this->metaTablesSQL;
+ $mask = $this->qstr(strtolower($mask));
+ if ($info['version']>=7.3)
+ $this->metaTablesSQL = "
+select tablename,'T' from pg_tables where tablename like $mask and schemaname not in ( 'pg_catalog','information_schema')
+ union
+select viewname,'V' from pg_views where viewname like $mask and schemaname not in ( 'pg_catalog','information_schema') ";
+ else
+ $this->metaTablesSQL = "
+select tablename,'T' from pg_tables where tablename like $mask
+ union
+select viewname,'V' from pg_views where viewname like $mask";
+ }
+ $ret = ADOConnection::MetaTables($ttype,$showSchema);
+
+ if ($mask) {
+ $this->metaTablesSQL = $save;
+ }
+ return $ret;
+ }
+
+ function MetaColumns($table,$normalize=true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $schema = false;
+ $this->_findschema($table,$schema);
+
+ if ($normalize) $table = strtolower($table);
+
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
+
+ if ($schema) $rs = $this->Execute(sprintf($this->metaColumnsSQL1,$table,$table,$schema));
+ else $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table,$table));
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+
+ if ($rs === false) {
+ $false = false;
+ return $false;
+ }
+ if (!empty($this->metaKeySQL)) {
+ // If we want the primary keys, we have to issue a separate query
+ // Of course, a modified version of the metaColumnsSQL query using a
+ // LEFT JOIN would have been much more elegant, but postgres does
+ // not support OUTER JOINS. So here is the clumsy way.
+
+ $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+
+ $rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));
+ // fetch all result in once for performance.
+ $keys = $rskey->GetArray();
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+
+ $rskey->Close();
+ unset($rskey);
+ }
+
+ $rsdefa = array();
+ if (!empty($this->metaDefaultsSQL)) {
+ $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+ $sql = sprintf($this->metaDefaultsSQL, ($table));
+ $rsdef = $this->Execute($sql);
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+
+ if ($rsdef) {
+ while (!$rsdef->EOF) {
+ $num = $rsdef->fields['num'];
+ $s = $rsdef->fields['def'];
+ if (strpos($s,'::')===false && substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */
+ $s = substr($s, 1);
+ $s = substr($s, 0, strlen($s) - 1);
+ }
+
+ $rsdefa[$num] = $s;
+ $rsdef->MoveNext();
+ }
+ } else {
+ ADOConnection::outp( "==> SQL => " . $sql);
+ }
+ unset($rsdef);
+ }
+
+ $retarr = array();
+ while (!$rs->EOF) {
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $fld->type = $rs->fields[1];
+ $fld->max_length = $rs->fields[2];
+ if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4;
+ if ($fld->max_length <= 0) $fld->max_length = -1;
+ if ($fld->type == 'numeric') {
+ $fld->scale = $fld->max_length & 0xFFFF;
+ $fld->max_length >>= 16;
+ }
+ // dannym
+ // 5 hasdefault; 6 num-of-column
+ $fld->has_default = ($rs->fields[5] == 't');
+ if ($fld->has_default) {
+ $fld->default_value = $rsdefa[$rs->fields[6]];
+ }
+
+ //Freek
+ if ($rs->fields[4] == $this->true) {
+ $fld->not_null = true;
+ }
+
+ // Freek
+ if (is_array($keys)) {
+ foreach($keys as $key) {
+ if ($fld->name == $key['column_name'] AND $key['primary_key'] == $this->true)
+ $fld->primary_key = true;
+ if ($fld->name == $key['column_name'] AND $key['unique_key'] == $this->true)
+ $fld->unique = true; // What name is more compatible?
+ }
+ }
+
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
+ else $retarr[($normalize) ? strtoupper($fld->name) : $fld->name] = $fld;
+
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ if (empty($retarr)) {
+ $false = false;
+ return $false;
+ } else return $retarr;
+
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-pdo_sqlite.inc.php b/vendor/adodb/adodb-php/drivers/adodb-pdo_sqlite.inc.php
new file mode 100644
index 0000000..2d2f8be
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-pdo_sqlite.inc.php
@@ -0,0 +1,206 @@
+<?php
+
+/*
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence. See License.txt.
+ Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Thanks Diogo Toscano (diogo#scriptcase.net) for the code.
+ And also Sid Dunayer [sdunayer#interserv.com] for extensive fixes.
+*/
+
+class ADODB_pdo_sqlite extends ADODB_pdo {
+ var $metaTablesSQL = "SELECT name FROM sqlite_master WHERE type='table'";
+ var $sysDate = 'current_date';
+ var $sysTimeStamp = 'current_timestamp';
+ var $nameQuote = '`';
+ var $replaceQuote = "''";
+ var $hasGenID = true;
+ var $_genIDSQL = "UPDATE %s SET id=id+1 WHERE id=%s";
+ var $_genSeqSQL = "CREATE TABLE %s (id integer)";
+ var $_genSeqCountSQL = 'SELECT COUNT(*) FROM %s';
+ var $_genSeq2SQL = 'INSERT INTO %s VALUES(%s)';
+ var $_dropSeqSQL = 'DROP TABLE %s';
+ var $concat_operator = '||';
+ var $pdoDriver = false;
+ var $random='abs(random())';
+
+ function _init($parentDriver)
+ {
+ $this->pdoDriver = $parentDriver;
+ $parentDriver->_bindInputArray = true;
+ $parentDriver->hasTransactions = false; // // should be set to false because of PDO SQLite driver not supporting changing autocommit mode
+ $parentDriver->hasInsertID = true;
+ }
+
+ function ServerInfo()
+ {
+ $parent = $this->pdoDriver;
+ @($ver = array_pop($parent->GetCol("SELECT sqlite_version()")));
+ @($enc = array_pop($parent->GetCol("PRAGMA encoding")));
+
+ $arr['version'] = $ver;
+ $arr['description'] = 'SQLite ';
+ $arr['encoding'] = $enc;
+
+ return $arr;
+ }
+
+ function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ $parent = $this->pdoDriver;
+ $offsetStr = ($offset >= 0) ? " OFFSET $offset" : '';
+ $limitStr = ($nrows >= 0) ? " LIMIT $nrows" : ($offset >= 0 ? ' LIMIT 999999999' : '');
+ if ($secs2cache)
+ $rs = $parent->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);
+ else
+ $rs = $parent->Execute($sql."$limitStr$offsetStr",$inputarr);
+
+ return $rs;
+ }
+
+ function GenID($seq='adodbseq',$start=1)
+ {
+ $parent = $this->pdoDriver;
+ // if you have to modify the parameter below, your database is overloaded,
+ // or you need to implement generation of id's yourself!
+ $MAXLOOPS = 100;
+ while (--$MAXLOOPS>=0) {
+ @($num = array_pop($parent->GetCol("SELECT id FROM {$seq}")));
+ if ($num === false || !is_numeric($num)) {
+ @$parent->Execute(sprintf($this->_genSeqSQL ,$seq));
+ $start -= 1;
+ $num = '0';
+ $cnt = $parent->GetOne(sprintf($this->_genSeqCountSQL,$seq));
+ if (!$cnt) {
+ $ok = $parent->Execute(sprintf($this->_genSeq2SQL,$seq,$start));
+ }
+ if (!$ok) return false;
+ }
+ $parent->Execute(sprintf($this->_genIDSQL,$seq,$num));
+
+ if ($parent->affected_rows() > 0) {
+ $num += 1;
+ $parent->genID = intval($num);
+ return intval($num);
+ }
+ }
+ if ($fn = $parent->raiseErrorFn) {
+ $fn($parent->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
+ }
+ return false;
+ }
+
+ function CreateSequence($seqname='adodbseq',$start=1)
+ {
+ $parent = $this->pdoDriver;
+ $ok = $parent->Execute(sprintf($this->_genSeqSQL,$seqname));
+ if (!$ok) return false;
+ $start -= 1;
+ return $parent->Execute("insert into $seqname values($start)");
+ }
+
+ function SetTransactionMode($transaction_mode)
+ {
+ $parent = $this->pdoDriver;
+ $parent->_transmode = strtoupper($transaction_mode);
+ }
+
+ function BeginTrans()
+ {
+ $parent = $this->pdoDriver;
+ if ($parent->transOff) return true;
+ $parent->transCnt += 1;
+ $parent->_autocommit = false;
+ return $parent->Execute("BEGIN {$parent->_transmode}");
+ }
+
+ function CommitTrans($ok=true)
+ {
+ $parent = $this->pdoDriver;
+ if ($parent->transOff) return true;
+ if (!$ok) return $parent->RollbackTrans();
+ if ($parent->transCnt) $parent->transCnt -= 1;
+ $parent->_autocommit = true;
+
+ $ret = $parent->Execute('COMMIT');
+ return $ret;
+ }
+
+ function RollbackTrans()
+ {
+ $parent = $this->pdoDriver;
+ if ($parent->transOff) return true;
+ if ($parent->transCnt) $parent->transCnt -= 1;
+ $parent->_autocommit = true;
+
+ $ret = $parent->Execute('ROLLBACK');
+ return $ret;
+ }
+
+
+ // mark newnham
+ function MetaColumns($tab,$normalize=true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $parent = $this->pdoDriver;
+ $false = false;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+ if ($parent->fetchMode !== false) $savem = $parent->SetFetchMode(false);
+ $rs = $parent->Execute("PRAGMA table_info('$tab')");
+ if (isset($savem)) $parent->SetFetchMode($savem);
+ if (!$rs) {
+ $ADODB_FETCH_MODE = $save;
+ return $false;
+ }
+ $arr = array();
+ while ($r = $rs->FetchRow()) {
+ $type = explode('(',$r['type']);
+ $size = '';
+ if (sizeof($type)==2)
+ $size = trim($type[1],')');
+ $fn = strtoupper($r['name']);
+ $fld = new ADOFieldObject;
+ $fld->name = $r['name'];
+ $fld->type = $type[0];
+ $fld->max_length = $size;
+ $fld->not_null = $r['notnull'];
+ $fld->primary_key = $r['pk'];
+ $fld->default_value = $r['dflt_value'];
+ $fld->scale = 0;
+ if ($save == ADODB_FETCH_NUM) $arr[] = $fld;
+ else $arr[strtoupper($fld->name)] = $fld;
+ }
+ $rs->Close();
+ $ADODB_FETCH_MODE = $save;
+ return $arr;
+ }
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ $parent = $this->pdoDriver;
+
+ if ($mask) {
+ $save = $this->metaTablesSQL;
+ $mask = $this->qstr(strtoupper($mask));
+ $this->metaTablesSQL .= " AND name LIKE $mask";
+ }
+
+ $ret = $parent->GetCol($this->metaTablesSQL);
+
+ if ($mask) {
+ $this->metaTablesSQL = $save;
+ }
+ return $ret;
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-pdo_sqlsrv.inc.php b/vendor/adodb/adodb-php/drivers/adodb-pdo_sqlsrv.inc.php
new file mode 100644
index 0000000..869e8e1
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-pdo_sqlsrv.inc.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * Provided by Ned Andre to support sqlsrv library
+ */
+class ADODB_pdo_sqlsrv extends ADODB_pdo
+{
+
+ var $hasTop = 'top';
+ var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
+ var $sysTimeStamp = 'GetDate()';
+
+ function _init(ADODB_pdo $parentDriver)
+ {
+ $parentDriver->hasTransactions = true;
+ $parentDriver->_bindInputArray = true;
+ $parentDriver->hasInsertID = true;
+ $parentDriver->fmtTimeStamp = "'Y-m-d H:i:s'";
+ $parentDriver->fmtDate = "'Y-m-d'";
+ }
+
+ function BeginTrans()
+ {
+ $returnval = parent::BeginTrans();
+ return $returnval;
+ }
+
+ function MetaColumns($table, $normalize = true)
+ {
+ return false;
+ }
+
+ function MetaTables($ttype = false, $showSchema = false, $mask = false)
+ {
+ return false;
+ }
+
+ function SelectLimit($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs2cache = 0)
+ {
+ $ret = ADOConnection::SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
+ return $ret;
+ }
+
+ function ServerInfo()
+ {
+ return ADOConnection::ServerInfo();
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-postgres.inc.php b/vendor/adodb/adodb-php/drivers/adodb-postgres.inc.php
new file mode 100644
index 0000000..95fdbe5
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-postgres.inc.php
@@ -0,0 +1,14 @@
+<?php
+/*
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 4.
+
+ NOTE: Since 3.31, this file is no longer used, and the "postgres" driver is
+ remapped to "postgres7". Maintaining multiple postgres drivers is no easy
+ job, so hopefully this will ensure greater consistency and fewer bugs.
+*/
diff --git a/vendor/adodb/adodb-php/drivers/adodb-postgres64.inc.php b/vendor/adodb/adodb-php/drivers/adodb-postgres64.inc.php
new file mode 100644
index 0000000..657e23c
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-postgres64.inc.php
@@ -0,0 +1,1118 @@
+<?php
+/*
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 8.
+
+ Original version derived from Alberto Cerezal (acerezalp@dbnet.es) - DBNet Informatica & Comunicaciones.
+ 08 Nov 2000 jlim - Minor corrections, removing mysql stuff
+ 09 Nov 2000 jlim - added insertid support suggested by "Christopher Kings-Lynne" <chriskl@familyhealth.com.au>
+ jlim - changed concat operator to || and data types to MetaType to match documented pgsql types
+ see http://www.postgresql.org/devel-corner/docs/postgres/datatype.htm
+ 22 Nov 2000 jlim - added changes to FetchField() and MetaTables() contributed by "raser" <raser@mail.zen.com.tw>
+ 27 Nov 2000 jlim - added changes to _connect/_pconnect from ideas by "Lennie" <leen@wirehub.nl>
+ 15 Dec 2000 jlim - added changes suggested by Additional code changes by "Eric G. Werk" egw@netguide.dk.
+ 31 Jan 2002 jlim - finally installed postgresql. testing
+ 01 Mar 2001 jlim - Freek Dijkstra changes, also support for text type
+
+ See http://www.varlena.com/varlena/GeneralBits/47.php
+
+ -- What indexes are on my table?
+ select * from pg_indexes where tablename = 'tablename';
+
+ -- What triggers are on my table?
+ select c.relname as "Table", t.tgname as "Trigger Name",
+ t.tgconstrname as "Constraint Name", t.tgenabled as "Enabled",
+ t.tgisconstraint as "Is Constraint", cc.relname as "Referenced Table",
+ p.proname as "Function Name"
+ from pg_trigger t, pg_class c, pg_class cc, pg_proc p
+ where t.tgfoid = p.oid and t.tgrelid = c.oid
+ and t.tgconstrrelid = cc.oid
+ and c.relname = 'tablename';
+
+ -- What constraints are on my table?
+ select r.relname as "Table", c.conname as "Constraint Name",
+ contype as "Constraint Type", conkey as "Key Columns",
+ confkey as "Foreign Columns", consrc as "Source"
+ from pg_class r, pg_constraint c
+ where r.oid = c.conrelid
+ and relname = 'tablename';
+
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+function adodb_addslashes($s)
+{
+ $len = strlen($s);
+ if ($len == 0) return "''";
+ if (strncmp($s,"'",1) === 0 && substr($s,$len-1) == "'") return $s; // already quoted
+
+ return "'".addslashes($s)."'";
+}
+
+class ADODB_postgres64 extends ADOConnection{
+ var $databaseType = 'postgres64';
+ var $dataProvider = 'postgres';
+ var $hasInsertID = true;
+ var $_resultid = false;
+ var $concat_operator='||';
+ var $metaDatabasesSQL = "select datname from pg_database where datname not in ('template0','template1') order by 1";
+ var $metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
+ and tablename not in ('sql_features', 'sql_implementation_info', 'sql_languages',
+ 'sql_packages', 'sql_sizing', 'sql_sizing_profiles')
+ union
+ select viewname,'V' from pg_views where viewname not like 'pg\_%'";
+ //"select tablename from pg_tables where tablename not like 'pg_%' order by 1";
+ var $isoDates = true; // accepts dates in ISO format
+ var $sysDate = "CURRENT_DATE";
+ var $sysTimeStamp = "CURRENT_TIMESTAMP";
+ var $blobEncodeType = 'C';
+ var $metaColumnsSQL = "SELECT a.attname,t.typname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,a.attnum
+ FROM pg_class c, pg_attribute a,pg_type t
+ WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s')) and a.attname not like '....%%'
+ AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
+
+ // used when schema defined
+ var $metaColumnsSQL1 = "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum
+ FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n
+ WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s'))
+ and c.relnamespace=n.oid and n.nspname='%s'
+ and a.attname not like '....%%' AND a.attnum > 0
+ AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
+
+ // get primary key etc -- from Freek Dijkstra
+ var $metaKeySQL = "SELECT ic.relname AS index_name, a.attname AS column_name,i.indisunique AS unique_key, i.indisprimary AS primary_key
+ FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a
+ WHERE bc.oid = i.indrelid AND ic.oid = i.indexrelid
+ AND (i.indkey[0] = a.attnum OR i.indkey[1] = a.attnum OR i.indkey[2] = a.attnum OR i.indkey[3] = a.attnum OR i.indkey[4] = a.attnum OR i.indkey[5] = a.attnum OR i.indkey[6] = a.attnum OR i.indkey[7] = a.attnum)
+ AND a.attrelid = bc.oid AND bc.relname = '%s'";
+
+ var $hasAffectedRows = true;
+ var $hasLimit = false; // set to true for pgsql 7 only. support pgsql/mysql SELECT * FROM TABLE LIMIT 10
+ // below suggested by Freek Dijkstra
+ var $true = 'TRUE'; // string that represents TRUE for a database
+ var $false = 'FALSE'; // string that represents FALSE for a database
+ var $fmtDate = "'Y-m-d'"; // used by DBDate() as the default date format used by the database
+ var $fmtTimeStamp = "'Y-m-d H:i:s'"; // used by DBTimeStamp as the default timestamp fmt.
+ var $hasMoveFirst = true;
+ var $hasGenID = true;
+ var $_genIDSQL = "SELECT NEXTVAL('%s')";
+ var $_genSeqSQL = "CREATE SEQUENCE %s START %s";
+ var $_dropSeqSQL = "DROP SEQUENCE %s";
+ var $metaDefaultsSQL = "SELECT d.adnum as num, d.adsrc as def from pg_attrdef d, pg_class c where d.adrelid=c.oid and c.relname='%s' order by d.adnum";
+ var $random = 'random()'; /// random function
+ var $autoRollback = true; // apparently pgsql does not autorollback properly before php 4.3.4
+ // http://bugs.php.net/bug.php?id=25404
+
+ var $uniqueIisR = true;
+ var $_bindInputArray = false; // requires postgresql 7.3+ and ability to modify database
+ var $disableBlobs = false; // set to true to disable blob checking, resulting in 2-5% improvement in performance.
+
+ var $_pnum = 0;
+
+ // The last (fmtTimeStamp is not entirely correct:
+ // PostgreSQL also has support for time zones,
+ // and writes these time in this format: "2001-03-01 18:59:26+02".
+ // There is no code for the "+02" time zone information, so I just left that out.
+ // I'm not familiar enough with both ADODB as well as Postgres
+ // to know what the concequences are. The other values are correct (wheren't in 0.94)
+ // -- Freek Dijkstra
+
+ function __construct()
+ {
+ // changes the metaColumnsSQL, adds columns: attnum[6]
+ }
+
+ function ServerInfo()
+ {
+ if (isset($this->version)) return $this->version;
+
+ $arr['description'] = $this->GetOne("select version()");
+ $arr['version'] = ADOConnection::_findvers($arr['description']);
+ $this->version = $arr;
+ return $arr;
+ }
+
+ function IfNull( $field, $ifNull )
+ {
+ return " coalesce($field, $ifNull) ";
+ }
+
+ // get the last id - never tested
+ function pg_insert_id($tablename,$fieldname)
+ {
+ $result=pg_query($this->_connectionID, 'SELECT last_value FROM '. $tablename .'_'. $fieldname .'_seq');
+ if ($result) {
+ $arr = @pg_fetch_row($result,0);
+ pg_free_result($result);
+ if (isset($arr[0])) return $arr[0];
+ }
+ return false;
+ }
+
+ /**
+ * Warning from http://www.php.net/manual/function.pg-getlastoid.php:
+ * Using a OID as a unique identifier is not generally wise.
+ * Unless you are very careful, you might end up with a tuple having
+ * a different OID if a database must be reloaded.
+ */
+ function _insertid($table,$column)
+ {
+ if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
+ $oid = pg_getlastoid($this->_resultid);
+ // to really return the id, we need the table and column-name, else we can only return the oid != id
+ return empty($table) || empty($column) ? $oid : $this->GetOne("SELECT $column FROM $table WHERE oid=".(int)$oid);
+ }
+
+ function _affectedrows()
+ {
+ if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
+ return pg_affected_rows($this->_resultid);
+ }
+
+
+ /**
+ * @return true/false
+ */
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ return pg_query($this->_connectionID, 'begin '.$this->_transmode);
+ }
+
+ function RowLock($tables,$where,$col='1 as adodbignore')
+ {
+ if (!$this->transCnt) $this->BeginTrans();
+ return $this->GetOne("select $col from $tables where $where for update");
+ }
+
+ // returns true/false.
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) return true;
+ if (!$ok) return $this->RollbackTrans();
+
+ $this->transCnt -= 1;
+ return pg_query($this->_connectionID, 'commit');
+ }
+
+ // returns true/false
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt -= 1;
+ return pg_query($this->_connectionID, 'rollback');
+ }
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ $info = $this->ServerInfo();
+ if ($info['version'] >= 7.3) {
+ $this->metaTablesSQL = "
+ select table_name,'T' from information_schema.tables where table_schema not in ( 'pg_catalog','information_schema')
+ union
+ select table_name,'V' from information_schema.views where table_schema not in ( 'pg_catalog','information_schema') ";
+ }
+ if ($mask) {
+ $save = $this->metaTablesSQL;
+ $mask = $this->qstr(strtolower($mask));
+ if ($info['version']>=7.3)
+ $this->metaTablesSQL = "
+ select table_name,'T' from information_schema.tables where table_name like $mask and table_schema not in ( 'pg_catalog','information_schema')
+ union
+ select table_name,'V' from information_schema.views where table_name like $mask and table_schema not in ( 'pg_catalog','information_schema') ";
+ else
+ $this->metaTablesSQL = "
+ select tablename,'T' from pg_tables where tablename like $mask
+ union
+ select viewname,'V' from pg_views where viewname like $mask";
+ }
+ $ret = ADOConnection::MetaTables($ttype,$showSchema);
+
+ if ($mask) {
+ $this->metaTablesSQL = $save;
+ }
+ return $ret;
+ }
+
+
+ // if magic quotes disabled, use pg_escape_string()
+ function qstr($s,$magic_quotes=false)
+ {
+ if (is_bool($s)) return $s ? 'true' : 'false';
+
+ if (!$magic_quotes) {
+ if (ADODB_PHPVER >= 0x5200 && $this->_connectionID) {
+ return "'".pg_escape_string($this->_connectionID,$s)."'";
+ }
+ if (ADODB_PHPVER >= 0x4200) {
+ return "'".pg_escape_string($s)."'";
+ }
+ if ($this->replaceQuote[0] == '\\'){
+ $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\\000"),$s);
+ }
+ return "'".str_replace("'",$this->replaceQuote,$s)."'";
+ }
+
+ // undo magic quotes for "
+ $s = str_replace('\\"','"',$s);
+ return "'$s'";
+ }
+
+
+
+ // Format date column in sql string given an input format that understands Y M D
+ function SQLDate($fmt, $col=false)
+ {
+ if (!$col) $col = $this->sysTimeStamp;
+ $s = 'TO_CHAR('.$col.",'";
+
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ $ch = $fmt[$i];
+ switch($ch) {
+ case 'Y':
+ case 'y':
+ $s .= 'YYYY';
+ break;
+ case 'Q':
+ case 'q':
+ $s .= 'Q';
+ break;
+
+ case 'M':
+ $s .= 'Mon';
+ break;
+
+ case 'm':
+ $s .= 'MM';
+ break;
+ case 'D':
+ case 'd':
+ $s .= 'DD';
+ break;
+
+ case 'H':
+ $s.= 'HH24';
+ break;
+
+ case 'h':
+ $s .= 'HH';
+ break;
+
+ case 'i':
+ $s .= 'MI';
+ break;
+
+ case 's':
+ $s .= 'SS';
+ break;
+
+ case 'a':
+ case 'A':
+ $s .= 'AM';
+ break;
+
+ case 'w':
+ $s .= 'D';
+ break;
+
+ case 'l':
+ $s .= 'DAY';
+ break;
+
+ case 'W':
+ $s .= 'WW';
+ break;
+
+ default:
+ // handle escape characters...
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ if (strpos('-/.:;, ',$ch) !== false) $s .= $ch;
+ else $s .= '"'.$ch.'"';
+
+ }
+ }
+ return $s. "')";
+ }
+
+
+
+ /*
+ * Load a Large Object from a file
+ * - the procedure stores the object id in the table and imports the object using
+ * postgres proprietary blob handling routines
+ *
+ * contributed by Mattia Rossi mattia@technologist.com
+ * modified for safe mode by juraj chlebec
+ */
+ function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
+ {
+ pg_query($this->_connectionID, 'begin');
+
+ $fd = fopen($path,'r');
+ $contents = fread($fd,filesize($path));
+ fclose($fd);
+
+ $oid = pg_lo_create($this->_connectionID);
+ $handle = pg_lo_open($this->_connectionID, $oid, 'w');
+ pg_lo_write($handle, $contents);
+ pg_lo_close($handle);
+
+ // $oid = pg_lo_import ($path);
+ pg_query($this->_connectionID, 'commit');
+ $rs = ADOConnection::UpdateBlob($table,$column,$oid,$where,$blobtype);
+ $rez = !empty($rs);
+ return $rez;
+ }
+
+ /*
+ * Deletes/Unlinks a Blob from the database, otherwise it
+ * will be left behind
+ *
+ * Returns TRUE on success or FALSE on failure.
+ *
+ * contributed by Todd Rogers todd#windfox.net
+ */
+ function BlobDelete( $blob )
+ {
+ pg_query($this->_connectionID, 'begin');
+ $result = @pg_lo_unlink($blob);
+ pg_query($this->_connectionID, 'commit');
+ return( $result );
+ }
+
+ /*
+ Hueristic - not guaranteed to work.
+ */
+ function GuessOID($oid)
+ {
+ if (strlen($oid)>16) return false;
+ return is_numeric($oid);
+ }
+
+ /*
+ * If an OID is detected, then we use pg_lo_* to open the oid file and read the
+ * real blob from the db using the oid supplied as a parameter. If you are storing
+ * blobs using bytea, we autodetect and process it so this function is not needed.
+ *
+ * contributed by Mattia Rossi mattia@technologist.com
+ *
+ * see http://www.postgresql.org/idocs/index.php?largeobjects.html
+ *
+ * Since adodb 4.54, this returns the blob, instead of sending it to stdout. Also
+ * added maxsize parameter, which defaults to $db->maxblobsize if not defined.
+ */
+ function BlobDecode($blob,$maxsize=false,$hastrans=true)
+ {
+ if (!$this->GuessOID($blob)) return $blob;
+
+ if ($hastrans) pg_query($this->_connectionID,'begin');
+ $fd = @pg_lo_open($this->_connectionID,$blob,'r');
+ if ($fd === false) {
+ if ($hastrans) pg_query($this->_connectionID,'commit');
+ return $blob;
+ }
+ if (!$maxsize) $maxsize = $this->maxblobsize;
+ $realblob = @pg_lo_read($fd,$maxsize);
+ @pg_loclose($fd);
+ if ($hastrans) pg_query($this->_connectionID,'commit');
+ return $realblob;
+ }
+
+ /*
+ See http://www.postgresql.org/idocs/index.php?datatype-binary.html
+
+ NOTE: SQL string literals (input strings) must be preceded with two backslashes
+ due to the fact that they must pass through two parsers in the PostgreSQL
+ backend.
+ */
+ function BlobEncode($blob)
+ {
+ if (ADODB_PHPVER >= 0x5200) return pg_escape_bytea($this->_connectionID, $blob);
+ if (ADODB_PHPVER >= 0x4200) return pg_escape_bytea($blob);
+
+ /*92=backslash, 0=null, 39=single-quote*/
+ $badch = array(chr(92),chr(0),chr(39)); # \ null '
+ $fixch = array('\\\\134','\\\\000','\\\\047');
+ return adodb_str_replace($badch,$fixch,$blob);
+
+ // note that there is a pg_escape_bytea function only for php 4.2.0 or later
+ }
+
+ // assumes bytea for blob, and varchar for clob
+ function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ {
+ if ($blobtype == 'CLOB') {
+ return $this->Execute("UPDATE $table SET $column=" . $this->qstr($val) . " WHERE $where");
+ }
+ // do not use bind params which uses qstr(), as blobencode() already quotes data
+ return $this->Execute("UPDATE $table SET $column='".$this->BlobEncode($val)."'::bytea WHERE $where");
+ }
+
+ function OffsetDate($dayFraction,$date=false)
+ {
+ if (!$date) $date = $this->sysDate;
+ else if (strncmp($date,"'",1) == 0) {
+ $len = strlen($date);
+ if (10 <= $len && $len <= 12) $date = 'date '.$date;
+ else $date = 'timestamp '.$date;
+ }
+
+
+ return "($date+interval'".($dayFraction * 1440)." minutes')";
+ #return "($date+interval'$dayFraction days')";
+ }
+
+ /**
+ * Generate the SQL to retrieve MetaColumns data
+ * @param string $table Table name
+ * @param string $schema Schema name (can be blank)
+ * @return string SQL statement to execute
+ */
+ protected function _generateMetaColumnsSQL($table, $schema)
+ {
+ if ($schema) {
+ return sprintf($this->metaColumnsSQL1, $table, $table, $schema);
+ }
+ else {
+ return sprintf($this->metaColumnsSQL, $table, $table, $schema);
+ }
+ }
+
+ // for schema support, pass in the $table param "$schema.$tabname".
+ // converts field names to lowercase, $upper is ignored
+ // see http://phplens.com/lens/lensforum/msgs.php?id=14018 for more info
+ function MetaColumns($table,$normalize=true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $schema = false;
+ $false = false;
+ $this->_findschema($table,$schema);
+
+ if ($normalize) $table = strtolower($table);
+
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
+
+ $rs = $this->Execute($this->_generateMetaColumnsSQL($table, $schema));
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+
+ if ($rs === false) {
+ return $false;
+ }
+ if (!empty($this->metaKeySQL)) {
+ // If we want the primary keys, we have to issue a separate query
+ // Of course, a modified version of the metaColumnsSQL query using a
+ // LEFT JOIN would have been much more elegant, but postgres does
+ // not support OUTER JOINS. So here is the clumsy way.
+
+ $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+
+ $rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));
+ // fetch all result in once for performance.
+ $keys = $rskey->GetArray();
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+
+ $rskey->Close();
+ unset($rskey);
+ }
+
+ $rsdefa = array();
+ if (!empty($this->metaDefaultsSQL)) {
+ $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+ $sql = sprintf($this->metaDefaultsSQL, ($table));
+ $rsdef = $this->Execute($sql);
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+
+ if ($rsdef) {
+ while (!$rsdef->EOF) {
+ $num = $rsdef->fields['num'];
+ $s = $rsdef->fields['def'];
+ if (strpos($s,'::')===false && substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */
+ $s = substr($s, 1);
+ $s = substr($s, 0, strlen($s) - 1);
+ }
+
+ $rsdefa[$num] = $s;
+ $rsdef->MoveNext();
+ }
+ } else {
+ ADOConnection::outp( "==> SQL => " . $sql);
+ }
+ unset($rsdef);
+ }
+
+ $retarr = array();
+ while (!$rs->EOF) {
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $fld->type = $rs->fields[1];
+ $fld->max_length = $rs->fields[2];
+ $fld->attnum = $rs->fields[6];
+
+ if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4;
+ if ($fld->max_length <= 0) $fld->max_length = -1;
+ if ($fld->type == 'numeric') {
+ $fld->scale = $fld->max_length & 0xFFFF;
+ $fld->max_length >>= 16;
+ }
+ // dannym
+ // 5 hasdefault; 6 num-of-column
+ $fld->has_default = ($rs->fields[5] == 't');
+ if ($fld->has_default) {
+ $fld->default_value = $rsdefa[$rs->fields[6]];
+ }
+
+ //Freek
+ $fld->not_null = $rs->fields[4] == 't';
+
+
+ // Freek
+ if (is_array($keys)) {
+ foreach($keys as $key) {
+ if ($fld->name == $key['column_name'] AND $key['primary_key'] == 't')
+ $fld->primary_key = true;
+ if ($fld->name == $key['column_name'] AND $key['unique_key'] == 't')
+ $fld->unique = true; // What name is more compatible?
+ }
+ }
+
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
+ else $retarr[($normalize) ? strtoupper($fld->name) : $fld->name] = $fld;
+
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ if (empty($retarr))
+ return $false;
+ else
+ return $retarr;
+
+ }
+
+ function Param($name,$type='C')
+ {
+ if ($name) {
+ $this->_pnum += 1;
+ } else {
+ // Reset param num if $name is false
+ $this->_pnum = 1;
+ }
+ return '$'.$this->_pnum;
+ }
+
+ function MetaIndexes ($table, $primary = FALSE, $owner = false)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $schema = false;
+ $this->_findschema($table,$schema);
+
+ if ($schema) { // requires pgsql 7.3+ - pg_namespace used.
+ $sql = '
+ SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
+ FROM pg_catalog.pg_class c
+ JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
+ JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
+ ,pg_namespace n
+ WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\'))
+ and c.relnamespace=c2.relnamespace
+ and c.relnamespace=n.oid
+ and n.nspname=\'%s\'';
+ } else {
+ $sql = '
+ SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
+ FROM pg_catalog.pg_class c
+ JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
+ JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
+ WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\'))';
+ }
+
+ if ($primary == FALSE) {
+ $sql .= ' AND i.indisprimary=false;';
+ }
+
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+
+ $rs = $this->Execute(sprintf($sql,$table,$table,$schema));
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ if (!is_object($rs)) {
+ $false = false;
+ return $false;
+ }
+
+ $col_names = $this->MetaColumnNames($table,true,true);
+ // 3rd param is use attnum,
+ // see https://sourceforge.net/p/adodb/bugs/45/
+ $indexes = array();
+ while ($row = $rs->FetchRow()) {
+ $columns = array();
+ foreach (explode(' ', $row[2]) as $col) {
+ $columns[] = $col_names[$col];
+ }
+
+ $indexes[$row[0]] = array(
+ 'unique' => ($row[1] == 't'),
+ 'columns' => $columns
+ );
+ }
+ return $indexes;
+ }
+
+ // returns true or false
+ //
+ // examples:
+ // $db->Connect("host=host1 user=user1 password=secret port=4341");
+ // $db->Connect('host1','user1','secret');
+ function _connect($str,$user='',$pwd='',$db='',$ctype=0)
+ {
+ if (!function_exists('pg_connect')) return null;
+
+ $this->_errorMsg = false;
+
+ if ($user || $pwd || $db) {
+ $user = adodb_addslashes($user);
+ $pwd = adodb_addslashes($pwd);
+ if (strlen($db) == 0) $db = 'template1';
+ $db = adodb_addslashes($db);
+ if ($str) {
+ $host = explode(":", $str);
+ if ($host[0]) $str = "host=".adodb_addslashes($host[0]);
+ else $str = '';
+ if (isset($host[1])) $str .= " port=$host[1]";
+ else if (!empty($this->port)) $str .= " port=".$this->port;
+ }
+ if ($user) $str .= " user=".$user;
+ if ($pwd) $str .= " password=".$pwd;
+ if ($db) $str .= " dbname=".$db;
+ }
+
+ //if ($user) $linea = "user=$user host=$linea password=$pwd dbname=$db port=5432";
+
+ if ($ctype === 1) { // persistent
+ $this->_connectionID = pg_pconnect($str);
+ } else {
+ if ($ctype === -1) { // nconnect, we trick pgsql ext by changing the connection str
+ static $ncnt;
+
+ if (empty($ncnt)) $ncnt = 1;
+ else $ncnt += 1;
+
+ $str .= str_repeat(' ',$ncnt);
+ }
+ $this->_connectionID = pg_connect($str);
+ }
+ if ($this->_connectionID === false) return false;
+ $this->Execute("set datestyle='ISO'");
+
+ $info = $this->ServerInfo();
+ $this->pgVersion = (float) substr($info['version'],0,3);
+ if ($this->pgVersion >= 7.1) { // good till version 999
+ $this->_nestedSQL = true;
+ }
+
+ # PostgreSQL 9.0 changed the default output for bytea from 'escape' to 'hex'
+ # PHP does not handle 'hex' properly ('x74657374' is returned as 't657374')
+ # https://bugs.php.net/bug.php?id=59831 states this is in fact not a bug,
+ # so we manually set bytea_output
+ if ( !empty($this->connection->noBlobs) && version_compare($info['version'], '9.0', '>=')) {
+ $this->Execute('set bytea_output=escape');
+ }
+
+ return true;
+ }
+
+ function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
+ {
+ return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName,-1);
+ }
+
+ // returns true or false
+ //
+ // examples:
+ // $db->PConnect("host=host1 user=user1 password=secret port=4341");
+ // $db->PConnect('host1','user1','secret');
+ function _pconnect($str,$user='',$pwd='',$db='')
+ {
+ return $this->_connect($str,$user,$pwd,$db,1);
+ }
+
+
+ // returns queryID or false
+ function _query($sql,$inputarr=false)
+ {
+ $this->_pnum = 0;
+ $this->_errorMsg = false;
+ if ($inputarr) {
+ /*
+ It appears that PREPARE/EXECUTE is slower for many queries.
+
+ For query executed 1000 times:
+ "select id,firstname,lastname from adoxyz
+ where firstname not like ? and lastname not like ? and id = ?"
+
+ with plan = 1.51861286163 secs
+ no plan = 1.26903700829 secs
+ */
+ $plan = 'P'.md5($sql);
+
+ $execp = '';
+ foreach($inputarr as $v) {
+ if ($execp) $execp .= ',';
+ if (is_string($v)) {
+ if (strncmp($v,"'",1) !== 0) $execp .= $this->qstr($v);
+ } else {
+ $execp .= $v;
+ }
+ }
+
+ if ($execp) $exsql = "EXECUTE $plan ($execp)";
+ else $exsql = "EXECUTE $plan";
+
+
+ $rez = @pg_execute($this->_connectionID,$exsql);
+ if (!$rez) {
+ # Perhaps plan does not exist? Prepare/compile plan.
+ $params = '';
+ foreach($inputarr as $v) {
+ if ($params) $params .= ',';
+ if (is_string($v)) {
+ $params .= 'VARCHAR';
+ } else if (is_integer($v)) {
+ $params .= 'INTEGER';
+ } else {
+ $params .= "REAL";
+ }
+ }
+ $sqlarr = explode('?',$sql);
+ //print_r($sqlarr);
+ $sql = '';
+ $i = 1;
+ foreach($sqlarr as $v) {
+ $sql .= $v.' $'.$i;
+ $i++;
+ }
+ $s = "PREPARE $plan ($params) AS ".substr($sql,0,strlen($sql)-2);
+ //adodb_pr($s);
+ $rez = pg_execute($this->_connectionID,$s);
+ //echo $this->ErrorMsg();
+ }
+ if ($rez)
+ $rez = pg_execute($this->_connectionID,$exsql);
+ } else {
+ //adodb_backtrace();
+ $rez = pg_query($this->_connectionID,$sql);
+ }
+ // check if no data returned, then no need to create real recordset
+ if ($rez && pg_num_fields($rez) <= 0) {
+ if (is_resource($this->_resultid) && get_resource_type($this->_resultid) === 'pgsql result') {
+ pg_free_result($this->_resultid);
+ }
+ $this->_resultid = $rez;
+ return true;
+ }
+
+ return $rez;
+ }
+
+ function _errconnect()
+ {
+ if (defined('DB_ERROR_CONNECT_FAILED')) return DB_ERROR_CONNECT_FAILED;
+ else return 'Database connection failed';
+ }
+
+ /* Returns: the last error message from previous database operation */
+ function ErrorMsg()
+ {
+ if ($this->_errorMsg !== false) return $this->_errorMsg;
+ if (ADODB_PHPVER >= 0x4300) {
+ if (!empty($this->_resultid)) {
+ $this->_errorMsg = @pg_result_error($this->_resultid);
+ if ($this->_errorMsg) return $this->_errorMsg;
+ }
+
+ if (!empty($this->_connectionID)) {
+ $this->_errorMsg = @pg_last_error($this->_connectionID);
+ } else $this->_errorMsg = $this->_errconnect();
+ } else {
+ if (empty($this->_connectionID)) $this->_errconnect();
+ else $this->_errorMsg = @pg_errormessage($this->_connectionID);
+ }
+ return $this->_errorMsg;
+ }
+
+ function ErrorNo()
+ {
+ $e = $this->ErrorMsg();
+ if (strlen($e)) {
+ return ADOConnection::MetaError($e);
+ }
+ return 0;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ if ($this->transCnt) $this->RollbackTrans();
+ if ($this->_resultid) {
+ @pg_free_result($this->_resultid);
+ $this->_resultid = false;
+ }
+ @pg_close($this->_connectionID);
+ $this->_connectionID = false;
+ return true;
+ }
+
+
+ /*
+ * Maximum size of C field
+ */
+ function CharMax()
+ {
+ return 1000000000; // should be 1 Gb?
+ }
+
+ /*
+ * Maximum size of X field
+ */
+ function TextMax()
+ {
+ return 1000000000; // should be 1 Gb?
+ }
+
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_postgres64 extends ADORecordSet{
+ var $_blobArr;
+ var $databaseType = "postgres64";
+ var $canSeek = true;
+
+ function __construct($queryID, $mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ switch ($mode)
+ {
+ case ADODB_FETCH_NUM: $this->fetchMode = PGSQL_NUM; break;
+ case ADODB_FETCH_ASSOC:$this->fetchMode = PGSQL_ASSOC; break;
+
+ case ADODB_FETCH_DEFAULT:
+ case ADODB_FETCH_BOTH:
+ default: $this->fetchMode = PGSQL_BOTH; break;
+ }
+ $this->adodbFetchMode = $mode;
+
+ // Parent's constructor
+ parent::__construct($queryID);
+ }
+
+ function GetRowAssoc($upper = ADODB_ASSOC_CASE)
+ {
+ if ($this->fetchMode == PGSQL_ASSOC && $upper == ADODB_ASSOC_CASE_LOWER) {
+ return $this->fields;
+ }
+ $row = ADORecordSet::GetRowAssoc($upper);
+ return $row;
+ }
+
+
+ function _initrs()
+ {
+ global $ADODB_COUNTRECS;
+ $qid = $this->_queryID;
+ $this->_numOfRows = ($ADODB_COUNTRECS)? @pg_num_rows($qid):-1;
+ $this->_numOfFields = @pg_num_fields($qid);
+
+ // cache types for blob decode check
+ // apparently pg_field_type actually performs an sql query on the database to get the type.
+ if (empty($this->connection->noBlobs))
+ for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
+ if (pg_field_type($qid,$i) == 'bytea') {
+ $this->_blobArr[$i] = pg_field_name($qid,$i);
+ }
+ }
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode != PGSQL_NUM) return @$this->fields[$colname];
+
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+ function FetchField($off = 0)
+ {
+ // offsets begin at 0
+
+ $o= new ADOFieldObject();
+ $o->name = @pg_field_name($this->_queryID,$off);
+ $o->type = @pg_field_type($this->_queryID,$off);
+ $o->max_length = @pg_fieldsize($this->_queryID,$off);
+ return $o;
+ }
+
+ function _seek($row)
+ {
+ return @pg_fetch_row($this->_queryID,$row);
+ }
+
+ function _decode($blob)
+ {
+ if ($blob === NULL) return NULL;
+// eval('$realblob="'.adodb_str_replace(array('"','$'),array('\"','\$'),$blob).'";');
+ return pg_unescape_bytea($blob);
+ }
+
+ function _fixblobs()
+ {
+ if ($this->fetchMode == PGSQL_NUM || $this->fetchMode == PGSQL_BOTH) {
+ foreach($this->_blobArr as $k => $v) {
+ $this->fields[$k] = ADORecordSet_postgres64::_decode($this->fields[$k]);
+ }
+ }
+ if ($this->fetchMode == PGSQL_ASSOC || $this->fetchMode == PGSQL_BOTH) {
+ foreach($this->_blobArr as $k => $v) {
+ $this->fields[$v] = ADORecordSet_postgres64::_decode($this->fields[$v]);
+ }
+ }
+ }
+
+ // 10% speedup to move MoveNext to child class
+ function MoveNext()
+ {
+ if (!$this->EOF) {
+ $this->_currentRow++;
+ if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) {
+ $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
+ if (is_array($this->fields) && $this->fields) {
+ if (isset($this->_blobArr)) $this->_fixblobs();
+ return true;
+ }
+ }
+ $this->fields = false;
+ $this->EOF = true;
+ }
+ return false;
+ }
+
+ function _fetch()
+ {
+
+ if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0)
+ return false;
+
+ $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
+
+ if ($this->fields && isset($this->_blobArr)) $this->_fixblobs();
+
+ return (is_array($this->fields));
+ }
+
+ function _close()
+ {
+ return @pg_free_result($this->_queryID);
+ }
+
+ function MetaType($t,$len=-1,$fieldobj=false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+ switch (strtoupper($t)) {
+ case 'MONEY': // stupid, postgres expects money to be a string
+ case 'INTERVAL':
+ case 'CHAR':
+ case 'CHARACTER':
+ case 'VARCHAR':
+ case 'NAME':
+ case 'BPCHAR':
+ case '_VARCHAR':
+ case 'INET':
+ case 'MACADDR':
+ if ($len <= $this->blobSize) return 'C';
+
+ case 'TEXT':
+ return 'X';
+
+ case 'IMAGE': // user defined type
+ case 'BLOB': // user defined type
+ case 'BIT': // This is a bit string, not a single bit, so don't return 'L'
+ case 'VARBIT':
+ case 'BYTEA':
+ return 'B';
+
+ case 'BOOL':
+ case 'BOOLEAN':
+ return 'L';
+
+ case 'DATE':
+ return 'D';
+
+
+ case 'TIMESTAMP WITHOUT TIME ZONE':
+ case 'TIME':
+ case 'DATETIME':
+ case 'TIMESTAMP':
+ case 'TIMESTAMPTZ':
+ return 'T';
+
+ case 'SMALLINT':
+ case 'BIGINT':
+ case 'INTEGER':
+ case 'INT8':
+ case 'INT4':
+ case 'INT2':
+ if (isset($fieldobj) &&
+ empty($fieldobj->primary_key) && (!$this->connection->uniqueIisR || empty($fieldobj->unique))) return 'I';
+
+ case 'OID':
+ case 'SERIAL':
+ return 'R';
+
+ default:
+ return 'N';
+ }
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-postgres7.inc.php b/vendor/adodb/adodb-php/drivers/adodb-postgres7.inc.php
new file mode 100644
index 0000000..55a5e5c
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-postgres7.inc.php
@@ -0,0 +1,388 @@
+<?php
+/*
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 4.
+
+ Postgres7 support.
+ 28 Feb 2001: Currently indicate that we support LIMIT
+ 01 Dec 2001: dannym added support for default values
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR."/drivers/adodb-postgres64.inc.php");
+
+class ADODB_postgres7 extends ADODB_postgres64 {
+ var $databaseType = 'postgres7';
+ var $hasLimit = true; // set to true for pgsql 6.5+ only. support pgsql/mysql SELECT * FROM TABLE LIMIT 10
+ var $ansiOuter = true;
+ var $charSet = true; //set to true for Postgres 7 and above - PG client supports encodings
+
+ // Richard 3/18/2012 - Modified SQL to return SERIAL type correctly AS old driver no longer return SERIAL as data type.
+ var $metaColumnsSQL = "
+ SELECT
+ a.attname,
+ CASE
+ WHEN x.sequence_name != ''
+ THEN 'SERIAL'
+ ELSE t.typname
+ END AS typname,
+ a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum
+ FROM
+ pg_class c,
+ pg_attribute a
+ JOIN pg_type t ON a.atttypid = t.oid
+ LEFT JOIN (
+ SELECT
+ c.relname as sequence_name,
+ c1.relname as related_table,
+ a.attname as related_column
+ FROM pg_class c
+ JOIN pg_depend d ON d.objid = c.oid
+ LEFT JOIN pg_class c1 ON d.refobjid = c1.oid
+ LEFT JOIN pg_attribute a ON (d.refobjid, d.refobjsubid) = (a.attrelid, a.attnum)
+ WHERE c.relkind = 'S' AND c1.relname = '%s'
+ ) x ON x.related_column= a.attname
+ WHERE
+ c.relkind in ('r','v')
+ AND (c.relname='%s' or c.relname = lower('%s'))
+ AND a.attname not like '....%%'
+ AND a.attnum > 0
+ AND a.attrelid = c.oid
+ ORDER BY
+ a.attnum";
+
+ // used when schema defined
+ var $metaColumnsSQL1 = "
+ SELECT
+ a.attname,
+ CASE
+ WHEN x.sequence_name != ''
+ THEN 'SERIAL'
+ ELSE t.typname
+ END AS typname,
+ a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum
+ FROM
+ pg_class c,
+ pg_namespace n,
+ pg_attribute a
+ JOIN pg_type t ON a.atttypid = t.oid
+ LEFT JOIN (
+ SELECT
+ c.relname as sequence_name,
+ c1.relname as related_table,
+ a.attname as related_column
+ FROM pg_class c
+ JOIN pg_depend d ON d.objid = c.oid
+ LEFT JOIN pg_class c1 ON d.refobjid = c1.oid
+ LEFT JOIN pg_attribute a ON (d.refobjid, d.refobjsubid) = (a.attrelid, a.attnum)
+ WHERE c.relkind = 'S' AND c1.relname = '%s'
+ ) x ON x.related_column= a.attname
+ WHERE
+ c.relkind in ('r','v')
+ AND (c.relname='%s' or c.relname = lower('%s'))
+ AND c.relnamespace=n.oid and n.nspname='%s'
+ AND a.attname not like '....%%'
+ AND a.attnum > 0
+ AND a.atttypid = t.oid
+ AND a.attrelid = c.oid
+ ORDER BY a.attnum";
+
+
+ function __construct()
+ {
+ parent::__construct();
+ if (ADODB_ASSOC_CASE !== ADODB_ASSOC_CASE_NATIVE) {
+ $this->rsPrefix .= 'assoc_';
+ }
+ $this->_bindInputArray = PHP_VERSION >= 5.1;
+ }
+
+
+ // the following should be compat with postgresql 7.2,
+ // which makes obsolete the LIMIT limit,offset syntax
+ function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ $offsetStr = ($offset >= 0) ? " OFFSET ".((integer)$offset) : '';
+ $limitStr = ($nrows >= 0) ? " LIMIT ".((integer)$nrows) : '';
+ if ($secs2cache)
+ $rs = $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);
+ else
+ $rs = $this->Execute($sql."$limitStr$offsetStr",$inputarr);
+
+ return $rs;
+ }
+
+ /*
+ function Prepare($sql)
+ {
+ $info = $this->ServerInfo();
+ if ($info['version']>=7.3) {
+ return array($sql,false);
+ }
+ return $sql;
+ }
+ */
+
+ /**
+ * Generate the SQL to retrieve MetaColumns data
+ * @param string $table Table name
+ * @param string $schema Schema name (can be blank)
+ * @return string SQL statement to execute
+ */
+ protected function _generateMetaColumnsSQL($table, $schema)
+ {
+ if ($schema) {
+ return sprintf($this->metaColumnsSQL1, $table, $table, $table, $schema);
+ }
+ else {
+ return sprintf($this->metaColumnsSQL, $table, $table, $schema);
+ }
+ }
+
+ /**
+ * @returns assoc array where keys are tables, and values are foreign keys
+ */
+ function MetaForeignKeys($table, $owner=false, $upper=false)
+ {
+ # Regex isolates the 2 terms between parenthesis using subexpressions
+ $regex = '^.*\((.*)\).*\((.*)\).*$';
+ $sql="
+ SELECT
+ lookup_table,
+ regexp_replace(consrc, '$regex', '\\2') AS lookup_field,
+ dep_table,
+ regexp_replace(consrc, '$regex', '\\1') AS dep_field
+ FROM (
+ SELECT
+ pg_get_constraintdef(c.oid) AS consrc,
+ t.relname AS dep_table,
+ ft.relname AS lookup_table
+ FROM pg_constraint c
+ JOIN pg_class t ON (t.oid = c.conrelid)
+ JOIN pg_class ft ON (ft.oid = c.confrelid)
+ JOIN pg_namespace nft ON (nft.oid = ft.relnamespace)
+ LEFT JOIN pg_description ds ON (ds.objoid = c.oid)
+ JOIN pg_namespace n ON (n.oid = t.relnamespace)
+ WHERE c.contype = 'f'::\"char\"
+ ORDER BY t.relname, n.nspname, c.conname, c.oid
+ ) constraints
+ WHERE
+ dep_table='".strtolower($table)."'
+ ORDER BY
+ lookup_table,
+ dep_table,
+ dep_field";
+ $rs = $this->Execute($sql);
+
+ if (!$rs || $rs->EOF) return false;
+
+ $a = array();
+ while (!$rs->EOF) {
+ if ($upper) {
+ $a[strtoupper($rs->Fields('lookup_table'))][] = strtoupper(str_replace('"','',$rs->Fields('dep_field').'='.$rs->Fields('lookup_field')));
+ } else {
+ $a[$rs->Fields('lookup_table')][] = str_replace('"','',$rs->Fields('dep_field').'='.$rs->Fields('lookup_field'));
+ }
+ $rs->MoveNext();
+ }
+
+ return $a;
+
+ }
+
+ // from Edward Jaramilla, improved version - works on pg 7.4
+ function _old_MetaForeignKeys($table, $owner=false, $upper=false)
+ {
+ $sql = 'SELECT t.tgargs as args
+ FROM
+ pg_trigger t,pg_class c,pg_proc p
+ WHERE
+ t.tgenabled AND
+ t.tgrelid = c.oid AND
+ t.tgfoid = p.oid AND
+ p.proname = \'RI_FKey_check_ins\' AND
+ c.relname = \''.strtolower($table).'\'
+ ORDER BY
+ t.tgrelid';
+
+ $rs = $this->Execute($sql);
+
+ if (!$rs || $rs->EOF) return false;
+
+ $arr = $rs->GetArray();
+ $a = array();
+ foreach($arr as $v) {
+ $data = explode(chr(0), $v['args']);
+ $size = count($data)-1; //-1 because the last node is empty
+ for($i = 4; $i < $size; $i++) {
+ if ($upper)
+ $a[strtoupper($data[2])][] = strtoupper($data[$i].'='.$data[++$i]);
+ else
+ $a[$data[2]][] = $data[$i].'='.$data[++$i];
+ }
+ }
+ return $a;
+ }
+
+ function _query($sql,$inputarr=false)
+ {
+ if (! $this->_bindInputArray) {
+ // We don't have native support for parameterized queries, so let's emulate it at the parent
+ return ADODB_postgres64::_query($sql, $inputarr);
+ }
+
+ $this->_pnum = 0;
+ $this->_errorMsg = false;
+ // -- added Cristiano da Cunha Duarte
+ if ($inputarr) {
+ $sqlarr = explode('?',trim($sql));
+ $sql = '';
+ $i = 1;
+ $last = sizeof($sqlarr)-1;
+ foreach($sqlarr as $v) {
+ if ($last < $i) $sql .= $v;
+ else $sql .= $v.' $'.$i;
+ $i++;
+ }
+
+ $rez = pg_query_params($this->_connectionID,$sql, $inputarr);
+ } else {
+ $rez = pg_query($this->_connectionID,$sql);
+ }
+ // check if no data returned, then no need to create real recordset
+ if ($rez && pg_num_fields($rez) <= 0) {
+ if (is_resource($this->_resultid) && get_resource_type($this->_resultid) === 'pgsql result') {
+ pg_free_result($this->_resultid);
+ }
+ $this->_resultid = $rez;
+ return true;
+ }
+ return $rez;
+ }
+
+ // this is a set of functions for managing client encoding - very important if the encodings
+ // of your database and your output target (i.e. HTML) don't match
+ //for instance, you may have UNICODE database and server it on-site as WIN1251 etc.
+ // GetCharSet - get the name of the character set the client is using now
+ // the functions should work with Postgres 7.0 and above, the set of charsets supported
+ // depends on compile flags of postgres distribution - if no charsets were compiled into the server
+ // it will return 'SQL_ANSI' always
+ function GetCharSet()
+ {
+ //we will use ADO's builtin property charSet
+ $this->charSet = @pg_client_encoding($this->_connectionID);
+ if (!$this->charSet) {
+ return false;
+ } else {
+ return $this->charSet;
+ }
+ }
+
+ // SetCharSet - switch the client encoding
+ function SetCharSet($charset_name)
+ {
+ $this->GetCharSet();
+ if ($this->charSet !== $charset_name) {
+ $if = pg_set_client_encoding($this->_connectionID, $charset_name);
+ if ($if == "0" & $this->GetCharSet() == $charset_name) {
+ return true;
+ } else return false;
+ } else return true;
+ }
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_postgres7 extends ADORecordSet_postgres64{
+
+ var $databaseType = "postgres7";
+
+
+ function __construct($queryID, $mode=false)
+ {
+ parent::__construct($queryID, $mode);
+ }
+
+ // 10% speedup to move MoveNext to child class
+ function MoveNext()
+ {
+ if (!$this->EOF) {
+ $this->_currentRow++;
+ if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) {
+ $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
+
+ if (is_array($this->fields)) {
+ if ($this->fields && isset($this->_blobArr)) $this->_fixblobs();
+ return true;
+ }
+ }
+ $this->fields = false;
+ $this->EOF = true;
+ }
+ return false;
+ }
+
+}
+
+class ADORecordSet_assoc_postgres7 extends ADORecordSet_postgres64{
+
+ var $databaseType = "postgres7";
+
+
+ function __construct($queryID, $mode=false)
+ {
+ parent::__construct($queryID, $mode);
+ }
+
+ function _fetch()
+ {
+ if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0) {
+ return false;
+ }
+
+ $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
+
+ if ($this->fields) {
+ if (isset($this->_blobArr)) $this->_fixblobs();
+ $this->_updatefields();
+ }
+
+ return (is_array($this->fields));
+ }
+
+ function MoveNext()
+ {
+ if (!$this->EOF) {
+ $this->_currentRow++;
+ if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) {
+ $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
+
+ if (is_array($this->fields)) {
+ if ($this->fields) {
+ if (isset($this->_blobArr)) $this->_fixblobs();
+
+ $this->_updatefields();
+ }
+ return true;
+ }
+ }
+
+
+ $this->fields = false;
+ $this->EOF = true;
+ }
+ return false;
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-postgres8.inc.php b/vendor/adodb/adodb-php/drivers/adodb-postgres8.inc.php
new file mode 100644
index 0000000..f1b8576
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-postgres8.inc.php
@@ -0,0 +1,50 @@
+<?php
+/*
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 4.
+
+ Postgres8 support.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR."/drivers/adodb-postgres7.inc.php");
+
+class ADODB_postgres8 extends ADODB_postgres7
+{
+ var $databaseType = 'postgres8';
+
+
+ /**
+ * Retrieve last inserted ID
+ * Don't use OIDs, since as per {@link http://php.net/function.pg-last-oid php manual }
+ * they won't be there in Postgres 8.1
+ * (and they're not what the application wants back, anyway).
+ * @param string $table
+ * @param string $column
+ * @return int last inserted ID for given table/column, or the most recently
+ * returned one if $table or $column are empty
+ */
+ function _insertid($table, $column)
+ {
+ return empty($table) || empty($column)
+ ? $this->GetOne("SELECT lastval()")
+ : $this->GetOne("SELECT currval(pg_get_serial_sequence('$table', '$column'))");
+ }
+}
+
+class ADORecordSet_postgres8 extends ADORecordSet_postgres7
+{
+ var $databaseType = "postgres8";
+}
+
+class ADORecordSet_assoc_postgres8 extends ADORecordSet_assoc_postgres7
+{
+ var $databaseType = "postgres8";
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-postgres9.inc.php b/vendor/adodb/adodb-php/drivers/adodb-postgres9.inc.php
new file mode 100644
index 0000000..72ddb9a
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-postgres9.inc.php
@@ -0,0 +1,32 @@
+<?php
+/*
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 4.
+
+ Postgres9 support.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR."/drivers/adodb-postgres8.inc.php");
+
+class ADODB_postgres9 extends ADODB_postgres8
+{
+ var $databaseType = 'postgres9';
+}
+
+class ADORecordSet_postgres9 extends ADORecordSet_postgres8
+{
+ var $databaseType = "postgres9";
+}
+
+class ADORecordSet_assoc_postgres9 extends ADORecordSet_assoc_postgres8
+{
+ var $databaseType = "postgres9";
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-proxy.inc.php b/vendor/adodb/adodb-php/drivers/adodb-proxy.inc.php
new file mode 100644
index 0000000..79ba006
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-proxy.inc.php
@@ -0,0 +1,33 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 4.
+
+ Synonym for csv driver.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (! defined("_ADODB_PROXY_LAYER")) {
+ define("_ADODB_PROXY_LAYER", 1 );
+ include(ADODB_DIR."/drivers/adodb-csv.inc.php");
+
+ class ADODB_proxy extends ADODB_csv {
+ var $databaseType = 'proxy';
+ var $databaseProvider = 'csv';
+ }
+ class ADORecordset_proxy extends ADORecordset_csv {
+ var $databaseType = "proxy";
+
+ function __construct($id,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+ };
+} // define
diff --git a/vendor/adodb/adodb-php/drivers/adodb-sapdb.inc.php b/vendor/adodb/adodb-php/drivers/adodb-sapdb.inc.php
new file mode 100644
index 0000000..4ab9ffb
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-sapdb.inc.php
@@ -0,0 +1,185 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ SAPDB data driver. Requires ODBC.
+
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (!defined('_ADODB_ODBC_LAYER')) {
+ include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
+}
+if (!defined('ADODB_SAPDB')){
+define('ADODB_SAPDB',1);
+
+class ADODB_SAPDB extends ADODB_odbc {
+ var $databaseType = "sapdb";
+ var $concat_operator = '||';
+ var $sysDate = 'DATE';
+ var $sysTimeStamp = 'TIMESTAMP';
+ var $fmtDate = "'Y-m-d'"; /// used by DBDate() as the default date format used by the database
+ var $fmtTimeStamp = "'Y-m-d H:i:s'"; /// used by DBTimeStamp as the default timestamp fmt.
+ var $hasInsertId = true;
+ var $_bindInputArray = true;
+
+ function __construct()
+ {
+ //if (strncmp(PHP_OS,'WIN',3) === 0) $this->curmode = SQL_CUR_USE_ODBC;
+ parent::__construct();
+ }
+
+ function ServerInfo()
+ {
+ $info = ADODB_odbc::ServerInfo();
+ if (!$info['version'] && preg_match('/([0-9.]+)/',$info['description'],$matches)) {
+ $info['version'] = $matches[1];
+ }
+ return $info;
+ }
+
+ function MetaPrimaryKeys($table, $owner = false)
+ {
+ $table = $this->Quote(strtoupper($table));
+
+ return $this->GetCol("SELECT columnname FROM COLUMNS WHERE tablename=$table AND mode='KEY' ORDER BY pos");
+ }
+
+ function MetaIndexes ($table, $primary = FALSE, $owner = false)
+ {
+ $table = $this->Quote(strtoupper($table));
+
+ $sql = "SELECT INDEXNAME,TYPE,COLUMNNAME FROM INDEXCOLUMNS ".
+ " WHERE TABLENAME=$table".
+ " ORDER BY INDEXNAME,COLUMNNO";
+
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+
+ $rs = $this->Execute($sql);
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ if (!is_object($rs)) {
+ return FALSE;
+ }
+
+ $indexes = array();
+ while ($row = $rs->FetchRow()) {
+ $indexes[$row[0]]['unique'] = $row[1] == 'UNIQUE';
+ $indexes[$row[0]]['columns'][] = $row[2];
+ }
+ if ($primary) {
+ $indexes['SYSPRIMARYKEYINDEX'] = array(
+ 'unique' => True, // by definition
+ 'columns' => $this->GetCol("SELECT columnname FROM COLUMNS WHERE tablename=$table AND mode='KEY' ORDER BY pos"),
+ );
+ }
+ return $indexes;
+ }
+
+ function MetaColumns ($table, $normalize = true)
+ {
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+ $table = $this->Quote(strtoupper($table));
+
+ $retarr = array();
+ foreach($this->GetAll("SELECT COLUMNNAME,DATATYPE,LEN,DEC,NULLABLE,MODE,\"DEFAULT\",CASE WHEN \"DEFAULT\" IS NULL THEN 0 ELSE 1 END AS HAS_DEFAULT FROM COLUMNS WHERE tablename=$table ORDER BY pos") as $column)
+ {
+ $fld = new ADOFieldObject();
+ $fld->name = $column[0];
+ $fld->type = $column[1];
+ $fld->max_length = $fld->type == 'LONG' ? 2147483647 : $column[2];
+ $fld->scale = $column[3];
+ $fld->not_null = $column[4] == 'NO';
+ $fld->primary_key = $column[5] == 'KEY';
+ if ($fld->has_default = $column[7]) {
+ if ($fld->primary_key && $column[6] == 'DEFAULT SERIAL (1)') {
+ $fld->auto_increment = true;
+ $fld->has_default = false;
+ } else {
+ $fld->default_value = $column[6];
+ switch($fld->type) {
+ case 'VARCHAR':
+ case 'CHARACTER':
+ case 'LONG':
+ $fld->default_value = $column[6];
+ break;
+ default:
+ $fld->default_value = trim($column[6]);
+ break;
+ }
+ }
+ }
+ $retarr[$fld->name] = $fld;
+ }
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ return $retarr;
+ }
+
+ function MetaColumnNames($table, $numIndexes = false, $useattnum = false)
+ {
+ $table = $this->Quote(strtoupper($table));
+
+ return $this->GetCol("SELECT columnname FROM COLUMNS WHERE tablename=$table ORDER BY pos");
+ }
+
+ // unlike it seems, this depends on the db-session and works in a multiuser environment
+ function _insertid($table,$column)
+ {
+ return empty($table) ? False : $this->GetOne("SELECT $table.CURRVAL FROM DUAL");
+ }
+
+ /*
+ SelectLimit implementation problems:
+
+ The following will return random 10 rows as order by performed after "WHERE rowno<10"
+ which is not ideal...
+
+ select * from table where rowno < 10 order by 1
+
+ This means that we have to use the adoconnection base class SelectLimit when
+ there is an "order by".
+
+ See http://listserv.sap.com/pipermail/sapdb.general/2002-January/010405.html
+ */
+
+};
+
+
+class ADORecordSet_sapdb extends ADORecordSet_odbc {
+
+ var $databaseType = "sapdb";
+
+ function __construct($id,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+}
+
+} //define
diff --git a/vendor/adodb/adodb-php/drivers/adodb-sqlanywhere.inc.php b/vendor/adodb/adodb-php/drivers/adodb-sqlanywhere.inc.php
new file mode 100644
index 0000000..80a7ace
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-sqlanywhere.inc.php
@@ -0,0 +1,165 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+reserved.
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ 21.02.2002 - Wade Johnson wade@wadejohnson.de
+ Extended ODBC class for Sybase SQLAnywhere.
+ 1) Added support to retrieve the last row insert ID on tables with
+ primary key column using autoincrement function.
+
+ 2) Added blob support. Usage:
+ a) create blob variable on db server:
+
+ $dbconn->create_blobvar($blobVarName);
+
+ b) load blob var from file. $filename must be complete path
+
+ $dbcon->load_blobvar_from_file($blobVarName, $filename);
+
+ c) Use the $blobVarName in SQL insert or update statement in the values
+ clause:
+
+ $recordSet = $dbconn->Execute('INSERT INTO tabname (idcol, blobcol) '
+ .
+ 'VALUES (\'test\', ' . $blobVarName . ')');
+
+ instead of loading blob from a file, you can also load from
+ an unformatted (raw) blob variable:
+ $dbcon->load_blobvar_from_var($blobVarName, $varName);
+
+ d) drop blob variable on db server to free up resources:
+ $dbconn->drop_blobvar($blobVarName);
+
+ Sybase_SQLAnywhere data driver. Requires ODBC.
+
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (!defined('_ADODB_ODBC_LAYER')) {
+ include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
+}
+
+if (!defined('ADODB_SYBASE_SQLANYWHERE')){
+
+ define('ADODB_SYBASE_SQLANYWHERE',1);
+
+ class ADODB_sqlanywhere extends ADODB_odbc {
+ var $databaseType = "sqlanywhere";
+ var $hasInsertID = true;
+
+ function _insertid() {
+ return $this->GetOne('select @@identity');
+ }
+
+ function create_blobvar($blobVarName) {
+ $this->Execute("create variable $blobVarName long binary");
+ return;
+ }
+
+ function drop_blobvar($blobVarName) {
+ $this->Execute("drop variable $blobVarName");
+ return;
+ }
+
+ function load_blobvar_from_file($blobVarName, $filename) {
+ $chunk_size = 1000;
+
+ $fd = fopen ($filename, "rb");
+
+ $integer_chunks = (integer)filesize($filename) / $chunk_size;
+ $modulus = filesize($filename) % $chunk_size;
+ if ($modulus != 0){
+ $integer_chunks += 1;
+ }
+
+ for($loop=1;$loop<=$integer_chunks;$loop++){
+ $contents = fread ($fd, $chunk_size);
+ $contents = bin2hex($contents);
+
+ $hexstring = '';
+
+ for($loop2=0;$loop2<strlen($contents);$loop2+=2){
+ $hexstring .= '\x' . substr($contents,$loop2,2);
+ }
+
+ $hexstring = $this->qstr($hexstring);
+
+ $this->Execute("set $blobVarName = $blobVarName || " . $hexstring);
+ }
+
+ fclose ($fd);
+ return;
+ }
+
+ function load_blobvar_from_var($blobVarName, &$varName) {
+ $chunk_size = 1000;
+
+ $integer_chunks = (integer)strlen($varName) / $chunk_size;
+ $modulus = strlen($varName) % $chunk_size;
+ if ($modulus != 0){
+ $integer_chunks += 1;
+ }
+
+ for($loop=1;$loop<=$integer_chunks;$loop++){
+ $contents = substr ($varName, (($loop - 1) * $chunk_size), $chunk_size);
+ $contents = bin2hex($contents);
+
+ $hexstring = '';
+
+ for($loop2=0;$loop2<strlen($contents);$loop2+=2){
+ $hexstring .= '\x' . substr($contents,$loop2,2);
+ }
+
+ $hexstring = $this->qstr($hexstring);
+
+ $this->Execute("set $blobVarName = $blobVarName || " . $hexstring);
+ }
+
+ return;
+ }
+
+ /*
+ Insert a null into the blob field of the table first.
+ Then use UpdateBlob to store the blob.
+
+ Usage:
+
+ $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
+ $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
+ */
+ function UpdateBlob($table,$column,&$val,$where,$blobtype='BLOB')
+ {
+ $blobVarName = 'hold_blob';
+ $this->create_blobvar($blobVarName);
+ $this->load_blobvar_from_var($blobVarName, $val);
+ $this->Execute("UPDATE $table SET $column=$blobVarName WHERE $where");
+ $this->drop_blobvar($blobVarName);
+ return true;
+ }
+ }; //class
+
+ class ADORecordSet_sqlanywhere extends ADORecordSet_odbc {
+
+ var $databaseType = "sqlanywhere";
+
+ function __construct($id,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+
+
+ }; //class
+
+
+} //define
diff --git a/vendor/adodb/adodb-php/drivers/adodb-sqlite.inc.php b/vendor/adodb/adodb-php/drivers/adodb-sqlite.inc.php
new file mode 100644
index 0000000..aa32223
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-sqlite.inc.php
@@ -0,0 +1,453 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+
+ Latest version is available at http://adodb.org/
+
+ SQLite info: http://www.hwaci.com/sw/sqlite/
+
+ Install Instructions:
+ ====================
+ 1. Place this in adodb/drivers
+ 2. Rename the file, remove the .txt prefix.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+class ADODB_sqlite extends ADOConnection {
+ var $databaseType = "sqlite";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $concat_operator='||';
+ var $_errorNo = 0;
+ var $hasLimit = true;
+ var $hasInsertID = true; /// supports autoincrement ID?
+ var $hasAffectedRows = true; /// supports affected rows for update/delete?
+ var $metaTablesSQL = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
+ var $sysDate = "adodb_date('Y-m-d')";
+ var $sysTimeStamp = "adodb_date('Y-m-d H:i:s')";
+ var $fmtTimeStamp = "'Y-m-d H:i:s'";
+
+ function __construct()
+ {
+ }
+
+ function ServerInfo()
+ {
+ $arr['version'] = sqlite_libversion();
+ $arr['description'] = 'SQLite ';
+ $arr['encoding'] = sqlite_libencoding();
+ return $arr;
+ }
+
+ function BeginTrans()
+ {
+ if ($this->transOff) {
+ return true;
+ }
+ $ret = $this->Execute("BEGIN TRANSACTION");
+ $this->transCnt += 1;
+ return true;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) {
+ return true;
+ }
+ if (!$ok) {
+ return $this->RollbackTrans();
+ }
+ $ret = $this->Execute("COMMIT");
+ if ($this->transCnt > 0) {
+ $this->transCnt -= 1;
+ }
+ return !empty($ret);
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) {
+ return true;
+ }
+ $ret = $this->Execute("ROLLBACK");
+ if ($this->transCnt > 0) {
+ $this->transCnt -= 1;
+ }
+ return !empty($ret);
+ }
+
+ // mark newnham
+ function MetaColumns($table, $normalize=true)
+ {
+ global $ADODB_FETCH_MODE;
+ $false = false;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+ if ($this->fetchMode !== false) {
+ $savem = $this->SetFetchMode(false);
+ }
+ $rs = $this->Execute("PRAGMA table_info('$table')");
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ if (!$rs) {
+ $ADODB_FETCH_MODE = $save;
+ return $false;
+ }
+ $arr = array();
+ while ($r = $rs->FetchRow()) {
+ $type = explode('(',$r['type']);
+ $size = '';
+ if (sizeof($type)==2) {
+ $size = trim($type[1],')');
+ }
+ $fn = strtoupper($r['name']);
+ $fld = new ADOFieldObject;
+ $fld->name = $r['name'];
+ $fld->type = $type[0];
+ $fld->max_length = $size;
+ $fld->not_null = $r['notnull'];
+ $fld->default_value = $r['dflt_value'];
+ $fld->scale = 0;
+ if (isset($r['pk']) && $r['pk']) {
+ $fld->primary_key=1;
+ }
+ if ($save == ADODB_FETCH_NUM) {
+ $arr[] = $fld;
+ } else {
+ $arr[strtoupper($fld->name)] = $fld;
+ }
+ }
+ $rs->Close();
+ $ADODB_FETCH_MODE = $save;
+ return $arr;
+ }
+
+ function _init($parentDriver)
+ {
+ $parentDriver->hasTransactions = false;
+ $parentDriver->hasInsertID = true;
+ }
+
+ function _insertid()
+ {
+ return sqlite_last_insert_rowid($this->_connectionID);
+ }
+
+ function _affectedrows()
+ {
+ return sqlite_changes($this->_connectionID);
+ }
+
+ function ErrorMsg()
+ {
+ if ($this->_logsql) {
+ return $this->_errorMsg;
+ }
+ return ($this->_errorNo) ? sqlite_error_string($this->_errorNo) : '';
+ }
+
+ function ErrorNo()
+ {
+ return $this->_errorNo;
+ }
+
+ function SQLDate($fmt, $col=false)
+ {
+ $fmt = $this->qstr($fmt);
+ return ($col) ? "adodb_date2($fmt,$col)" : "adodb_date($fmt)";
+ }
+
+
+ function _createFunctions()
+ {
+ @sqlite_create_function($this->_connectionID, 'adodb_date', 'adodb_date', 1);
+ @sqlite_create_function($this->_connectionID, 'adodb_date2', 'adodb_date2', 2);
+ }
+
+
+ // returns true or false
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('sqlite_open')) {
+ return null;
+ }
+ if (empty($argHostname) && $argDatabasename) {
+ $argHostname = $argDatabasename;
+ }
+
+ $this->_connectionID = sqlite_open($argHostname);
+ if ($this->_connectionID === false) {
+ return false;
+ }
+ $this->_createFunctions();
+ return true;
+ }
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('sqlite_open')) {
+ return null;
+ }
+ if (empty($argHostname) && $argDatabasename) {
+ $argHostname = $argDatabasename;
+ }
+
+ $this->_connectionID = sqlite_popen($argHostname);
+ if ($this->_connectionID === false) {
+ return false;
+ }
+ $this->_createFunctions();
+ return true;
+ }
+
+ // returns query ID if successful, otherwise false
+ function _query($sql,$inputarr=false)
+ {
+ $rez = sqlite_query($sql,$this->_connectionID);
+ if (!$rez) {
+ $this->_errorNo = sqlite_last_error($this->_connectionID);
+ }
+ // If no data was returned, we don't need to create a real recordset
+ // Note: this code is untested, as I don't have a sqlite2 setup available
+ elseif (sqlite_num_fields($rez) == 0) {
+ $rez = true;
+ }
+
+ return $rez;
+ }
+
+ function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ $offsetStr = ($offset >= 0) ? " OFFSET $offset" : '';
+ $limitStr = ($nrows >= 0) ? " LIMIT $nrows" : ($offset >= 0 ? ' LIMIT 999999999' : '');
+ if ($secs2cache) {
+ $rs = $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);
+ } else {
+ $rs = $this->Execute($sql."$limitStr$offsetStr",$inputarr);
+ }
+
+ return $rs;
+ }
+
+ /*
+ This algorithm is not very efficient, but works even if table locking
+ is not available.
+
+ Will return false if unable to generate an ID after $MAXLOOPS attempts.
+ */
+ var $_genSeqSQL = "create table %s (id integer)";
+
+ function GenID($seq='adodbseq',$start=1)
+ {
+ // if you have to modify the parameter below, your database is overloaded,
+ // or you need to implement generation of id's yourself!
+ $MAXLOOPS = 100;
+ //$this->debug=1;
+ while (--$MAXLOOPS>=0) {
+ @($num = $this->GetOne("select id from $seq"));
+ if ($num === false) {
+ $this->Execute(sprintf($this->_genSeqSQL ,$seq));
+ $start -= 1;
+ $num = '0';
+ $ok = $this->Execute("insert into $seq values($start)");
+ if (!$ok) {
+ return false;
+ }
+ }
+ $this->Execute("update $seq set id=id+1 where id=$num");
+
+ if ($this->affected_rows() > 0) {
+ $num += 1;
+ $this->genID = $num;
+ return $num;
+ }
+ }
+ if ($fn = $this->raiseErrorFn) {
+ $fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
+ }
+ return false;
+ }
+
+ function CreateSequence($seqname='adodbseq',$start=1)
+ {
+ if (empty($this->_genSeqSQL)) {
+ return false;
+ }
+ $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
+ if (!$ok) {
+ return false;
+ }
+ $start -= 1;
+ return $this->Execute("insert into $seqname values($start)");
+ }
+
+ var $_dropSeqSQL = 'drop table %s';
+ function DropSequence($seqname = 'adodbseq')
+ {
+ if (empty($this->_dropSeqSQL)) {
+ return false;
+ }
+ return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
+ }
+
+ // returns true or false
+ function _close()
+ {
+ return @sqlite_close($this->_connectionID);
+ }
+
+ function MetaIndexes($table, $primary = FALSE, $owner = false)
+ {
+ $false = false;
+ // save old fetch mode
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+ $SQL=sprintf("SELECT name,sql FROM sqlite_master WHERE type='index' AND tbl_name='%s'", strtolower($table));
+ $rs = $this->Execute($SQL);
+ if (!is_object($rs)) {
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+ return $false;
+ }
+
+ $indexes = array ();
+ while ($row = $rs->FetchRow()) {
+ if ($primary && preg_match("/primary/i",$row[1]) == 0) {
+ continue;
+ }
+ if (!isset($indexes[$row[0]])) {
+ $indexes[$row[0]] = array(
+ 'unique' => preg_match("/unique/i",$row[1]),
+ 'columns' => array()
+ );
+ }
+ /**
+ * There must be a more elegant way of doing this,
+ * the index elements appear in the SQL statement
+ * in cols[1] between parentheses
+ * e.g CREATE UNIQUE INDEX ware_0 ON warehouse (org,warehouse)
+ */
+ $cols = explode("(",$row[1]);
+ $cols = explode(")",$cols[1]);
+ array_pop($cols);
+ $indexes[$row[0]]['columns'] = $cols;
+ }
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ }
+ return $indexes;
+ }
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordset_sqlite extends ADORecordSet {
+
+ var $databaseType = "sqlite";
+ var $bind = false;
+
+ function __construct($queryID,$mode=false)
+ {
+
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ switch($mode) {
+ case ADODB_FETCH_NUM:
+ $this->fetchMode = SQLITE_NUM;
+ break;
+ case ADODB_FETCH_ASSOC:
+ $this->fetchMode = SQLITE_ASSOC;
+ break;
+ default:
+ $this->fetchMode = SQLITE_BOTH;
+ break;
+ }
+ $this->adodbFetchMode = $mode;
+
+ $this->_queryID = $queryID;
+
+ $this->_inited = true;
+ $this->fields = array();
+ if ($queryID) {
+ $this->_currentRow = 0;
+ $this->EOF = !$this->_fetch();
+ @$this->_initrs();
+ } else {
+ $this->_numOfRows = 0;
+ $this->_numOfFields = 0;
+ $this->EOF = true;
+ }
+
+ return $this->_queryID;
+ }
+
+
+ function FetchField($fieldOffset = -1)
+ {
+ $fld = new ADOFieldObject;
+ $fld->name = sqlite_field_name($this->_queryID, $fieldOffset);
+ $fld->type = 'VARCHAR';
+ $fld->max_length = -1;
+ return $fld;
+ }
+
+ function _initrs()
+ {
+ $this->_numOfRows = @sqlite_num_rows($this->_queryID);
+ $this->_numOfFields = @sqlite_num_fields($this->_queryID);
+ }
+
+ function Fields($colname)
+ {
+ if ($this->fetchMode != SQLITE_NUM) {
+ return $this->fields[$colname];
+ }
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+ function _seek($row)
+ {
+ return sqlite_seek($this->_queryID, $row);
+ }
+
+ function _fetch($ignore_fields=false)
+ {
+ $this->fields = @sqlite_fetch_array($this->_queryID,$this->fetchMode);
+ return !empty($this->fields);
+ }
+
+ function _close()
+ {
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-sqlite3.inc.php b/vendor/adodb/adodb-php/drivers/adodb-sqlite3.inc.php
new file mode 100644
index 0000000..1953c21
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-sqlite3.inc.php
@@ -0,0 +1,440 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+
+ Latest version is available at http://adodb.org/
+
+ SQLite info: http://www.hwaci.com/sw/sqlite/
+
+ Install Instructions:
+ ====================
+ 1. Place this in adodb/drivers
+ 2. Rename the file, remove the .txt prefix.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+class ADODB_sqlite3 extends ADOConnection {
+ var $databaseType = "sqlite3";
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $concat_operator='||';
+ var $_errorNo = 0;
+ var $hasLimit = true;
+ var $hasInsertID = true; /// supports autoincrement ID?
+ var $hasAffectedRows = true; /// supports affected rows for update/delete?
+ var $metaTablesSQL = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
+ var $sysDate = "adodb_date('Y-m-d')";
+ var $sysTimeStamp = "adodb_date('Y-m-d H:i:s')";
+ var $fmtTimeStamp = "'Y-m-d H:i:s'";
+
+ function __construct()
+ {
+ }
+
+ function ServerInfo()
+ {
+ $version = SQLite3::version();
+ $arr['version'] = $version['versionString'];
+ $arr['description'] = 'SQLite 3';
+ return $arr;
+ }
+
+ function BeginTrans()
+ {
+ if ($this->transOff) {
+ return true;
+ }
+ $ret = $this->Execute("BEGIN TRANSACTION");
+ $this->transCnt += 1;
+ return true;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) {
+ return true;
+ }
+ if (!$ok) {
+ return $this->RollbackTrans();
+ }
+ $ret = $this->Execute("COMMIT");
+ if ($this->transCnt > 0) {
+ $this->transCnt -= 1;
+ }
+ return !empty($ret);
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) {
+ return true;
+ }
+ $ret = $this->Execute("ROLLBACK");
+ if ($this->transCnt > 0) {
+ $this->transCnt -= 1;
+ }
+ return !empty($ret);
+ }
+
+ // mark newnham
+ function MetaColumns($table, $normalize=true)
+ {
+ global $ADODB_FETCH_MODE;
+ $false = false;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+ if ($this->fetchMode !== false) {
+ $savem = $this->SetFetchMode(false);
+ }
+ $rs = $this->Execute("PRAGMA table_info('$table')");
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ if (!$rs) {
+ $ADODB_FETCH_MODE = $save;
+ return $false;
+ }
+ $arr = array();
+ while ($r = $rs->FetchRow()) {
+ $type = explode('(',$r['type']);
+ $size = '';
+ if (sizeof($type)==2) {
+ $size = trim($type[1],')');
+ }
+ $fn = strtoupper($r['name']);
+ $fld = new ADOFieldObject;
+ $fld->name = $r['name'];
+ $fld->type = $type[0];
+ $fld->max_length = $size;
+ $fld->not_null = $r['notnull'];
+ $fld->default_value = $r['dflt_value'];
+ $fld->scale = 0;
+ if (isset($r['pk']) && $r['pk']) {
+ $fld->primary_key=1;
+ }
+ if ($save == ADODB_FETCH_NUM) {
+ $arr[] = $fld;
+ } else {
+ $arr[strtoupper($fld->name)] = $fld;
+ }
+ }
+ $rs->Close();
+ $ADODB_FETCH_MODE = $save;
+ return $arr;
+ }
+
+ function _init($parentDriver)
+ {
+ $parentDriver->hasTransactions = false;
+ $parentDriver->hasInsertID = true;
+ }
+
+ function _insertid()
+ {
+ return $this->_connectionID->lastInsertRowID();
+ }
+
+ function _affectedrows()
+ {
+ return $this->_connectionID->changes();
+ }
+
+ function ErrorMsg()
+ {
+ if ($this->_logsql) {
+ return $this->_errorMsg;
+ }
+ return ($this->_errorNo) ? $this->ErrorNo() : ''; //**tochange?
+ }
+
+ function ErrorNo()
+ {
+ return $this->_connectionID->lastErrorCode(); //**tochange??
+ }
+
+ function SQLDate($fmt, $col=false)
+ {
+ $fmt = $this->qstr($fmt);
+ return ($col) ? "adodb_date2($fmt,$col)" : "adodb_date($fmt)";
+ }
+
+
+ function _createFunctions()
+ {
+ $this->_connectionID->createFunction('adodb_date', 'adodb_date', 1);
+ $this->_connectionID->createFunction('adodb_date2', 'adodb_date2', 2);
+ }
+
+
+ // returns true or false
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (empty($argHostname) && $argDatabasename) {
+ $argHostname = $argDatabasename;
+ }
+ $this->_connectionID = new SQLite3($argHostname);
+ $this->_createFunctions();
+
+ return true;
+ }
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ // There's no permanent connect in SQLite3
+ return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
+ }
+
+ // returns query ID if successful, otherwise false
+ function _query($sql,$inputarr=false)
+ {
+ $rez = $this->_connectionID->query($sql);
+ if ($rez === false) {
+ $this->_errorNo = $this->_connectionID->lastErrorCode();
+ }
+ // If no data was returned, we don't need to create a real recordset
+ elseif ($rez->numColumns() == 0) {
+ $rez->finalize();
+ $rez = true;
+ }
+
+ return $rez;
+ }
+
+ function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
+ {
+ $nrows = (int) $nrows;
+ $offset = (int) $offset;
+ $offsetStr = ($offset >= 0) ? " OFFSET $offset" : '';
+ $limitStr = ($nrows >= 0) ? " LIMIT $nrows" : ($offset >= 0 ? ' LIMIT 999999999' : '');
+ if ($secs2cache) {
+ $rs = $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);
+ } else {
+ $rs = $this->Execute($sql."$limitStr$offsetStr",$inputarr);
+ }
+
+ return $rs;
+ }
+
+ /*
+ This algorithm is not very efficient, but works even if table locking
+ is not available.
+
+ Will return false if unable to generate an ID after $MAXLOOPS attempts.
+ */
+ var $_genSeqSQL = "create table %s (id integer)";
+
+ function GenID($seq='adodbseq',$start=1)
+ {
+ // if you have to modify the parameter below, your database is overloaded,
+ // or you need to implement generation of id's yourself!
+ $MAXLOOPS = 100;
+ //$this->debug=1;
+ while (--$MAXLOOPS>=0) {
+ @($num = $this->GetOne("select id from $seq"));
+ if ($num === false) {
+ $this->Execute(sprintf($this->_genSeqSQL ,$seq));
+ $start -= 1;
+ $num = '0';
+ $ok = $this->Execute("insert into $seq values($start)");
+ if (!$ok) {
+ return false;
+ }
+ }
+ $this->Execute("update $seq set id=id+1 where id=$num");
+
+ if ($this->affected_rows() > 0) {
+ $num += 1;
+ $this->genID = $num;
+ return $num;
+ }
+ }
+ if ($fn = $this->raiseErrorFn) {
+ $fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
+ }
+ return false;
+ }
+
+ function CreateSequence($seqname='adodbseq',$start=1)
+ {
+ if (empty($this->_genSeqSQL)) {
+ return false;
+ }
+ $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
+ if (!$ok) {
+ return false;
+ }
+ $start -= 1;
+ return $this->Execute("insert into $seqname values($start)");
+ }
+
+ var $_dropSeqSQL = 'drop table %s';
+ function DropSequence($seqname = 'adodbseq')
+ {
+ if (empty($this->_dropSeqSQL)) {
+ return false;
+ }
+ return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
+ }
+
+ // returns true or false
+ function _close()
+ {
+ return $this->_connectionID->close();
+ }
+
+ function MetaIndexes($table, $primary = FALSE, $owner = false)
+ {
+ $false = false;
+ // save old fetch mode
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+ $SQL=sprintf("SELECT name,sql FROM sqlite_master WHERE type='index' AND tbl_name='%s'", strtolower($table));
+ $rs = $this->Execute($SQL);
+ if (!is_object($rs)) {
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+ return $false;
+ }
+
+ $indexes = array ();
+ while ($row = $rs->FetchRow()) {
+ if ($primary && preg_match("/primary/i",$row[1]) == 0) {
+ continue;
+ }
+ if (!isset($indexes[$row[0]])) {
+ $indexes[$row[0]] = array(
+ 'unique' => preg_match("/unique/i",$row[1]),
+ 'columns' => array()
+ );
+ }
+ /**
+ * There must be a more elegant way of doing this,
+ * the index elements appear in the SQL statement
+ * in cols[1] between parentheses
+ * e.g CREATE UNIQUE INDEX ware_0 ON warehouse (org,warehouse)
+ */
+ $cols = explode("(",$row[1]);
+ $cols = explode(")",$cols[1]);
+ array_pop($cols);
+ $indexes[$row[0]]['columns'] = $cols;
+ }
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ }
+ return $indexes;
+ }
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordset_sqlite3 extends ADORecordSet {
+
+ var $databaseType = "sqlite3";
+ var $bind = false;
+
+ function __construct($queryID,$mode=false)
+ {
+
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ switch($mode) {
+ case ADODB_FETCH_NUM:
+ $this->fetchMode = SQLITE3_NUM;
+ break;
+ case ADODB_FETCH_ASSOC:
+ $this->fetchMode = SQLITE3_ASSOC;
+ break;
+ default:
+ $this->fetchMode = SQLITE3_BOTH;
+ break;
+ }
+ $this->adodbFetchMode = $mode;
+
+ $this->_queryID = $queryID;
+
+ $this->_inited = true;
+ $this->fields = array();
+ if ($queryID) {
+ $this->_currentRow = 0;
+ $this->EOF = !$this->_fetch();
+ @$this->_initrs();
+ } else {
+ $this->_numOfRows = 0;
+ $this->_numOfFields = 0;
+ $this->EOF = true;
+ }
+
+ return $this->_queryID;
+ }
+
+
+ function FetchField($fieldOffset = -1)
+ {
+ $fld = new ADOFieldObject;
+ $fld->name = $this->_queryID->columnName($fieldOffset);
+ $fld->type = 'VARCHAR';
+ $fld->max_length = -1;
+ return $fld;
+ }
+
+ function _initrs()
+ {
+ $this->_numOfFields = $this->_queryID->numColumns();
+
+ }
+
+ function Fields($colname)
+ {
+ if ($this->fetchMode != SQLITE3_NUM) {
+ return $this->fields[$colname];
+ }
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+ function _seek($row)
+ {
+ // sqlite3 does not implement seek
+ if ($this->debug) {
+ ADOConnection::outp("SQLite3 does not implement seek");
+ }
+ return false;
+ }
+
+ function _fetch($ignore_fields=false)
+ {
+ $this->fields = $this->_queryID->fetchArray($this->fetchMode);
+ return !empty($this->fields);
+ }
+
+ function _close()
+ {
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-sqlitepo.inc.php b/vendor/adodb/adodb-php/drivers/adodb-sqlitepo.inc.php
new file mode 100644
index 0000000..edf71ef
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-sqlitepo.inc.php
@@ -0,0 +1,58 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+
+ Portable version of sqlite driver, to make it more similar to other database drivers.
+ The main differences are
+
+ 1. When selecting (joining) multiple tables, in assoc mode the table
+ names are included in the assoc keys in the "sqlite" driver.
+
+ In "sqlitepo" driver, the table names are stripped from the returned column names.
+ When this results in a conflict, the first field get preference.
+
+ Contributed by Herman Kuiper herman#ozuzo.net
+*/
+
+if (!defined('ADODB_DIR')) die();
+
+include_once(ADODB_DIR.'/drivers/adodb-sqlite.inc.php');
+
+class ADODB_sqlitepo extends ADODB_sqlite {
+ var $databaseType = 'sqlitepo';
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordset_sqlitepo extends ADORecordset_sqlite {
+
+ var $databaseType = 'sqlitepo';
+
+ function __construct($queryID,$mode=false)
+ {
+ parent::__construct($queryID,$mode);
+ }
+
+ // Modified to strip table names from returned fields
+ function _fetch($ignore_fields=false)
+ {
+ $this->fields = array();
+ $fields = @sqlite_fetch_array($this->_queryID,$this->fetchMode);
+ if(is_array($fields))
+ foreach($fields as $n => $v)
+ {
+ if(($p = strpos($n, ".")) !== false)
+ $n = substr($n, $p+1);
+ $this->fields[$n] = $v;
+ }
+
+ return !empty($this->fields);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-sybase.inc.php b/vendor/adodb/adodb-php/drivers/adodb-sybase.inc.php
new file mode 100644
index 0000000..62aef61
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-sybase.inc.php
@@ -0,0 +1,445 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim. All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Sybase driver contributed by Toni (toni.tunkkari@finebyte.com)
+
+ - MSSQL date patch applied.
+
+ Date patch by Toni 15 Feb 2002
+*/
+
+ // security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+class ADODB_sybase extends ADOConnection {
+ var $databaseType = "sybase";
+ var $dataProvider = 'sybase';
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $fmtDate = "'Y-m-d'";
+ var $fmtTimeStamp = "'Y-m-d H:i:s'";
+ var $hasInsertID = true;
+ var $hasAffectedRows = true;
+ var $metaTablesSQL="select name from sysobjects where type='U' or type='V'";
+ // see http://sybooks.sybase.com/onlinebooks/group-aw/awg0800e/dbrfen8/@ebt-link;pt=5981;uf=0?target=0;window=new;showtoc=true;book=dbrfen8
+ var $metaColumnsSQL = "SELECT c.column_name, c.column_type, c.width FROM syscolumn c, systable t WHERE t.table_name='%s' AND c.table_id=t.table_id AND t.table_type='BASE'";
+ /*
+ "select c.name,t.name,c.length from
+ syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id
+ where o.name='%s'";
+ */
+ var $concat_operator = '+';
+ var $arrayClass = 'ADORecordSet_array_sybase';
+ var $sysDate = 'GetDate()';
+ var $leftOuter = '*=';
+ var $rightOuter = '=*';
+
+ var $port;
+
+ function __construct()
+ {
+ }
+
+ // might require begintrans -- committrans
+ function _insertid()
+ {
+ return $this->GetOne('select @@identity');
+ }
+ // might require begintrans -- committrans
+ function _affectedrows()
+ {
+ return $this->GetOne('select @@rowcount');
+ }
+
+
+ function BeginTrans()
+ {
+
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+
+ $this->Execute('BEGIN TRAN');
+ return true;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) return true;
+
+ if (!$ok) return $this->RollbackTrans();
+
+ $this->transCnt -= 1;
+ $this->Execute('COMMIT TRAN');
+ return true;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt -= 1;
+ $this->Execute('ROLLBACK TRAN');
+ return true;
+ }
+
+ // http://www.isug.com/Sybase_FAQ/ASE/section6.1.html#6.1.4
+ function RowLock($tables,$where,$col='top 1 null as ignore')
+ {
+ if (!$this->_hastrans) $this->BeginTrans();
+ $tables = str_replace(',',' HOLDLOCK,',$tables);
+ return $this->GetOne("select $col from $tables HOLDLOCK where $where");
+
+ }
+
+ function SelectDB($dbName)
+ {
+ $this->database = $dbName;
+ $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
+ if ($this->_connectionID) {
+ return @sybase_select_db($dbName);
+ }
+ else return false;
+ }
+
+ /* Returns: the last error message from previous database operation
+ Note: This function is NOT available for Microsoft SQL Server. */
+
+
+ function ErrorMsg()
+ {
+ if ($this->_logsql) return $this->_errorMsg;
+ if (function_exists('sybase_get_last_message'))
+ $this->_errorMsg = sybase_get_last_message();
+ else {
+ $this->_errorMsg = 'SYBASE error messages not supported on this platform';
+ }
+
+ return $this->_errorMsg;
+ }
+
+ // returns true or false
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('sybase_connect')) return null;
+
+ // Sybase connection on custom port
+ if ($this->port) {
+ $argHostname .= ':' . $this->port;
+ }
+
+ if ($this->charSet) {
+ $this->_connectionID = @sybase_connect($argHostname,$argUsername,$argPassword, $this->charSet);
+ } else {
+ $this->_connectionID = @sybase_connect($argHostname,$argUsername,$argPassword);
+ }
+
+ if ($this->_connectionID === false) return false;
+ if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ return true;
+ }
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('sybase_connect')) return null;
+
+ // Sybase connection on custom port
+ if ($this->port) {
+ $argHostname .= ':' . $this->port;
+ }
+
+ if ($this->charSet) {
+ $this->_connectionID = @sybase_pconnect($argHostname,$argUsername,$argPassword, $this->charSet);
+ } else {
+ $this->_connectionID = @sybase_pconnect($argHostname,$argUsername,$argPassword);
+ }
+
+ if ($this->_connectionID === false) return false;
+ if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ return true;
+ }
+
+ // returns query ID if successful, otherwise false
+ function _query($sql,$inputarr=false)
+ {
+ global $ADODB_COUNTRECS;
+
+ if ($ADODB_COUNTRECS == false && ADODB_PHPVER >= 0x4300)
+ return sybase_unbuffered_query($sql,$this->_connectionID);
+ else
+ return sybase_query($sql,$this->_connectionID);
+ }
+
+ // See http://www.isug.com/Sybase_FAQ/ASE/section6.2.html#6.2.12
+ function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
+ {
+ if ($secs2cache > 0) {// we do not cache rowcount, so we have to load entire recordset
+ $rs = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
+ return $rs;
+ }
+
+ $nrows = (integer) $nrows;
+ $offset = (integer) $offset;
+
+ $cnt = ($nrows >= 0) ? $nrows : 999999999;
+ if ($offset > 0 && $cnt) $cnt += $offset;
+
+ $this->Execute("set rowcount $cnt");
+ $rs = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,0);
+ $this->Execute("set rowcount 0");
+
+ return $rs;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ return @sybase_close($this->_connectionID);
+ }
+
+ static function UnixDate($v)
+ {
+ return ADORecordSet_array_sybase::UnixDate($v);
+ }
+
+ static function UnixTimeStamp($v)
+ {
+ return ADORecordSet_array_sybase::UnixTimeStamp($v);
+ }
+
+
+
+ # Added 2003-10-05 by Chris Phillipson
+ # Used ASA SQL Reference Manual -- http://sybooks.sybase.com/onlinebooks/group-aw/awg0800e/dbrfen8/@ebt-link;pt=16756?target=%25N%15_12018_START_RESTART_N%25
+ # to convert similar Microsoft SQL*Server (mssql) API into Sybase compatible version
+ // Format date column in sql string given an input format that understands Y M D
+ function SQLDate($fmt, $col=false)
+ {
+ if (!$col) $col = $this->sysTimeStamp;
+ $s = '';
+
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ if ($s) $s .= '+';
+ $ch = $fmt[$i];
+ switch($ch) {
+ case 'Y':
+ case 'y':
+ $s .= "datename(yy,$col)";
+ break;
+ case 'M':
+ $s .= "convert(char(3),$col,0)";
+ break;
+ case 'm':
+ $s .= "str_replace(str(month($col),2),' ','0')";
+ break;
+ case 'Q':
+ case 'q':
+ $s .= "datename(qq,$col)";
+ break;
+ case 'D':
+ case 'd':
+ $s .= "str_replace(str(datepart(dd,$col),2),' ','0')";
+ break;
+ case 'h':
+ $s .= "substring(convert(char(14),$col,0),13,2)";
+ break;
+
+ case 'H':
+ $s .= "str_replace(str(datepart(hh,$col),2),' ','0')";
+ break;
+
+ case 'i':
+ $s .= "str_replace(str(datepart(mi,$col),2),' ','0')";
+ break;
+ case 's':
+ $s .= "str_replace(str(datepart(ss,$col),2),' ','0')";
+ break;
+ case 'a':
+ case 'A':
+ $s .= "substring(convert(char(19),$col,0),18,2)";
+ break;
+
+ default:
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ $s .= $this->qstr($ch);
+ break;
+ }
+ }
+ return $s;
+ }
+
+ # Added 2003-10-07 by Chris Phillipson
+ # Used ASA SQL Reference Manual -- http://sybooks.sybase.com/onlinebooks/group-aw/awg0800e/dbrfen8/@ebt-link;pt=5981;uf=0?target=0;window=new;showtoc=true;book=dbrfen8
+ # to convert similar Microsoft SQL*Server (mssql) API into Sybase compatible version
+ function MetaPrimaryKeys($table, $owner = false)
+ {
+ $sql = "SELECT c.column_name " .
+ "FROM syscolumn c, systable t " .
+ "WHERE t.table_name='$table' AND c.table_id=t.table_id " .
+ "AND t.table_type='BASE' " .
+ "AND c.pkey = 'Y' " .
+ "ORDER BY c.column_id";
+
+ $a = $this->GetCol($sql);
+ if ($a && sizeof($a)>0) return $a;
+ return false;
+ }
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+global $ADODB_sybase_mths;
+$ADODB_sybase_mths = array(
+ 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,
+ 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
+
+class ADORecordset_sybase extends ADORecordSet {
+
+ var $databaseType = "sybase";
+ var $canSeek = true;
+ // _mths works only in non-localised system
+ var $_mths = array('JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
+
+ function __construct($id,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ if (!$mode) $this->fetchMode = ADODB_FETCH_ASSOC;
+ else $this->fetchMode = $mode;
+ parent::__construct($id,$mode);
+ }
+
+ /* Returns: an object containing field information.
+ Get column information in the Recordset object. fetchField() can be used in order to obtain information about
+ fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
+ fetchField() is retrieved. */
+ function FetchField($fieldOffset = -1)
+ {
+ if ($fieldOffset != -1) {
+ $o = @sybase_fetch_field($this->_queryID, $fieldOffset);
+ }
+ else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */
+ $o = @sybase_fetch_field($this->_queryID);
+ }
+ // older versions of PHP did not support type, only numeric
+ if ($o && !isset($o->type)) $o->type = ($o->numeric) ? 'float' : 'varchar';
+ return $o;
+ }
+
+ function _initrs()
+ {
+ global $ADODB_COUNTRECS;
+ $this->_numOfRows = ($ADODB_COUNTRECS)? @sybase_num_rows($this->_queryID):-1;
+ $this->_numOfFields = @sybase_num_fields($this->_queryID);
+ }
+
+ function _seek($row)
+ {
+ return @sybase_data_seek($this->_queryID, $row);
+ }
+
+ function _fetch($ignore_fields=false)
+ {
+ if ($this->fetchMode == ADODB_FETCH_NUM) {
+ $this->fields = @sybase_fetch_row($this->_queryID);
+ } else if ($this->fetchMode == ADODB_FETCH_ASSOC) {
+ $this->fields = @sybase_fetch_assoc($this->_queryID);
+
+ if (is_array($this->fields)) {
+ $this->fields = $this->GetRowAssoc();
+ return true;
+ }
+ return false;
+ } else {
+ $this->fields = @sybase_fetch_array($this->_queryID);
+ }
+ if ( is_array($this->fields)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /* close() only needs to be called if you are worried about using too much memory while your script
+ is running. All associated result memory for the specified result identifier will automatically be freed. */
+ function _close() {
+ return @sybase_free_result($this->_queryID);
+ }
+
+ // sybase/mssql uses a default date like Dec 30 2000 12:00AM
+ static function UnixDate($v)
+ {
+ return ADORecordSet_array_sybase::UnixDate($v);
+ }
+
+ static function UnixTimeStamp($v)
+ {
+ return ADORecordSet_array_sybase::UnixTimeStamp($v);
+ }
+}
+
+class ADORecordSet_array_sybase extends ADORecordSet_array {
+ function __construct($id=-1)
+ {
+ parent::__construct($id);
+ }
+
+ // sybase/mssql uses a default date like Dec 30 2000 12:00AM
+ static function UnixDate($v)
+ {
+ global $ADODB_sybase_mths;
+
+ //Dec 30 2000 12:00AM
+ if (!preg_match( "/([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})/"
+ ,$v, $rr)) return parent::UnixDate($v);
+
+ if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
+
+ $themth = substr(strtoupper($rr[1]),0,3);
+ $themth = $ADODB_sybase_mths[$themth];
+ if ($themth <= 0) return false;
+ // h-m-s-MM-DD-YY
+ return adodb_mktime(0,0,0,$themth,$rr[2],$rr[3]);
+ }
+
+ static function UnixTimeStamp($v)
+ {
+ global $ADODB_sybase_mths;
+ //11.02.2001 Toni Tunkkari toni.tunkkari@finebyte.com
+ //Changed [0-9] to [0-9 ] in day conversion
+ if (!preg_match( "/([A-Za-z]{3})[-/\. ]([0-9 ]{1,2})[-/\. ]([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})/"
+ ,$v, $rr)) return parent::UnixTimeStamp($v);
+ if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
+
+ $themth = substr(strtoupper($rr[1]),0,3);
+ $themth = $ADODB_sybase_mths[$themth];
+ if ($themth <= 0) return false;
+
+ switch (strtoupper($rr[6])) {
+ case 'P':
+ if ($rr[4]<12) $rr[4] += 12;
+ break;
+ case 'A':
+ if ($rr[4]==12) $rr[4] = 0;
+ break;
+ default:
+ break;
+ }
+ // h-m-s-MM-DD-YY
+ return adodb_mktime($rr[4],$rr[5],0,$themth,$rr[2],$rr[3]);
+ }
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-sybase_ase.inc.php b/vendor/adodb/adodb-php/drivers/adodb-sybase_ase.inc.php
new file mode 100644
index 0000000..070432d
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-sybase_ase.inc.php
@@ -0,0 +1,120 @@
+<?php
+/*
+ @version v5.20.14 06-Jan-2019
+ @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+ @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+
+ Set tabs to 4.
+
+ Contributed by Interakt Online. Thx Cristian MARIN cristic#interaktonline.com
+*/
+
+
+require_once ADODB_DIR."/drivers/adodb-sybase.inc.php";
+
+class ADODB_sybase_ase extends ADODB_sybase {
+ var $databaseType = "sybase_ase";
+
+ var $metaTablesSQL="SELECT sysobjects.name FROM sysobjects, sysusers WHERE sysobjects.type='U' AND sysobjects.uid = sysusers.uid";
+ var $metaColumnsSQL = "SELECT syscolumns.name AS field_name, systypes.name AS type, systypes.length AS width FROM sysobjects, syscolumns, systypes WHERE sysobjects.name='%s' AND syscolumns.id = sysobjects.id AND systypes.type=syscolumns.type";
+ var $metaDatabasesSQL ="SELECT a.name FROM master.dbo.sysdatabases a, master.dbo.syslogins b WHERE a.suid = b.suid and a.name like '%' and a.name != 'tempdb' and a.status3 != 256 order by 1";
+
+ function __construct()
+ {
+ }
+
+ // split the Views, Tables and procedures.
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ $false = false;
+ if ($this->metaTablesSQL) {
+ // complicated state saving by the need for backward compat
+
+ if ($ttype == 'VIEWS'){
+ $sql = str_replace('U', 'V', $this->metaTablesSQL);
+ }elseif (false === $ttype){
+ $sql = str_replace('U',"U' OR type='V", $this->metaTablesSQL);
+ }else{ // TABLES OR ANY OTHER
+ $sql = $this->metaTablesSQL;
+ }
+ $rs = $this->Execute($sql);
+
+ if ($rs === false || !method_exists($rs, 'GetArray')){
+ return $false;
+ }
+ $arr = $rs->GetArray();
+
+ $arr2 = array();
+ foreach($arr as $key=>$value){
+ $arr2[] = trim($value['name']);
+ }
+ return $arr2;
+ }
+ return $false;
+ }
+
+ function MetaDatabases()
+ {
+ $arr = array();
+ if ($this->metaDatabasesSQL!='') {
+ $rs = $this->Execute($this->metaDatabasesSQL);
+ if ($rs && !$rs->EOF){
+ while (!$rs->EOF){
+ $arr[] = $rs->Fields('name');
+ $rs->MoveNext();
+ }
+ return $arr;
+ }
+ }
+ return false;
+ }
+
+ // fix a bug which prevent the metaColumns query to be executed for Sybase ASE
+ function MetaColumns($table,$upper=false)
+ {
+ $false = false;
+ if (!empty($this->metaColumnsSQL)) {
+
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
+ if ($rs === false) return $false;
+
+ $retarr = array();
+ while (!$rs->EOF) {
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->Fields('field_name');
+ $fld->type = $rs->Fields('type');
+ $fld->max_length = $rs->Fields('width');
+ $retarr[strtoupper($fld->name)] = $fld;
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ return $retarr;
+ }
+ return $false;
+ }
+
+ function getProcedureList($schema)
+ {
+ return false;
+ }
+
+ function ErrorMsg()
+ {
+ if (!function_exists('sybase_connect')){
+ return 'Your PHP doesn\'t contain the Sybase connection module!';
+ }
+ return parent::ErrorMsg();
+ }
+}
+
+class adorecordset_sybase_ase extends ADORecordset_sybase {
+var $databaseType = "sybase_ase";
+function __construct($id,$mode=false)
+ {
+ parent::__construct($id,$mode);
+ }
+
+}
diff --git a/vendor/adodb/adodb-php/drivers/adodb-text.inc.php b/vendor/adodb/adodb-php/drivers/adodb-text.inc.php
new file mode 100644
index 0000000..62073b3
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-text.inc.php
@@ -0,0 +1,388 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Set tabs to 4.
+*/
+
+/*
+Setup:
+
+ $db = NewADOConnection('text');
+ $db->Connect($array,[$types],[$colnames]);
+
+ Parameter $array is the 2 dimensional array of data. The first row can contain the
+ column names. If column names is not defined in first row, you MUST define $colnames,
+ the 3rd parameter.
+
+ Parameter $types is optional. If defined, it should contain an array matching
+ the number of columns in $array, with each element matching the correct type defined
+ by MetaType: (B,C,I,L,N). If undefined, we will probe for $this->_proberows rows
+ to guess the type. Only C,I and N are recognised.
+
+ Parameter $colnames is optional. If defined, it is an array that contains the
+ column names of $array. If undefined, we assume the first row of $array holds the
+ column names.
+
+ The Execute() function will return a recordset. The recordset works like a normal recordset.
+ We have partial support for SQL parsing. We process the SQL using the following rules:
+
+ 1. SQL order by's always work for the first column ordered. Subsequent cols are ignored
+
+ 2. All operations take place on the same table. No joins possible. In fact the FROM clause
+ is ignored! You can use any name for the table.
+
+ 3. To simplify code, all columns are returned, except when selecting 1 column
+
+ $rs = $db->Execute('select col1,col2 from table'); // sql ignored, will generate all cols
+
+ We special case handling of 1 column because it is used in filter popups
+
+ $rs = $db->Execute('select col1 from table');
+ // sql accepted and processed -- any table name is accepted
+
+ $rs = $db->Execute('select distinct col1 from table');
+ // sql accepted and processed
+
+4. Where clauses are ignored, but searching with the 3rd parameter of Execute is permitted.
+ This has to use PHP syntax and we will eval() it. You can even use PHP functions.
+
+ $rs = $db->Execute('select * from table',false,"\$COL1='abc' and $\COL2=3")
+ // the 3rd param is searched -- make sure that $COL1 is a legal column name
+ // and all column names must be in upper case.
+
+4. Group by, having, other clauses are ignored
+
+5. Expression columns, min(), max() are ignored
+
+6. All data is readonly. Only SELECTs permitted.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (! defined("_ADODB_TEXT_LAYER")) {
+ define("_ADODB_TEXT_LAYER", 1 );
+
+// for sorting in _query()
+function adodb_cmp($a, $b) {
+ if ($a[0] == $b[0]) return 0;
+ return ($a[0] < $b[0]) ? -1 : 1;
+}
+// for sorting in _query()
+function adodb_cmpr($a, $b) {
+ if ($a[0] == $b[0]) return 0;
+ return ($a[0] > $b[0]) ? -1 : 1;
+}
+class ADODB_text extends ADOConnection {
+ var $databaseType = 'text';
+
+ var $_origarray; // original data
+ var $_types;
+ var $_proberows = 8;
+ var $_colnames;
+ var $_skiprow1=false;
+ var $readOnly = true;
+ var $hasTransactions = false;
+
+ var $_rezarray;
+ var $_reznames;
+ var $_reztypes;
+
+ function __construct()
+ {
+ }
+
+ function RSRecordCount()
+ {
+ if (!empty($this->_rezarray)) return sizeof($this->_rezarray);
+
+ return sizeof($this->_origarray);
+ }
+
+ function _insertid()
+ {
+ return false;
+ }
+
+ function _affectedrows()
+ {
+ return false;
+ }
+
+ // returns true or false
+ function PConnect(&$array, $types = false, $colnames = false)
+ {
+ return $this->Connect($array, $types, $colnames);
+ }
+ // returns true or false
+ function Connect(&$array, $types = false, $colnames = false)
+ {
+ if (is_string($array) and $array === 'iluvphplens') return 'me2';
+
+ if (!$array) {
+ $this->_origarray = false;
+ return true;
+ }
+ $row = $array[0];
+ $cols = sizeof($row);
+
+
+ if ($colnames) $this->_colnames = $colnames;
+ else {
+ $this->_colnames = $array[0];
+ $this->_skiprow1 = true;
+ }
+ if (!$types) {
+ // probe and guess the type
+ $types = array();
+ $firstrow = true;
+ if ($this->_proberows > sizeof($array)) $max = sizeof($array);
+ else $max = $this->_proberows;
+ for ($j=($this->_skiprow1)?1:0;$j < $max; $j++) {
+ $row = $array[$j];
+ if (!$row) break;
+ $i = -1;
+ foreach($row as $v) {
+ $i += 1;
+ //print " ($i ".$types[$i]. "$v) ";
+ $v = trim($v);
+ if (!preg_match('/^[+-]{0,1}[0-9\.]+$/',$v)) {
+ $types[$i] = 'C'; // once C, always C
+ continue;
+ }
+ if (isset($types[$i]) && $types[$i]=='C') continue;
+ if ($firstrow) {
+ // If empty string, we presume is character
+ // test for integer for 1st row only
+ // after that it is up to testing other rows to prove
+ // that it is not an integer
+ if (strlen($v) == 0) $types[0] = 'C';
+ if (strpos($v,'.') !== false) $types[0] = 'N';
+ else $types[$i] = 'I';
+ continue;
+ }
+
+ if (strpos($v,'.') !== false) $types[$i] = 'N';
+
+ }
+ $firstrow = false;
+ }
+ }
+ //print_r($types);
+ $this->_origarray = $array;
+ $this->_types = $types;
+ return true;
+ }
+
+
+
+ // returns queryID or false
+ // We presume that the select statement is on the same table (what else?),
+ // with the only difference being the order by.
+ //You can filter by using $eval and each clause is stored in $arr .eg. $arr[1] == 'name'
+ // also supports SELECT [DISTINCT] COL FROM ... -- only 1 col supported
+ function _query($sql,$input_arr,$eval=false)
+ {
+ if ($this->_origarray === false) return false;
+
+ $eval = $this->evalAll;
+ $usql = strtoupper(trim($sql));
+ $usql = preg_replace("/[\t\n\r]/",' ',$usql);
+ $usql = preg_replace('/ *BY/i',' BY',strtoupper($usql));
+
+ $eregword ='([A-Z_0-9]*)';
+ //print "<BR> $sql $eval ";
+ if ($eval) {
+ $i = 0;
+ foreach($this->_colnames as $n) {
+ $n = strtoupper(trim($n));
+ $eval = str_replace("\$$n","\$arr[$i]",$eval);
+
+ $i += 1;
+ }
+
+ $i = 0;
+ $eval = "\$rez=($eval);";
+ //print "<p>Eval string = $eval </p>";
+ $where_arr = array();
+
+ reset($this->_origarray);
+ foreach ($this->_origarray as $arr) {
+
+ if ($i == 0 && $this->_skiprow1)
+ $where_arr[] = $arr;
+ else {
+ eval($eval);
+ //print " $i: result=$rez arr[0]={$arr[0]} arr[1]={$arr[1]} <BR>\n ";
+ if ($rez) $where_arr[] = $arr;
+ }
+ $i += 1;
+ }
+ $this->_rezarray = $where_arr;
+ }else
+ $where_arr = $this->_origarray;
+
+ // THIS PROJECTION CODE ONLY WORKS FOR 1 COLUMN,
+ // OTHERWISE IT RETURNS ALL COLUMNS
+ if (substr($usql,0,7) == 'SELECT ') {
+ $at = strpos($usql,' FROM ');
+ $sel = trim(substr($usql,7,$at-7));
+
+ $distinct = false;
+ if (substr($sel,0,8) == 'DISTINCT') {
+ $distinct = true;
+ $sel = trim(substr($sel,8,$at));
+ }
+
+ // $sel holds the selection clause, comma delimited
+ // currently we only project if one column is involved
+ // this is to support popups in PHPLens
+ if (strpos(',',$sel)===false) {
+ $colarr = array();
+
+ preg_match("/$eregword/",$sel,$colarr);
+ $col = $colarr[1];
+ $i = 0;
+ $n = '';
+ reset($this->_colnames);
+ foreach ($this->_colnames as $n) {
+
+ if ($col == strtoupper(trim($n))) break;
+ $i += 1;
+ }
+
+ if ($n && $col) {
+ $distarr = array();
+ $projarray = array();
+ $projtypes = array($this->_types[$i]);
+ $projnames = array($n);
+
+ foreach ($where_arr as $a) {
+ if ($i == 0 && $this->_skiprow1) {
+ $projarray[] = array($n);
+ continue;
+ }
+
+ if ($distinct) {
+ $v = strtoupper($a[$i]);
+ if (! $distarr[$v]) {
+ $projarray[] = array($a[$i]);
+ $distarr[$v] = 1;
+ }
+ } else
+ $projarray[] = array($a[$i]);
+
+ } //foreach
+ //print_r($projarray);
+ }
+ } // check 1 column in projection
+ } // is SELECT
+
+ if (empty($projarray)) {
+ $projtypes = $this->_types;
+ $projarray = $where_arr;
+ $projnames = $this->_colnames;
+ }
+ $this->_rezarray = $projarray;
+ $this->_reztypes = $projtypes;
+ $this->_reznames = $projnames;
+
+
+ $pos = strpos($usql,' ORDER BY ');
+ if ($pos === false) return $this;
+ $orderby = trim(substr($usql,$pos+10));
+
+ preg_match("/$eregword/",$orderby,$arr);
+ if (sizeof($arr) < 2) return $this; // actually invalid sql
+ $col = $arr[1];
+ $at = (integer) $col;
+ if ($at == 0) {
+ $i = 0;
+ reset($projnames);
+ foreach ($projnames as $n) {
+ if (strtoupper(trim($n)) == $col) {
+ $at = $i+1;
+ break;
+ }
+ $i += 1;
+ }
+ }
+
+ if ($at <= 0 || $at > sizeof($projarray[0])) return $this; // cannot find sort column
+ $at -= 1;
+
+ // generate sort array consisting of (sortval1, row index1) (sortval2, row index2)...
+ $sorta = array();
+ $t = $projtypes[$at];
+ $num = ($t == 'I' || $t == 'N');
+ for ($i=($this->_skiprow1)?1:0, $max = sizeof($projarray); $i < $max; $i++) {
+ $row = $projarray[$i];
+ $val = ($num)?(float)$row[$at]:$row[$at];
+ $sorta[]=array($val,$i);
+ }
+
+ // check for desc sort
+ $orderby = substr($orderby,strlen($col)+1);
+ $arr == array();
+ preg_match('/([A-Z_0-9]*)/i',$orderby,$arr);
+
+ if (trim($arr[1]) == 'DESC') $sortf = 'adodb_cmpr';
+ else $sortf = 'adodb_cmp';
+
+ // hasta la sorta babe
+ usort($sorta, $sortf);
+
+ // rearrange original array
+ $arr2 = array();
+ if ($this->_skiprow1) $arr2[] = $projarray[0];
+ foreach($sorta as $v) {
+ $arr2[] = $projarray[$v[1]];
+ }
+
+ $this->_rezarray = $arr2;
+ return $this;
+ }
+
+ /* Returns: the last error message from previous database operation */
+ function ErrorMsg()
+ {
+ return '';
+ }
+
+ /* Returns: the last error number from previous database operation */
+ function ErrorNo()
+ {
+ return 0;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ }
+
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+
+class ADORecordSet_text extends ADORecordSet_array
+{
+
+ var $databaseType = "text";
+
+ function __construct(&$conn,$mode=false)
+ {
+ parent::__construct();
+ $this->InitArray($conn->_rezarray,$conn->_reztypes,$conn->_reznames);
+ $conn->_rezarray = false;
+ }
+
+} // class ADORecordSet_text
+
+
+} // defined
diff --git a/vendor/adodb/adodb-php/drivers/adodb-vfp.inc.php b/vendor/adodb/adodb-php/drivers/adodb-vfp.inc.php
new file mode 100644
index 0000000..4a28884
--- /dev/null
+++ b/vendor/adodb/adodb-php/drivers/adodb-vfp.inc.php
@@ -0,0 +1,103 @@
+<?php
+/*
+@version v5.20.14 06-Jan-2019
+@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
+@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+Set tabs to 4 for best viewing.
+
+ Latest version is available at http://adodb.org/
+
+ Microsoft Visual FoxPro data driver. Requires ODBC. Works only on MS Windows.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (!defined('_ADODB_ODBC_LAYER')) {
+ include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
+}
+if (!defined('ADODB_VFP')){
+define('ADODB_VFP',1);
+class ADODB_vfp extends ADODB_odbc {
+ var $databaseType = "vfp";
+ var $fmtDate = "{^Y-m-d}";
+ var $fmtTimeStamp = "{^Y-m-d, h:i:sA}";
+ var $replaceQuote = "'+chr(39)+'" ;
+ var $true = '.T.';
+ var $false = '.F.';
+ var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE
+ var $_bindInputArray = false; // strangely enough, setting to true does not work reliably
+ var $sysTimeStamp = 'datetime()';
+ var $sysDate = 'date()';
+ var $ansiOuter = true;
+ var $hasTransactions = false;
+ var $curmode = false ; // See sqlext.h, SQL_CUR_DEFAULT == SQL_CUR_USE_DRIVER == 2L
+
+ function Time()
+ {
+ return time();
+ }
+
+ function BeginTrans() { return false;}
+
+ // quote string to be sent back to database
+ function qstr($s,$nofixquotes=false)
+ {
+ if (!$nofixquotes) return "'".str_replace("\r\n","'+chr(13)+'",str_replace("'",$this->replaceQuote,$s))."'";
+ return "'".$s."'";
+ }
+
+
+ // TOP requires ORDER BY for VFP
+ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
+ {
+ $this->hasTop = preg_match('/ORDER[ \t\r\n]+BY/is',$sql) ? 'top' : false;
+ $ret = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
+ return $ret;
+ }
+
+
+
+};
+
+
+class ADORecordSet_vfp extends ADORecordSet_odbc {
+
+ var $databaseType = "vfp";
+
+
+ function __construct($id,$mode=false)
+ {
+ return parent::__construct($id,$mode);
+ }
+
+ function MetaType($t, $len = -1, $fieldobj = false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+ switch (strtoupper($t)) {
+ case 'C':
+ if ($len <= $this->blobSize) return 'C';
+ case 'M':
+ return 'X';
+
+ case 'D': return 'D';
+
+ case 'T': return 'T';
+
+ case 'L': return 'L';
+
+ case 'I': return 'I';
+
+ default: return 'N';
+ }
+ }
+}
+
+} //define