0012755_followup.patch

Administrator Admin, 2009-11-25 22:45

Download (30 KB)

View differences:

typo3/sysext/adodb/adodb/drivers/adodb-db2oci.inc.php (Revision 0)
1
<?php
2
/* 
3
V5.10 10 Nov 2009   (c) 2000-2009 John Lim (jlim#natsoft.com). All rights reserved.
4
  Released under both BSD license and Lesser GPL library license. 
5
  Whenever there is any discrepancy between the two licenses, 
6
  the BSD license will take precedence. 
7
Set tabs to 4 for best viewing.
8
  
9
  Latest version is available at http://adodb.sourceforge.net
10
  
11
  Microsoft Visual FoxPro data driver. Requires ODBC. Works only on MS Windows.
12
*/
13

  
14
// security - hide paths
15
if (!defined('ADODB_DIR')) die();
16
include(ADODB_DIR."/drivers/adodb-db2.inc.php");
17

  
18

  
19
if (!defined('ADODB_DB2OCI')){
20
define('ADODB_DB2OCI',1);
21

  
22
/*
23
// regex code for smart remapping of :0, :1 bind vars to ? ?
24
function _colontrack($p)
25
{
26
global $_COLONARR,$_COLONSZ;
27
	$v = (integer) substr($p,1);
28
	if ($v > $_COLONSZ) return $p;
29
	$_COLONARR[] = $v;
30
	return '?';
31
}
32

  
33
// smart remapping of :0, :1 bind vars to ? ?
34
function _colonscope($sql,$arr)
35
{
36
global $_COLONARR,$_COLONSZ;
37

  
38
	$_COLONARR = array();
39
	$_COLONSZ = sizeof($arr);
40
	
41
	$sql2 = preg_replace("/(:[0-9]+)/e","_colontrack('\\1')",$sql);
42
	
43
	if (empty($_COLONARR)) return array($sql,$arr);
44
	
45
	foreach($_COLONARR as $k => $v) {
46
		$arr2[] = $arr[$v]; 
47
	}
48
	
49
	return array($sql2,$arr2);
50
}
51
*/
52

  
53
/*
54
	Smart remapping of :0, :1 bind vars to ? ?
55
	
56
	Handles colons in comments -- and / * * / and in quoted strings.
57
*/
58

  
59
function _colonparser($sql,$arr)
60
{
61
	$lensql = strlen($sql);
62
	$arrsize = sizeof($arr);
63
	$state = 'NORM';
64
	$at = 1;
65
	$ch = $sql[0]; 
66
	$ch2 = @$sql[1];
67
	$sql2 = '';
68
	$arr2 = array();
69
	$nprev = 0;
70
	
71
	
72
	while (strlen($ch)) {
73
	
74
		switch($ch) {
75
		case '/':
76
			if ($state == 'NORM' && $ch2 == '*') {
77
				$state = 'COMMENT';
78
				
79
				$at += 1;
80
				$ch = $ch2;
81
				$ch2 = $at < $lensql ? $sql[$at] : '';
82
			}
83
			break;
84
			
85
		case '*':
86
			if ($state == 'COMMENT' && $ch2 == '/') {
87
				$state = 'NORM';
88
				
89
				$at += 1;
90
				$ch = $ch2;
91
				$ch2 = $at < $lensql ? $sql[$at] : '';
92
			}
93
			break;
94
		
95
		case "\n":
96
		case "\r":
97
			if ($state == 'COMMENT2') $state = 'NORM';
98
			break;
99
		
100
		case "'":
101
			do {
102
				$at += 1;
103
				$ch = $ch2;
104
				$ch2 = $at < $lensql ? $sql[$at] : '';
105
			} while ($ch !== "'");
106
			break;
107
			
108
		case ':':
109
			if ($state == 'COMMENT' || $state == 'COMMENT2') break;
110
			
111
			//echo "$at=$ch $ch2, ";
112
			if ('0' <= $ch2 && $ch2 <= '9') {
113
				$n = '';
114
				$nat = $at;
115
				do {
116
					$at += 1;
117
					$ch = $ch2;
118
					$n .= $ch;
119
					$ch2 = $at < $lensql ? $sql[$at] : '';
120
				} while ('0' <= $ch && $ch <= '9');
121
				#echo "$n $arrsize ] ";
122
				$n = (integer) $n;
123
				if ($n < $arrsize) {
124
					$sql2 .= substr($sql,$nprev,$nat-$nprev-1).'?';
125
					$nprev = $at-1;
126
					$arr2[] = $arr[$n];
127
				}
128
			}
129
			break;
130
			
131
		case '-':
132
			if ($state == 'NORM') {
133
				if ($ch2 == '-') $state = 'COMMENT2';
134
				$at += 1;
135
				$ch = $ch2;
136
				$ch2 = $at < $lensql ? $sql[$at] : '';
137
			}
138
			break;
139
		}
140
		
141
		$at += 1;
142
		$ch = $ch2;
143
		$ch2 = $at < $lensql ? $sql[$at] : '';
144
	}
145
	
146
	if ($nprev == 0) {
147
		$sql2 = $sql;
148
	} else {
149
		$sql2 .= substr($sql,$nprev);
150
	}
151
	
152
	return array($sql2,$arr2);
153
}
154

  
155
class ADODB_db2oci extends ADODB_db2 {
156
	var $databaseType = "db2oci";	
157
	var $sysTimeStamp = 'sysdate';
158
	var $sysDate = 'trunc(sysdate)';
159
	var $_bindInputArray = true;
160
	
161
	function ADODB_db2oci()
162
	{
163
		parent::ADODB_db2();
164
	}
165
	
166
	function Param($name,$type=false)
167
	{
168
		return ':'.$name;
169
	}
170
	
171
	
172
	function MetaTables($ttype=false,$schema=false)
173
	{
174
	global $ADODB_FETCH_MODE;
175
	
176
		$savem = $ADODB_FETCH_MODE;
177
		$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
178
		$qid = db2_tables($this->_connectionID);
179
		
180
		$rs = new ADORecordSet_db2($qid);
181
		
182
		$ADODB_FETCH_MODE = $savem;
183
		if (!$rs) {
184
			$false = false;
185
			return $false;
186
		}
187
		
188
		$arr = $rs->GetArray();
189
		$rs->Close();
190
		$arr2 = array();
191
	//	adodb_pr($arr);
192
		if ($ttype) {
193
			$isview = strncmp($ttype,'V',1) === 0;
194
		}
195
		for ($i=0; $i < sizeof($arr); $i++) {
196
			if (!$arr[$i][2]) continue;
197
			$type = $arr[$i][3];
198
			$schemaval = ($schema) ? $arr[$i][1].'.' : '';
199
			$name = $schemaval.$arr[$i][2];
200
			$owner = $arr[$i][1];
201
			if (substr($name,0,8) == 'EXPLAIN_') continue;
202
			if ($ttype) { 
203
				if ($isview) {
204
					if (strncmp($type,'V',1) === 0) $arr2[] = $name;
205
				} else if (strncmp($type,'T',1) === 0 && strncmp($owner,'SYS',3) !== 0) $arr2[] = $name;
206
			} else if (strncmp($type,'T',1) === 0 && strncmp($owner,'SYS',3) !== 0) $arr2[] = $name;
207
		}
208
		return $arr2;
209
	}
210
	
211
	function _Execute($sql, $inputarr=false	)
212
	{
213
		if ($inputarr) list($sql,$inputarr) = _colonparser($sql, $inputarr);
214
		return parent::_Execute($sql, $inputarr);
215
	}
216
};
217
 
218

  
219
class  ADORecordSet_db2oci extends ADORecordSet_db2 {	
220
	
221
	var $databaseType = "db2oci";		
222
	
223
	function ADORecordSet_db2oci($id,$mode=false)
224
	{
225
		return $this->ADORecordSet_db2($id,$mode);
226
	}
227
}
228

  
229
} //define
230
?>
typo3/sysext/adodb/adodb/drivers/adodb-ads.inc.php (Revision 0)
1
<?php
2
/*
3
  (c) 2000-2007 John Lim (jlim#natsoft.com.my). All rights reserved.
4
  Portions Copyright (c) 2007-2009, iAnywhere Solutions, Inc.
5
  All rights reserved. All unpublished rights reserved.
6

  
7
  Released under both BSD license and Lesser GPL library license.
8
  Whenever there is any discrepancy between the two licenses,
9
  the BSD license will take precedence.
10

  
11
Set tabs to 4 for best viewing.
12

  
13

  
14
NOTE: This driver requires the Advantage PHP client libraries, which
15
      can be downloaded for free via:
16
      http://devzone.advantagedatabase.com/dz/content.aspx?key=20
17

  
18
DELPHI FOR PHP USERS:
19
      The following steps can be taken to utilize this driver from the
20
      CodeGear Delphi for PHP product:
21
        1 - See note above, download and install the Advantage PHP client.
22
        2 - Copy the following files to the Delphi for PHP\X.X\php\ext directory:
23
              ace32.dll
24
              axcws32.dll
25
              adsloc32.dll
26
              php_advantage.dll (rename the existing php_advantage.dll.5.x.x file)
27
        3 - Add the following line to the Delphi for PHP\X.X\php\php.ini.template file:
28
              extension=php_advantage.dll
29
        4 - To use: enter "ads" as the DriverName on a connection component, and set
30
            a Host property similar to "DataDirectory=c:\". See the Advantage PHP
31
            help file topic for ads_connect for details on connection path options
32
            and formatting.
33
        5 - (optional) - Modify the Delphi for PHP\X.X\vcl\packages\database.packages.php
34
            file and add ads to the list of strings returned when registering the
35
            Database object's DriverName property.
36

  
37
*/
38
// security - hide paths
39
if (!defined('ADODB_DIR')) die();
40

  
41
  define("_ADODB_ADS_LAYER", 2 );
