Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   1  <?php
   2  
   3  /**
   4    @version   v5.20.16  12-Jan-2020
   5    @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
   6    @copyright (c) 2014      Damien Regad, Mark Newnham and the ADOdb community
   7    Released under both BSD license and Lesser GPL library license.
   8    Whenever there is any discrepancy between the two licenses,
   9    the BSD license will take precedence.
  10  
  11    Set tabs to 4 for best viewing.
  12  
  13   	 DOCUMENTATION:
  14  
  15  	 	 See adodb/tests/test-datadict.php for docs and examples.
  16  */
  17  
  18  /*
  19  	 Test script for parser
  20  */
  21  
  22  // security - hide paths
  23  if (!defined('ADODB_DIR')) die();
  24  
  25  function Lens_ParseTest()
  26  {
  27  $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";
  28  print "<p>$str</p>";
  29  $a= Lens_ParseArgs($str);
  30  print "<pre>";
  31  print_r($a);
  32  print "</pre>";
  33  }
  34  
  35  
  36  if (!function_exists('ctype_alnum')) {
  37  	function ctype_alnum($text) {
  38  	 	 return preg_match('/^[a-z0-9]*$/i', $text);
  39  	 }
  40  }
  41  
  42  //Lens_ParseTest();
  43  
  44  /**
  45  	 Parse arguments, treat "text" (text) and 'text' as quotation marks.
  46  	 To escape, use "" or '' or ))
  47  
  48  	 Will read in "abc def" sans quotes, as: abc def
  49  	 Same with 'abc def'.
  50  	 However if `abc def`, then will read in as `abc def`
  51  
  52  	 @param endstmtchar    Character that indicates end of statement
  53  	 @param tokenchars     Include the following characters in tokens apart from A-Z and 0-9
  54  	 @returns 2 dimensional array containing parsed tokens.
  55  */
  56  function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-')
  57  {
  58  	 $pos = 0;
  59  	 $intoken = false;
  60  	 $stmtno = 0;
  61  	 $endquote = false;
  62  	 $tokens = array();
  63  	 $tokens[$stmtno] = array();
  64  	 $max = strlen($args);
  65  	 $quoted = false;
  66  	 $tokarr = array();
  67  
  68  	 while ($pos < $max) {
  69  	 	 $ch = substr($args,$pos,1);
  70  	 	 switch($ch) {
  71  	 	 case ' ':
  72  	 	 case "\t":
  73  	 	 case "\n":
  74  	 	 case "\r":
  75  	 	 	 if (!$quoted) {
  76  	 	 	 	 if ($intoken) {
  77  	 	 	 	 	 $intoken = false;
  78  	 	 	 	 	 $tokens[$stmtno][] = implode('',$tokarr);
  79  	 	 	 	 }
  80  	 	 	 	 break;
  81  	 	 	 }
  82  
  83  	 	 	 $tokarr[] = $ch;
  84  	 	 	 break;
  85  
  86  	 	 case '`':
  87  	 	 	 if ($intoken) $tokarr[] = $ch;
  88  	 	 case '(':
  89  	 	 case ')':
  90  	 	 case '"':
  91  	 	 case "'":
  92  
  93  	 	 	 if ($intoken) {
  94  	 	 	 	 if (empty($endquote)) {
  95  	 	 	 	 	 $tokens[$stmtno][] = implode('',$tokarr);
  96  	 	 	 	 	 if ($ch == '(') $endquote = ')';
  97  	 	 	 	 	 else $endquote = $ch;
  98  	 	 	 	 	 $quoted = true;
  99  	 	 	 	 	 $intoken = true;
 100  	 	 	 	 	 $tokarr = array();
 101  	 	 	 	 } else if ($endquote == $ch) {
 102  	 	 	 	 	 $ch2 = substr($args,$pos+1,1);
 103  	 	 	 	 	 if ($ch2 == $endquote) {
 104  	 	 	 	 	 	 $pos += 1;
 105  	 	 	 	 	 	 $tokarr[] = $ch2;
 106  	 	 	 	 	 } else {
 107  	 	 	 	 	 	 $quoted = false;
 108  	 	 	 	 	 	 $intoken = false;
 109  	 	 	 	 	 	 $tokens[$stmtno][] = implode('',$tokarr);
 110  	 	 	 	 	 	 $endquote = '';
 111  	 	 	 	 	 }
 112  	 	 	 	 } else
 113  	 	 	 	 	 $tokarr[] = $ch;
 114  
 115  	 	 	 }else {
 116  
 117  	 	 	 	 if ($ch == '(') $endquote = ')';
 118  	 	 	 	 else $endquote = $ch;
 119  	 	 	 	 $quoted = true;
 120  	 	 	 	 $intoken = true;
 121  	 	 	 	 $tokarr = array();
 122  	 	 	 	 if ($ch == '`') $tokarr[] = '`';
 123  	 	 	 }
 124  	 	 	 break;
 125  
 126  	 	 default:
 127  
 128  	 	 	 if (!$intoken) {
 129  	 	 	 	 if ($ch == $endstmtchar) {
 130  	 	 	 	 	 $stmtno += 1;
 131  	 	 	 	 	 $tokens[$stmtno] = array();
 132  	 	 	 	 	 break;
 133  	 	 	 	 }
 134  
 135  	 	 	 	 $intoken = true;
 136  	 	 	 	 $quoted = false;
 137  	 	 	 	 $endquote = false;
 138  	 	 	 	 $tokarr = array();
 139  
 140  	 	 	 }
 141  
 142  	 	 	 if ($quoted) $tokarr[] = $ch;
 143  	 	 	 else if (ctype_alnum($ch) || strpos($tokenchars,$ch) !== false) $tokarr[] = $ch;
 144  	 	 	 else {
 145  	 	 	 	 if ($ch == $endstmtchar) {
 146  	 	 	 	 	 $tokens[$stmtno][] = implode('',$tokarr);
 147  	 	 	 	 	 $stmtno += 1;
 148  	 	 	 	 	 $tokens[$stmtno] = array();
 149  	 	 	 	 	 $intoken = false;
 150  	 	 	 	 	 $tokarr = array();
 151  	 	 	 	 	 break;
 152  	 	 	 	 }
 153  	 	 	 	 $tokens[$stmtno][] = implode('',$tokarr);
 154  	 	 	 	 $tokens[$stmtno][] = $ch;
 155  	 	 	 	 $intoken = false;
 156  	 	 	 }
 157  	 	 }
 158  	 	 $pos += 1;
 159  	 }
 160  	 if ($intoken) $tokens[$stmtno][] = implode('',$tokarr);
 161  
 162  	 return $tokens;
 163  }
 164  
 165  
 166  class ADODB_DataDict {
 167  	 var $connection;
 168  	 var $debug = false;
 169  	 var $dropTable = 'DROP TABLE %s';
 170  	 var $renameTable = 'RENAME TABLE %s TO %s';
 171  	 var $dropIndex = 'DROP INDEX %s';
 172  	 var $addCol = ' ADD';
 173  	 var $alterCol = ' ALTER COLUMN';
 174  	 var $dropCol = ' DROP COLUMN';
 175  	 var $renameColumn = 'ALTER TABLE %s RENAME COLUMN %s TO %s';	 // table, old-column, new-column, column-definitions (not used by default)
 176  	 var $nameRegex = '\w';
 177  	 var $nameRegexBrackets = 'a-zA-Z0-9_\(\)';
 178  	 var $schema = false;
 179  	 var $serverInfo = array();
 180  	 var $autoIncrement = false;
 181  	 var $dataProvider;
 182  	 var $invalidResizeTypes4 = array('CLOB','BLOB','TEXT','DATE','TIME'); // for changetablesql
 183  	 var $blobSize = 100; 	 /// any varchar/char field this size or greater is treated as a blob
 184  	 	 	 	 	 	 	 /// in other words, we use a text area for editting.
 185  
 186  	function GetCommentSQL($table,$col)
 187  	 {
 188  	 	 return false;
 189  	 }
 190  
 191  	function SetCommentSQL($table,$col,$cmt)
 192  	 {
 193  	 	 return false;
 194  	 }
 195  
 196  	function MetaTables()
 197  	 {
 198  	 	 if (!$this->connection->IsConnected()) return array();
 199  	 	 return $this->connection->MetaTables();
 200  	 }
 201  
 202  	function MetaColumns($tab, $upper=true, $schema=false)
 203  	 {
 204  	 	 if (!$this->connection->IsConnected()) return array();
 205  	 	 return $this->connection->MetaColumns($this->TableName($tab), $upper, $schema);
 206  	 }
 207  
 208  	function MetaPrimaryKeys($tab,$owner=false,$intkey=false)
 209  	 {
 210  	 	 if (!$this->connection->IsConnected()) return array();
 211  	 	 return $this->connection->MetaPrimaryKeys($this->TableName($tab), $owner, $intkey);
 212  	 }
 213  
 214  	function MetaIndexes($table, $primary = false, $owner = false)
 215  	 {
 216  	 	 if (!$this->connection->IsConnected()) return array();
 217  	 	 return $this->connection->MetaIndexes($this->TableName($table), $primary, $owner);
 218  	 }
 219  
 220  	function MetaType($t,$len=-1,$fieldobj=false)
 221  	 {
 222  	 	 static $typeMap = array(
 223  	 	 'VARCHAR' => 'C',
 224  	 	 'VARCHAR2' => 'C',
 225  	 	 'CHAR' => 'C',
 226  	 	 'C' => 'C',
 227  	 	 'STRING' => 'C',
 228  	 	 'NCHAR' => 'C',
 229  	 	 'NVARCHAR' => 'C',
 230  	 	 'VARYING' => 'C',
 231  	 	 'BPCHAR' => 'C',
 232  	 	 'CHARACTER' => 'C',
 233  	 	 'INTERVAL' => 'C',  # Postgres
 234  	 	 'MACADDR' => 'C', # postgres
 235  	 	 'VAR_STRING' => 'C', # mysql
 236  	 	 ##
 237  	 	 'LONGCHAR' => 'X',
 238  	 	 'TEXT' => 'X',
 239  	 	 'NTEXT' => 'X',
 240  	 	 'M' => 'X',
 241  	 	 'X' => 'X',
 242  	 	 'CLOB' => 'X',
 243  	 	 'NCLOB' => 'X',
 244  	 	 'LVARCHAR' => 'X',
 245  	 	 ##
 246  	 	 'BLOB' => 'B',
 247  	 	 'IMAGE' => 'B',
 248  	 	 'BINARY' => 'B',
 249  	 	 'VARBINARY' => 'B',
 250  	 	 'LONGBINARY' => 'B',
 251  	 	 'B' => 'B',
 252  	 	 ##
 253  	 	 'YEAR' => 'D', // mysql
 254  	 	 'DATE' => 'D',
 255  	 	 'D' => 'D',
 256  	 	 ##
 257  	 	 'UNIQUEIDENTIFIER' => 'C', # MS SQL Server
 258  	 	 ##
 259  	 	 'TIME' => 'T',
 260  	 	 'TIMESTAMP' => 'T',
 261  	 	 'DATETIME' => 'T',
 262  	 	 'TIMESTAMPTZ' => 'T',
 263  	 	 'SMALLDATETIME' => 'T',
 264  	 	 'T' => 'T',
 265  	 	 'TIMESTAMP WITHOUT TIME ZONE' => 'T', // postgresql
 266  	 	 ##
 267  	 	 'BOOL' => 'L',
 268  	 	 'BOOLEAN' => 'L',
 269  	 	 'BIT' => 'L',
 270  	 	 'L' => 'L',
 271  	 	 ##
 272  	 	 'COUNTER' => 'R',
 273  	 	 'R' => 'R',
 274  	 	 'SERIAL' => 'R', // ifx
 275  	 	 'INT IDENTITY' => 'R',
 276  	 	 ##
 277  	 	 'INT' => 'I',
 278  	 	 'INT2' => 'I',
 279  	 	 'INT4' => 'I',
 280  	 	 'INT8' => 'I',
 281  	 	 'INTEGER' => 'I',
 282  	 	 'INTEGER UNSIGNED' => 'I',
 283  	 	 'SHORT' => 'I',
 284  	 	 'TINYINT' => 'I',
 285  	 	 'SMALLINT' => 'I',
 286  	 	 'I' => 'I',
 287  	 	 ##
 288  	 	 'LONG' => 'N', // interbase is numeric, oci8 is blob
 289  	 	 'BIGINT' => 'N', // this is bigger than PHP 32-bit integers
 290  	 	 'DECIMAL' => 'N',
 291  	 	 'DEC' => 'N',
 292  	 	 'REAL' => 'N',
 293  	 	 'DOUBLE' => 'N',
 294  	 	 'DOUBLE PRECISION' => 'N',
 295  	 	 'SMALLFLOAT' => 'N',
 296  	 	 'FLOAT' => 'N',
 297  	 	 'NUMBER' => 'N',
 298  	 	 'NUM' => 'N',
 299  	 	 'NUMERIC' => 'N',
 300  	 	 'MONEY' => 'N',
 301  
 302  	 	 ## informix 9.2
 303  	 	 'SQLINT' => 'I',
 304  	 	 'SQLSERIAL' => 'I',
 305  	 	 'SQLSMINT' => 'I',
 306  	 	 'SQLSMFLOAT' => 'N',
 307  	 	 'SQLFLOAT' => 'N',
 308  	 	 'SQLMONEY' => 'N',
 309  	 	 'SQLDECIMAL' => 'N',
 310  	 	 'SQLDATE' => 'D',
 311  	 	 'SQLVCHAR' => 'C',
 312  	 	 'SQLCHAR' => 'C',
 313  	 	 'SQLDTIME' => 'T',
 314  	 	 'SQLINTERVAL' => 'N',
 315  	 	 'SQLBYTES' => 'B',
 316  	 	 'SQLTEXT' => 'X',
 317  	 	  ## informix 10
 318  	 	 "SQLINT8" => 'I8',
 319  	 	 "SQLSERIAL8" => 'I8',
 320  	 	 "SQLNCHAR" => 'C',
 321  	 	 "SQLNVCHAR" => 'C',
 322  	 	 "SQLLVARCHAR" => 'X',
 323  	 	 "SQLBOOL" => 'L'
 324  	 	 );
 325  
 326  	 	 if (!$this->connection->IsConnected()) {
 327  	 	 	 $t = strtoupper($t);
 328  	 	 	 if (isset($typeMap[$t])) return $typeMap[$t];
 329  	 	 	 return 'N';
 330  	 	 }
 331  	 	 return $this->connection->MetaType($t,$len,$fieldobj);
 332  	 }
 333  
 334  	function NameQuote($name = NULL,$allowBrackets=false)
 335  	 {
 336  	 	 if (!is_string($name)) {
 337  	 	 	 return FALSE;
 338  	 	 }
 339  
 340  	 	 $name = trim($name);
 341  
 342  	 	 if ( !is_object($this->connection) ) {
 343  	 	 	 return $name;
 344  	 	 }
 345  
 346  	 	 $quote = $this->connection->nameQuote;
 347  
 348  	 	 // if name is of the form `name`, quote it
 349  	 	 if ( preg_match('/^`(.+)`$/', $name, $matches) ) {
 350  	 	 	 return $quote . $matches[1] . $quote;
 351  	 	 }
 352  
 353  	 	 // if name contains special characters, quote it
 354  	 	 $regex = ($allowBrackets) ? $this->nameRegexBrackets : $this->nameRegex;
 355  
 356  	 	 if ( !preg_match('/^[' . $regex . ']+$/', $name) ) {
 357  	 	 	 return $quote . $name . $quote;
 358  	 	 }
 359  
 360  	 	 return $name;
 361  	 }
 362  
 363  	function TableName($name)
 364  	 {
 365  	 	 if ( $this->schema ) {
 366  	 	 	 return $this->NameQuote($this->schema) .'.'. $this->NameQuote($name);
 367  	 	 }
 368  	 	 return $this->NameQuote($name);
 369  	 }
 370  
 371  	 // Executes the sql array returned by GetTableSQL and GetIndexSQL
 372  	function ExecuteSQLArray($sql, $continueOnError = true)
 373  	 {
 374  	 	 $rez = 2;
 375  	 	 $conn = $this->connection;
 376  	 	 $saved = $conn->debug;
 377  	 	 foreach($sql as $line) {
 378  
 379  	 	 	 if ($this->debug) $conn->debug = true;
 380  	 	 	 $ok = $conn->Execute($line);
 381  	 	 	 $conn->debug = $saved;
 382  	 	 	 if (!$ok) {
 383  	 	 	 	 if ($this->debug) ADOConnection::outp($conn->ErrorMsg());
 384  	 	 	 	 if (!$continueOnError) return 0;
 385  	 	 	 	 $rez = 1;
 386  	 	 	 }
 387  	 	 }
 388  	 	 return $rez;
 389  	 }
 390  
 391  	 /**
 392  	  	 Returns the actual type given a character code.
 393  
 394  	 	 C:  varchar
 395  	 	 X:  CLOB (character large object) or largest varchar size if CLOB is not supported
 396  	 	 C2: Multibyte varchar
 397  	 	 X2: Multibyte CLOB
 398  
 399  	 	 B:  BLOB (binary large object)
 400  
 401  	 	 D:  Date
 402  	 	 T:  Date-time
 403  	 	 L:  Integer field suitable for storing booleans (0 or 1)
 404  	 	 I:  Integer
 405  	 	 F:  Floating point number
 406  	 	 N:  Numeric or decimal number
 407  	 */
 408  
 409  	function ActualType($meta)
 410  	 {
 411  	 	 return $meta;
 412  	 }
 413  
 414  	function CreateDatabase($dbname,$options=false)
 415  	 {
 416  	 	 $options = $this->_Options($options);
 417  	 	 $sql = array();
 418  
 419  	 	 $s = 'CREATE DATABASE ' . $this->NameQuote($dbname);
 420  	 	 if (isset($options[$this->upperName]))
 421  	 	 	 $s .= ' '.$options[$this->upperName];
 422  
 423  	 	 $sql[] = $s;
 424  	 	 return $sql;
 425  	 }
 426  
 427  	 /*
 428  	  Generates the SQL to create index. Returns an array of sql strings.
 429  	 */
 430  	function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false)
 431  	 {
 432  	 	 if (!is_array($flds)) {
 433  	 	 	 $flds = explode(',',$flds);
 434  	 	 }
 435  
 436  	 	 foreach($flds as $key => $fld) {
 437  	 	 	 # some indexes can use partial fields, eg. index first 32 chars of "name" with NAME(32)
 438  	 	 	 $flds[$key] = $this->NameQuote($fld,$allowBrackets=true);
 439  	 	 }
 440  
 441  	 	 return $this->_IndexSQL($this->NameQuote($idxname), $this->TableName($tabname), $flds, $this->_Options($idxoptions));
 442  	 }
 443  
 444  	function DropIndexSQL ($idxname, $tabname = NULL)
 445  	 {
 446  	 	 return array(sprintf($this->dropIndex, $this->NameQuote($idxname), $this->TableName($tabname)));
 447  	 }
 448  
 449  	function SetSchema($schema)
 450  	 {
 451  	 	 $this->schema = $schema;
 452  	 }
 453  
 454  	function AddColumnSQL($tabname, $flds)
 455  	 {
 456  	 	 $tabname = $this->TableName ($tabname);
 457  	 	 $sql = array();
 458  	 	 list($lines,$pkey,$idxs) = $this->_GenFields($flds);
 459  	 	 // genfields can return FALSE at times
 460  	 	 if ($lines  == null) $lines = array();
 461  	 	 $alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' ';
 462  	 	 foreach($lines as $v) {
 463  	 	 	 $sql[] = $alter . $v;
 464  	 	 }
 465  	 	 if (is_array($idxs)) {
 466  	 	 	 foreach($idxs as $idx => $idxdef) {
 467  	 	 	 	 $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
 468  	 	 	 	 $sql = array_merge($sql, $sql_idxs);
 469  	 	 	 }
 470  	 	 }
 471  	 	 return $sql;
 472  	 }
 473  
 474  	 /**
 475  	  * Change the definition of one column
 476  	  *
 477  	  * As some DBM's can't do that on there own, you need to supply the complete defintion of the new table,
 478  	  * to allow, recreating the table and copying the content over to the new table
 479  	  * @param string $tabname table-name
 480  	  * @param string $flds column-name and type for the changed column
 481  	  * @param string $tableflds='' complete defintion of the new table, eg. for postgres, default ''
 482  	  * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default ''
 483  	  * @return array with SQL strings
 484  	  */
 485  	function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
 486  	 {
 487  	 	 $tabname = $this->TableName ($tabname);
 488  	 	 $sql = array();
 489  	 	 list($lines,$pkey,$idxs) = $this->_GenFields($flds);
 490  	 	 // genfields can return FALSE at times
 491  	 	 if ($lines == null) $lines = array();
 492  	 	 $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' ';
 493  	 	 foreach($lines as $v) {
 494  	 	 	 $sql[] = $alter . $v;
 495  	 	 }
 496  	 	 if (is_array($idxs)) {
 497  	 	 	 foreach($idxs as $idx => $idxdef) {
 498  	 	 	 	 $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
 499  	 	 	 	 $sql = array_merge($sql, $sql_idxs);
 500  	 	 	 }
 501  
 502  	 	 }
 503  	 	 return $sql;
 504  	 }
 505  
 506  	 /**
 507  	  * Rename one column
 508  	  *
 509  	  * Some DBM's can only do this together with changeing the type of the column (even if that stays the same, eg. mysql)
 510  	  * @param string $tabname table-name
 511  	  * @param string $oldcolumn column-name to be renamed
 512  	  * @param string $newcolumn new column-name
 513  	  * @param string $flds='' complete column-defintion-string like for AddColumnSQL, only used by mysql atm., default=''
 514  	  * @return array with SQL strings
 515  	  */
 516  	function RenameColumnSQL($tabname,$oldcolumn,$newcolumn,$flds='')
 517  	 {
 518  	 	 $tabname = $this->TableName ($tabname);
 519  	 	 if ($flds) {
 520  	 	 	 list($lines,$pkey,$idxs) = $this->_GenFields($flds);
 521  	 	 	 // genfields can return FALSE at times
 522  	 	 	 if ($lines == null) $lines = array();
 523  	 	 	 $first  = current($lines);
 524  	 	 	 list(,$column_def) = preg_split("/[\t ]+/",$first,2);
 525  	 	 }
 526  	 	 return array(sprintf($this->renameColumn,$tabname,$this->NameQuote($oldcolumn),$this->NameQuote($newcolumn),$column_def));
 527  	 }
 528  
 529  	 /**
 530  	  * Drop one column
 531  	  *
 532  	  * Some DBM's can't do that on there own, you need to supply the complete defintion of the new table,
 533  	  * to allow, recreating the table and copying the content over to the new table
 534  	  * @param string $tabname table-name
 535  	  * @param string $flds column-name and type for the changed column
 536  	  * @param string $tableflds='' complete defintion of the new table, eg. for postgres, default ''
 537  	  * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default ''
 538  	  * @return array with SQL strings
 539  	  */
 540  	function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
 541  	 {
 542  	 	 $tabname = $this->TableName ($tabname);
 543  	 	 if (!is_array($flds)) $flds = explode(',',$flds);
 544  	 	 $sql = array();
 545  	 	 $alter = 'ALTER TABLE ' . $tabname . $this->dropCol . ' ';
 546  	 	 foreach($flds as $v) {
 547  	 	 	 $sql[] = $alter . $this->NameQuote($v);
 548  	 	 }
 549  	 	 return $sql;
 550  	 }
 551  
 552  	function DropTableSQL($tabname)
 553  	 {
 554  	 	 return array (sprintf($this->dropTable, $this->TableName($tabname)));
 555  	 }
 556  
 557  	function RenameTableSQL($tabname,$newname)
 558  	 {
 559  	 	 return array (sprintf($this->renameTable, $this->TableName($tabname),$this->TableName($newname)));
 560  	 }
 561  
 562  	 /**
 563  	  Generate the SQL to create table. Returns an array of sql strings.
 564  	 */
 565  	function CreateTableSQL($tabname, $flds, $tableoptions=array())
 566  	 {
 567  	 	 list($lines,$pkey,$idxs) = $this->_GenFields($flds, true);
 568  	 	 // genfields can return FALSE at times
 569  	 	 if ($lines == null) $lines = array();
 570  
 571  	 	 $taboptions = $this->_Options($tableoptions);
 572  	 	 $tabname = $this->TableName ($tabname);
 573  	 	 $sql = $this->_TableSQL($tabname,$lines,$pkey,$taboptions);
 574  
 575  	 	 // ggiunta - 2006/10/12 - KLUDGE:
 576          // if we are on autoincrement, and table options includes REPLACE, the
 577          // autoincrement sequence has already been dropped on table creation sql, so
 578          // we avoid passing REPLACE to trigger creation code. This prevents
 579          // creating sql that double-drops the sequence
 580          if ($this->autoIncrement && isset($taboptions['REPLACE']))
 581          	 unset($taboptions['REPLACE']);
 582  	 	 $tsql = $this->_Triggers($tabname,$taboptions);
 583  	 	 foreach($tsql as $s) $sql[] = $s;
 584  
 585  	 	 if (is_array($idxs)) {
 586  	 	 	 foreach($idxs as $idx => $idxdef) {
 587  	 	 	 	 $sql_idxs = $this->CreateIndexSql($idx, $tabname,  $idxdef['cols'], $idxdef['opts']);
 588  	 	 	 	 $sql = array_merge($sql, $sql_idxs);
 589  	 	 	 }
 590  	 	 }
 591  
 592  	 	 return $sql;
 593  	 }
 594  
 595  
 596  
 597  	function _GenFields($flds,$widespacing=false)
 598  	 {
 599  	 	 if (is_string($flds)) {
 600  	 	 	 $padding = '     ';
 601  	 	 	 $txt = $flds.$padding;
 602  	 	 	 $flds = array();
 603  	 	 	 $flds0 = Lens_ParseArgs($txt,',');
 604  	 	 	 $hasparam = false;
 605  	 	 	 foreach($flds0 as $f0) {
 606  	 	 	 	 $f1 = array();
 607  	 	 	 	 foreach($f0 as $token) {
 608  	 	 	 	 	 switch (strtoupper($token)) {
 609  	 	 	 	 	 case 'INDEX':
 610  	 	 	 	 	 	 $f1['INDEX'] = '';
 611  	 	 	 	 	 	 // fall through intentionally
 612  	 	 	 	 	 case 'CONSTRAINT':
 613  	 	 	 	 	 case 'DEFAULT':
 614  	 	 	 	 	 	 $hasparam = $token;
 615  	 	 	 	 	 	 break;
 616  	 	 	 	 	 default:
 617  	 	 	 	 	 	 if ($hasparam) $f1[$hasparam] = $token;
 618  	 	 	 	 	 	 else $f1[] = $token;
 619  	 	 	 	 	 	 $hasparam = false;
 620  	 	 	 	 	 	 break;
 621  	 	 	 	 	 }
 622  	 	 	 	 }
 623  	 	 	 	 // 'index' token without a name means single column index: name it after column
 624  	 	 	 	 if (array_key_exists('INDEX', $f1) && $f1['INDEX'] == '') {
 625  	 	 	 	 	 $f1['INDEX'] = isset($f0['NAME']) ? $f0['NAME'] : $f0[0];
 626  	 	 	 	 	 // check if column name used to create an index name was quoted
 627  	 	 	 	 	 if (($f1['INDEX'][0] == '"' || $f1['INDEX'][0] == "'" || $f1['INDEX'][0] == "`") &&
 628  	 	 	 	 	 	 ($f1['INDEX'][0] == substr($f1['INDEX'], -1))) {
 629  	 	 	 	 	 	 $f1['INDEX'] = $f1['INDEX'][0].'idx_'.substr($f1['INDEX'], 1, -1).$f1['INDEX'][0];
 630  	 	 	 	 	 }
 631  	 	 	 	 	 else
 632  	 	 	 	 	 	 $f1['INDEX'] = 'idx_'.$f1['INDEX'];
 633  	 	 	 	 }
 634  	 	 	 	 // reset it, so we don't get next field 1st token as INDEX...
 635  	 	 	 	 $hasparam = false;
 636  
 637  	 	 	 	 $flds[] = $f1;
 638  
 639  	 	 	 }
 640  	 	 }
 641  	 	 $this->autoIncrement = false;
 642  	 	 $lines = array();
 643  	 	 $pkey = array();
 644  	 	 $idxs = array();
 645  	 	 foreach($flds as $fld) {
 646  	 	 	 $fld = _array_change_key_case($fld);
 647  
 648  	 	 	 $fname = false;
 649  	 	 	 $fdefault = false;
 650  	 	 	 $fautoinc = false;
 651  	 	 	 $ftype = false;
 652  	 	 	 $fsize = false;
 653  	 	 	 $fprec = false;
 654  	 	 	 $fprimary = false;
 655  	 	 	 $fnoquote = false;
 656  	 	 	 $fdefts = false;
 657  	 	 	 $fdefdate = false;
 658  	 	 	 $fconstraint = false;
 659  	 	 	 $fnotnull = false;
 660  	 	 	 $funsigned = false;
 661  	 	 	 $findex = '';
 662  	 	 	 $funiqueindex = false;
 663  
 664  	 	 	 //-----------------
 665  	 	 	 // Parse attributes
 666  	 	 	 foreach($fld as $attr => $v) {
 667  	 	 	 	 if ($attr == 2 && is_numeric($v)) $attr = 'SIZE';
 668  	 	 	 	 else if (is_numeric($attr) && $attr > 1 && !is_numeric($v)) $attr = strtoupper($v);
 669  
 670  	 	 	 	 switch($attr) {
 671  	 	 	 	 case '0':
 672  	 	 	 	 case 'NAME': 	 $fname = $v; break;
 673  	 	 	 	 case '1':
 674  	 	 	 	 case 'TYPE': 	 $ty = $v; $ftype = $this->ActualType(strtoupper($v)); break;
 675  
 676  	 	 	 	 case 'SIZE':
 677  	 	 	 	 	 	 	 	 $dotat = strpos($v,'.'); if ($dotat === false) $dotat = strpos($v,',');
 678  	 	 	 	 	 	 	 	 if ($dotat === false) $fsize = $v;
 679  	 	 	 	 	 	 	 	 else {
 680  	 	 	 	 	 	 	 	 	 $fsize = substr($v,0,$dotat);
 681  	 	 	 	 	 	 	 	 	 $fprec = substr($v,$dotat+1);
 682  	 	 	 	 	 	 	 	 }
 683  	 	 	 	 	 	 	 	 break;
 684  	 	 	 	 case 'UNSIGNED': $funsigned = true; break;
 685  	 	 	 	 case 'AUTOINCREMENT':
 686  	 	 	 	 case 'AUTO':	 $fautoinc = true; $fnotnull = true; break;
 687  	 	 	 	 case 'KEY':
 688                  // a primary key col can be non unique in itself (if key spans many cols...)
 689  	 	 	 	 case 'PRIMARY':	 $fprimary = $v; $fnotnull = true; /*$funiqueindex = true;*/ break;
 690  	 	 	 	 case 'DEF':
 691  	 	 	 	 case 'DEFAULT': $fdefault = $v; break;
 692  	 	 	 	 case 'NOTNULL': $fnotnull = $v; break;
 693  	 	 	 	 case 'NOQUOTE': $fnoquote = $v; break;
 694  	 	 	 	 case 'DEFDATE': $fdefdate = $v; break;
 695  	 	 	 	 case 'DEFTIMESTAMP': $fdefts = $v; break;
 696  	 	 	 	 case 'CONSTRAINT': $fconstraint = $v; break;
 697  	 	 	 	 // let INDEX keyword create a 'very standard' index on column
 698  	 	 	 	 case 'INDEX': $findex = $v; break;
 699  	 	 	 	 case 'UNIQUE': $funiqueindex = true; break;
 700  	 	 	 	 } //switch
 701  	 	 	 } // foreach $fld
 702  
 703  	 	 	 //--------------------
 704  	 	 	 // VALIDATE FIELD INFO
 705  	 	 	 if (!strlen($fname)) {
 706  	 	 	 	 if ($this->debug) ADOConnection::outp("Undefined NAME");
 707  	 	 	 	 return false;
 708  	 	 	 }
 709  
 710  	 	 	 $fid = strtoupper(preg_replace('/^`(.+)`$/', '$1', $fname));
 711  	 	 	 $fname = $this->NameQuote($fname);
 712  
 713  	 	 	 if (!strlen($ftype)) {
 714  	 	 	 	 if ($this->debug) ADOConnection::outp("Undefined TYPE for field '$fname'");
 715  	 	 	 	 return false;
 716  	 	 	 } else {
 717  	 	 	 	 $ftype = strtoupper($ftype);
 718  	 	 	 }
 719  
 720  	 	 	 $ftype = $this->_GetSize($ftype, $ty, $fsize, $fprec);
 721  
 722  	 	 	 if ($ty == 'X' || $ty == 'X2' || $ty == 'B') $fnotnull = false; // some blob types do not accept nulls
 723  
 724  	 	 	 if ($fprimary) $pkey[] = $fname;
 725  
 726  	 	 	 // some databases do not allow blobs to have defaults
 727  	 	 	 if ($ty == 'X') $fdefault = false;
 728  
 729  	 	 	 // build list of indexes
 730  	 	 	 if ($findex != '') {
 731  	 	 	 	 if (array_key_exists($findex, $idxs)) {
 732  	 	 	 	 	 $idxs[$findex]['cols'][] = ($fname);
 733  	 	 	 	 	 if (in_array('UNIQUE', $idxs[$findex]['opts']) != $funiqueindex) {
 734  	 	 	 	 	 	 if ($this->debug) ADOConnection::outp("Index $findex defined once UNIQUE and once not");
 735  	 	 	 	 	 }
 736  	 	 	 	 	 if ($funiqueindex && !in_array('UNIQUE', $idxs[$findex]['opts']))
 737  	 	 	 	 	 	 $idxs[$findex]['opts'][] = 'UNIQUE';
 738  	 	 	 	 }
 739  	 	 	 	 else
 740  	 	 	 	 {
 741  	 	 	 	 	 $idxs[$findex] = array();
 742  	 	 	 	 	 $idxs[$findex]['cols'] = array($fname);
 743  	 	 	 	 	 if ($funiqueindex)
 744  	 	 	 	 	 	 $idxs[$findex]['opts'] = array('UNIQUE');
 745  	 	 	 	 	 else
 746  	 	 	 	 	 	 $idxs[$findex]['opts'] = array();
 747  	 	 	 	 }
 748  	 	 	 }
 749  
 750  	 	 	 //--------------------
 751  	 	 	 // CONSTRUCT FIELD SQL
 752  	 	 	 if ($fdefts) {
 753  	 	 	 	 if (substr($this->connection->databaseType,0,5) == 'mysql') {
 754  	 	 	 	 	 $ftype = 'TIMESTAMP';
 755  	 	 	 	 } else {
 756  	 	 	 	 	 $fdefault = $this->connection->sysTimeStamp;
 757  	 	 	 	 }
 758  	 	 	 } else if ($fdefdate) {
 759  	 	 	 	 if (substr($this->connection->databaseType,0,5) == 'mysql') {
 760  	 	 	 	 	 $ftype = 'TIMESTAMP';
 761  	 	 	 	 } else {
 762  	 	 	 	 	 $fdefault = $this->connection->sysDate;
 763  	 	 	 	 }
 764  	 	 	 } else if ($fdefault !== false && !$fnoquote) {
 765  	 	 	 	 if ($ty == 'C' or $ty == 'X' or
 766  	 	 	 	 	 ( substr($fdefault,0,1) != "'" && !is_numeric($fdefault))) {
 767  
 768  	 	 	 	 	 if (($ty == 'D' || $ty == 'T') && strtolower($fdefault) != 'null') {
 769  	 	 	 	 	 	 // convert default date into database-aware code
 770  	 	 	 	 	 	 if ($ty == 'T')
 771  	 	 	 	 	 	 {
 772  	 	 	 	 	 	 	 $fdefault = $this->connection->DBTimeStamp($fdefault);
 773  	 	 	 	 	 	 }
 774  	 	 	 	 	 	 else
 775  	 	 	 	 	 	 {
 776  	 	 	 	 	 	 	 $fdefault = $this->connection->DBDate($fdefault);
 777  	 	 	 	 	 	 }
 778  	 	 	 	 	 }
 779  	 	 	 	 	 else
 780  	 	 	 	 	 if (strlen($fdefault) != 1 && substr($fdefault,0,1) == ' ' && substr($fdefault,strlen($fdefault)-1) == ' ')
 781  	 	 	 	 	 	 $fdefault = trim($fdefault);
 782  	 	 	 	 	 else if (strtolower($fdefault) != 'null')
 783  	 	 	 	 	 	 $fdefault = $this->connection->qstr($fdefault);
 784  	 	 	 	 }
 785  	 	 	 }
 786  	 	 	 $suffix = $this->_CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned);
 787  
 788  	 	 	 // add index creation
 789  	 	 	 if ($widespacing) $fname = str_pad($fname,24);
 790  
 791  	 	 	  // check for field names appearing twice
 792              if (array_key_exists($fid, $lines)) {
 793              	  ADOConnection::outp("Field '$fname' defined twice");
 794              }
 795  
 796  	 	 	 $lines[$fid] = $fname.' '.$ftype.$suffix;
 797  
 798  	 	 	 if ($fautoinc) $this->autoIncrement = true;
 799  	 	 } // foreach $flds
 800  
 801  	 	 return array($lines,$pkey,$idxs);
 802  	 }
 803  
 804  	 /**
 805  	 	  GENERATE THE SIZE PART OF THE DATATYPE
 806  	 	 	 $ftype is the actual type
 807  	 	 	 $ty is the type defined originally in the DDL
 808  	 */
 809  	function _GetSize($ftype, $ty, $fsize, $fprec)
 810  	 {
 811  	 	 if (strlen($fsize) && $ty != 'X' && $ty != 'B' && strpos($ftype,'(') === false) {
 812  	 	 	 $ftype .= "(".$fsize;
 813  	 	 	 if (strlen($fprec)) $ftype .= ",".$fprec;
 814  	 	 	 $ftype .= ')';
 815  	 	 }
 816  	 	 return $ftype;
 817  	 }
 818  
 819  
 820  	 // return string must begin with space
 821  	function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
 822  	 {
 823  	 	 $suffix = '';
 824  	 	 if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
 825  	 	 if ($fnotnull) $suffix .= ' NOT NULL';
 826  	 	 if ($fconstraint) $suffix .= ' '.$fconstraint;
 827  	 	 return $suffix;
 828  	 }
 829  
 830  	function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
 831  	 {
 832  	 	 $sql = array();
 833  
 834  	 	 if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
 835  	 	 	 $sql[] = sprintf ($this->dropIndex, $idxname);
 836  	 	 	 if ( isset($idxoptions['DROP']) )
 837  	 	 	 	 return $sql;
 838  	 	 }
 839  
 840  	 	 if ( empty ($flds) ) {
 841  	 	 	 return $sql;
 842  	 	 }
 843  
 844  	 	 $unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
 845  
 846  	 	 $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';
 847  
 848  	 	 if ( isset($idxoptions[$this->upperName]) )
 849  	 	 	 $s .= $idxoptions[$this->upperName];
 850  
 851  	 	 if ( is_array($flds) )
 852  	 	 	 $flds = implode(', ',$flds);
 853  	 	 $s .= '(' . $flds . ')';
 854  	 	 $sql[] = $s;
 855  
 856  	 	 return $sql;
 857  	 }
 858  
 859  	function _DropAutoIncrement($tabname)
 860  	 {
 861  	 	 return false;
 862  	 }
 863  
 864  	function _TableSQL($tabname,$lines,$pkey,$tableoptions)
 865  	 {
 866  	 	 $sql = array();
 867  
 868  	 	 if (isset($tableoptions['REPLACE']) || isset ($tableoptions['DROP'])) {
 869  	 	 	 $sql[] = sprintf($this->dropTable,$tabname);
 870  	 	 	 if ($this->autoIncrement) {
 871  	 	 	 	 $sInc = $this->_DropAutoIncrement($tabname);
 872  	 	 	 	 if ($sInc) $sql[] = $sInc;
 873  	 	 	 }
 874  	 	 	 if ( isset ($tableoptions['DROP']) ) {
 875  	 	 	 	 return $sql;
 876  	 	 	 }
 877  	 	 }
 878  	 	 $s = "CREATE TABLE $tabname (\n";
 879  	 	 $s .= implode(",\n", $lines);
 880  	 	 if (sizeof($pkey)>0) {
 881  	 	 	 $s .= ",\n                 PRIMARY KEY (";
 882  	 	 	 $s .= implode(", ",$pkey).")";
 883  	 	 }
 884  	 	 if (isset($tableoptions['CONSTRAINTS']))
 885  	 	 	 $s .= "\n".$tableoptions['CONSTRAINTS'];
 886  
 887  	 	 if (isset($tableoptions[$this->upperName.'_CONSTRAINTS']))
 888  	 	 	 $s .= "\n".$tableoptions[$this->upperName.'_CONSTRAINTS'];
 889  
 890  	 	 $s .= "\n)";
 891  	 	 if (isset($tableoptions[$this->upperName])) $s .= $tableoptions[$this->upperName];
 892  	 	 $sql[] = $s;
 893  
 894  	 	 return $sql;
 895  	 }
 896  
 897  	 /**
 898  	 	 GENERATE TRIGGERS IF NEEDED
 899  	 	 used when table has auto-incrementing field that is emulated using triggers
 900  	 */
 901  	function _Triggers($tabname,$taboptions)
 902  	 {
 903  	 	 return array();
 904  	 }
 905  
 906  	 /**
 907  	 	 Sanitize options, so that array elements with no keys are promoted to keys
 908  	 */
 909  	function _Options($opts)
 910  	 {
 911  	 	 if (!is_array($opts)) return array();
 912  	 	 $newopts = array();
 913  	 	 foreach($opts as $k => $v) {
 914  	 	 	 if (is_numeric($k)) $newopts[strtoupper($v)] = $v;
 915  	 	 	 else $newopts[strtoupper($k)] = $v;
 916  	 	 }
 917  	 	 return $newopts;
 918  	 }
 919  
 920  
 921  	function _getSizePrec($size)
 922  	 {
 923  	 	 $fsize = false;
 924  	 	 $fprec = false;
 925  	 	 $dotat = strpos($size,'.');
 926  	 	 if ($dotat === false) $dotat = strpos($size,',');
 927  	 	 if ($dotat === false) $fsize = $size;
 928  	 	 else {
 929  	 	 	 $fsize = substr($size,0,$dotat);
 930  	 	 	 $fprec = substr($size,$dotat+1);
 931  	 	 }
 932  	 	 return array($fsize, $fprec);
 933  	 }
 934  
 935  	 /**
 936  	 "Florian Buzin [ easywe ]" <florian.buzin#easywe.de>
 937  
 938  	 This function changes/adds new fields to your table. You don't
 939  	 have to know if the col is new or not. It will check on its own.
 940  	 */
 941  	function ChangeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=false)
 942  	 {
 943  	 global $ADODB_FETCH_MODE;
 944  
 945  	 	 $save = $ADODB_FETCH_MODE;
 946  	 	 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
 947  	 	 if ($this->connection->fetchMode !== false) $savem = $this->connection->SetFetchMode(false);
 948  
 949  	 	 // check table exists
 950  	 	 $save_handler = $this->connection->raiseErrorFn;
 951  	 	 $this->connection->raiseErrorFn = '';
 952  	 	 $cols = $this->MetaColumns($tablename);
 953  	 	 $this->connection->raiseErrorFn = $save_handler;
 954  
 955  	 	 if (isset($savem)) $this->connection->SetFetchMode($savem);
 956  	 	 $ADODB_FETCH_MODE = $save;
 957  
 958  	 	 if ( empty($cols)) {
 959  	 	 	 return $this->CreateTableSQL($tablename, $flds, $tableoptions);
 960  	 	 }
 961  
 962  	 	 if (is_array($flds)) {
 963  	 	 // Cycle through the update fields, comparing
 964  	 	 // existing fields to fields to update.
 965  	 	 // if the Metatype and size is exactly the
 966  	 	 // same, ignore - by Mark Newham
 967  	 	 	 $holdflds = array();
 968  	 	 	 foreach($flds as $k=>$v) {
 969  	 	 	 	 if ( isset($cols[$k]) && is_object($cols[$k]) ) {
 970  	 	 	 	 	 // If already not allowing nulls, then don't change
 971  	 	 	 	 	 $obj = $cols[$k];
 972  	 	 	 	 	 if (isset($obj->not_null) && $obj->not_null)
 973  	 	 	 	 	 	 $v = str_replace('NOT NULL','',$v);
 974  	 	 	 	 	 if (isset($obj->auto_increment) && $obj->auto_increment && empty($v['AUTOINCREMENT']))
 975  	 	 	 	 	     $v = str_replace('AUTOINCREMENT','',$v);
 976  
 977  	 	 	 	 	 $c = $cols[$k];
 978  	 	 	 	 	 $ml = $c->max_length;
 979  	 	 	 	 	 $mt = $this->MetaType($c->type,$ml);
 980  
 981  	 	 	 	 	 if (isset($c->scale)) $sc = $c->scale;
 982  	 	 	 	 	 else $sc = 99; // always force change if scale not known.
 983  
 984  	 	 	 	 	 if ($sc == -1) $sc = false;
 985  	 	 	 	 	 list($fsize, $fprec) = $this->_getSizePrec($v['SIZE']);
 986  
 987  	 	 	 	 	 if ($ml == -1) $ml = '';
 988  	 	 	 	 	 if ($mt == 'X') $ml = $v['SIZE'];
 989  	 	 	 	 	 if (($mt != $v['TYPE']) || ($ml != $fsize || $sc != $fprec) || (isset($v['AUTOINCREMENT']) && $v['AUTOINCREMENT'] != $obj->auto_increment)) {
 990  	 	 	 	 	 	 $holdflds[$k] = $v;
 991  	 	 	 	 	 }
 992  	 	 	 	 } else {
 993  	 	 	 	 	 $holdflds[$k] = $v;
 994  	 	 	 	 }
 995  	 	 	 }
 996  	 	 	 $flds = $holdflds;
 997  	 	 }
 998  
 999  
1000  	 	 // already exists, alter table instead
1001  	 	 list($lines,$pkey,$idxs) = $this->_GenFields($flds);
1002  	 	 // genfields can return FALSE at times
1003  	 	 if ($lines == null) $lines = array();
1004  	 	 $alter = 'ALTER TABLE ' . $this->TableName($tablename);
1005  	 	 $sql = array();
1006  
1007  	 	 foreach ( $lines as $id => $v ) {
1008  	 	 	 if ( isset($cols[$id]) && is_object($cols[$id]) ) {
1009  
1010  	 	 	 	 $flds = Lens_ParseArgs($v,',');
1011  
1012  	 	 	 	 //  We are trying to change the size of the field, if not allowed, simply ignore the request.
1013  	 	 	 	 // $flds[1] holds the type, $flds[2] holds the size -postnuke addition
1014  	 	 	 	 if ($flds && in_array(strtoupper(substr($flds[0][1],0,4)),$this->invalidResizeTypes4)
1015  	 	 	 	  && (isset($flds[0][2]) && is_numeric($flds[0][2]))) {
1016  	 	 	 	 	 if ($this->debug) ADOConnection::outp(sprintf("<h3>%s cannot be changed to %s currently</h3>", $flds[0][0], $flds[0][1]));
1017  	 	 	 	 	 #echo "<h3>$this->alterCol cannot be changed to $flds currently</h3>";
1018  	 	 	 	 	 continue;
1019  	  	 	 	 }
1020  	 	 	 	 $sql[] = $alter . $this->alterCol . ' ' . $v;
1021  	 	 	 } else {
1022  	 	 	 	 $sql[] = $alter . $this->addCol . ' ' . $v;
1023  	 	 	 }
1024  	 	 }
1025  
1026  	 	 if ($dropOldFlds) {
1027  	 	 	 foreach ( $cols as $id => $v )
1028  	 	 	     if ( !isset($lines[$id]) )
1029  	 	 	 	 	 $sql[] = $alter . $this->dropCol . ' ' . $v->name;
1030  	 	 }
1031  	 	 return $sql;
1032  	 }
1033  } // class