Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
36 kaklik 1
<?php
2
/* 
3
V4.80 8 Mar 2006  (c) 2000-2006 John Lim (jlim@natsoft.com.my). 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 ADO data driver. Requires ADO. Works only on MS Windows. PHP5 compat version.
12
*/
13
 
14
// security - hide paths
15
if (!defined('ADODB_DIR')) die();
16
 
17
define("_ADODB_ADO_LAYER", 1 );
18
/*--------------------------------------------------------------------------------------
19
--------------------------------------------------------------------------------------*/
20
 
21
 
22
class ADODB_ado extends ADOConnection {
23
	var $databaseType = "ado";	
24
	var $_bindInputArray = false;
25
	var $fmtDate = "'Y-m-d'";
26
	var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
27
	var $replaceQuote = "''"; // string to use to replace quotes
28
	var $dataProvider = "ado";	
29
	var $hasAffectedRows = true;
30
	var $adoParameterType = 201; // 201 = long varchar, 203=long wide varchar, 205 = long varbinary
31
	var $_affectedRows = false;
32
	var $_thisTransactions;
33
	var $_cursor_type = 3; // 3=adOpenStatic,0=adOpenForwardOnly,1=adOpenKeyset,2=adOpenDynamic
34
	var $_cursor_location = 3; // 2=adUseServer, 3 = adUseClient;
35
	var $_lock_type = -1;
36
	var $_execute_option = -1;
37
	var $poorAffectedRows = true; 
38
	var $charPage;
39
 
40
	function ADODB_ado() 
41
	{ 	
42
		$this->_affectedRows = new VARIANT;
43
	}
44
 
45
	function ServerInfo()
46
	{
47
		if (!empty($this->_connectionID)) $desc = $this->_connectionID->provider;
48
		return array('description' => $desc, 'version' => '');
49
	}
50
 
51
	function _affectedrows()
52
	{
53
		if (PHP_VERSION >= 5) return $this->_affectedRows;
54
 
55
		return $this->_affectedRows->value;
56
	}
57
 
58
	// you can also pass a connection string like this:
59
	//
60
	// $DB->Connect('USER ID=sa;PASSWORD=pwd;SERVER=mangrove;DATABASE=ai',false,false,'SQLOLEDB');
61
	function _connect($argHostname, $argUsername, $argPassword, $argProvider= 'MSDASQL')
62
	{
63
		try {
64
		$u = 'UID';
65
		$p = 'PWD';
66
 
67
		if (!empty($this->charPage))
68
			$dbc = new COM('ADODB.Connection',null,$this->charPage);
69
		else
70
			$dbc = new COM('ADODB.Connection');
71
 
72
		if (! $dbc) return false;
73
 
74
		/* special support if provider is mssql or access */
75
		if ($argProvider=='mssql') {
76
			$u = 'User Id';  //User parameter name for OLEDB
77
			$p = 'Password'; 
78
			$argProvider = "SQLOLEDB"; // SQL Server Provider
79
 
80
			// not yet
81
			//if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename";
82
 
83
			//use trusted conection for SQL if username not specified
84
			if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes";
85
		} else if ($argProvider=='access')
86
			$argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider
87
 
88
		if ($argProvider) $dbc->Provider = $argProvider;	
89
 
90
		if ($argUsername) $argHostname .= ";$u=$argUsername";
91
		if ($argPassword)$argHostname .= ";$p=$argPassword";
92
 
93
		if ($this->debug) ADOConnection::outp( "Host=".$argHostname."<BR>\n version=$dbc->version");
94
		// @ added below for php 4.0.1 and earlier
95
		@$dbc->Open((string) $argHostname);
96
 
97
		$this->_connectionID = $dbc;
98
 
99
		$dbc->CursorLocation = $this->_cursor_location;
100
		return  $dbc->State > 0;
101
		} catch (exception $e) {
102
		}
103
 
104
		return false;
105
	}
106
 
107
	// returns true or false
108
	function _pconnect($argHostname, $argUsername, $argPassword, $argProvider='MSDASQL')
109
	{
110
		return $this->_connect($argHostname,$argUsername,$argPassword,$argProvider);
111
	}	
112
 
113
/*
114
	adSchemaCatalogs	= 1,
115
	adSchemaCharacterSets	= 2,
116
	adSchemaCollations	= 3,
117
	adSchemaColumns	= 4,
118
	adSchemaCheckConstraints	= 5,
119
	adSchemaConstraintColumnUsage	= 6,
120
	adSchemaConstraintTableUsage	= 7,
121
	adSchemaKeyColumnUsage	= 8,
122
	adSchemaReferentialContraints	= 9,
123
	adSchemaTableConstraints	= 10,
124
	adSchemaColumnsDomainUsage	= 11,
125
	adSchemaIndexes	= 12,
126
	adSchemaColumnPrivileges	= 13,
127
	adSchemaTablePrivileges	= 14,
128
	adSchemaUsagePrivileges	= 15,
129
	adSchemaProcedures	= 16,
130
	adSchemaSchemata	= 17,
131
	adSchemaSQLLanguages	= 18,
132
	adSchemaStatistics	= 19,
133
	adSchemaTables	= 20,
134
	adSchemaTranslations	= 21,
135
	adSchemaProviderTypes	= 22,
136
	adSchemaViews	= 23,
137
	adSchemaViewColumnUsage	= 24,
138
	adSchemaViewTableUsage	= 25,
139
	adSchemaProcedureParameters	= 26,
140
	adSchemaForeignKeys	= 27,
141
	adSchemaPrimaryKeys	= 28,
142
	adSchemaProcedureColumns	= 29,
143
	adSchemaDBInfoKeywords	= 30,
144
	adSchemaDBInfoLiterals	= 31,
145
	adSchemaCubes	= 32,
146
	adSchemaDimensions	= 33,
147
	adSchemaHierarchies	= 34,
148
	adSchemaLevels	= 35,
149
	adSchemaMeasures	= 36,
150
	adSchemaProperties	= 37,
151
	adSchemaMembers	= 38
152
 
153
*/
154
 
155
	function &MetaTables()
156
	{
157
		$arr= array();
158
		$dbc = $this->_connectionID;
159
 
160
		$adors=@$dbc->OpenSchema(20);//tables
161
		if ($adors){
162
			$f = $adors->Fields(2);//table/view name
163
			$t = $adors->Fields(3);//table type
164
			while (!$adors->EOF){
165
				$tt=substr($t->value,0,6);
166
				if ($tt!='SYSTEM' && $tt !='ACCESS')
167
					$arr[]=$f->value;
168
				//print $f->value . ' ' . $t->value.'<br>';
169
				$adors->MoveNext();
170
			}
171
			$adors->Close();
172
		}
173
 
174
		return $arr;
175
	}
176
 
177
	function &MetaColumns($table)
178
	{
179
		$table = strtoupper($table);
180
		$arr= array();
181
		$dbc = $this->_connectionID;
182
 
183
		$adors=@$dbc->OpenSchema(4);//tables
184
 
185
		if ($adors){
186
			$t = $adors->Fields(2);//table/view name
187
			while (!$adors->EOF){
188
 
189
 
190
				if (strtoupper($t->Value) == $table) {
191
 
192
					$fld = new ADOFieldObject();
193
					$c = $adors->Fields(3);
194
					$fld->name = $c->Value;
195
					$fld->type = 'CHAR'; // cannot discover type in ADO!
196
					$fld->max_length = -1;
197
					$arr[strtoupper($fld->name)]=$fld;
198
				}
199
 
200
				$adors->MoveNext();
201
			}
202
			$adors->Close();
203
		}
204
 
205
		return $arr;
206
	}
207
 
208
 
209
 
210
 
211
	/* returns queryID or false */
212
	function &_query($sql,$inputarr=false) 
213
	{
214
		try { // In PHP5, all COM errors are exceptions, so to maintain old behaviour...
215
 
216
		$dbc = $this->_connectionID;
217
 
218
	//	return rs	
219
		if ($inputarr) {
220
 
221
			if (!empty($this->charPage))
222
				$oCmd = new COM('ADODB.Command',null,$this->charPage);
223
			else
224
				$oCmd = new COM('ADODB.Command');
225
			$oCmd->ActiveConnection = $dbc;
226
			$oCmd->CommandText = $sql;
227
			$oCmd->CommandType = 1;
228
 
229
			foreach($inputarr as $val) {
230
				// name, type, direction 1 = input, len,
231
				$this->adoParameterType = 130;
232
				$p = $oCmd->CreateParameter('name',$this->adoParameterType,1,strlen($val),$val);
233
				//print $p->Type.' '.$p->value;
234
				$oCmd->Parameters->Append($p);
235
			}
236
			$p = false;
237
			$rs = $oCmd->Execute();
238
			$e = $dbc->Errors;
239
			if ($dbc->Errors->Count > 0) return false;
240
			return $rs;
241
		}
242
 
243
		$rs = @$dbc->Execute($sql,$this->_affectedRows, $this->_execute_option);
244
 
245
		if ($dbc->Errors->Count > 0) return false;
246
		if (! $rs) return false;
247
 
248
		if ($rs->State == 0) return true; // 0 = adStateClosed means no records returned
249
		return $rs;
250
 
251
		} catch (exception $e) {
252
 
253
		}
254
		return false;
255
	}
256
 
257
 
258
	function BeginTrans() 
259
	{ 
260
		if ($this->transOff) return true;
261
 
262
		if (isset($this->_thisTransactions))
263
			if (!$this->_thisTransactions) return false;
264
		else {
265
			$o = $this->_connectionID->Properties("Transaction DDL");
266
			$this->_thisTransactions = $o ? true : false;
267
			if (!$o) return false;
268
		}
269
		@$this->_connectionID->BeginTrans();
270
		$this->transCnt += 1;
271
		return true;
272
	}
273
	function CommitTrans($ok=true) 
274
	{ 
275
		if (!$ok) return $this->RollbackTrans();
276
		if ($this->transOff) return true;
277
 
278
		@$this->_connectionID->CommitTrans();
279
		if ($this->transCnt) @$this->transCnt -= 1;
280
		return true;
281
	}
282
	function RollbackTrans() {
283
		if ($this->transOff) return true;
284
		@$this->_connectionID->RollbackTrans();
285
		if ($this->transCnt) @$this->transCnt -= 1;
286
		return true;
287
	}
288
 
289
	/*	Returns: the last error message from previous database operation	*/	
290
 
291
	function ErrorMsg() 
292
	{
293
		$errc = $this->_connectionID->Errors;
294
		if ($errc->Count == 0) return '';
295
		$err = $errc->Item($errc->Count-1);
296
		return $err->Description;
297
	}
298
 
299
	function ErrorNo() 
300
	{
301
		$errc = $this->_connectionID->Errors;
302
		if ($errc->Count == 0) return 0;
303
		$err = $errc->Item($errc->Count-1);
304
		return $err->NativeError;
305
	}
306
 
307
	// returns true or false
308
	function _close()
309
	{
310
		if ($this->_connectionID) $this->_connectionID->Close();
311
		$this->_connectionID = false;
312
		return true;
313
	}
314
 
315
 
316
}
317
 