42

  
43
/*--------------------------------------------------------------------------------------
44
--------------------------------------------------------------------------------------*/
45

  
46

  
47
class ADODB_ads extends ADOConnection {
48
  var $databaseType = "ads";
49
  var $fmt = "'m-d-Y'";
50
  var $fmtTimeStamp = "'Y-m-d H:i:s'";
51
        var $concat_operator = '';
52
  var $replaceQuote = "''"; // string to use to replace quotes
53
  var $dataProvider = "ads";
54
  var $hasAffectedRows = true;
55
  var $binmode = ODBC_BINMODE_RETURN;
56
  var $useFetchArray = false; // setting this to true will make array elements in FETCH_ASSOC mode case-sensitive
57
                        // breaking backward-compat
58
  //var $longreadlen = 8000; // default number of chars to return for a Blob/Long field
59
  var $_bindInputArray = false;
60
  var $curmode = SQL_CUR_USE_DRIVER; // See sqlext.h, SQL_CUR_DEFAULT == SQL_CUR_USE_DRIVER == 2L
61
  var $_genSeqSQL = "create table %s (id integer)";
62
  var $_autocommit = true;
63
  var $_haserrorfunctions = true;
64
  var $_has_stupid_odbc_fetch_api_change = true;
65
  var $_lastAffectedRows = 0;
66
  var $uCaseTables = true; // for meta* functions, uppercase table names
67

  
68

  
69
  function ADODB_ads()
70
  {
71
    $this->_haserrorfunctions = ADODB_PHPVER >= 0x4050;
72
    $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
73
  }
74

  
75
  // returns true or false
76
  function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
77
  {
78
          global $php_errormsg;
79

  
80
    if (!function_exists('ads_connect')) return null;
81

  
82
    if ($this->debug && $argDatabasename && $this->databaseType != 'vfp') {
83
      ADOConnection::outp("For Advantage Connect(), $argDatabasename is not used. Place dsn in 1st parameter.");
84
    }
85
    if (isset($php_errormsg)) $php_errormsg = '';
86
    if ($this->curmode === false) $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword);
87
    else $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword,$this->curmode);
