ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/WEBCONDDB/php_CondDB/adodb/adodb-datadict.inc.php
Revision: 1.1
Committed: Fri Jun 29 07:49:19 2007 UTC (17 years, 10 months ago) by kdziedzi
Branch: MAIN
CVS Tags: V01-01-02, V01-01-01, V1_01_00, V01-01-00, V1_00_01, HEAD
Log Message:
Introducing new order in project

File Contents

# User Rev Content
1 kdziedzi 1.1 <?php
2    
3     /**
4     V4.93 10 Oct 2006 (c) 2000-2006 John Lim (jlim#natsoft.com.my). All rights reserved.
5     Released under both BSD license and Lesser GPL library license.
6     Whenever there is any discrepancy between the two licenses,
7     the BSD license will take precedence.
8    
9     Set tabs to 4 for best viewing.
10    
11     DOCUMENTATION:
12    
13     See adodb/tests/test-datadict.php for docs and examples.
14     */
15    
16     /*
17     Test script for parser
18     */
19    
20     // security - hide paths
21     if (!defined('ADODB_DIR')) die();
22    
23     function Lens_ParseTest()
24     {
25     $str = "`zcol ACOL` NUMBER(32,2) DEFAULT 'The \"cow\" (and Jim''s dog) jumps over the moon' PRIMARY, INTI INT AUTO DEFAULT 0, zcol2\"afs ds";
26     print "<p>$str</p>";
27     $a= Lens_ParseArgs($str);
28     print "<pre>";
29     print_r($a);
30     print "</pre>";
31     }
32    
33    
34     if (!function_exists('ctype_alnum')) {
35     function ctype_alnum($text) {
36     return preg_match('/^[a-z0-9]*$/i', $text);
37     }
38     }
39    
40     //Lens_ParseTest();
41    
42     /**
43     Parse arguments, treat "text" (text) and 'text' as quotation marks.
44     To escape, use "" or '' or ))
45    
46     Will read in "abc def" sans quotes, as: abc def
47     Same with 'abc def'.
48     However if `abc def`, then will read in as `abc def`
49    
50     @param endstmtchar Character that indicates end of statement
51     @param tokenchars Include the following characters in tokens apart from A-Z and 0-9
52     @returns 2 dimensional array containing parsed tokens.
53     */
54     function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-')
55     {
56     $pos = 0;
57     $intoken = false;
58     $stmtno = 0;
59     $endquote = false;
60     $tokens = array();
61     $tokens[$stmtno] = array();
62     $max = strlen($args);
63     $quoted = false;
64     $tokarr = array();
65    
66     while ($pos < $max) {
67     $ch = substr($args,$pos,1);
68     switch($ch) {
69     case ' ':
70     case "\t":
71     case "\n":
72     case "\r":
73     if (!$quoted) {
74     if ($intoken) {
75     $intoken = false;
76     $tokens[$stmtno][] = implode('',$tokarr);
77     }
78     break;
79     }
80    
81     $tokarr[] = $ch;
82     break;
83    
84     case '`':
85     if ($intoken) $tokarr[] = $ch;
86     case '(':
87     case ')':
88     case '"':
89     case "'":
90    
91     if ($intoken) {
92     if (empty($endquote)) {
93     $tokens[$stmtno][] = implode('',$tokarr);
94     if ($ch == '(') $endquote = ')';
95     else $endquote = $ch;
96     $quoted = true;
97     $intoken = true;
98     $tokarr = array();
99     } else if ($endquote == $ch) {
100     $ch2 = substr($args,$pos+1,1);
101     if ($ch2 == $endquote) {
102     $pos += 1;
103     $tokarr[] = $ch2;
104     } else {
105     $quoted = false;
106     $intoken = false;
107     $tokens[$stmtno][] = implode('',$tokarr);
108     $endquote = '';
109     }
110     } else
111     $tokarr[] = $ch;
112    
113     }else {
114    
115     if ($ch == '(') $endquote = ')';
116     else $endquote = $ch;
117     $quoted = true;
118     $intoken = true;
119     $tokarr = array();
120     if ($ch == '`') $tokarr[] = '`';
121     }
122     break;
123    
124     default:
125    
126     if (!$intoken) {
127     if ($ch == $endstmtchar) {
128     $stmtno += 1;
129     $tokens[$stmtno] = array();
130     break;
131     }
132    
133     $intoken = true;
134     $quoted = false;
135     $endquote = false;
136     $tokarr = array();
137    
138     }
139    
140     if ($quoted) $tokarr[] = $ch;
141     else if (ctype_alnum($ch) || strpos($tokenchars,$ch) !== false) $tokarr[] = $ch;
142     else {
143     if ($ch == $endstmtchar) {
144     $tokens[$stmtno][] = implode('',$tokarr);
145     $stmtno += 1;
146     $tokens[$stmtno] = array();
147     $intoken = false;
148     $tokarr = array();
149     break;
150     }
151     $tokens[$stmtno][] = implode('',$tokarr);
152     $tokens[$stmtno][] = $ch;
153     $intoken = false;
154     }
155     }
156     $pos += 1;
157     }
158     if ($intoken) $tokens[$stmtno][] = implode('',$tokarr);
159    
160     return $tokens;
161     }
162    
163    
164     class ADODB_DataDict {
165     var $connection;
166     var $debug = false;
167     var $dropTable = 'DROP TABLE %s';
168     var $renameTable = 'RENAME TABLE %s TO %s';
169     var $dropIndex = 'DROP INDEX %s';
170     var $addCol = ' ADD';
171     var $alterCol = ' ALTER COLUMN';
172     var $dropCol = ' DROP COLUMN';
173     var $renameColumn = 'ALTER TABLE %s RENAME COLUMN %s TO %s'; // table, old-column, new-column, column-definitions (not used by default)
174     var $nameRegex = '\w';
175     var $nameRegexBrackets = 'a-zA-Z0-9_\(\)';
176     var $schema = false;
177     var $serverInfo = array();
178     var $autoIncrement = false;
179     var $dataProvider;
180     var $invalidResizeTypes4 = array('CLOB','BLOB','TEXT','DATE','TIME'); // for changetablesql
181     var $blobSize = 100; /// any varchar/char field this size or greater is treated as a blob
182     /// in other words, we use a text area for editting.
183    
184     function GetCommentSQL($table,$col)
185     {
186     return false;
187     }
188    
189     function SetCommentSQL($table,$col,$cmt)
190     {
191     return false;
192     }
193    
194     function MetaTables()
195     {
196     if (!$this->connection->IsConnected()) return array();
197     return $this->connection->MetaTables();
198     }
199    
200     function MetaColumns($tab, $upper=true, $schema=false)
201     {
202     if (!$this->connection->IsConnected()) return array();
203     return $this->connection->MetaColumns($this->TableName($tab), $upper, $schema);
204     }
205    
206     function MetaPrimaryKeys($tab,$owner=false,$intkey=false)
207     {
208     if (!$this->connection->IsConnected()) return array();
209     return $this->connection->MetaPrimaryKeys($this->TableName($tab), $owner, $intkey);
210     }
211    
212     function MetaIndexes($table, $primary = false, $owner = false)
213     {
214     if (!$this->connection->IsConnected()) return array();
215     return $this->connection->MetaIndexes($this->TableName($table), $primary, $owner);
216     }
217    
218     function MetaType($t,$len=-1,$fieldobj=false)
219     {
220     return ADORecordSet::MetaType($t,$len,$fieldobj);
221     }
222    
223     function NameQuote($name = NULL,$allowBrackets=false)
224     {
225     if (!is_string($name)) {
226     return FALSE;
227     }
228    
229     $name = trim($name);
230    
231     if ( !is_object($this->connection) ) {
232     return $name;
233     }
234    
235     $quote = $this->connection->nameQuote;
236    
237     // if name is of the form `name`, quote it
238     if ( preg_match('/^`(.+)`$/', $name, $matches) ) {
239     return $quote . $matches[1] . $quote;
240     }
241    
242     // if name contains special characters, quote it
243     $regex = ($allowBrackets) ? $this->nameRegexBrackets : $this->nameRegex;
244    
245     if ( !preg_match('/^[' . $regex . ']+$/', $name) ) {
246     return $quote . $name . $quote;
247     }
248    
249     return $name;
250     }
251    
252     function TableName($name)
253     {
254     if ( $this->schema ) {
255     return $this->NameQuote($this->schema) .'.'. $this->NameQuote($name);
256     }
257     return $this->NameQuote($name);
258     }
259    
260     // Executes the sql array returned by GetTableSQL and GetIndexSQL
261     function ExecuteSQLArray($sql, $continueOnError = true)
262     {
263     $rez = 2;
264     $conn = &$this->connection;
265     $saved = $conn->debug;
266     foreach($sql as $line) {
267    
268     if ($this->debug) $conn->debug = true;
269     $ok = $conn->Execute($line);
270     $conn->debug = $saved;
271     if (!$ok) {
272     if ($this->debug) ADOConnection::outp($conn->ErrorMsg());
273     if (!$continueOnError) return 0;
274     $rez = 1;
275     }
276     }
277     return $rez;
278     }
279    
280     /*
281     Returns the actual type given a character code.
282    
283     C: varchar
284     X: CLOB (character large object) or largest varchar size if CLOB is not supported
285     C2: Multibyte varchar
286     X2: Multibyte CLOB
287    
288     B: BLOB (binary large object)
289    
290     D: Date
291     T: Date-time
292     L: Integer field suitable for storing booleans (0 or 1)
293     I: Integer
294     F: Floating point number
295     N: Numeric or decimal number
296     */
297    
298     function ActualType($meta)
299     {
300     return $meta;
301     }
302    
303     function CreateDatabase($dbname,$options=false)
304     {
305     $options = $this->_Options($options);
306     $sql = array();
307    
308     $s = 'CREATE DATABASE ' . $this->NameQuote($dbname);
309     if (isset($options[$this->upperName]))
310     $s .= ' '.$options[$this->upperName];
311    
312     $sql[] = $s;
313     return $sql;
314     }
315    
316     /*
317     Generates the SQL to create index. Returns an array of sql strings.
318     */
319     function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false)
320     {
321     if (!is_array($flds)) {
322     $flds = explode(',',$flds);
323     }
324    
325     foreach($flds as $key => $fld) {
326     # some indexes can use partial fields, eg. index first 32 chars of "name" with NAME(32)
327     $flds[$key] = $this->NameQuote($fld,$allowBrackets=true);
328     }
329    
330     return $this->_IndexSQL($this->NameQuote($idxname), $this->TableName($tabname), $flds, $this->_Options($idxoptions));
331     }
332    
333     function DropIndexSQL ($idxname, $tabname = NULL)
334     {
335     return array(sprintf($this->dropIndex, $this->NameQuote($idxname), $this->TableName($tabname)));
336     }
337    
338     function SetSchema($schema)
339     {
340     $this->schema = $schema;
341     }
342    
343     function AddColumnSQL($tabname, $flds)
344     {
345     $tabname = $this->TableName ($tabname);
346     $sql = array();
347     list($lines,$pkey) = $this->_GenFields($flds);
348     $alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' ';
349     foreach($lines as $v) {
350     $sql[] = $alter . $v;
351     }
352     return $sql;
353     }
354    
355     /**
356     * Change the definition of one column
357     *
358     * As some DBM's can't do that on there own, you need to supply the complete defintion of the new table,
359     * to allow, recreating the table and copying the content over to the new table
360     * @param string $tabname table-name
361     * @param string $flds column-name and type for the changed column
362     * @param string $tableflds='' complete defintion of the new table, eg. for postgres, default ''
363     * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default ''
364     * @return array with SQL strings
365     */
366     function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
367     {
368     $tabname = $this->TableName ($tabname);
369     $sql = array();
370     list($lines,$pkey) = $this->_GenFields($flds);
371     $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' ';
372     foreach($lines as $v) {
373     $sql[] = $alter . $v;
374     }
375     return $sql;
376     }
377    
378     /**
379     * Rename one column
380     *
381     * Some DBM's can only do this together with changeing the type of the column (even if that stays the same, eg. mysql)
382     * @param string $tabname table-name
383     * @param string $oldcolumn column-name to be renamed
384     * @param string $newcolumn new column-name
385     * @param string $flds='' complete column-defintion-string like for AddColumnSQL, only used by mysql atm., default=''
386     * @return array with SQL strings
387     */
388     function RenameColumnSQL($tabname,$oldcolumn,$newcolumn,$flds='')
389     {
390     $tabname = $this->TableName ($tabname);
391     if ($flds) {
392     list($lines,$pkey) = $this->_GenFields($flds);
393     list(,$first) = each($lines);
394     list(,$column_def) = split("[\t ]+",$first,2);
395     }
396     return array(sprintf($this->renameColumn,$tabname,$this->NameQuote($oldcolumn),$this->NameQuote($newcolumn),$column_def));
397     }
398    
399     /**
400     * Drop one column
401     *
402     * Some DBM's can't do that on there own, you need to supply the complete defintion of the new table,
403     * to allow, recreating the table and copying the content over to the new table
404     * @param string $tabname table-name
405     * @param string $flds column-name and type for the changed column
406     * @param string $tableflds='' complete defintion of the new table, eg. for postgres, default ''
407     * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default ''
408     * @return array with SQL strings
409     */
410     function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
411     {
412     $tabname = $this->TableName ($tabname);
413     if (!is_array($flds)) $flds = explode(',',$flds);
414     $sql = array();
415     $alter = 'ALTER TABLE ' . $tabname . $this->dropCol . ' ';
416     foreach($flds as $v) {
417     $sql[] = $alter . $this->NameQuote($v);
418     }
419     return $sql;
420     }
421    
422     function DropTableSQL($tabname)
423     {
424     return array (sprintf($this->dropTable, $this->TableName($tabname)));
425     }
426    
427     function RenameTableSQL($tabname,$newname)
428     {
429     return array (sprintf($this->renameTable, $this->TableName($tabname),$this->TableName($newname)));
430     }
431    
432     /*
433     Generate the SQL to create table. Returns an array of sql strings.
434     */
435     function CreateTableSQL($tabname, $flds, $tableoptions=false)
436     {
437     if (!$tableoptions) $tableoptions = array();
438    
439     list($lines,$pkey) = $this->_GenFields($flds, true);
440    
441     $taboptions = $this->_Options($tableoptions);
442     $tabname = $this->TableName ($tabname);
443     $sql = $this->_TableSQL($tabname,$lines,$pkey,$taboptions);
444    
445     $tsql = $this->_Triggers($tabname,$taboptions);
446     foreach($tsql as $s) $sql[] = $s;
447    
448     return $sql;
449     }
450    
451     function _GenFields($flds,$widespacing=false)
452     {
453     if (is_string($flds)) {
454     $padding = ' ';
455     $txt = $flds.$padding;
456     $flds = array();
457     $flds0 = Lens_ParseArgs($txt,',');
458     $hasparam = false;
459     foreach($flds0 as $f0) {
460     $f1 = array();
461     foreach($f0 as $token) {
462     switch (strtoupper($token)) {
463     case 'CONSTRAINT':
464     case 'DEFAULT':
465     $hasparam = $token;
466     break;
467     default:
468     if ($hasparam) $f1[$hasparam] = $token;
469     else $f1[] = $token;
470     $hasparam = false;
471     break;
472     }
473     }
474     $flds[] = $f1;
475    
476     }
477     }
478     $this->autoIncrement = false;
479     $lines = array();
480     $pkey = array();
481     foreach($flds as $fld) {
482     $fld = _array_change_key_case($fld);
483    
484     $fname = false;
485     $fdefault = false;
486     $fautoinc = false;
487     $ftype = false;
488     $fsize = false;
489     $fprec = false;
490     $fprimary = false;
491     $fnoquote = false;
492     $fdefts = false;
493     $fdefdate = false;
494     $fconstraint = false;
495     $fnotnull = false;
496     $funsigned = false;
497    
498     //-----------------
499     // Parse attributes
500     foreach($fld as $attr => $v) {
501     if ($attr == 2 && is_numeric($v)) $attr = 'SIZE';
502     else if (is_numeric($attr) && $attr > 1 && !is_numeric($v)) $attr = strtoupper($v);
503    
504     switch($attr) {
505     case '0':
506     case 'NAME': $fname = $v; break;
507     case '1':
508     case 'TYPE': $ty = $v; $ftype = $this->ActualType(strtoupper($v)); break;
509    
510     case 'SIZE':
511     $dotat = strpos($v,'.'); if ($dotat === false) $dotat = strpos($v,',');
512     if ($dotat === false) $fsize = $v;
513     else {
514     $fsize = substr($v,0,$dotat);
515     $fprec = substr($v,$dotat+1);
516     }
517     break;
518     case 'UNSIGNED': $funsigned = true; break;
519     case 'AUTOINCREMENT':
520     case 'AUTO': $fautoinc = true; $fnotnull = true; break;
521     case 'KEY':
522     case 'PRIMARY': $fprimary = $v; $fnotnull = true; break;
523     case 'DEF':
524     case 'DEFAULT': $fdefault = $v; break;
525     case 'NOTNULL': $fnotnull = $v; break;
526     case 'NOQUOTE': $fnoquote = $v; break;
527     case 'DEFDATE': $fdefdate = $v; break;
528     case 'DEFTIMESTAMP': $fdefts = $v; break;
529     case 'CONSTRAINT': $fconstraint = $v; break;
530     } //switch
531     } // foreach $fld
532    
533     //--------------------
534     // VALIDATE FIELD INFO
535     if (!strlen($fname)) {
536     if ($this->debug) ADOConnection::outp("Undefined NAME");
537     return false;
538     }
539    
540     $fid = strtoupper(preg_replace('/^`(.+)`$/', '$1', $fname));
541     $fname = $this->NameQuote($fname);
542    
543     if (!strlen($ftype)) {
544     if ($this->debug) ADOConnection::outp("Undefined TYPE for field '$fname'");
545     return false;
546     } else {
547     $ftype = strtoupper($ftype);
548     }
549    
550     $ftype = $this->_GetSize($ftype, $ty, $fsize, $fprec);
551    
552     if ($ty == 'X' || $ty == 'X2' || $ty == 'B') $fnotnull = false; // some blob types do not accept nulls
553    
554     if ($fprimary) $pkey[] = $fname;
555    
556     // some databases do not allow blobs to have defaults
557     if ($ty == 'X') $fdefault = false;
558    
559     //--------------------
560     // CONSTRUCT FIELD SQL
561     if ($fdefts) {
562     if (substr($this->connection->databaseType,0,5) == 'mysql') {
563     $ftype = 'TIMESTAMP';
564     } else {
565     $fdefault = $this->connection->sysTimeStamp;
566     }
567     } else if ($fdefdate) {
568     if (substr($this->connection->databaseType,0,5) == 'mysql') {
569     $ftype = 'TIMESTAMP';
570     } else {
571     $fdefault = $this->connection->sysDate;
572     }
573     } else if ($fdefault !== false && !$fnoquote)
574     if ($ty == 'C' or $ty == 'X' or
575     ( substr($fdefault,0,1) != "'" && !is_numeric($fdefault)))
576     if (strlen($fdefault) != 1 && substr($fdefault,0,1) == ' ' && substr($fdefault,strlen($fdefault)-1) == ' ')
577     $fdefault = trim($fdefault);
578     else if (strtolower($fdefault) != 'null')
579     $fdefault = $this->connection->qstr($fdefault);
580     $suffix = $this->_CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned);
581    
582     if ($widespacing) $fname = str_pad($fname,24);
583     $lines[$fid] = $fname.' '.$ftype.$suffix;
584    
585     if ($fautoinc) $this->autoIncrement = true;
586     } // foreach $flds
587    
588     return array($lines,$pkey);
589     }
590     /*
591     GENERATE THE SIZE PART OF THE DATATYPE
592     $ftype is the actual type
593     $ty is the type defined originally in the DDL
594     */
595     function _GetSize($ftype, $ty, $fsize, $fprec)
596     {
597     if (strlen($fsize) && $ty != 'X' && $ty != 'B' && strpos($ftype,'(') === false) {
598     $ftype .= "(".$fsize;
599     if (strlen($fprec)) $ftype .= ",".$fprec;
600     $ftype .= ')';
601     }
602     return $ftype;
603     }
604    
605    
606     // return string must begin with space
607     function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint)
608     {
609     $suffix = '';
610     if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
611     if ($fnotnull) $suffix .= ' NOT NULL';
612     if ($fconstraint) $suffix .= ' '.$fconstraint;
613     return $suffix;
614     }
615    
616     function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
617     {
618     $sql = array();
619    
620     if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
621     $sql[] = sprintf ($this->dropIndex, $idxname);
622     if ( isset($idxoptions['DROP']) )
623     return $sql;
624     }
625    
626     if ( empty ($flds) ) {
627     return $sql;
628     }
629    
630     $unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
631    
632     $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';
633    
634     if ( isset($idxoptions[$this->upperName]) )
635     $s .= $idxoptions[$this->upperName];
636    
637     if ( is_array($flds) )
638     $flds = implode(', ',$flds);
639     $s .= '(' . $flds . ')';
640     $sql[] = $s;
641    
642     return $sql;
643     }
644    
645     function _DropAutoIncrement($tabname)
646     {
647     return false;
648     }
649    
650     function _TableSQL($tabname,$lines,$pkey,$tableoptions)
651     {
652     $sql = array();
653    
654     if (isset($tableoptions['REPLACE']) || isset ($tableoptions['DROP'])) {
655     $sql[] = sprintf($this->dropTable,$tabname);
656     if ($this->autoIncrement) {
657     $sInc = $this->_DropAutoIncrement($tabname);
658     if ($sInc) $sql[] = $sInc;
659     }
660     if ( isset ($tableoptions['DROP']) ) {
661     return $sql;
662     }
663     }
664     $s = "CREATE TABLE $tabname (\n";
665     $s .= implode(",\n", $lines);
666     if (sizeof($pkey)>0) {
667     $s .= ",\n PRIMARY KEY (";
668     $s .= implode(", ",$pkey).")";
669     }
670     if (isset($tableoptions['CONSTRAINTS']))
671     $s .= "\n".$tableoptions['CONSTRAINTS'];
672    
673     if (isset($tableoptions[$this->upperName.'_CONSTRAINTS']))
674     $s .= "\n".$tableoptions[$this->upperName.'_CONSTRAINTS'];
675    
676     $s .= "\n)";
677     if (isset($tableoptions[$this->upperName])) $s .= $tableoptions[$this->upperName];
678     $sql[] = $s;
679    
680     return $sql;
681     }
682    
683     /*
684     GENERATE TRIGGERS IF NEEDED
685     used when table has auto-incrementing field that is emulated using triggers
686     */
687     function _Triggers($tabname,$taboptions)
688     {
689     return array();
690     }
691    
692     /*
693     Sanitize options, so that array elements with no keys are promoted to keys
694     */
695     function _Options($opts)
696     {
697     if (!is_array($opts)) return array();
698     $newopts = array();
699     foreach($opts as $k => $v) {
700     if (is_numeric($k)) $newopts[strtoupper($v)] = $v;
701     else $newopts[strtoupper($k)] = $v;
702     }
703     return $newopts;
704     }
705    
706     /*
707     "Florian Buzin [ easywe ]" <florian.buzin#easywe.de>
708    
709     This function changes/adds new fields to your table. You don't
710     have to know if the col is new or not. It will check on its own.
711     */
712     function ChangeTableSQL($tablename, $flds, $tableoptions = false)
713     {
714     global $ADODB_FETCH_MODE;
715    
716     $save = $ADODB_FETCH_MODE;
717     $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
718     if ($this->connection->fetchMode !== false) $savem = $this->connection->SetFetchMode(false);
719    
720     // check table exists
721     $save_handler = $this->connection->raiseErrorFn;
722     $this->connection->raiseErrorFn = '';
723     $cols = $this->MetaColumns($tablename);
724     $this->connection->raiseErrorFn = $save_handler;
725    
726     if (isset($savem)) $this->connection->SetFetchMode($savem);
727     $ADODB_FETCH_MODE = $save;
728    
729     if ( empty($cols)) {
730     return $this->CreateTableSQL($tablename, $flds, $tableoptions);
731     }
732    
733     if (is_array($flds)) {
734     // Cycle through the update fields, comparing
735     // existing fields to fields to update.
736     // if the Metatype and size is exactly the
737     // same, ignore - by Mark Newham
738     $holdflds = array();
739     foreach($flds as $k=>$v) {
740     if ( isset($cols[$k]) && is_object($cols[$k]) ) {
741     // If already not allowing nulls, then don't change
742     $obj = $cols[$k];
743     if (isset($obj->not_null) && $obj->not_null)
744     $v = str_replace('NOT NULL','',$v);
745    
746     $c = $cols[$k];
747     $ml = $c->max_length;
748     $mt = $this->MetaType($c->type,$ml);
749     if ($ml == -1) $ml = '';
750     if ($mt == 'X') $ml = $v['SIZE'];
751     if (($mt != $v['TYPE']) || $ml != $v['SIZE']) {
752     $holdflds[$k] = $v;
753     }
754     } else {
755     $holdflds[$k] = $v;
756     }
757     }
758     $flds = $holdflds;
759     }
760    
761    
762     // already exists, alter table instead
763     list($lines,$pkey) = $this->_GenFields($flds);
764     $alter = 'ALTER TABLE ' . $this->TableName($tablename);
765     $sql = array();
766    
767     foreach ( $lines as $id => $v ) {
768     if ( isset($cols[$id]) && is_object($cols[$id]) ) {
769    
770     $flds = Lens_ParseArgs($v,',');
771    
772     // We are trying to change the size of the field, if not allowed, simply ignore the request.
773     if ($flds && in_array(strtoupper(substr($flds[0][1],0,4)),$this->invalidResizeTypes4)) continue;
774    
775     $sql[] = $alter . $this->alterCol . ' ' . $v;
776     } else {
777     $sql[] = $alter . $this->addCol . ' ' . $v;
778     }
779     }
780    
781     return $sql;
782     }
783     } // class
784     ?>