Updated Rico 2 and Rico 3 with all patches submitted on Sourceforge.
[infodrom/rico3] / plugins / php / dbClass3.php
1 <?php\r
2 /*****************************************************************\r
3  Page        : dbClass3.php\r
4  Description : Routines to access MySQL, PostgreSQL, SQL Server, Oracle, & ODBC databases\r
5  Date        : 25 May 2006\r
6  Author      : Matt Brown (dowdybrown@yahoo.com)\r
7  Copyright (C) 2006-2011 Matt Brown\r
8 \r
9  Rico is licensed under the Apache License, Version 2.0 (the "License"); you may not use this
10  file except in compliance with the License. You may obtain a copy of the License at
11  http://www.apache.org/licenses/LICENSE-2.0
12 ******************************************************************/\r
13 \r
14 \r
15 //********************************************************************************************************\r
16 // Parse a SQL statement\r
17 //********************************************************************************************************\r
18 \r
19 class sqlParse {\r
20   var $IsDistinct;\r
21   var $arSelList;\r
22   var $arSelListAs;\r
23   var $FromClause;\r
24   var $WhereClause;\r
25   var $arGroupBy;\r
26   var $HavingClause;\r
27   var $arOrderBy;\r
28 \r
29   function ToArray() {\r
30     return array($this->arSelList,$this->arSelListAs,$this->FromClause,$this->WhereClause,$this->arGroupBy,$this->HavingClause,$this->arOrderBy,$this->IsDistinct);\r
31   }\r
32 \r
33   function LoadArray($a) {\r
34     $this->arSelList=$a[0];\r
35     $this->arSelListAs=$a[1];\r
36     $this->FromClause=$a[2];\r
37     $this->WhereClause=$a[3];\r
38     $this->arGroupBy=$a[4];\r
39     $this->HavingClause=$a[5];\r
40     $this->arOrderBy=$a[6];\r
41     $this->IsDistinct=$a[7];\r
42   }\r
43 \r
44   // -------------------------------------------------------------\r
45   // Rebuilds a SQL select statement that was parsed by ParseSelect\r
46   // -------------------------------------------------------------\r
47   function Unparse($arSkipCols) {\r
48     $sqltext="SELECT ";\r
49     if ($this->IsDistinct) $sqltext.="DISTINCT ";\r
50     $sqltext.=$this->UnparseColumnListSkip($arSkipCols)." FROM ".$this->FromClause;\r
51     if (!empty($this->WhereClause)) {\r
52       $sqltext.=" WHERE ".$this->WhereClause;\r
53     }\r
54     if (is_array($this->arGroupBy)) {\r
55       if (count($this->arGroupBy) >  0) {\r
56         $sqltext.=" GROUP BY ".implode(",",$this->arGroupBy);\r
57       }\r
58     }\r
59     if (!empty($this->HavingClause)) {\r
60       $sqltext.=" HAVING ".$this->HavingClause;\r
61     }\r
62     if (is_array($this->arOrderBy)) {\r
63       if (count($this->arOrderBy) >  0) {\r
64         $sqltext.=" ORDER BY ".implode(",",$this->arOrderBy);\r
65       }\r
66     }\r
67     return $sqltext;\r
68   }\r
69 \r
70   function UnparseSelect() {\r
71     return $this->Unparse(array());\r
72   }\r
73 \r
74   function UnparseSelectSkip($arSkipCols) {\r
75     return $this->Unparse($arSkipCols);\r
76   }\r
77 \r
78   function UnparseSelectDistinct() {\r
79     $this->IsDistinct=true;\r
80     return $this->Unparse(array());\r
81   }\r
82 \r
83   function UnparseDistinctColumn($colnum) {\r
84     $sqltext="SELECT DISTINCT ".$this->UnparseColumn($colnum)." FROM ".$this->FromClause;\r
85     if (!empty($this->WhereClause)) {\r
86       $sqltext.=" WHERE ".$this->WhereClause;\r
87     }\r
88     $sqltext.=" ORDER BY ".$this->arSelList[$colnum];\r
89     return $sqltext;\r
90   }\r
91 \r
92   function UnparseColumn($i) {\r
93     $s=$this->arSelList[$i];\r
94     if (!empty($this->arSelListAs[$i])) {\r
95       $s.=" AS ".$this->arSelListAs[$i];\r
96     }\r
97     return $s;\r
98   }\r
99 \r
100   function UnparseColumnList() {\r
101     if (empty($this->arSelList)) return "";\r
102     $sqltext=$this->UnparseColumn(0);\r
103     for ($i=1; $i<count($this->arSelList); $i++) {\r
104       $sqltext.=",".$this->UnparseColumn($i);\r
105     }\r
106     return $sqltext;\r
107   }\r
108 \r
109   function UnparseColumnListSkip($arSkipCols) {\r
110     for ($i=0,$SkipIdx=0; $i<count($this->arSelList); $i++) {\r
111       $skip=false;\r
112       if ($SkipIdx < count($arSkipCols)) {\r
113         $skip=($arSkipCols[$SkipIdx]==$i);\r
114         if ($skip) $SkipIdx++;\r
115       }\r
116       if (!$skip) {\r
117         if (empty($sqltext)) {\r
118           $sqltext=$this->UnparseColumn($i);\r
119         } else {\r
120           $sqltext.=",".$this->UnparseColumn($i);\r
121         }\r
122       }\r
123     }\r
124     return $sqltext;\r
125   }\r
126 \r
127   function DebugPrint() {\r
128     echo "<p>Parse Result:";\r
129     echo "<table border='1'>";\r
130     if ($this->IsDistinct) echo "<tr valign='top'><td>DISTINCT<td>&nbsp;";\r
131     echo "<tr valign='top'><td>COLUMNS:<td><ol>";\r
132     if (!empty($this->arSelList)) {\r
133       for ($i=0; $i<count($this->arSelList); $i++) {\r
134         echo "<li>".$this->UnparseColumn($i);\r
135       }\r
136     }\r
137     echo "</ol><tr valign='top'><td>FROM:<td>" . $this->FromClause;\r
138     if (!empty($this->WhereClause)) {\r
139       echo "<tr valign='top'><td>WHERE:<td>".$this->WhereClause;\r
140     }\r
141     if (is_array($this->arGroupBy)) {\r
142       if (count($this->arGroupBy) >  0) {\r
143         echo "<tr valign='top'><td>GROUP BY:<td>".implode("<br>",$this->arGroupBy);\r
144       }\r
145     }\r
146     if (!empty($this->HavingClause)) {\r
147       echo "<tr valign='top'><td>HAVING:<td>".$this->HavingClause;\r
148     }\r
149     if (is_array($this->arOrderBy)) {\r
150       if (count($this->arOrderBy) >  0) {\r
151         echo "<tr valign='top'><td>ORDER BY:<td>".implode("<br>",$this->arOrderBy);\r
152       }\r
153     }\r
154     echo "</table>";\r
155   }\r
156 \r
157   function Init() {\r
158     $this->arSelList=array();\r
159     $this->arSelListAs=array();\r
160     $this->arGroupBy=array();\r
161     $this->arOrderBy=array();\r
162     $this->FromClause=NULL;\r
163     $this->WhereClause=NULL;\r
164     $this->HavingClause=NULL;\r
165     $this->IsDistinct=false;\r
166   }\r
167   // -------------------------------------------------------------\r
168   // Parse a SQL select statement into its major components\r
169   // Does not handle:\r
170   // 1) union queries\r
171   // 2) select into\r
172   // 3) more than one space between "group" and "by", or "order" and "by"\r
173   // If distinct is specified, it will be part of the first item in arSelList\r
174   // -------------------------------------------------------------\r
175 \r
176   function ParseSelect($sqltext) {\r
177     $this->Init();\r
178     $clause='';\r
179     $_retval=false;\r
180     $sqltext=str_replace("\n"," ",$sqltext);\r
181     $sqltext=" ".str_replace("\r"," ",$sqltext)." SELECT ";\r
182     // SELECT suffix forces last curfield to be saved\r
183     $l=strlen($sqltext);\r
184     $parencnt=0;\r
185     $inquote=false;\r
186     $curfield="";\r
187     for ($i=0; $i<$l; $i++) {\r
188       $ch=substr($sqltext,$i,1);\r
189       if ($inquote) {\r
190         if ($ch == $endquote) {\r
191           if ($endquote=="'" && substr($sqltext,$i,2) == "''") {\r
192             $curfield.="'";\r
193             $i++;\r
194           }\r
195           else {\r
196             $inquote=false;\r
197           }\r
198         }\r
199         $curfield.=$ch;\r
200       }\r
201       elseif ($ch == "'" || $ch == "\"" || $ch == "`") {\r
202         $inquote=true;\r
203         $endquote=$ch;\r
204         $curfield.=$ch;\r
205       }\r
206       elseif ($ch == "[") {\r
207         $inquote=true;\r
208         $endquote="]";\r
209         $curfield.=$ch;\r
210       }\r
211       elseif ($ch == "(") {\r
212         $parencnt++;\r
213         $curfield.=$ch;\r
214       }\r
215       elseif ($ch == ")") {\r
216         if ($parencnt == 0) {\r
217           return $_retval;\r
218           // sql statement has a syntax error\r
219         }\r
220         $parencnt--;\r
221         $curfield.=$ch;\r
222       }\r
223       elseif ($parencnt > 0) {\r
224         $curfield.=$ch;\r
225       }\r
226       elseif ($ch == ",") {\r
227         switch ($clause) {\r
228           case "SELECT":\r
229             array_push($this->arSelList, $curfield);\r
230             array_push($this->arSelListAs, NULL);\r
231             $curfield='';\r
232             break;\r
233           case "AS":\r
234             $this->arSelListAs[count($this->arSelList)-1]=$curfield;\r
235             $curfield='';\r
236             $clause="SELECT";\r
237             break;\r
238           case "GROUP BY":\r
239             array_push($this->arGroupBy, $curfield);\r
240             $curfield='';\r
241             break;\r
242           case "ORDER BY":\r
243             array_push($this->arOrderBy, $curfield);\r
244             $curfield='';\r
245             break;\r
246           default:\r
247             $curfield.=$ch;\r
248             break;\r
249         }\r
250       }\r
251       elseif ($ch == " ") {\r
252         $j=strpos($sqltext," ",$i+1);\r
253         if ($j===false)\r
254         {\r
255           $curfield.=$ch;\r
256         }\r
257           else\r
258         {\r
259           if (strtoupper(substr($sqltext,$j+1,3))=="BY ") $j+=3;\r
260           $nexttoken=strtoupper(substr($sqltext,$i+1,$j-$i-1));\r
261           //echo '<br>'.$nexttoken;\r
262           switch ($nexttoken) {\r
263 \r
264             case "SELECT":\r
265             case "INTO":\r
266             case "FROM":\r
267             case "WHERE":\r
268             case "GROUP BY":\r
269             case "HAVING":\r
270             case "ORDER BY":\r
271               switch ($clause) {\r
272                 case "SELECT":\r
273                   $this->AddColumn($curfield, NULL);\r
274                   $curfield='';\r
275                   break;\r
276                 case "AS":\r
277                   $this->arSelListAs[count($this->arSelList)-1]=$curfield;\r
278                   $curfield='';\r
279                   break;\r
280                 case "FROM":     $this->FromClause=$curfield;             $curfield=''; break;\r
281                 case "WHERE":    $this->WhereClause=$curfield;            $curfield=''; break;\r
282                 case "GROUP BY": array_push($this->arGroupBy, $curfield); $curfield=''; break;\r
283                 case "HAVING":   $this->HavingClause=$curfield;           $curfield=''; break;\r
284                 case "ORDER BY": array_push($this->arOrderBy, $curfield); $curfield=''; break;\r
285               }\r
286               $clause=$nexttoken;\r
287               $i=$j-1;\r
288               break;\r
289 \r
290             case "AS":\r
291               if ($clause=="SELECT") {\r
292                 $this->AddColumn($curfield, NULL);\r
293                 $curfield='';\r
294                 $clause=$nexttoken;\r
295                 $i=$j;\r
296               } else if ($curfield != "") {\r
297                 $curfield.=$ch;\r
298               }\r
299               break;\r
300 \r
301             case "DISTINCT":\r
302               if ($clause=="SELECT") {\r
303                 $this->IsDistinct=true;\r
304                 $curfield='';\r
305                 $i=$j;\r
306               } else if ($curfield != "") {\r
307                 $curfield.=$ch;\r
308               }\r
309               break;\r
310 \r
311             default:\r
312               if ($curfield != "") {\r
313                 $curfield.=$ch;\r
314               }\r
315               break;\r
316           }\r
317         }\r
318       }\r
319       else {\r
320         $curfield.=$ch;\r
321       }\r
322     }\r
323     return true;\r
324   }\r
325 \r
326   // -------------------------------------------------------------\r
327   // Add column to select list\r
328   // -------------------------------------------------------------\r
329   function AddColumn($ColumnSql, $ColumnName) {\r
330     array_push($this->arSelList, $ColumnSql);\r
331     array_push($this->arSelListAs, $ColumnName);\r
332   }\r
333 \r
334   // -------------------------------------------------------------\r
335   // Add a join to the from clause\r
336   // -------------------------------------------------------------\r
337   function AddJoin($JoinClause) {\r
338     if (preg_match("/ join /i",$this->FromClause)) {\r
339       $this->FromClause="(".$this->FromClause.")";\r
340       // required by Access\r
341     }\r
342     $this->FromClause.=" ".$JoinClause;\r
343   }\r
344 \r
345   function SplitSortSpec($sortspec, &$sortcol, &$sortdir) {\r
346     $sortspec=strtoupper($sortspec);\r
347     if (substr($sortspec,-3) == "ASC") {\r
348       $sortcol=trim(substr($sortspec,0,-3));\r
349       $sortdir="ASC";\r
350     }\r
351     elseif (substr($sortspec,-4) == "DESC") {\r
352       $sortcol=trim(substr($sortspec,0,-4));\r
353       $sortdir="DESC";\r
354     }\r
355     else {\r
356       $sortcol=trim($sortspec);\r
357       $sortdir="";\r
358     }\r
359   }\r
360 \r
361   function FindSortColumn($sortspec) {\r
362     $this->SplitSortSpec($sortspec, $findcol, $finddir);\r
363     for ($i=0; $i<=count($this->arOrderBy)-1; $i++) {\r
364       $this->SplitSortSpec($this->arOrderBy[$i], $sortcol, $sortdir);\r
365       if ($sortcol == $findcol) {\r
366         return $i;\r
367       }\r
368     }\r
369     return -1;\r
370   }\r
371 \r
372   // -------------------------------------------------------------\r
373   // Add sort criteria to the beginning of the order by clause\r
374   // -------------------------------------------------------------\r
375   function AddSort($NewSort) {\r
376     $colidx=$this->FindSortColumn($NewSort);\r
377     if ($colidx >= 0) {\r
378       for ($i=$colidx; $i>0; $i--) {\r
379         $this->arOrderBy[$i]=$this->arOrderBy[$i-1];\r
380       }\r
381       $this->arOrderBy[0]=$NewSort;\r
382     }\r
383     else {\r
384       array_unshift($this->arOrderBy, $NewSort);\r
385     }\r
386   }\r
387 \r
388   // -------------------------------------------------------------\r
389   // Append sort criteria to the order by clause\r
390   // -------------------------------------------------------------\r
391   function AppendSort($NewSort) {\r
392     array_push($this->arOrderBy, $NewSort);\r
393   }\r
394 \r
395   // -------------------------------------------------------------\r
396   // Add a condition to the where clause\r
397   // -------------------------------------------------------------\r
398   function AddWhereCondition($NewCondition) {\r
399     $this->AddCondition($this->WhereClause, $NewCondition);\r
400   }\r
401 \r
402   // -------------------------------------------------------------\r
403   // Add a condition to the having clause\r
404   // -------------------------------------------------------------\r
405   function AddHavingCondition($NewCondition) {\r
406     $this->AddCondition($this->HavingClause, $NewCondition);\r
407   }\r
408 \r
409   function AddCondition(&$Clause, $NewCondition) {\r
410     if (empty($NewCondition)) {\r
411       return;\r
412     }\r
413     if (empty($Clause)) {\r
414       $Clause="(".$NewCondition.")";\r
415     }\r
416     else {\r
417       $Clause.=" AND (".$NewCondition.")";\r
418     }\r
419   }\r
420 }\r
421 \r
422 \r
423 // -------------------------------------------------------------\r
424 // created by dbClass.GetColumnInfo()\r
425 // -------------------------------------------------------------\r
426 class dbColumn\r
427 {\r
428   var $ColName,$Nullable,$ColType,$ColLength,$Writeable,$IsPKey;\r
429 }\r
430 \r
431 // tested ok with MySQL 4 & 5\r
432 class dbClass_mysql\r
433 {\r
434   var $lastQuery;\r
435   function dbClass_mysql($conn) { $this->conn=$conn; }\r
436   function HasError() { return mysql_errno()!=0; }\r
437   function ErrorMsg() { return mysql_error(); }\r
438   function Close() { return mysql_close($this->conn); }\r
439   function FreeResult($rsLookUp) { return mysql_free_result($rsLookUp); }\r
440   function RunQuery($sqltext) { $this->lastQuery=$sqltext; return mysql_query($sqltext,$this->conn); }\r
441   function NumFields($rsMain) { return mysql_num_fields($rsMain); }\r
442   function NumRows($rsMain) { return mysql_num_rows($rsMain); }\r
443   function FieldType($rsMain,$i) { return mysql_field_type($rsMain,$i); }\r
444   function FieldName($rsMain,$i) { return mysql_field_name($rsMain,$i); }\r
445   function FetchRow($rsMain,&$result) { $result=mysql_fetch_row($rsMain); return ($result==false) ? false : true; }\r
446   function FetchAssoc($rsMain,&$result) { $result=mysql_fetch_assoc($rsMain); return ($result==false) ? false : true; }\r
447   function FetchArray($rsMain,&$result) { $result=mysql_fetch_array($rsMain,MYSQL_NUM); return ($result==false) ? false : true; }\r
448   function AffectedRows($rsMain) { return mysql_affected_rows($this->conn); }\r
449   function Seek($rsMain,$offset) { return mysql_data_seek($rsMain,$offset); }\r
450   function RunParamQuery($query, $phs = array()) {\r
451     foreach ($phs as $ph) {   // from php.net\r
452       if ( isset($ph) ) {\r
453         $ph = "'" . mysql_real_escape_string($ph) . "'";\r
454       } else {\r
455         $ph = "NULL" ;\r
456       }\r
457       $query = substr_replace($query, $ph, strpos($query, '?'), 1);\r
458     }\r
459     $this->lastQuery=$query;\r
460     return mysql_query($query,$this->conn);\r
461   }\r
462   function GetColumnInfo($TableName) {\r
463     $rsMain=$this->RunQuery("SHOW COLUMNS FROM ".$TableName);\r
464     if (!$rsMain) return null;\r
465     $arColumns=array();\r
466     while($this->FetchAssoc($rsMain,$row)) {\r
467       $colinfo=new dbColumn;\r
468       $colinfo->IsPKey=($row["Key"]=="PRI");\r
469       $colinfo->ColName=$row["Field"];\r
470       $colinfo->ColType=$row["Type"];\r
471       $colinfo->Nullable=($row["Null"]=="YES");\r
472       if (preg_match("/\((\d+)\)/", $row["Type"], $matches))\r
473         $colinfo->ColLength=$matches[1];\r
474       else\r
475         $colinfo->ColLength=0;\r
476       $colinfo->Writeable=($row["Extra"] != 'auto_increment');\r
477       array_push($arColumns, $colinfo);\r
478     }\r
479     $this->FreeResult($rsMain);\r
480     return $arColumns;\r
481   }\r
482   function GetTableList($TableType) {\r
483     if ($TableType!='VIEW') $TableType='BASE TABLE';\r
484     $rsMain=$this->RunQuery("SHOW FULL TABLES WHERE Table_type='".$TableType."'");\r
485     if (!$rsMain) return null;\r
486     $arTables=array();\r
487     while($this->FetchRow($rsMain,$row)) {\r
488       array_push($arTables, $row[0]);\r
489     }\r
490     $this->FreeResult($rsMain);\r
491     return $arTables;\r
492   }\r
493   function Concat($arStrings) {\r
494     return "concat(".implode(",",$arStrings).")";\r
495   }\r
496   function Convert2Char($s) {\r
497     return $s; // implicit conversion\r
498   }\r
499   function SqlDay($s) {\r
500     return "dayofmonth(".$s.")";\r
501   }\r
502   function SqlMonth($s) {\r
503     return "month(".$s.")";\r
504   }\r
505   function SqlYear($s) {\r
506     return "year(".$s.")";\r
507   }\r
508   function CurrentTime() {\r
509     return "LOCALTIMESTAMP";\r
510   }\r
511 }\r
512 \r
513 \r
514 // tested ok with Oracle XE\r
515 class dbClass_oci\r
516 {\r
517   var $lastQuery;\r
518   function dbClass_oci($conn) { $this->conn=$conn; }\r
519   function HasError() { return is_array(ocierror()); }\r
520   function ErrorMsg() { $e=ocierror(); return is_array($e) ? $e['message'] : ''; }\r
521   function Close() { return ocilogoff($this->conn); }\r
522   function FreeResult($rsLookUp) { return ocifreestatement($rsLookUp); }\r
523   function RunQuery($sqltext) { $this->lastQuery=$sqltext; $stmt=ociparse($this->conn, $sqltext); ociexecute($stmt); return $stmt; }\r
524   function NumFields($rsMain) { return ocinumcols($rsMain); }\r
525   function NumRows($rsMain) { return -1; }\r
526   function FieldType($rsMain,$i) { return ocicolumntype($rsMain,$i+1); }\r
527   function FieldName($rsMain,$i) { return oci_field_name($rsMain,$i); }\r
528   function FetchRow($rsMain,&$result) { return ocifetchinto($rsMain,$result,OCI_NUM); }\r
529   function FetchAssoc($rsMain,&$result) { return ocifetchinto($rsMain,$result,OCI_ASSOC); }\r
530   function FetchArray($rsMain,&$result) { return ocifetchinto($rsMain,$result,OCI_NUM); }\r
531   function AffectedRows($rsMain) { return (is_resource($rsMain) ? ocirowcount($rsMain) : false); }\r
532   function Seek($rsMain,$offset) {\r
533     for($i=0; $i<$offset; $i++) ocifetchrow($rsMain);\r
534   }\r
535   function RunParamQuery($query, $phs = array()) {\r
536     foreach ($phs as $ph) {   // from php.net\r
537       $ph = isset($ph) ? "'" . str_replace("'","''",$ph) . "'" : "NULL";\r
538       $query = substr_replace($query, $ph, strpos($query, '?'), 1);\r
539     }\r
540     $this->lastQuery=$query;\r
541     return $this->RunQuery($query);\r
542   }\r
543   function GetColumnInfo($TableName) {\r
544     $TableName=strtoupper($TableName);\r
545     $rsMain=$this->RunQuery("select * from col WHERE tname='$TableName' order by colno");\r
546     if (!$rsMain) return null;\r
547     $arColumns=array();\r
548     while($this->FetchAssoc($rsMain,$row)) {\r
549       $colinfo=new dbColumn;\r
550       $colinfo->IsPKey=false;\r
551       $colinfo->ColName=$row["CNAME"];\r
552       $colinfo->ColType=$row["COLTYPE"];\r
553       $colinfo->Nullable=($row["NULLS"]=="NULL");\r
554       $colinfo->ColLength=$row["WIDTH"];\r
555       $colinfo->Writeable=true;   // need to figure out where to find this\r
556       array_push($arColumns, $colinfo);\r
557       //echo "<p>GetColumnInfo: ".$row["CNAME"].' - '.$row["COLTYPE"]."</p>";\r
558     }\r
559     $this->FreeResult($rsMain);\r
560     $sql = "SELECT b.column_name FROM USER_CONSTRAINTS a, USER_CONS_COLUMNS b WHERE (b.table_name='$TableName') AND (a.table_name='$TableName') AND (a.constraint_type = 'P') AND (a.constraint_name = b.constraint_name)";
561     $rsMain = $this->RunQuery($sql);
562     if ($rsMain) {\r
563       while($this->FetchRow($rsMain,$row)) {\r
564         $colname=$row[0];\r
565         //echo "<p>GetColumnInfo pk: ".$colname."</p>";\r
566         for($i=0; $i<count($arColumns); $i++) {\r
567           if ($arColumns[$i]->ColName==$colname) {\r
568             $arColumns[$i]->IsPKey=true;\r
569             break;\r
570           }\r
571         }\r
572       }\r
573       $this->FreeResult($rsMain);\r
574     }\r
575     return $arColumns;\r
576   }\r
577   function Concat($arStrings) {\r
578     return implode(" || ",$arStrings);\r
579   }\r
580   function Convert2Char($s) {\r
581     return "cast(".$s." as varchar2(20))";\r
582   }\r
583   function SqlDay($s) {\r
584     return "to_char(".$s.",'DD')";\r
585   }\r
586   function SqlMonth($s) {\r
587     return "to_char(".$s.",'MM')";\r
588   }\r
589   function SqlYear($s) {\r
590     return "to_char(".$s.",'YYYY')";\r
591   }\r
592   function CurrentTime() {\r
593     return "LOCALTIMESTAMP";\r
594   }\r
595   function GetTableList($TableType) {\r
596     if ($TableType!='VIEW'){\r
597       $TableType='TABLE';\r
598       $tableFiltre="and exists (select 'X' from USER_TABLES where TABLE_NAME = OBJECT_NAME) ";\r
599     }\r
600     $rsMain=$this->RunQuery("SELECT OBJECT_NAME FROM ALL_OBJECTS WHERE OBJECT_TYPE = '".$TableType."' and OWNER = UPPER('".$GLOBALS['appName']."') ".$tableFiltre."order by 1");\r
601     if (!$rsMain) return null;\r
602     $arTables=array();\r
603     while($this->FetchRow($rsMain,$row)) {\r
604       array_push($arTables, $row[0]);\r
605     }\r
606     $this->FreeResult($rsMain);\r
607     return $arTables;\r
608   }\r
609 }\r
610 \r
611 \r
612 // tested ok with MS SQL Server & MS Access\r
613 // Oracle works ok except for GetColumnInfo\r
614 class dbClass_odbc\r
615 {\r
616   var $lastQuery,$dbc;\r
617   function dbClass_odbc(&$dbc) { $this->dbc=$dbc; }\r
618   function HasError() { return odbc_error()!=''; }\r
619   function ErrorMsg() { return @odbc_error() . ' ' . @odbc_errormsg(); }\r
620   function Close() { return odbc_close(); }\r
621   function FreeResult($rsLookUp) { return odbc_free_result($rsLookUp); }\r
622   function RunQuery($sqltext) { $this->lastQuery=$sqltext; return odbc_exec($this->dbc->dbMain,$sqltext); }\r
623   function NumFields($rsMain) { return odbc_num_fields($rsMain); }\r
624   function NumRows($rsMain) { return odbc_num_rows($rsMain); }\r
625   function FieldType($rsMain,$i) { return odbc_field_type($rsMain,$i+1); }\r
626   function FieldName($rsMain,$i) { return odbc_field_name($rsMain,$i); }\r
627   function FetchRow($rsMain,&$result) { $rc=odbc_fetch_into($rsMain,$result); return ($rc==false) ? false : true; }\r
628   function FetchAssoc($rsMain,&$result) { $result=odbc_fetch_array($rsMain); return ($result==false) ? false : true; }\r
629   function FetchArray($rsMain,&$result) { $rc=odbc_fetch_into($rsMain,$result); return ($rc==false) ? false : true; }\r
630   function AffectedRows($rsMain) { return odbc_num_rows($rsMain); }\r
631   function Seek($rsMain,$offset) {\r
632     for($i=0; $i<$offset; $i++) odbc_fetch_row($rsMain);\r
633   }\r
634   function RunParamQuery($query, $phs = array()) {\r
635     // odbc_prepare/odbc_execute chokes on this: SELECT * FROM (SELECT * FROM orders WHERE ShipCountry=?) AS rico_Main\r
636     // so that approach cannot be used\r
637     foreach ($phs as $ph) {\r
638       if ( isset($ph) ) {\r
639         if (preg_match("/^\d\d\d\d-?\d\d-?\d\d(?:[T ](\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|(?:([-+])(\d\d)(?::?(\d\d))?)?)?)?$/",$ph)) {\r
640           $ph = "{ts '".$ph."'}";\r
641         } else {\r
642           $ph = "'" . str_replace("'","''",$ph) . "'";\r
643         }\r
644       } else {\r
645         $ph = "NULL" ;\r
646       }\r
647       $query = substr_replace($query, $ph, strpos($query, '?'), 1);\r
648     }\r
649     $this->lastQuery=$query;\r
650     return odbc_exec($this->dbc->dbMain,$query);\r
651   }\r
652   function GetColumnInfo($TableName) {\r
653     switch ($this->dbc->Dialect) {\r
654       case "TSQL":\r
655         $qualifier=$this->dbc->dbDefault;\r
656         $schema="%";\r
657         break;\r
658       case "Access":\r
659         $qualifier=$this->dbc->dsn;\r
660         $schema="";\r
661         break;\r
662       default:\r
663         return null;\r
664     }\r
665     //echo "<p>GetColumnInfo: ".$qualifier.".".$schema.".".$TableName."</p>";\r
666     $rsMain=odbc_columns($this->dbc->dbMain, $qualifier, $schema, $TableName);\r
667     //odbc_result_all($rsMain);\r
668     if (!$rsMain) return null;\r
669     $arColumns=array();\r
670     while($this->FetchAssoc($rsMain,$row)) {\r
671       if ($row["TABLE_NAME"]!=$TableName) continue;\r
672       $colinfo=new dbColumn;\r
673       //echo "<p>GetColumnInfo: ".$row["COLUMN_NAME"].':'.$row["TYPE_NAME"]."</p>";\r
674       $colinfo->ColName=$row["COLUMN_NAME"];\r
675       $colinfo->ColType=$row["TYPE_NAME"];\r
676       if (array_key_exists("PRECISION",$row)) {\r
677         $colinfo->ColLength=$row["PRECISION"];\r
678       } else if (array_key_exists("COLUMN_SIZE",$row)) {\r
679         $colinfo->ColLength=$row["COLUMN_SIZE"];\r
680       }\r
681       $colinfo->Nullable=($row["NULLABLE"]=="YES");\r
682       $colinfo->IsPKey=false;\r
683       $colinfo->Writeable=($row["TYPE_NAME"] != 'int identity');\r
684       array_push($arColumns, $colinfo);\r
685     }\r
686     $this->FreeResult($rsMain);\r
687     //$rsMain=odbc_columnprivileges($this->dbc->dbMain, $qualifier, $schema, $TableName,"%");\r
688     //odbc_result_all($rsMain);\r
689     //$this->FreeResult($rsMain);\r
690     $rsMain=odbc_primarykeys($this->dbc->dbMain, $qualifier, $schema, $TableName);\r
691     if ($rsMain) {\r
692       while($this->FetchAssoc($rsMain,$row)) {\r
693         $colname=$row["COLUMN_NAME"];\r
694         //echo "<p>GetColumnInfo pk: ".$colname."</p>";\r
695         for($i=0; $i<count($arColumns); $i++) {\r
696           if ($arColumns[$i]->ColName==$colname) {\r
697             $arColumns[$i]->IsPKey=true;\r
698             break;\r
699           }\r
700         }\r
701       }\r
702       $this->FreeResult($rsMain);\r
703     }\r
704     return $arColumns;\r
705   }\r
706   function Concat($arStrings) {\r
707     $cnt=count($arStrings);\r
708     switch ($cnt) {\r
709       case 0: return '';\r
710       case 1: return $arStrings[0];\r
711       default:\r
712         $result="{fn concat(".$arStrings[0].",".$arStrings[1].")}";\r
713         for ($i=2; $i<$cnt; $i++) {\r
714           $result="{fn concat(".$result.",".$arStrings[$i].")}";\r
715         }\r
716     }\r
717     return $result;\r
718   }\r
719   function Convert2Char($s) {\r
720     return "{fn CONVERT(" . $s . ",SQL_VARCHAR)}";\r
721   }\r
722   function SqlDay($s) {\r
723     return "{fn DAYOFMONTH(" . $s . ")}";\r
724   }\r
725   function SqlMonth($s) {\r
726     return "{fn MONTH(" . $s . ")}";\r
727   }\r
728   function SqlYear($s) {\r
729     return "{fn YEAR(" . $s . ")}";\r
730   }\r
731   function CurrentTime() {\r
732     return "{fn CURDATE()}";\r
733   }\r
734 }\r
735 \r
736 // For MS SQL Server\r
737 class dbClass_mssql\r
738 {\r
739   var $lastQuery,$dbc;\r
740   function dbClass_mssql($conn) { $this->conn=$conn; }\r
741   function HasError() { return mssql_get_last_message()!=0; }\r
742   function ErrorMsg() { return mssql_get_last_message(); }\r
743   function Close() { return mssql_close($this->conn); }\r
744   function FreeResult($rsLookUp) { return mssql_free_result($rsLookUp); }\r
745   function RunQuery($sqltext) { $this->lastQuery=$sqltext; return mssql_query($sqltext,$this->conn); }\r
746   function NumFields($rsMain) { return mssql_num_fields($rsMain); }\r
747   function NumRows($rsMain) { return mssql_num_rows($rsMain); }\r
748   function FieldType($rsMain,$i) { return mssql_field_type($rsMain,$i); }\r
749   function FieldName($rsMain,$i) { return mssql_field_name($rsMain,$i); }\r
750   function FetchRow($rsMain,&$result) { $result=mssql_fetch_row($rsMain); return ($result==false) ? false : true; }\r
751   function FetchAssoc($rsMain,&$result) { $result=mssql_fetch_assoc($rsMain); return ($result==false) ? false : true; }\r
752   function FetchArray($rsMain,&$result) { $result=mssql_fetch_array($rsMain,MSSQL_NUM); return ($result==false) ? false : true; }\r
753   function AffectedRows($rsMain) { return mssql_rows_affected($rsMain); }\r
754   function Seek($rsMain,$offset) { return mssql_data_seek($rsMain,$offset); }\r
755   function RunParamQuery($query, $phs = array()) {\r
756     foreach ($phs as $ph) {\r
757       if ( isset($ph) ) {\r
758         $ph = "'" . str_replace("'","''",$ph) . "'";\r
759       } else {\r
760         $ph = "NULL" ;\r
761       }\r
762       $query = substr_replace($query, $ph, strpos($query, '?'), 1);\r
763     }\r
764     $this->lastQuery=$query;\r
765     return mssql_query($query,$this->conn);\r
766   }\r
767 \r
768   function GetColumnInfo($TableName) {\r
769     $TableName=strtoupper($TableName);\r
770     $rsMain=$this->RunQuery("exec sp_columns '$TableName'");\r
771     if (!$rsMain) return null;\r
772     $arColumns=array();\r
773 \r
774     while($this->FetchAssoc($rsMain,$row)) {\r
775       if (strtoupper($row["TABLE_NAME"]) != $TableName) continue;  // sp_columns treats "Order_Details" and "Order Details" as the same\r
776       $colinfo=new dbColumn;\r
777       $colinfo->ColName=$row["COLUMN_NAME"];\r
778       $colinfo->ColType=$row["TYPE_NAME"];\r
779       if (array_key_exists("PRECISION",$row)) {\r
780         $colinfo->ColLength=$row["PRECISION"];\r
781       } else if (array_key_exists("LENGTH",$row)) {\r
782         $colinfo->ColLength=$row["LENGTH"];\r
783       }\r
784       $colinfo->Nullable=($row["NULLABLE"]==1);\r
785       $colinfo->IsPKey=false;\r
786       $colinfo->Writeable=(strtoupper($row["TYPE_NAME"]) != "INT IDENTITY");\r
787       array_push($arColumns, $colinfo);\r
788     }\r
789     $this->FreeResult($rsMain);\r
790     // Get Primary Keys\r
791     $rsMain=$this->RunQuery("exec sp_pkeys '$TableName'");\r
792     if ($rsMain) {\r
793       while($this->FetchAssoc($rsMain,$row)) {\r
794         $colname=$row["COLUMN_NAME"];\r
795         for($i=0; $i<count($arColumns); $i++) {\r
796           if ($arColumns[$i]->ColName==$colname) {\r
797             $arColumns[$i]->IsPKey=true;\r
798             break;\r
799           }\r
800         }\r
801       }\r
802       $this->FreeResult($rsMain);\r
803     }\r
804     return $arColumns;\r
805   }\r
806 \r
807   function GetTableList($TableType) { \r
808     $typecode=$TableType!='VIEW' ? 'U' : 'V';\r
809     $rsMain=$this->RunQuery("select name from sysobjects where type='".$typecode."' order by name"); \r
810     if (!$rsMain) return null; \r
811     $arTables=array(); \r
812     while($this->FetchRow($rsMain,$row)) { \r
813       array_push($arTables, $row[0]); \r
814     }  \r
815     $this->FreeResult($rsMain); \r
816     return $arTables; \r
817   } \r
818   \r
819   function Concat($arStrings) {\r
820     return implode("+",$arStrings);\r
821   }\r
822   function Convert2Char($s) {\r
823     return "CAST(" . $s . " AS VARCHAR)";\r
824   }\r
825   function SqlDay($s) {\r
826     return "DAY(" . $s . ")";\r
827   }\r
828   function SqlMonth($s) {\r
829     return "MONTH(" . $s . ")";\r
830   }\r
831   function SqlYear($s) {\r
832     return "YEAR(" . $s . ")";\r
833   }\r
834   function CurrentTime() {\r
835     return "CURRENT_TIMESTAMP";\r
836   }\r
837 }\r
838 \r
839 // for PostgreSQL server\r
840 class dbClass_postgresql\r
841 {\r
842   var $lastQuery;\r
843   function dbClass_postgresql($conn) { $this->conn=$conn; }\r
844   function HasError() { return pg_last_error() !== ''; }\r
845   function ErrorMsg() { return pg_last_error(); }\r
846   function Close() { return pg_close(); }\r
847   function FreeResult($rsLookUp) { return pg_free_result($rsLookUp); }\r
848   function RunQuery($sqltext) { $this->lastQuery=$sqltext; return pg_query($sqltext); }\r
849   function NumFields($rsMain) { return pg_num_fields($rsMain); }\r
850   function NumRows($rsMain) { return pg_num_rows($rsMain); }\r
851   function FieldType($rsMain,$i) { return pg_field_type($rsMain,$i); }\r
852   function FetchRow($rsMain,&$result) { $result=pg_fetch_row($rsMain); return ($result==false) ? false : true; }\r
853   function FetchAssoc($rsMain,&$result) { $result=pg_fetch_assoc($rsMain); return ($result==false) ? false : true; }\r
854   function FetchArray($rsMain,&$result) { $result=pg_fetch_array($rsMain); return ($result==false) ? false : true; }\r
855   function AffectedRows($rsMain) { return pg_affected_rows($this->conn); }\r
856   function Seek($rsMain,$offset) { return pg_result_seek($rsMain,$offset); }\r
857   function RunParamQuery($query, $phs = array()) {\r
858     foreach ($phs as $ph) {   // from php.net\r
859       if ( isset($ph) ) {\r
860         $ph = "'" . pg_escape_string($ph) . "'";\r
861       } else {\r
862         $ph = "NULL" ;\r
863       }\r
864       $query = substr_replace($query, $ph, strpos($query, '?'), 1);\r
865     }\r
866     $this->lastQuery=$query;\r
867     return pg_query($query);\r
868   }\r
869   function GetColumnInfo($TableName) {\r
870     $rsMain=$this->RunQuery("SHOW COLUMNS FROM ".$TableName);\r
871     if (!$rsMain) return null;\r
872     $arColumns=array();\r
873     while($this->FetchAssoc($rsMain,$row)) {\r
874       $colinfo=new dbColumn;\r
875       $colinfo->IsPKey=($row["Key"]=="PRI");\r
876       $colinfo->ColName=$row["Field"];\r
877       $colinfo->ColType=$row["Type"];\r
878       $colinfo->Nullable=($row["Null"]=="YES");\r
879       if (preg_match("/\((\d+)\)/", $row["Type"], $matches))\r
880         $colinfo->ColLength=$matches[1];\r
881       else\r
882         $colinfo->ColLength=0;\r
883       $colinfo->Writeable=($row["Extra"] != 'auto_increment');\r
884       array_push($arColumns, $colinfo);\r
885     } \r
886     $this->FreeResult($rsMain);\r
887     return $arColumns;\r
888   }\r
889   function GetTableList($TableType) {\r
890     if ($TableType!='VIEW') $TableType='BASE TABLE';\r
891     $rsMain=$this->RunQuery("SHOW FULL TABLES WHERE Table_type='".$TableType."'");\r
892     if (!$rsMain) return null;\r
893     $arTables=array();\r
894     while($this->FetchRow($rsMain,$row)) {\r
895       array_push($arTables, $row[0]);\r
896     } \r
897     $this->FreeResult($rsMain);\r
898     return $arTables;\r
899   }\r
900   function Concat($arStrings) {\r
901     return "concat(".implode(",",$arStrings).")";\r
902   }\r
903   function Convert2Char($s) {\r
904     return $s; // implicit conversion\r
905   }\r
906   function SqlDay($s) {\r
907     return "dayofmonth(".$s.")";\r
908   }\r
909   function SqlMonth($s) {\r
910     return "month(".$s.")";\r
911   }\r
912   function SqlYear($s) {\r
913     return "year(".$s.")";\r
914   }\r
915   function CurrentTime() {\r
916     return "LOCALTIMESTAMP";\r
917   }\r
918 }\r
919 \r
920 \r
921 class dbClass\r
922 {\r
923 \r
924   var $debug,$ConnTimeout,$CmdTimeout,$LockTimeout,$Provider;\r
925   var $ErrMsgFmt;\r
926   var $DisplayErrors;\r
927   var $LastErrorMsg;\r
928   var $Dialect;\r
929   var $Wildcard;\r
930   // these are private:\r
931   var $dbMain,$DisplayFunc,$dbDefault;\r
932 \r
933 // -------------------------------------------------------------\r
934 // Class Constructor\r
935 // -------------------------------------------------------------\r
936   function dbClass()\r
937   {\r
938     $this->Provider="127.0.0.1";\r
939     $this->debug=false;\r
940     $this->ConnTimeout=30; // seconds\r
941     $this->LockTimeout=5000; // milliseconds\r
942     $this->DisplayErrors=true;\r
943     $this->CmdTimeout=120; // 2 minutes\r
944     $this->ErrMsgFmt="HTML";\r
945     $this->DisplayFunc="echo";\r
946     $this->Dialect="MySQL";\r
947     $this->Wildcard="%";\r
948   }\r
949 \r
950 // -------------------------------------------------------------\r
951 // Class Destructor (only called if php5)\r
952 // -------------------------------------------------------------\r
953   function __destruct()\r
954   {\r
955     $this->dbClose();\r
956   }\r
957 \r
958   function DefaultDB()\r
959   {\r
960     return $this->dbDefault;\r
961   }\r
962 \r
963 //********************************************************************************************************\r
964 // If the database is down, then an explanation can be placed here\r
965 //********************************************************************************************************\r
966   function MaintenanceMsg()\r
967   {\r
968     return "";\r
969   }\r
970 \r
971   function DisplayMsg($msg)\r
972   {\r
973     if (!empty($this->DisplayFunc))\r
974     {\r
975       if ($this->ErrMsgFmt=="HTML" && substr($msg,0,1)!="<")\r
976       {\r
977         $msg="<p>".htmlspecialchars(str_replace("\n","<br>",$msg))."</p>";\r
978       }\r
979         else\r
980       {\r
981         $msg=str_replace("\n"," ",$msg);\r
982       }\r
983       eval($this->DisplayFunc."(\"".$msg."\");");\r
984     }\r
985   }\r
986 \r
987   function HandleError($msg)\r
988   {\r
989     if ($this->DisplayErrors)\r
990     {\r
991       $this->DisplayMsg($this->LastErrorMsg);\r
992     }\r
993   }\r
994 \r
995 //********************************************************************************************************\r
996 // Checks if an error has occurred, and if so, displays a message & returns true\r
997 //********************************************************************************************************\r
998   function CheckForError($msg)\r
999   {\r
1000     if (!$this->db->HasError()) return false;\r
1001     $this->LastErrorMsg=$msg;\r
1002     if (empty($this->ErrMsgFmt)) return true;\r
1003     $this->HandleError($this->FormatErrorMsg($msg));\r
1004     return true;\r
1005   }\r
1006 \r
1007 //********************************************************************************************************\r
1008 // Attempts to connect to the Database. Returns true on success.\r
1009 //********************************************************************************************************\r
1010   function MySqlLogon($DefDB,$userid,$pw)\r
1011   {\r
1012     $this->Dialect="MySQL";\r
1013     $this->dbDefault = $DefDB;\r
1014     $this->dbMain = mysql_connect($this->Provider,$userid,$pw);\r
1015     $this->db =& new dbClass_mysql($this->dbMain);\r
1016     if ($this->CheckForError("opening connection to " . $this->Provider)) return false;\r
1017     mysql_select_db($DefDB,$this->dbMain);\r
1018     if ($this->CheckForError("selecting database " . $DefDB)) return false;\r
1019     return true;\r
1020   }\r
1021 \r
1022 //********************************************************************************************************\r
1023 // Attempts to connect to the Database. Returns true on success.\r
1024 //********************************************************************************************************\r
1025   function PostgreSqlLogon($connection_string)\r
1026   {\r
1027     $this->Dialect="PostgreSQL";\r
1028     $this->dbDefault = "";\r
1029     $this->dbMain = pg_connect($connection_string);\r
1030     $this->db =& new dbClass_postgresql($this->dbMain);\r
1031     if ($this->CheckForError("opening connection")) return false;\r
1032     return true;\r
1033   }\r
1034 \r
1035 //********************************************************************************************************\r
1036 // Attempts to connect to the Database. Returns true on success.\r
1037 //********************************************************************************************************\r
1038   function OracleLogon($sim,$user,$pw)\r
1039   {\r
1040     $this->Dialect="Oracle";\r
1041     $this->dbDefault = $user;\r
1042     $this->dbMain = ocilogon($user,$pw,$sim);\r
1043     $this->db =& new dbClass_oci($this->dbMain);\r
1044     if ($this->CheckForError("opening connection")) return false;\r
1045     $this->RunActionQuery("alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'");\r
1046     return true;\r
1047   }\r
1048 \r
1049 //********************************************************************************************************\r
1050 // Attempts to connect to the Database. Returns true on success.\r
1051 //********************************************************************************************************\r
1052   function MSSqlLogon($servername,$DefDB,$user,$pw)\r
1053   {\r
1054     $this->Dialect="TSQL";\r
1055     $this->dbDefault = $DefDB;\r
1056     ini_set("mssql.datetimeconvert","Off");\r
1057     $this->dbMain = mssql_connect($servername,$user,$pw);\r
1058     if (!is_resource($this->dbMain)) {\r
1059       $this->LastErrorMsg="Error while connecting to ".$servername;\r
1060       return false;\r
1061     }\r
1062     $this->db =& new dbClass_mssql($this->dbMain);\r
1063     mssql_select_db($DefDB,$this->dbMain);\r
1064     return true;\r
1065   }\r
1066 \r
1067 //********************************************************************************************************\r
1068 // Attempts to connect to the Database. Returns true on success.\r
1069 //********************************************************************************************************\r
1070   function OdbcLogon($dsn,$DefDB,$userid,$pw)\r
1071   {\r
1072     $this->dsn = $dsn;\r
1073     $this->dbDefault = $DefDB;\r
1074     $this->dbMain = odbc_connect($dsn,$userid,$pw,SQL_CUR_USE_ODBC);\r
1075     if (!is_resource($this->dbMain)) {\r
1076       $this->LastErrorMsg="Error while opening ODBC connection: " . odbc_error();\r
1077       return false;\r
1078     } else {\r
1079       $this->db = new dbClass_odbc($this);\r
1080       return true;\r
1081     }\r
1082   }\r
1083 \r
1084 //********************************************************************************************************\r
1085 // Close database connection\r
1086 //********************************************************************************************************\r
1087   function dbClose() {\r
1088     if (is_resource($this->dbMain)) $this->db->Close();\r
1089     $this->dbMain = NULL;\r
1090     return true;\r
1091   }\r
1092 \r
1093   function CurrentTime() {\r
1094     return $this->db->CurrentTime();\r
1095   }\r
1096 \r
1097   function Convert2Char($s) {\r
1098     return $this->db->Convert2Char($s);\r
1099   }\r
1100 \r
1101   // returns SQL that converts a datetime value to a date in YYYY-MM-DD format\r
1102   function SqlDate($s) {\r
1103     return $this->Concat(array($this->SqlYear($s),"'-'",$this->SqlMonth($s),"'-'",$this->SqlDay($s)),false);\r
1104   }\r
1105 \r
1106   // returns SQL that converts a datetime value to the day-of-month\r
1107   function SqlDay($s) {\r
1108     return $this->db->SqlDay($s);\r
1109   }\r
1110 \r
1111   // returns SQL that converts a datetime value to the month number\r
1112   function SqlMonth($s) {\r
1113     return $this->db->SqlMonth($s);\r
1114   }\r
1115 \r
1116   // returns SQL that converts a datetime value to the year\r
1117   function SqlYear($s) {\r
1118     return $this->db->SqlYear($s);\r
1119   }\r
1120 \r
1121   // requires an active db connection when using MySQL\r
1122   function addQuotes($s) {\r
1123     if (get_magic_quotes_gpc())\r
1124       $s = stripslashes($s);\r
1125 \r
1126     switch ($this->Dialect) {\r
1127       case "MySQL": return "'" . mysql_real_escape_string($s) . "'";\r
1128       default:      return "'".str_replace("'","''",$s)."'";\r
1129     }\r
1130   }\r
1131 \r
1132   // returns SQL that concatenates an array of strings\r
1133   function Concat($arStrings, $addQuotes) {\r
1134     if ($addQuotes) {\r
1135       for ($i=0; $i<count($arStrings); $i++)\r
1136         $arStrings[$i]=$this->addQuotes($arStrings[$i]);\r
1137     }\r
1138     return $this->db->Concat($arStrings);\r
1139   }\r
1140 \r
1141 //********************************************************************************************************\r
1142 // Return a string containing an error message\r
1143 // String format is based on ErrMsgFmt\r
1144 //********************************************************************************************************\r
1145   function FormatErrorMsg($ContextMsg)\r
1146   {\r
1147     switch ($this->ErrMsgFmt)\r
1148     {\r
1149       case "HTML":\r
1150         $function_ret="<p class=dberror id=dbError>Error! " . $this->db->ErrorMsg() ."</p>".\r
1151           "<p class=dberror id=dbErrorDetail><u>Operation that caused the error:</u><br>".$ContextMsg."</p>";\r
1152         break;\r
1153       case "MULTILINE":\r
1154         $function_ret="Error! " . $this->db->ErrorMsg() ."\n\nOperation that caused the error:\n".$ContextMsg;\r
1155         break;\r
1156       case "1LINE":\r
1157         $function_ret="Error! " . $this->db->ErrorMsg() ."  (".$ContextMsg.")";\r
1158         break;\r
1159     }\r
1160     return $function_ret;\r
1161   }\r
1162 \r
1163 //********************************************************************************************************\r
1164 // Runs a query and moves to the first record.\r
1165 // Use only for queries that return records (no updates or deletes).\r
1166 // If the query generated an error then Nothing is returned, otherwise it returns a new recordset object.\r
1167 //********************************************************************************************************\r
1168   function RunQuery($sqltext) {\r
1169     $rsLookUp=$this->db->RunQuery($sqltext);\r
1170     if ($this->CheckForError($sqltext)) return null;\r
1171     if ($this->debug) $this->DisplayMsg($sqltext);\r
1172     return $rsLookUp;\r
1173   }\r
1174 \r
1175 \r
1176 //********************************************************************************************************\r
1177 // Runs a parameterized query (put ? in $sqltext to indicate where parameters should be inserted)\r
1178 // Use only for queries that return records (no updates or deletes).\r
1179 // If the query generated an error then null is returned, otherwise it returns a new recordset object.\r
1180 //********************************************************************************************************\r
1181   function RunParamQuery($sqltext, $arParams) {\r
1182     $rsLookUp=$this->db->RunParamQuery($sqltext, $arParams);\r
1183     if ($this->CheckForError($sqltext)) return null;\r
1184     if ($this->debug) $this->DisplayMsg($sqltext);\r
1185     return $rsLookUp;\r
1186   }\r
1187 \r
1188 \r
1189 //********************************************************************************************************\r
1190 // Safely close a recordset\r
1191 //********************************************************************************************************\r
1192   function rsClose($rsLookUp) {\r
1193     if (is_resource($rsLookUp)) $this->db->FreeResult($rsLookUp);\r
1194     $rsLookUp = NULL;\r
1195   }\r
1196 \r
1197 //********************************************************************************************************\r
1198 // Runs a query and returns results from the first record in arData.\r
1199 // Returns true if arData is modified (ie. a record exists).\r
1200 // If the query generates an error then arData is left unchanged\r
1201 // returns arData as an array, fields indexed numerically\r
1202 //********************************************************************************************************\r
1203   function SingleRecordQuery($sqltext,&$arData)\r
1204   {\r
1205     $rsMain=$this->RunQuery($sqltext);\r
1206     if (!$rsMain) return false;\r
1207     $success=$this->db->FetchArray($rsMain,$arData);\r
1208     $this->rsClose($rsMain);\r
1209     return $success;\r
1210   }\r
1211 \r
1212 \r
1213 //********************************************************************************************************\r
1214 // Runs a query where no result set is expected (updates, deletes, etc)\r
1215 //   - returns the number of records affected by the action query\r
1216 //********************************************************************************************************\r
1217   function RunActionQuery($sqltext)\r
1218   {\r
1219     $rsMain=$this->db->RunQuery($sqltext);\r
1220     if ($this->CheckForError($sqltext)) {\r
1221       return 0;\r
1222     }\r
1223     else if ($this->debug) {\r
1224       $this->DisplayMsg($sqltext);\r
1225     }\r
1226     return $this->db->AffectedRows($rsMain);\r
1227   }\r
1228 \r
1229 \r
1230 //********************************************************************************************************\r
1231 // Runs a query where no result set is expected (updates, deletes, etc)\r
1232 //   - if an error occurs, then the message is returned in errmsg\r
1233 //********************************************************************************************************\r
1234   function RunActionQueryReturnMsg($sqltext,&$errmsg)\r
1235   {\r
1236     $tmpDisplayErrors=$this->DisplayErrors;\r
1237     $this->DisplayErrors=false;\r
1238     $this->LastErrorMsg="";\r
1239     $function_ret=$this->RunActionQuery($sqltext);\r
1240     if (!empty($this->LastErrorMsg))\r
1241     {\r
1242       $errmsg=$this->LastErrorMsg;\r
1243     }\r
1244     $this->DisplayErrors=$tmpDisplayErrors;\r
1245     return $function_ret;\r
1246   }\r
1247 \r
1248 \r
1249 //********************************************************************************************************\r
1250 // Takes a sql create (table or view) statement and performs:\r
1251 //   1) a conditional drop (if it already exists)\r
1252 //   2) the create\r
1253 //   3) grants select access to public (if not a temp table)\r
1254 //\r
1255 // for views, all actions must occur on the default database for the connection\r
1256 //********************************************************************************************************\r
1257   function DropCreate($sqlcreate)\r
1258   {\r
1259     $parsed=explode(" ",$sqlcreate);\r
1260     if (count($parsed) < 3) return;  // error\r
1261     $sqltext="DROP ".$parsed[1]." ".$parsed[2];\r
1262     $this->RunActionQueryReturnMsg($sqltext,$dropmsg);\r
1263     $this->RunActionQuery($sqlcreate);\r
1264   }\r
1265 \r
1266 //********************************************************************************************************\r
1267 // Returns a comma-separated list of column names that make up the primary key\r
1268 // Returns empty string if no primary key has been defined\r
1269 //********************************************************************************************************\r
1270   function PrimaryKey($TableName) {\r
1271     $keys='';\r
1272     $arColumns=$this->GetColumnInfo($TableName);\r
1273     if (!is_array($arColumns)) return '';\r
1274     foreach ($arColumns as $colinfo) {\r
1275       if ($colinfo->IsPKey) {\r
1276         if ($keys!='') $keys.=',';\r
1277         $keys.=$colinfo->ColName;\r
1278       }\r
1279     }\r
1280     return $keys;\r
1281   }\r
1282 \r
1283 \r
1284 //********************************************************************************************************\r
1285 // Returns array of column info - one entry for each column in $TableName\r
1286 //********************************************************************************************************\r
1287   function GetColumnInfo($TableName) {\r
1288     return $this->db->GetColumnInfo($TableName);\r
1289   }\r
1290 \r
1291 \r
1292 //********************************************************************************************************\r
1293 // Returns array of table/view names\r
1294 // $ObjectType is one of 'VIEW' or 'TABLE'\r
1295 //********************************************************************************************************\r
1296   function GetTableList($ObjectType) {\r
1297     return $this->db->GetTableList($ObjectType);\r
1298   }\r
1299 \r
1300 \r
1301 //********************************************************************************************************\r
1302 // Add a condition to a where or having clause\r
1303 //********************************************************************************************************\r
1304   function AddCondition(&$WhereClause,$NewCondition)\r
1305   {\r
1306     if (empty($WhereClause))\r
1307       $WhereClause="(".$NewCondition.")";\r
1308     else\r
1309       $WhereClause.=" AND (".$NewCondition.")";\r
1310   }\r
1311 \r
1312 }\r
1313 ?>\r