88
    $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
89
    if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
90

  
91
    return $this->_connectionID != false;
92
  }
93

  
94
  // returns true or false
95
  function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
96
  {
97
  global $php_errormsg;
98

  
99
    if (!function_exists('ads_connect')) return null;
100

  
101
    if (isset($php_errormsg)) $php_errormsg = '';
102
    $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
103
    if ($this->debug && $argDatabasename) {
104
            ADOConnection::outp("For PConnect(), $argDatabasename is not used. Place dsn in 1st parameter.");
105
    }
106
  //  print "dsn=$argDSN u=$argUsername p=$argPassword<br>"; flush();
107
    if ($this->curmode === false) $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword);
108
    else $this->_connectionID = ads_pconnect($argDSN,$argUsername,$argPassword,$this->curmode);
109

  
110
    $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
111
    if ($this->_connectionID && $this->autoRollback) @ads_rollback($this->_connectionID);
112
    if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
113

  
114
    return $this->_connectionID != false;
115
  }
116

  
117
  // returns the Server version and Description
118
  function ServerInfo()
119
  {
120

  
121
    if (!empty($this->host) && ADODB_PHPVER >= 0x4300) {
122
      $stmt = $this->Prepare('EXECUTE PROCEDURE sp_mgGetInstallInfo()');
123
                        $res =  $this->Execute($stmt);
124
                        if(!$res)
125
                                print $this->ErrorMsg();
126
                        else{
127
                                $ret["version"]= $res->fields[3];
128
                                $ret["description"]="Advantage Database Server";
129
                                return $ret;
130
                        }
131
                }
132
                else {
133
            return ADOConnection::ServerInfo();
134
    }
135
  }