318
/*--------------------------------------------------------------------------------------
319
	 Class Name: Recordset
320
--------------------------------------------------------------------------------------*/
321
 
322
class ADORecordSet_ado extends ADORecordSet {	
323
 
324
	var $bind = false;
325
	var $databaseType = "ado";	
326
	var $dataProvider = "ado";	
327
	var $_tarr = false; // caches the types
328
	var $_flds; // and field objects
329
	var $canSeek = true;
330
  	var $hideErrors = true;
331
 
332
	function ADORecordSet_ado($id,$mode=false)
333
	{
334
		if ($mode === false) { 
335
			global $ADODB_FETCH_MODE;
336
			$mode = $ADODB_FETCH_MODE;
337
		}
338
		$this->fetchMode = $mode;
339
		return $this->ADORecordSet($id,$mode);
340
	}
341
 
342
 
343
	// returns the field object
344
	function &FetchField($fieldOffset = -1) {
345
		$off=$fieldOffset+1; // offsets begin at 1
346
 
347
		$o= new ADOFieldObject();
348
		$rs = $this->_queryID;
349
		$f = $rs->Fields($fieldOffset);
350
		$o->name = $f->Name;
351
		$t = $f->Type;
352
		$o->type = $this->MetaType($t);
353
		$o->max_length = $f->DefinedSize;
354
		$o->ado_type = $t;
355
 
356
 
357
		//print "off=$off name=$o->name type=$o->type len=$o->max_length<br>";
358
		return $o;
359
	}
360
 
361
	/* Use associative array to get fields array */
362
	function Fields($colname)
363
	{
364
		if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
365
		if (!$this->bind) {
366
			$this->bind = array();
367
			for ($i=0; $i < $this->_numOfFields; $i++) {
368
				$o = $this->FetchField($i);
369
				$this->bind[strtoupper($o->name)] = $i;
370
			}
371
		}
372
 
373
		 return $this->fields[$this->bind[strtoupper($colname)]];
374
	}
375
 
376
 
377
	function _initrs()
378
	{
379
		$rs = $this->_queryID;
380
		$this->_numOfRows = $rs->RecordCount;
381
 
382
		$f = $rs->Fields;
383
		$this->_numOfFields = $f->Count;
384
	}
385
 
386
 
387
	 // should only be used to move forward as we normally use forward-only cursors
388
	function _seek($row)
389
	{
390
	   $rs = $this->_queryID; 
391
		// absoluteposition doesn't work -- my maths is wrong ?
392
		//	$rs->AbsolutePosition->$row-2;
393
		//	return true;
394
		if ($this->_currentRow > $row) return false;
395
		@$rs->Move((integer)$row - $this->_currentRow-1); //adBookmarkFirst
396
		return true;
397
	}
398
 
399
/*
400
	OLEDB types
401
 
402
	 enum DBTYPEENUM
403
	{	DBTYPE_EMPTY	= 0,
404
	DBTYPE_NULL	= 1,
405
	DBTYPE_I2	= 2,
406
	DBTYPE_I4	= 3,
407
	DBTYPE_R4	= 4,
408
	DBTYPE_R8	= 5,
409
	DBTYPE_CY	= 6,
410
	DBTYPE_DATE	= 7,
411
	DBTYPE_BSTR	= 8,
412
	DBTYPE_IDISPATCH	= 9,
413
	DBTYPE_ERROR	= 10,
414
	DBTYPE_BOOL	= 11,
415
	DBTYPE_VARIANT	= 12,
416
	DBTYPE_IUNKNOWN	= 13,
417
	DBTYPE_DECIMAL	= 14,
418
	DBTYPE_UI1	= 17,
419
	DBTYPE_ARRAY	= 0x2000,
420
	DBTYPE_BYREF	= 0x4000,
421
	DBTYPE_I1	= 16,
422
	DBTYPE_UI2	= 18,
423
	DBTYPE_UI4	= 19,
424
	DBTYPE_I8	= 20,
425
	DBTYPE_UI8	= 21,
426
	DBTYPE_GUID	= 72,
427
	DBTYPE_VECTOR	= 0x1000,
428
	DBTYPE_RESERVED	= 0x8000,
429
	DBTYPE_BYTES	= 128,
430
	DBTYPE_STR	= 129,
431
	DBTYPE_WSTR	= 130,
432
	DBTYPE_NUMERIC	= 131,
433
	DBTYPE_UDT	= 132,
434
	DBTYPE_DBDATE	= 133,
435
	DBTYPE_DBTIME	= 134,
436
	DBTYPE_DBTIMESTAMP	= 135
437
 
438
	ADO Types
439
 
440
   	adEmpty	= 0,
441
	adTinyInt	= 16,
442
	adSmallInt	= 2,
443
	adInteger	= 3,
444
	adBigInt	= 20,
445
	adUnsignedTinyInt	= 17,
446
	adUnsignedSmallInt	= 18,
447
	adUnsignedInt	= 19,
448
	adUnsignedBigInt	= 21,
449
	adSingle	= 4,
450
	adDouble	= 5,
451
	adCurrency	= 6,
452
	adDecimal	= 14,
453
	adNumeric	= 131,
454
	adBoolean	= 11,
455
	adError	= 10,
456
	adUserDefined	= 132,
457
	adVariant	= 12,
458
	adIDispatch	= 9,
459
	adIUnknown	= 13,	
460
	adGUID	= 72,
461
	adDate	= 7,
462
	adDBDate	= 133,
463
	adDBTime	= 134,
464
	adDBTimeStamp	= 135,
465
	adBSTR	= 8,
466
	adChar	= 129,
467
	adVarChar	= 200,
468
	adLongVarChar	= 201,
469
	adWChar	= 130,
470
	adVarWChar	= 202,
471
	adLongVarWChar	= 203,
472
	adBinary	= 128,
473
	adVarBinary	= 204,
474
	adLongVarBinary	= 205,
475
	adChapter	= 136,
476
	adFileTime	= 64,
477
	adDBFileTime	= 137,
478
	adPropVariant	= 138,
479
	adVarNumeric	= 139
480
*/
481
	function MetaType($t,$len=-1,$fieldobj=false)
482
	{
483
		if (is_object($t)) {
484
			$fieldobj = $t;
485
			$t = $fieldobj->type;
486
			$len = $fieldobj->max_length;
487
		}
488
 
489
		if (!is_numeric($t)) return $t;
490
 
491
		switch ($t) {
492
		case 0:
493
		case 12: // variant
494
		case 8: // bstr
495
		case 129: //char
496
		case 130: //wc
497
		case 200: // varc
498
		case 202:// varWC
499
		case 128: // bin
500
		case 204: // varBin
501
		case 72: // guid
502
			if ($len <= $this->blobSize) return 'C';
503
 
504
		case 201:
505
		case 203:
506
			return 'X';
507
		case 128:
508
		case 204:
509
		case 205:
510
			 return 'B';
511
		case 7:
512
		case 133: return 'D';
513
 
514
		case 134:
515
		case 135: return 'T';
516
 
517
		case 11: return 'L';
518
 
519
		case 16://	adTinyInt	= 16,
520
		case 2://adSmallInt	= 2,
521
		case 3://adInteger	= 3,
522
		case 4://adBigInt	= 20,
523
		case 17://adUnsignedTinyInt	= 17,
524
		case 18://adUnsignedSmallInt	= 18,
525
		case 19://adUnsignedInt	= 19,
526
		case 20://adUnsignedBigInt	= 21,
527
			return 'I';
528
		default: return 'N';
529
		}
530
	}
531
 
532
	// time stamp not supported yet
533
	function _fetch()
534
	{	
535
		$rs = $this->_queryID;
536
		if (!$rs or $rs->EOF) {
537
			$this->fields = false;
538
			return false;
539
		}
540
		$this->fields = array();
541
 
542
		if (!$this->_tarr) {
543
			$tarr = array();
544
			$flds = array();
545
			for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
546
				$f = $rs->Fields($i);
547
				$flds[] = $f;
548
				$tarr[] = $f->Type;
549
			}
550
			// bind types and flds only once
551
			$this->_tarr = $tarr; 
552
			$this->_flds = $flds;
553
		}
554
		$t = reset($this->_tarr);
555
		$f = reset($this->_flds);
556
 
557
		if ($this->hideErrors)  $olde = error_reporting(E_ERROR|E_CORE_ERROR);// sometimes $f->value be null
558
		for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
559
			//echo "<p>",$t,' ';var_dump($f->value); echo '</p>';
560
			switch($t) {
561
			case 135: // timestamp
562
				if (!strlen((string)$f->value)) $this->fields[] = false;
563
				else {
564
					if (!is_numeric($f->value)) # $val = variant_date_to_timestamp($f->value);
565
						// VT_DATE stores dates as (float) fractional days since 1899/12/30 00:00:00
566
						$val= (float) variant_cast($f->value,VT_R8)*3600*24-2209161600;
567
					else 
568
						$val = $f->value;
569
					$this->fields[] = adodb_date('Y-m-d H:i:s',$val);
570
				}
571
				break;			
572
			case 133:// A date value (yyyymmdd) 
573
				if ($val = $f->value) {
574
					$this->fields[] = substr($val,0,4).'-'.substr($val,4,2).'-'.substr($val,6,2);
575
				} else
576
					$this->fields[] = false;
577
				break;
578
			case 7: // adDate
579
				if (!strlen((string)$f->value)) $this->fields[] = false;
580
				else {
581
					if (!is_numeric($f->value)) $val = variant_date_to_timestamp($f->value);
582
					else $val = $f->value;
583
 
584
					if (($val % 86400) == 0) $this->fields[] = adodb_date('Y-m-d',$val);
585
					else $this->fields[] = adodb_date('Y-m-d H:i:s',$val);
586
				}
587
				break;
588
			case 1: // null
589
				$this->fields[] = false;
590
				break;
591
			case 6: // currency is not supported properly;
592
				ADOConnection::outp( '<b>'.$f->Name.': currency type not supported by PHP</b>');
593
				$this->fields[] = (float) $f->value;
594
				break;
595
			default:
596
				$this->fields[] = $f->value; 
597
				break;
598
			}
599
			//print " $f->value $t, ";
600
			$f = next($this->_flds);
601
			$t = next($this->_tarr);
602
		} // for
603
		if ($this->hideErrors) error_reporting($olde);
604
		@$rs->MoveNext(); // @ needed for some versions of PHP!
605
 
606
		if ($this->fetchMode & ADODB_FETCH_ASSOC) {
607
			$this->fields = &$this->GetRowAssoc(ADODB_ASSOC_CASE);
608
		}
609
		return true;
610
	}
611
 
612
		function NextRecordSet()
613
		{
614
			$rs = $this->_queryID;
615
			$this->_queryID = $rs->NextRecordSet();
616
			//$this->_queryID = $this->_QueryId->NextRecordSet();
617
			if ($this->_queryID == null) return false;
618
 
619
			$this->_currentRow = -1;
620
			$this->_currentPage = -1;
621
			$this->bind = false;
622
			$this->fields = false;
623
			$this->_flds = false;
624
			$this->_tarr = false;
625
 
626
			$this->_inited = false;
627
			$this->Init();
628
			return true;
629
		}
630
 
631
	function _close() {
632
		$this->_flds = false;
633
		@$this->_queryID->Close();// by Pete Dishman (peterd@telephonetics.co.uk)
634
		$this->_queryID = false;	
635
	}
636
 
637
}
638
 
639
?>