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