136

  
137

  
138
        // returns true or false
139
        function CreateSequence( $seqname,$start=1)
140
  {
141
                $res =  $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE");
142
                if(!$res){
143
                        print $this->ErrorMsg();
144
                        return false;
145
                }
146
                else
147
                        return true;
148

  
149
        }
150

  
151
        // returns true or false
152
        function DropSequence($seqname)
153
  {
154
                $res = $this->Execute("DROP TABLE $seqname");
155
                if(!$res){
156
                        print $this->ErrorMsg();
157
                        return false;
158
                }
159
                else
160
                        return true;
161
        }
162

  
163

  
164
  // returns the generated ID or false
165
        // checks if the table already exists, else creates the table and inserts a record into the table
166
        // and gets the ID number of the last inserted record.
167
        function GenID($seqname,$start=1)
168
        {
169
                $go = $this->Execute("select * from $seqname");
170
                if (!$go){
171
                        $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE");
172
                        if(!res){
173
                                print $this->ErrorMsg();
174
                                return false;
175
                        }
176
                }
177
                $res = $this->Execute("INSERT INTO $seqname VALUES( DEFAULT )");
178
                if(!$res){
179
                        print $this->ErrorMsg();
180
                        return false;
181
                }
182
                else{
183
                        $gen = $this->Execute("SELECT LastAutoInc( STATEMENT ) FROM system.iota");
184
                        $ret = $gen->fields[0];
185
                        return $ret;
186
                }
187

  
188
        }
189

  
190

  
191

  
192

  
193
  function ErrorMsg()
194
  {
195
    if ($this->_haserrorfunctions) {
196
      if ($this->_errorMsg !== false) return $this->_errorMsg;
197
      if (empty($this->_connectionID)) return @ads_errormsg();
198
      return @ads_errormsg($this->_connectionID);
199
    } else return ADOConnection::ErrorMsg();
200
  }
201

  
202

  
203
  function ErrorNo()
204
  {
205

  
206
                if ($this->_haserrorfunctions) {
207
      if ($this->_errorCode !== false) {
208
        // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
209
        return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode;
210
      }
211

  
212
      if (empty($this->_connectionID)) $e = @ads_error();
213
      else $e = @ads_error($this->_connectionID);
214

  
215
       // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
216
       // so we check and patch
217
      if (strlen($e)<=2) return 0;
218
      return $e;
219
    } else return ADOConnection::ErrorNo();
220
  }
221

  
222

  
223

  
224
  function BeginTrans()
225
  {
226
    if (!$this->hasTransactions) return false;
227
    if ($this->transOff) return true;
228
    $this->transCnt += 1;
229
    $this->_autocommit = false;
230
    return ads_autocommit($this->_connectionID,false);
231
  }
232

  
233
  function CommitTrans($ok=true)
234
  {
235
    if ($this->transOff) return true;
236
    if (!$ok) return $this->RollbackTrans();
237
    if ($this->transCnt) $this->transCnt -= 1;
238
    $this->_autocommit = true;
239
    $ret = ads_commit($this->_connectionID);
240
    ads_autocommit($this->_connectionID,true);
241
    return $ret;
242
  }
243

  
244
  function RollbackTrans()
245
  {
246
    if ($this->transOff) return true;
247
    if ($this->transCnt) $this->transCnt -= 1;
248
    $this->_autocommit = true;
249
    $ret = ads_rollback($this->_connectionID);
250
    ads_autocommit($this->_connectionID,true);
251
    return $ret;
252
  }
