1 | <?php |
---|
2 | /* |
---|
3 | V4.94 23 Jan 2007 (c) 2000-2007 John Lim. 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 | Informix port by Mitchell T. Young (mitch@youngfamily.org) |
---|
12 | |
---|
13 | Further mods by "Samuel CARRIERE" <samuel_carriere@hotmail.com> |
---|
14 | |
---|
15 | */ |
---|
16 | |
---|
17 | // security - hide paths |
---|
18 | if (!defined('ADODB_DIR')) die(); |
---|
19 | |
---|
20 | if (!defined('IFX_SCROLL')) define('IFX_SCROLL',1); |
---|
21 | |
---|
22 | class ADODB_informix72 extends ADOConnection { |
---|
23 | var $databaseType = "informix72"; |
---|
24 | var $dataProvider = "informix"; |
---|
25 | var $replaceQuote = "''"; // string to use to replace quotes |
---|
26 | var $fmtDate = "'Y-m-d'"; |
---|
27 | var $fmtTimeStamp = "'Y-m-d H:i:s'"; |
---|
28 | var $hasInsertID = true; |
---|
29 | var $hasAffectedRows = true; |
---|
30 | var $substr = 'substr'; |
---|
31 | var $metaTablesSQL="select tabname,tabtype from systables where tabtype in ('T','V') and owner!='informix'"; //Don't get informix tables and pseudo-tables |
---|
32 | |
---|
33 | |
---|
34 | var $metaColumnsSQL = |
---|
35 | "select c.colname, c.coltype, c.collength, d.default,c.colno |
---|
36 | from syscolumns c, systables t,outer sysdefaults d |
---|
37 | where c.tabid=t.tabid and d.tabid=t.tabid and d.colno=c.colno |
---|
38 | and tabname='%s' order by c.colno"; |
---|
39 | |
---|
40 | var $metaPrimaryKeySQL = |
---|
41 | "select part1,part2,part3,part4,part5,part6,part7,part8 from |
---|
42 | systables t,sysconstraints s,sysindexes i where t.tabname='%s' |
---|
43 | and s.tabid=t.tabid and s.constrtype='P' |
---|
44 | and i.idxname=s.idxname"; |
---|
45 | |
---|
46 | var $concat_operator = '||'; |
---|
47 | |
---|
48 | var $lastQuery = false; |
---|
49 | var $has_insertid = true; |
---|
50 | |
---|
51 | var $_autocommit = true; |
---|
52 | var $_bindInputArray = true; // set to true if ADOConnection.Execute() permits binding of array parameters. |
---|
53 | var $sysDate = 'TODAY'; |
---|
54 | var $sysTimeStamp = 'CURRENT'; |
---|
55 | var $cursorType = IFX_SCROLL; // IFX_SCROLL or IFX_HOLD or 0 |
---|
56 | |
---|
57 | function ADODB_informix72() |
---|
58 | { |
---|
59 | // alternatively, use older method: |
---|
60 | //putenv("DBDATE=Y4MD-"); |
---|
61 | |
---|
62 | // force ISO date format |
---|
63 | putenv('GL_DATE=%Y-%m-%d'); |
---|
64 | |
---|
65 | if (function_exists('ifx_byteasvarchar')) { |
---|
66 | ifx_byteasvarchar(1); // Mode "0" will return a blob id, and mode "1" will return a varchar with text content. |
---|
67 | ifx_textasvarchar(1); // Mode "0" will return a blob id, and mode "1" will return a varchar with text content. |
---|
68 | ifx_blobinfile_mode(0); // Mode "0" means save Byte-Blobs in memory, and mode "1" means save Byte-Blobs in a file. |
---|
69 | } |
---|
70 | } |
---|
71 | |
---|
72 | function ServerInfo() |
---|
73 | { |
---|
74 | if (isset($this->version)) return $this->version; |
---|
75 | |
---|
76 | $arr['description'] = $this->GetOne("select DBINFO('version','full') from systables where tabid = 1"); |
---|
77 | $arr['version'] = $this->GetOne("select DBINFO('version','major') || DBINFO('version','minor') from systables where tabid = 1"); |
---|
78 | $this->version = $arr; |
---|
79 | return $arr; |
---|
80 | } |
---|
81 | |
---|
82 | |
---|
83 | |
---|
84 | function _insertid() |
---|
85 | { |
---|
86 | $sqlca =ifx_getsqlca($this->lastQuery); |
---|
87 | return @$sqlca["sqlerrd1"]; |
---|
88 | } |
---|
89 | |
---|
90 | function _affectedrows() |
---|
91 | { |
---|
92 | if ($this->lastQuery) { |
---|
93 | return @ifx_affected_rows ($this->lastQuery); |
---|
94 | } |
---|
95 | return 0; |
---|
96 | } |
---|
97 | |
---|
98 | function BeginTrans() |
---|
99 | { |
---|
100 | if ($this->transOff) return true; |
---|
101 | $this->transCnt += 1; |
---|
102 | $this->Execute('BEGIN'); |
---|
103 | $this->_autocommit = false; |
---|
104 | return true; |
---|
105 | } |
---|
106 | |
---|
107 | function CommitTrans($ok=true) |
---|
108 | { |
---|
109 | if (!$ok) return $this->RollbackTrans(); |
---|
110 | if ($this->transOff) return true; |
---|
111 | if ($this->transCnt) $this->transCnt -= 1; |
---|
112 | $this->Execute('COMMIT'); |
---|
113 | $this->_autocommit = true; |
---|
114 | return true; |
---|
115 | } |
---|
116 | |
---|
117 | function RollbackTrans() |
---|
118 | { |
---|
119 | if ($this->transOff) return true; |
---|
120 | if ($this->transCnt) $this->transCnt -= 1; |
---|
121 | $this->Execute('ROLLBACK'); |
---|
122 | $this->_autocommit = true; |
---|
123 | return true; |
---|
124 | } |
---|
125 | |
---|
126 | function RowLock($tables,$where,$flds='1 as ignore') |
---|
127 | { |
---|
128 | if ($this->_autocommit) $this->BeginTrans(); |
---|
129 | return $this->GetOne("select $flds from $tables where $where for update"); |
---|
130 | } |
---|
131 | |
---|
132 | /* Returns: the last error message from previous database operation |
---|
133 | Note: This function is NOT available for Microsoft SQL Server. */ |
---|
134 | |
---|
135 | function ErrorMsg() |
---|
136 | { |
---|
137 | if (!empty($this->_logsql)) return $this->_errorMsg; |
---|
138 | $this->_errorMsg = ifx_errormsg(); |
---|
139 | return $this->_errorMsg; |
---|
140 | } |
---|
141 | |
---|
142 | function ErrorNo() |
---|
143 | { |
---|
144 | preg_match("/.*SQLCODE=([^\]]*)/",ifx_error(),$parse); |
---|
145 | if (is_array($parse) && isset($parse[1])) return (int)$parse[1]; |
---|
146 | return 0; |
---|
147 | } |
---|
148 | |
---|
149 | |
---|
150 | function &MetaColumns($table) |
---|
151 | { |
---|
152 | global $ADODB_FETCH_MODE; |
---|
153 | |
---|
154 | $false = false; |
---|
155 | if (!empty($this->metaColumnsSQL)) { |
---|
156 | $save = $ADODB_FETCH_MODE; |
---|
157 | $ADODB_FETCH_MODE = ADODB_FETCH_NUM; |
---|
158 | if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false); |
---|
159 | $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table)); |
---|
160 | if (isset($savem)) $this->SetFetchMode($savem); |
---|
161 | $ADODB_FETCH_MODE = $save; |
---|
162 | if ($rs === false) return $false; |
---|
163 | $rspkey = $this->Execute(sprintf($this->metaPrimaryKeySQL,$table)); //Added to get primary key colno items |
---|
164 | |
---|
165 | $retarr = array(); |
---|
166 | while (!$rs->EOF) { //print_r($rs->fields); |
---|
167 | $fld = new ADOFieldObject(); |
---|
168 | $fld->name = $rs->fields[0]; |
---|
169 | /* //!eos. |
---|
170 | $rs->fields[1] is not the correct adodb type |
---|
171 | $rs->fields[2] is not correct max_length, because can include not-null bit |
---|
172 | |
---|
173 | $fld->type = $rs->fields[1]; |
---|
174 | $fld->primary_key=$rspkey->fields && array_search($rs->fields[4],$rspkey->fields); //Added to set primary key flag |
---|
175 | $fld->max_length = $rs->fields[2];*/ |
---|
176 | $pr=ifx_props($rs->fields[1],$rs->fields[2]); //!eos |
---|
177 | $fld->type = $pr[0] ;//!eos |
---|
178 | $fld->primary_key=$rspkey->fields && array_search($rs->fields[4],$rspkey->fields); |
---|
179 | $fld->max_length = $pr[1]; //!eos |
---|
180 | $fld->precision = $pr[2] ;//!eos |
---|
181 | $fld->not_null = $pr[3]=="N"; //!eos |
---|
182 | |
---|
183 | if (trim($rs->fields[3]) != "AAAAAA 0") { |
---|
184 | $fld->has_default = 1; |
---|
185 | $fld->default_value = $rs->fields[3]; |
---|
186 | } else { |
---|
187 | $fld->has_default = 0; |
---|
188 | } |
---|
189 | |
---|
190 | $retarr[strtolower($fld->name)] = $fld; |
---|
191 | $rs->MoveNext(); |
---|
192 | } |
---|
193 | |
---|
194 | $rs->Close(); |
---|
195 | $rspkey->Close(); //!eos |
---|
196 | return $retarr; |
---|
197 | } |
---|
198 | |
---|
199 | return $false; |
---|
200 | } |
---|
201 | |
---|
202 | function &xMetaColumns($table) |
---|
203 | { |
---|
204 | return ADOConnection::MetaColumns($table,false); |
---|
205 | } |
---|
206 | |
---|
207 | function MetaForeignKeys($table, $owner=false, $upper=false) //!Eos |
---|
208 | { |
---|
209 | $sql = " |
---|
210 | select tr.tabname,updrule,delrule, |
---|
211 | i.part1 o1,i2.part1 d1,i.part2 o2,i2.part2 d2,i.part3 o3,i2.part3 d3,i.part4 o4,i2.part4 d4, |
---|
212 | i.part5 o5,i2.part5 d5,i.part6 o6,i2.part6 d6,i.part7 o7,i2.part7 d7,i.part8 o8,i2.part8 d8 |
---|
213 | from systables t,sysconstraints s,sysindexes i, |
---|
214 | sysreferences r,systables tr,sysconstraints s2,sysindexes i2 |
---|
215 | where t.tabname='$table' |
---|
216 | and s.tabid=t.tabid and s.constrtype='R' and r.constrid=s.constrid |
---|
217 | and i.idxname=s.idxname and tr.tabid=r.ptabid |
---|
218 | and s2.constrid=r.primary and i2.idxname=s2.idxname"; |
---|
219 | |
---|
220 | $rs = $this->Execute($sql); |
---|
221 | if (!$rs || $rs->EOF) return false; |
---|
222 | $arr =& $rs->GetArray(); |
---|
223 | $a = array(); |
---|
224 | foreach($arr as $v) { |
---|
225 | $coldest=$this->metaColumnNames($v["tabname"]); |
---|
226 | $colorig=$this->metaColumnNames($table); |
---|
227 | $colnames=array(); |
---|
228 | for($i=1;$i<=8 && $v["o$i"] ;$i++) { |
---|
229 | $colnames[]=$coldest[$v["d$i"]-1]."=".$colorig[$v["o$i"]-1]; |
---|
230 | } |
---|
231 | if($upper) |
---|
232 | $a[strtoupper($v["tabname"])] = $colnames; |
---|
233 | else |
---|
234 | $a[$v["tabname"]] = $colnames; |
---|
235 | } |
---|
236 | return $a; |
---|
237 | } |
---|
238 | |
---|
239 | function UpdateBlob($table, $column, $val, $where, $blobtype = 'BLOB') |
---|
240 | { |
---|
241 | $type = ($blobtype == 'TEXT') ? 1 : 0; |
---|
242 | $blobid = ifx_create_blob($type,0,$val); |
---|
243 | return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blobid)); |
---|
244 | } |
---|
245 | |
---|
246 | function BlobDecode($blobid) |
---|
247 | { |
---|
248 | return function_exists('ifx_byteasvarchar') ? $blobid : @ifx_get_blob($blobid); |
---|
249 | } |
---|
250 | |
---|
251 | // returns true or false |
---|
252 | function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) |
---|
253 | { |
---|
254 | if (!function_exists('ifx_connect')) return null; |
---|
255 | |
---|
256 | $dbs = $argDatabasename . "@" . $argHostname; |
---|
257 | if ($argHostname) putenv("INFORMIXSERVER=$argHostname"); |
---|
258 | putenv("INFORMIXSERVER=".trim($argHostname)); |
---|
259 | $this->_connectionID = ifx_connect($dbs,$argUsername,$argPassword); |
---|
260 | if ($this->_connectionID === false) return false; |
---|
261 | #if ($argDatabasename) return $this->SelectDB($argDatabasename); |
---|
262 | return true; |
---|
263 | } |
---|
264 | |
---|
265 | // returns true or false |
---|
266 | function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) |
---|
267 | { |
---|
268 | if (!function_exists('ifx_connect')) return null; |
---|
269 | |
---|
270 | $dbs = $argDatabasename . "@" . $argHostname; |
---|
271 | putenv("INFORMIXSERVER=".trim($argHostname)); |
---|
272 | $this->_connectionID = ifx_pconnect($dbs,$argUsername,$argPassword); |
---|
273 | if ($this->_connectionID === false) return false; |
---|
274 | #if ($argDatabasename) return $this->SelectDB($argDatabasename); |
---|
275 | return true; |
---|
276 | } |
---|
277 | /* |
---|
278 | // ifx_do does not accept bind parameters - weird ??? |
---|
279 | function Prepare($sql) |
---|
280 | { |
---|
281 | $stmt = ifx_prepare($sql); |
---|
282 | if (!$stmt) return $sql; |
---|
283 | else return array($sql,$stmt); |
---|
284 | } |
---|
285 | */ |
---|
286 | // returns query ID if successful, otherwise false |
---|
287 | function _query($sql,$inputarr) |
---|
288 | { |
---|
289 | global $ADODB_COUNTRECS; |
---|
290 | |
---|
291 | // String parameters have to be converted using ifx_create_char |
---|
292 | if ($inputarr) { |
---|
293 | foreach($inputarr as $v) { |
---|
294 | if (gettype($v) == 'string') { |
---|
295 | $tab[] = ifx_create_char($v); |
---|
296 | } |
---|
297 | else { |
---|
298 | $tab[] = $v; |
---|
299 | } |
---|
300 | } |
---|
301 | } |
---|
302 | |
---|
303 | // In case of select statement, we use a scroll cursor in order |
---|
304 | // to be able to call "move", or "movefirst" statements |
---|
305 | if (!$ADODB_COUNTRECS && preg_match("/^\s*select/is", $sql)) { |
---|
306 | if ($inputarr) { |
---|
307 | $this->lastQuery = ifx_query($sql,$this->_connectionID, $this->cursorType, $tab); |
---|
308 | } |
---|
309 | else { |
---|
310 | $this->lastQuery = ifx_query($sql,$this->_connectionID, $this->cursorType); |
---|
311 | } |
---|
312 | } |
---|
313 | else { |
---|
314 | if ($inputarr) { |
---|
315 | $this->lastQuery = ifx_query($sql,$this->_connectionID, $tab); |
---|
316 | } |
---|
317 | else { |
---|
318 | $this->lastQuery = ifx_query($sql,$this->_connectionID); |
---|
319 | } |
---|
320 | } |
---|
321 | |
---|
322 | // Following line have been commented because autocommit mode is |
---|
323 | // not supported by informix SE 7.2 |
---|
324 | |
---|
325 | //if ($this->_autocommit) ifx_query('COMMIT',$this->_connectionID); |
---|
326 | |
---|
327 | return $this->lastQuery; |
---|
328 | } |
---|
329 | |
---|
330 | // returns true or false |
---|
331 | function _close() |
---|
332 | { |
---|
333 | $this->lastQuery = false; |
---|
334 | return ifx_close($this->_connectionID); |
---|
335 | } |
---|
336 | } |
---|
337 | |
---|
338 | |
---|
339 | /*-------------------------------------------------------------------------------------- |
---|
340 | Class Name: Recordset |
---|
341 | --------------------------------------------------------------------------------------*/ |
---|
342 | |
---|
343 | class ADORecordset_informix72 extends ADORecordSet { |
---|
344 | |
---|
345 | var $databaseType = "informix72"; |
---|
346 | var $canSeek = true; |
---|
347 | var $_fieldprops = false; |
---|
348 | |
---|
349 | function ADORecordset_informix72($id,$mode=false) |
---|
350 | { |
---|
351 | if ($mode === false) { |
---|
352 | global $ADODB_FETCH_MODE; |
---|
353 | $mode = $ADODB_FETCH_MODE; |
---|
354 | } |
---|
355 | $this->fetchMode = $mode; |
---|
356 | return $this->ADORecordSet($id); |
---|
357 | } |
---|
358 | |
---|
359 | |
---|
360 | |
---|
361 | /* Returns: an object containing field information. |
---|
362 | Get column information in the Recordset object. fetchField() can be used in order to obtain information about |
---|
363 | fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by |
---|
364 | fetchField() is retrieved. */ |
---|
365 | function &FetchField($fieldOffset = -1) |
---|
366 | { |
---|
367 | if (empty($this->_fieldprops)) { |
---|
368 | $fp = ifx_fieldproperties($this->_queryID); |
---|
369 | foreach($fp as $k => $v) { |
---|
370 | $o = new ADOFieldObject; |
---|
371 | $o->name = $k; |
---|
372 | $arr = split(';',$v); //"SQLTYPE;length;precision;scale;ISNULLABLE" |
---|
373 | $o->type = $arr[0]; |
---|
374 | $o->max_length = $arr[1]; |
---|
375 | $this->_fieldprops[] = $o; |
---|
376 | $o->not_null = $arr[4]=="N"; |
---|
377 | } |
---|
378 | } |
---|
379 | $ret = $this->_fieldprops[$fieldOffset]; |
---|
380 | return $ret; |
---|
381 | } |
---|
382 | |
---|
383 | function _initrs() |
---|
384 | { |
---|
385 | $this->_numOfRows = -1; // ifx_affected_rows not reliable, only returns estimate -- ($ADODB_COUNTRECS)? ifx_affected_rows($this->_queryID):-1; |
---|
386 | $this->_numOfFields = ifx_num_fields($this->_queryID); |
---|
387 | } |
---|
388 | |
---|
389 | function _seek($row) |
---|
390 | { |
---|
391 | return @ifx_fetch_row($this->_queryID, (int) $row); |
---|
392 | } |
---|
393 | |
---|
394 | function MoveLast() |
---|
395 | { |
---|
396 | $this->fields = @ifx_fetch_row($this->_queryID, "LAST"); |
---|
397 | if ($this->fields) $this->EOF = false; |
---|
398 | $this->_currentRow = -1; |
---|
399 | |
---|
400 | if ($this->fetchMode == ADODB_FETCH_NUM) { |
---|
401 | foreach($this->fields as $v) { |
---|
402 | $arr[] = $v; |
---|
403 | } |
---|
404 | $this->fields = $arr; |
---|
405 | } |
---|
406 | |
---|
407 | return true; |
---|
408 | } |
---|
409 | |
---|
410 | function MoveFirst() |
---|
411 | { |
---|
412 | $this->fields = @ifx_fetch_row($this->_queryID, "FIRST"); |
---|
413 | if ($this->fields) $this->EOF = false; |
---|
414 | $this->_currentRow = 0; |
---|
415 | |
---|
416 | if ($this->fetchMode == ADODB_FETCH_NUM) { |
---|
417 | foreach($this->fields as $v) { |
---|
418 | $arr[] = $v; |
---|
419 | } |
---|
420 | $this->fields = $arr; |
---|
421 | } |
---|
422 | |
---|
423 | return true; |
---|
424 | } |
---|
425 | |
---|
426 | function _fetch($ignore_fields=false) |
---|
427 | { |
---|
428 | |
---|
429 | $this->fields = @ifx_fetch_row($this->_queryID); |
---|
430 | |
---|
431 | if (!is_array($this->fields)) return false; |
---|
432 | |
---|
433 | if ($this->fetchMode == ADODB_FETCH_NUM) { |
---|
434 | foreach($this->fields as $v) { |
---|
435 | $arr[] = $v; |
---|
436 | } |
---|
437 | $this->fields = $arr; |
---|
438 | } |
---|
439 | return true; |
---|
440 | } |
---|
441 | |
---|
442 | /* close() only needs to be called if you are worried about using too much memory while your script |
---|
443 | is running. All associated result memory for the specified result identifier will automatically be freed. */ |
---|
444 | function _close() |
---|
445 | { |
---|
446 | return ifx_free_result($this->_queryID); |
---|
447 | } |
---|
448 | |
---|
449 | } |
---|
450 | /** !Eos |
---|
451 | * Auxiliar function to Parse coltype,collength. Used by Metacolumns |
---|
452 | * return: array ($mtype,$length,$precision,$nullable) (similar to ifx_fieldpropierties) |
---|
453 | */ |
---|
454 | function ifx_props($coltype,$collength){ |
---|
455 | $itype=fmod($coltype+1,256); |
---|
456 | $nullable=floor(($coltype+1) /256) ?"N":"Y"; |
---|
457 | $mtype=substr(" CIIFFNNDN TBXCC ",$itype,1); |
---|
458 | switch ($itype){ |
---|
459 | case 2: |
---|
460 | $length=4; |
---|
461 | case 6: |
---|
462 | case 9: |
---|
463 | case 14: |
---|
464 | $length=floor($collength/256); |
---|
465 | $precision=fmod($collength,256); |
---|
466 | break; |
---|
467 | default: |
---|
468 | $precision=0; |
---|
469 | $length=$collength; |
---|
470 | } |
---|
471 | return array($mtype,$length,$precision,$nullable); |
---|
472 | } |
---|
473 | |
---|
474 | |
---|
475 | ?> |
---|