253

  
254

  
255
  // Returns tables,Views or both on succesfull execution. Returns
256
        // tables by default on succesfull execustion.
257
  function &MetaTables($ttype)
258
  {
259
          $recordSet1 = $this->Execute("select * from system.tables");
260
                if(!$recordSet1){
261
                        print $this->ErrorMsg();
262
                        return false;
263
                }
264
                $recordSet2 = $this->Execute("select * from system.views");
265
                if(!$recordSet2){
266
                        print $this->ErrorMsg();
267
                        return false;
268
                }
269
                $i=0;
270
                while (!$recordSet1->EOF){
271
                                 $arr["$i"] = $recordSet1->fields[0];
272
                                 $recordSet1->MoveNext();
273
                                 $i=$i+1;
274
                }
275
                if($ttype=='FALSE'){
276
                        while (!$recordSet2->EOF){
277
                                $arr["$i"] = $recordSet2->fields[0];
278
                                $recordSet2->MoveNext();
279
                                $i=$i+1;
280
                        }
281
                        return $arr;
282
                }
283
                elseif($ttype=='VIEWS'){
284
                        while (!$recordSet2->EOF){
285
                                $arrV["$i"] = $recordSet2->fields[0];
286
                                $recordSet2->MoveNext();
287
                                $i=$i+1;
288
                        }
289
                        return $arrV;
290
                }
291
                else{
292
                        return $arr;
293
                }
294

  
295
  }
296

  
297
        function &MetaPrimaryKeys($table)
298
  {
299
          $recordSet = $this->Execute("select table_primary_key from system.tables where name='$table'");
300
                if(!$recordSet){
301
                        print $this->ErrorMsg();
302
                        return false;
303
                }
304
                $i=0;
305
                while (!$recordSet->EOF){
306
                                 $arr["$i"] = $recordSet->fields[0];
307
                                 $recordSet->MoveNext();
308
                                 $i=$i+1;
309
                }
310
                return $arr;
311
        }
312

  
313
/*
314
See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcdatetime_data_type_changes.asp
315
/ SQL data type codes /
316
#define SQL_UNKNOWN_TYPE  0
317
#define SQL_CHAR      1
318
#define SQL_NUMERIC    2
319
#define SQL_DECIMAL    3
320
#define SQL_INTEGER    4
321
#define SQL_SMALLINT    5
322
#define SQL_FLOAT      6
323
#define SQL_REAL      7
324
#define SQL_DOUBLE      8
325
#if (ODBCVER >= 0x0300)
326
#define SQL_DATETIME    9
327
#endif
328
#define SQL_VARCHAR   12
329

  
330

  
331
/ One-parameter shortcuts for date/time data types /
332
#if (ODBCVER >= 0x0300)
333
#define SQL_TYPE_DATE   91
334
#define SQL_TYPE_TIME   92
335
#define SQL_TYPE_TIMESTAMP 93
336

  
337
#define SQL_UNICODE                             (-95)
338
#define SQL_UNICODE_VARCHAR                     (-96)
339
#define SQL_UNICODE_LONGVARCHAR                 (-97)
340
*/
341
  function ODBCTypes($t)
342
  {
343
    switch ((integer)$t) {
344
    case 1:
345
    case 12:
346
    case 0:
347
    case -95:
348
    case -96:
349
      return 'C';
350
    case -97:
351
    case -1: //text
352
      return 'X';
353
    case -4: //image
354
      return 'B';
355

  
356
    case 9:
357
    case 91:
358
      return 'D';
359

  
360
    case 10:
361
    case 11:
362
    case 92:
363
    case 93:
364
      return 'T';
365

  
366
    case 4:
367
    case 5:
368
    case -6:
369
      return 'I';
370

  
371
    case -11: // uniqidentifier
372
      return 'R';
373
    case -7: //bit
374
      return 'L';
375

  
376
    default:
377
      return 'N';
378
    }
379
  }
380

  
381
  function &MetaColumns($table)
382
  {
383
  global $ADODB_FETCH_MODE;
384

  
385
    $false = false;
386
    if ($this->uCaseTables) $table = strtoupper($table);
387
    $schema = '';
388
    $this->_findschema($table,$schema);
389

  
390
    $savem = $ADODB_FETCH_MODE;
391
    $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
392

  
393
    /*if (false) { // after testing, confirmed that the following does not work becoz of a bug
394
      $qid2 = ads_tables($this->_connectionID);
395
      $rs = new ADORecordSet_ads($qid2);
396
      $ADODB_FETCH_MODE = $savem;
397
      if (!$rs) return false;
398
      $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
399
      $rs->_fetch();
400

  
401
      while (!$rs->EOF) {
402
        if ($table == strtoupper($rs->fields[2])) {
403
          $q = $rs->fields[0];
404
          $o = $rs->fields[1];
405
          break;
406
        }
407
        $rs->MoveNext();
408
      }
409
      $rs->Close();
410

  
411
      $qid = ads_columns($this->_connectionID,$q,$o,strtoupper($table),'%');
412
    } */
413

  
414
    switch ($this->databaseType) {
415
    case 'access':
416
    case 'vfp':
417
      $qid = ads_columns($this->_connectionID);#,'%','',strtoupper($table),'%');
418
      break;
419

  
420

  
421
    case 'db2':
422
            $colname = "%";
423
            $qid = ads_columns($this->_connectionID, "", $schema, $table, $colname);
424
            break;
425

  
426
    default:
427
      $qid = @ads_columns($this->_connectionID,'%','%',strtoupper($table),'%');
428
      if (empty($qid)) $qid = ads_columns($this->_connectionID);
429
      break;
430
    }
431
    if (empty($qid)) return $false;
432

  
433
    $rs = new ADORecordSet_ads($qid);
434
    $ADODB_FETCH_MODE = $savem;
435

  
436
    if (!$rs) return $false;
437
    $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
438
    $rs->_fetch();
439

  
440
    $retarr = array();
441

  
442
    /*
443
    $rs->fields indices
444
    0 TABLE_QUALIFIER
445
    1 TABLE_SCHEM
446
    2 TABLE_NAME
447
    3 COLUMN_NAME
448
    4 DATA_TYPE
449
    5 TYPE_NAME
450
    6 PRECISION
451
    7 LENGTH
452
    8 SCALE
453
    9 RADIX
454
    10 NULLABLE
455
    11 REMARKS
456
    */
457
    while (!$rs->EOF) {
458
    //  adodb_pr($rs->fields);
459
      if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
460
        $fld = new ADOFieldObject();
461
        $fld->name = $rs->fields[3];
462
        $fld->type = $this->ODBCTypes($rs->fields[4]);
463

  
464
        // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp
465
        // access uses precision to store length for char/varchar
466
        if ($fld->type == 'C' or $fld->type == 'X') {
467
          if ($this->databaseType == 'access')
468
            $fld->max_length = $rs->fields[6];
469
          else if ($rs->fields[4] <= -95) // UNICODE
470
            $fld->max_length = $rs->fields[7]/2;
471
          else
472
            $fld->max_length = $rs->fields[7];
473
        } else
474
          $fld->max_length = $rs->fields[7];
475
        $fld->not_null = !empty($rs->fields[10]);
476
        $fld->scale = $rs->fields[8];
477
        $retarr[strtoupper($fld->name)] = $fld;
478
      } else if (sizeof($retarr)>0)
479
        break;
480
      $rs->MoveNext();
481
    }
482
    $rs->Close(); //-- crashes 4.03pl1 -- why?
483

  
484
    if (empty($retarr)) $retarr = false;
485
    return $retarr;
486
  }
487

  
488
        // Returns an array of columns names for a given table
489
        function &MetaColumnNames($table)
490
        {
491
                $recordSet = $this->Execute("select name from system.columns where parent='$table'");
492
                if(!$recordSet){
493
                        print $this->ErrorMsg();
494
                        return false;
495
                }
496
                else{
497
                        $i=0;
498
                        while (!$recordSet->EOF){
499
                                $arr["FIELD$i"] = $recordSet->fields[0];
500
                                $recordSet->MoveNext();
501
                                $i=$i+1;
502
                        }
503
                        return $arr;
504
                }
505
        }
506

  
507

  
508
  function Prepare($sql)
509
  {
510
    if (! $this->_bindInputArray) return $sql; // no binding
511
    $stmt = ads_prepare($this->_connectionID,$sql);
512
    if (!$stmt) {
513
      // we don't know whether odbc driver is parsing prepared stmts, so just return sql
514
      return $sql;
515
    }
516
    return array($sql,$stmt,false);
517
  }
518

  
519
  /* returns queryID or false */
520
  function _query($sql,$inputarr=false)
521
  {
522
  GLOBAL $php_errormsg;
523
    if (isset($php_errormsg)) $php_errormsg = '';
524
    $this->_error = '';
525

  
526
                if ($inputarr) {
527
      if (is_array($sql)) {
528
        $stmtid = $sql[1];
529
      } else {
530
        $stmtid = ads_prepare($this->_connectionID,$sql);
531

  
532
        if ($stmtid == false) {
533
          $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
534
          return false;
535
        }
536
      }
537

  
538
      if (! ads_execute($stmtid,$inputarr)) {
539
        //@ads_free_result($stmtid);
540
        if ($this->_haserrorfunctions) {
541
          $this->_errorMsg = ads_errormsg();
542
          $this->_errorCode = ads_error();
543
        }
544
        return false;
545
      }
546

  
547
    } else if (is_array($sql)) {
548
      $stmtid = $sql[1];
549
      if (!ads_execute($stmtid)) {
550
        //@ads_free_result($stmtid);
551
        if ($this->_haserrorfunctions) {
552
          $this->_errorMsg = ads_errormsg();
553
          $this->_errorCode = ads_error();
554
        }
555
        return false;
556
      }
557
    } else
558
                        {
559

  
560
      $stmtid = ads_exec($this->_connectionID,$sql);
561

  
562
                        }
563

  
564
                $this->_lastAffectedRows = 0;
565

  
566
    if ($stmtid)
567
                {
568

  
569
      if (@ads_num_fields($stmtid) == 0) {
570
        $this->_lastAffectedRows = ads_num_rows($stmtid);
571
        $stmtid = true;
572

  
573
      } else {
574

  
575
        $this->_lastAffectedRows = 0;
576
        ads_binmode($stmtid,$this->binmode);
577
        ads_longreadlen($stmtid,$this->maxblobsize);
578

  
579
      }
580

  
581
      if ($this->_haserrorfunctions)
582
                        {
583

  
584
        $this->_errorMsg = '';
585
        $this->_errorCode = 0;
586
      }
587
                        else
588
        $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
589
    }
590
                else
591
                {
592
      if ($this->_haserrorfunctions) {
593
        $this->_errorMsg = ads_errormsg();
594
        $this->_errorCode = ads_error();
595
      } else
596
        $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
597
    }
598

  
599
    return $stmtid;
600

  
601
  }
602

  
603
  /*
604
    Insert a null into the blob field of the table first.
605
    Then use UpdateBlob to store the blob.
606

  
607
    Usage:
608

  
609
    $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
610
    $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
611
   */
612
  function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
613
  {
614
                $sql = "UPDATE $table SET $column=? WHERE $where";
615
                $stmtid = ads_prepare($this->_connectionID,$sql);
616
                if ($stmtid == false){
617
                  $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
618
                  return false;
619
          }
620
                if (! ads_execute($stmtid,array($val),array(SQL_BINARY) )){
621
                        if ($this->_haserrorfunctions){
622
                                $this->_errorMsg = ads_errormsg();
623
                    $this->_errorCode = ads_error();
624
            }
625
                        return false;
626
           }
627
                 return TRUE;
628
        }
629

  
630
  // returns true or false
631
  function _close()
632
  {
633
    $ret = @ads_close($this->_connectionID);
634
    $this->_connectionID = false;
635
    return $ret;
636
  }
637

  
638
  function _affectedrows()
639
  {
640
    return $this->_lastAffectedRows;
641
  }
642

  
643
}
644

  
645
/*--------------------------------------------------------------------------------------
646
   Class Name: Recordset
647
--------------------------------------------------------------------------------------*/
648

  
649
class ADORecordSet_ads extends ADORecordSet {
650

  
651
  var $bind = false;
652
  var $databaseType = "ads";
653
  var $dataProvider = "ads";
654
  var $useFetchArray;
655
  var $_has_stupid_odbc_fetch_api_change;
656

  
657
  function ADORecordSet_ads($id,$mode=false)
658
  {
659
    if ($mode === false) {
660
      global $ADODB_FETCH_MODE;
661
      $mode = $ADODB_FETCH_MODE;
662
    }
663
    $this->fetchMode = $mode;
664

  
665
    $this->_queryID = $id;
666

  
667
    // the following is required for mysql odbc driver in 4.3.1 -- why?
668
    $this->EOF = false;
669
    $this->_currentRow = -1;
670
    //$this->ADORecordSet($id);
671
  }
672

  
673

  
674
  // returns the field object
675
  function &FetchField($fieldOffset = -1)
676
  {
677

  
678
    $off=$fieldOffset+1; // offsets begin at 1
679

  
680
    $o= new ADOFieldObject();
681
    $o->name = @ads_field_name($this->_queryID,$off);
682
    $o->type = @ads_field_type($this->_queryID,$off);
683
    $o->max_length = @ads_field_len($this->_queryID,$off);
684
    if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
685
    else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
686
    return $o;
687
  }
688

  
689
  /* Use associative array to get fields array */
690
  function Fields($colname)
691
  {
692
    if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
693
    if (!$this->bind) {
694
      $this->bind = array();
695
      for ($i=0; $i < $this->_numOfFields; $i++) {
696
        $o = $this->FetchField($i);
697
        $this->bind[strtoupper($o->name)] = $i;
698
      }
699
    }
700

  
701
     return $this->fields[$this->bind[strtoupper($colname)]];
702
  }
703

  
704

  
705
  function _initrs()
706
  {
707
  global $ADODB_COUNTRECS;
708
    $this->_numOfRows = ($ADODB_COUNTRECS) ? @ads_num_rows($this->_queryID) : -1;
709
    $this->_numOfFields = @ads_num_fields($this->_queryID);
710
    // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0
711
    if ($this->_numOfRows == 0) $this->_numOfRows = -1;
712
    //$this->useFetchArray = $this->connection->useFetchArray;
713
    $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
714
  }
715

  
716
  function _seek($row)
717
  {
718
    return false;
719
  }
720

  
721
  // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated
722
  function &GetArrayLimit($nrows,$offset=-1)
723
  {
724
    if ($offset <= 0) {
725
      $rs =& $this->GetArray($nrows);
726
      return $rs;
727
    }
728
    $savem = $this->fetchMode;
729
    $this->fetchMode = ADODB_FETCH_NUM;
730
    $this->Move($offset);
731
    $this->fetchMode = $savem;
732

  
733
    if ($this->fetchMode & ADODB_FETCH_ASSOC) {
734
      $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
735
    }
736

  
737
    $results = array();
738
    $cnt = 0;
739
    while (!$this->EOF && $nrows != $cnt) {
740
      $results[$cnt++] = $this->fields;
741
      $this->MoveNext();
742
    }
743

  
744
    return $results;
745
  }
746

  
747

  
748
  function MoveNext()
749
  {
750
    if ($this->_numOfRows != 0 && !$this->EOF) {
751
      $this->_currentRow++;
752

  
753
      if ($this->_has_stupid_odbc_fetch_api_change)
754
        $rez = @ads_fetch_into($this->_queryID,$this->fields);
755
      else {
756
        $row = 0;
757
        $rez = @ads_fetch_into($this->_queryID,$row,$this->fields);
758
      }
759
      if ($rez) {
760
        if ($this->fetchMode & ADODB_FETCH_ASSOC) {
761
          $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
762
        }
763
        return true;
764
      }
765
    }
766
    $this->fields = false;
767
    $this->EOF = true;
768
    return false;
769
  }
770

  
771
  function _fetch()
772
  {
773

  
774
    if ($this->_has_stupid_odbc_fetch_api_change)
775
      $rez = @ads_fetch_into($this->_queryID,$this->fields);
776
    else {
777
      $row = 0;
778
      $rez = @ads_fetch_into($this->_queryID,$row,$this->fields);
779
    }
780
    if ($rez) {
781
      if ($this->fetchMode & ADODB_FETCH_ASSOC) {
782
        $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
783
      }
784
      return true;
785
    }
786
    $this->fields = false;
787
    return false;
788
  }
789

  
790
  function _close()
791
  {
792
    return @ads_free_result($this->_queryID);
793
  }
794

  
795
}
796
?>