TYPO3 CMS  TYPO3_6-2
adodb-datadict.inc.php
Go to the documentation of this file.
1 <?php
2 
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 
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 
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;
180  var $invalidResizeTypes4 = array('CLOB','BLOB','TEXT','DATE','TIME'); // for changetablesql
181  var $blobSize = 100;
182 
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  static $typeMap = array(
221  'VARCHAR' => 'C',
222  'VARCHAR2' => 'C',
223  'CHAR' => 'C',
224  'C' => 'C',
225  'STRING' => 'C',
226  'NCHAR' => 'C',
227  'NVARCHAR' => 'C',
228  'VARYING' => 'C',
229  'BPCHAR' => 'C',
230  'CHARACTER' => 'C',
231  'INTERVAL' => 'C', # Postgres
232  'MACADDR' => 'C', # postgres
233  'VAR_STRING' => 'C', # mysql
234  ##
235  'LONGCHAR' => 'X',
236  'TEXT' => 'X',
237  'NTEXT' => 'X',
238  'M' => 'X',
239  'X' => 'X',
240  'CLOB' => 'X',
241  'NCLOB' => 'X',
242  'LVARCHAR' => 'X',
243  ##
244  'BLOB' => 'B',
245  'IMAGE' => 'B',
246  'BINARY' => 'B',
247  'VARBINARY' => 'B',
248  'LONGBINARY' => 'B',
249  'B' => 'B',
250  ##
251  'YEAR' => 'D', // mysql
252  'DATE' => 'D',
253  'D' => 'D',
254  ##
255  'UNIQUEIDENTIFIER' => 'C', # MS SQL Server
256  ##
257  'TIME' => 'T',
258  'TIMESTAMP' => 'T',
259  'DATETIME' => 'T',
260  'TIMESTAMPTZ' => 'T',
261  'SMALLDATETIME' => 'T',
262  'T' => 'T',
263  'TIMESTAMP WITHOUT TIME ZONE' => 'T', // postgresql
264  ##
265  'BOOL' => 'L',
266  'BOOLEAN' => 'L',
267  'BIT' => 'L',
268  'L' => 'L',
269  ##
270  'COUNTER' => 'R',
271  'R' => 'R',
272  'SERIAL' => 'R', // ifx
273  'INT IDENTITY' => 'R',
274  ##
275  'INT' => 'I',
276  'INT2' => 'I',
277  'INT4' => 'I',
278  'INT8' => 'I',
279  'INTEGER' => 'I',
280  'INTEGER UNSIGNED' => 'I',
281  'SHORT' => 'I',
282  'TINYINT' => 'I',
283  'SMALLINT' => 'I',
284  'I' => 'I',
285  ##
286  'LONG' => 'N', // interbase is numeric, oci8 is blob
287  'BIGINT' => 'N', // this is bigger than PHP 32-bit integers
288  'DECIMAL' => 'N',
289  'DEC' => 'N',
290  'REAL' => 'N',
291  'DOUBLE' => 'N',
292  'DOUBLE PRECISION' => 'N',
293  'SMALLFLOAT' => 'N',
294  'FLOAT' => 'N',
295  'NUMBER' => 'N',
296  'NUM' => 'N',
297  'NUMERIC' => 'N',
298  'MONEY' => 'N',
299 
300  ## informix 9.2
301  'SQLINT' => 'I',
302  'SQLSERIAL' => 'I',
303  'SQLSMINT' => 'I',
304  'SQLSMFLOAT' => 'N',
305  'SQLFLOAT' => 'N',
306  'SQLMONEY' => 'N',
307  'SQLDECIMAL' => 'N',
308  'SQLDATE' => 'D',
309  'SQLVCHAR' => 'C',
310  'SQLCHAR' => 'C',
311  'SQLDTIME' => 'T',
312  'SQLINTERVAL' => 'N',
313  'SQLBYTES' => 'B',
314  'SQLTEXT' => 'X',
315  ## informix 10
316  "SQLINT8" => 'I8',
317  "SQLSERIAL8" => 'I8',
318  "SQLNCHAR" => 'C',
319  "SQLNVCHAR" => 'C',
320  "SQLLVARCHAR" => 'X',
321  "SQLBOOL" => 'L'
322  );
323 
324  if (!$this->connection->IsConnected()) {
325  $t = strtoupper($t);
326  if (isset($typeMap[$t])) return $typeMap[$t];
327  return 'N';
328  }
329  return $this->connection->MetaType($t,$len,$fieldobj);
330  }
331 
332  function NameQuote($name = NULL,$allowBrackets=false)
333  {
334  if (!is_string($name)) {
335  return FALSE;
336  }
337 
338  $name = trim($name);
339 
340  if ( !is_object($this->connection) ) {
341  return $name;
342  }
343 
344  $quote = $this->connection->nameQuote;
345 
346  // if name is of the form `name`, quote it
347  if ( preg_match('/^`(.+)`$/', $name, $matches) ) {
348  return $quote . $matches[1] . $quote;
349  }
350 
351  // if name contains special characters, quote it
352  $regex = ($allowBrackets) ? $this->nameRegexBrackets : $this->nameRegex;
353 
354  if ( !preg_match('/^[' . $regex . ']+$/', $name) ) {
355  return $quote . $name . $quote;
356  }
357 
358  return $name;
359  }
360 
361  function TableName($name)
362  {
363  if ( $this->schema ) {
364  return $this->NameQuote($this->schema) .'.'. $this->NameQuote($name);
365  }
366  return $this->NameQuote($name);
367  }
368 
369  // Executes the sql array returned by GetTableSQL and GetIndexSQL
370  function ExecuteSQLArray($sql, $continueOnError = true)
371  {
372  $rez = 2;
374  $saved = $conn->debug;
375  foreach($sql as $line) {
376 
377  if ($this->debug) $conn->debug = true;
378  $ok = $conn->Execute($line);
379  $conn->debug = $saved;
380  if (!$ok) {
381  if ($this->debug) ADOConnection::outp($conn->ErrorMsg());
382  if (!$continueOnError) return 0;
383  $rez = 1;
384  }
385  }
386  return $rez;
387  }
388 
407  function ActualType($meta)
408  {
409  return $meta;
410  }
411 
412  function CreateDatabase($dbname,$options=false)
413  {
414  $options = $this->_Options($options);
415  $sql = array();
416 
417  $s = 'CREATE DATABASE ' . $this->NameQuote($dbname);
418  if (isset($options[$this->upperName]))
419  $s .= ' '.$options[$this->upperName];
420 
421  $sql[] = $s;
422  return $sql;
423  }
424 
425  /*
426  Generates the SQL to create index. Returns an array of sql strings.
427  */
428  function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false)
429  {
430  if (!is_array($flds)) {
431  $flds = explode(',',$flds);
432  }
433 
434  foreach($flds as $key => $fld) {
435  # some indexes can use partial fields, eg. index first 32 chars of "name" with NAME(32)
436  $flds[$key] = $this->NameQuote($fld,$allowBrackets=true);
437  }
438 
439  return $this->_IndexSQL($this->NameQuote($idxname), $this->TableName($tabname), $flds, $this->_Options($idxoptions));
440  }
441 
442  function DropIndexSQL ($idxname, $tabname = NULL)
443  {
444  return array(sprintf($this->dropIndex, $this->NameQuote($idxname), $this->TableName($tabname)));
445  }
446 
447  function SetSchema($schema)
448  {
449  $this->schema = $schema;
450  }
451 
452  function AddColumnSQL($tabname, $flds)
453  {
454  $tabname = $this->TableName ($tabname);
455  $sql = array();
456  list($lines,$pkey,$idxs) = $this->_GenFields($flds);
457  // genfields can return FALSE at times
458  if ($lines == null) $lines = array();
459  $alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' ';
460  foreach($lines as $v) {
461  $sql[] = $alter . $v;
462  }
463  if (is_array($idxs)) {
464  foreach($idxs as $idx => $idxdef) {
465  $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
466  $sql = array_merge($sql, $sql_idxs);
467  }
468  }
469  return $sql;
470  }
471 
483  function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
484  {
485  $tabname = $this->TableName ($tabname);
486  $sql = array();
487  list($lines,$pkey,$idxs) = $this->_GenFields($flds);
488  // genfields can return FALSE at times
489  if ($lines == null) $lines = array();
490  $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' ';
491  foreach($lines as $v) {
492  $sql[] = $alter . $v;
493  }
494  if (is_array($idxs)) {
495  foreach($idxs as $idx => $idxdef) {
496  $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
497  $sql = array_merge($sql, $sql_idxs);
498  }
499 
500  }
501  return $sql;
502  }
503 
514  function RenameColumnSQL($tabname,$oldcolumn,$newcolumn,$flds='')
515  {
516  $tabname = $this->TableName ($tabname);
517  if ($flds) {
518  list($lines,$pkey,$idxs) = $this->_GenFields($flds);
519  // genfields can return FALSE at times
520  if ($lines == null) $lines = array();
521  list(,$first) = each($lines);
522  list(,$column_def) = preg_split("/[\t ]+/",$first,2);
523  }
524  return array(sprintf($this->renameColumn,$tabname,$this->NameQuote($oldcolumn),$this->NameQuote($newcolumn),$column_def));
525  }
526 
538  function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
539  {
540  $tabname = $this->TableName ($tabname);
541  if (!is_array($flds)) $flds = explode(',',$flds);
542  $sql = array();
543  $alter = 'ALTER TABLE ' . $tabname . $this->dropCol . ' ';
544  foreach($flds as $v) {
545  $sql[] = $alter . $this->NameQuote($v);
546  }
547  return $sql;
548  }
549 
550  function DropTableSQL($tabname)
551  {
552  return array (sprintf($this->dropTable, $this->TableName($tabname)));
553  }
554 
555  function RenameTableSQL($tabname,$newname)
556  {
557  return array (sprintf($this->renameTable, $this->TableName($tabname),$this->TableName($newname)));
558  }
559 
563  function CreateTableSQL($tabname, $flds, $tableoptions=array())
564  {
565  list($lines,$pkey,$idxs) = $this->_GenFields($flds, true);
566  // genfields can return FALSE at times
567  if ($lines == null) $lines = array();
568 
569  $taboptions = $this->_Options($tableoptions);
570  $tabname = $this->TableName ($tabname);
571  $sql = $this->_TableSQL($tabname,$lines,$pkey,$taboptions);
572 
573  // ggiunta - 2006/10/12 - KLUDGE:
574  // if we are on autoincrement, and table options includes REPLACE, the
575  // autoincrement sequence has already been dropped on table creation sql, so
576  // we avoid passing REPLACE to trigger creation code. This prevents
577  // creating sql that double-drops the sequence
578  if ($this->autoIncrement && isset($taboptions['REPLACE']))
579  unset($taboptions['REPLACE']);
580  $tsql = $this->_Triggers($tabname,$taboptions);
581  foreach($tsql as $s) $sql[] = $s;
582 
583  if (is_array($idxs)) {
584  foreach($idxs as $idx => $idxdef) {
585  $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
586  $sql = array_merge($sql, $sql_idxs);
587  }
588  }
589 
590  return $sql;
591  }
592 
593 
594 
595  function _GenFields($flds,$widespacing=false)
596  {
597  if (is_string($flds)) {
598  $padding = ' ';
599  $txt = $flds.$padding;
600  $flds = array();
601  $flds0 = Lens_ParseArgs($txt,',');
602  $hasparam = false;
603  foreach($flds0 as $f0) {
604  $f1 = array();
605  foreach($f0 as $token) {
606  switch (strtoupper($token)) {
607  case 'INDEX':
608  $f1['INDEX'] = '';
609  // fall through intentionally
610  case 'CONSTRAINT':
611  case 'DEFAULT':
612  $hasparam = $token;
613  break;
614  default:
615  if ($hasparam) $f1[$hasparam] = $token;
616  else $f1[] = $token;
617  $hasparam = false;
618  break;
619  }
620  }
621  // 'index' token without a name means single column index: name it after column
622  if (array_key_exists('INDEX', $f1) && $f1['INDEX'] == '') {
623  $f1['INDEX'] = isset($f0['NAME']) ? $f0['NAME'] : $f0[0];
624  // check if column name used to create an index name was quoted
625  if (($f1['INDEX'][0] == '"' || $f1['INDEX'][0] == "'" || $f1['INDEX'][0] == "`") &&
626  ($f1['INDEX'][0] == substr($f1['INDEX'], -1))) {
627  $f1['INDEX'] = $f1['INDEX'][0].'idx_'.substr($f1['INDEX'], 1, -1).$f1['INDEX'][0];
628  }
629  else
630  $f1['INDEX'] = 'idx_'.$f1['INDEX'];
631  }
632  // reset it, so we don't get next field 1st token as INDEX...
633  $hasparam = false;
634 
635  $flds[] = $f1;
636 
637  }
638  }
639  $this->autoIncrement = false;
640  $lines = array();
641  $pkey = array();
642  $idxs = array();
643  foreach($flds as $fld) {
644  $fld = _array_change_key_case($fld);
645 
646  $fname = false;
647  $fdefault = false;
648  $fautoinc = false;
649  $ftype = false;
650  $fsize = false;
651  $fprec = false;
652  $fprimary = false;
653  $fnoquote = false;
654  $fdefts = false;
655  $fdefdate = false;
656  $fconstraint = false;
657  $fnotnull = false;
658  $funsigned = false;
659  $findex = '';
660  $funiqueindex = false;
661 
662  //-----------------
663  // Parse attributes
664  foreach($fld as $attr => $v) {
665  if ($attr == 2 && is_numeric($v)) $attr = 'SIZE';
666  else if (is_numeric($attr) && $attr > 1 && !is_numeric($v)) $attr = strtoupper($v);
667 
668  switch($attr) {
669  case '0':
670  case 'NAME': $fname = $v; break;
671  case '1':
672  case 'TYPE': $ty = $v; $ftype = $this->ActualType(strtoupper($v)); break;
673 
674  case 'SIZE':
675  $dotat = strpos($v,'.'); if ($dotat === false) $dotat = strpos($v,',');
676  if ($dotat === false) $fsize = $v;
677  else {
678  $fsize = substr($v,0,$dotat);
679  $fprec = substr($v,$dotat+1);
680  }
681  break;
682  case 'UNSIGNED': $funsigned = true; break;
683  case 'AUTOINCREMENT':
684  case 'AUTO': $fautoinc = true; $fnotnull = true; break;
685  case 'KEY':
686  // a primary key col can be non unique in itself (if key spans many cols...)
687  case 'PRIMARY': $fprimary = $v; $fnotnull = true; /*$funiqueindex = true;*/ break;
688  case 'DEF':
689  case 'DEFAULT': $fdefault = $v; break;
690  case 'NOTNULL': $fnotnull = $v; break;
691  case 'NOQUOTE': $fnoquote = $v; break;
692  case 'DEFDATE': $fdefdate = $v; break;
693  case 'DEFTIMESTAMP': $fdefts = $v; break;
694  case 'CONSTRAINT': $fconstraint = $v; break;
695  // let INDEX keyword create a 'very standard' index on column
696  case 'INDEX': $findex = $v; break;
697  case 'UNIQUE': $funiqueindex = true; break;
698  } //switch
699  } // foreach $fld
700 
701  //--------------------
702  // VALIDATE FIELD INFO
703  if (!strlen($fname)) {
704  if ($this->debug) ADOConnection::outp("Undefined NAME");
705  return false;
706  }
707 
708  $fid = strtoupper(preg_replace('/^`(.+)`$/', '$1', $fname));
709  $fname = $this->NameQuote($fname);
710 
711  if (!strlen($ftype)) {
712  if ($this->debug) ADOConnection::outp("Undefined TYPE for field '$fname'");
713  return false;
714  } else {
715  $ftype = strtoupper($ftype);
716  }
717 
718  $ftype = $this->_GetSize($ftype, $ty, $fsize, $fprec);
719 
720  if ($ty == 'X' || $ty == 'X2' || $ty == 'B') $fnotnull = false; // some blob types do not accept nulls
721 
722  if ($fprimary) $pkey[] = $fname;
723 
724  // some databases do not allow blobs to have defaults
725  if ($ty == 'X') $fdefault = false;
726 
727  // build list of indexes
728  if ($findex != '') {
729  if (array_key_exists($findex, $idxs)) {
730  $idxs[$findex]['cols'][] = ($fname);
731  if (in_array('UNIQUE', $idxs[$findex]['opts']) != $funiqueindex) {
732  if ($this->debug) ADOConnection::outp("Index $findex defined once UNIQUE and once not");
733  }
734  if ($funiqueindex && !in_array('UNIQUE', $idxs[$findex]['opts']))
735  $idxs[$findex]['opts'][] = 'UNIQUE';
736  }
737  else
738  {
739  $idxs[$findex] = array();
740  $idxs[$findex]['cols'] = array($fname);
741  if ($funiqueindex)
742  $idxs[$findex]['opts'] = array('UNIQUE');
743  else
744  $idxs[$findex]['opts'] = array();
745  }
746  }
747 
748  //--------------------
749  // CONSTRUCT FIELD SQL
750  if ($fdefts) {
751  if (substr($this->connection->databaseType,0,5) == 'mysql') {
752  $ftype = 'TIMESTAMP';
753  } else {
754  $fdefault = $this->connection->sysTimeStamp;
755  }
756  } else if ($fdefdate) {
757  if (substr($this->connection->databaseType,0,5) == 'mysql') {
758  $ftype = 'TIMESTAMP';
759  } else {
760  $fdefault = $this->connection->sysDate;
761  }
762  } else if ($fdefault !== false && !$fnoquote) {
763  if ($ty == 'C' or $ty == 'X' or
764  ( substr($fdefault,0,1) != "'" && !is_numeric($fdefault))) {
765 
766  if (($ty == 'D' || $ty == 'T') && strtolower($fdefault) != 'null') {
767  // convert default date into database-aware code
768  if ($ty == 'T')
769  {
770  $fdefault = $this->connection->DBTimeStamp($fdefault);
771  }
772  else
773  {
774  $fdefault = $this->connection->DBDate($fdefault);
775  }
776  }
777  else
778  if (strlen($fdefault) != 1 && substr($fdefault,0,1) == ' ' && substr($fdefault,strlen($fdefault)-1) == ' ')
779  $fdefault = trim($fdefault);
780  else if (strtolower($fdefault) != 'null')
781  $fdefault = $this->connection->qstr($fdefault);
782  }
783  }
784  $suffix = $this->_CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned);
785 
786  // add index creation
787  if ($widespacing) $fname = str_pad($fname,24);
788 
789  // check for field names appearing twice
790  if (array_key_exists($fid, $lines)) {
791  ADOConnection::outp("Field '$fname' defined twice");
792  }
793 
794  $lines[$fid] = $fname.' '.$ftype.$suffix;
795 
796  if ($fautoinc) $this->autoIncrement = true;
797  } // foreach $flds
798 
799  return array($lines,$pkey,$idxs);
800  }
801 
807  function _GetSize($ftype, $ty, $fsize, $fprec)
808  {
809  if (strlen($fsize) && $ty != 'X' && $ty != 'B' && strpos($ftype,'(') === false) {
810  $ftype .= "(".$fsize;
811  if (strlen($fprec)) $ftype .= ",".$fprec;
812  $ftype .= ')';
813  }
814  return $ftype;
815  }
816 
817 
818  // return string must begin with space
819  function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
820  {
821  $suffix = '';
822  if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
823  if ($fnotnull) $suffix .= ' NOT NULL';
824  if ($fconstraint) $suffix .= ' '.$fconstraint;
825  return $suffix;
826  }
827 
828  function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
829  {
830  $sql = array();
831 
832  if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
833  $sql[] = sprintf ($this->dropIndex, $idxname);
834  if ( isset($idxoptions['DROP']) )
835  return $sql;
836  }
837 
838  if ( empty ($flds) ) {
839  return $sql;
840  }
841 
842  $unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
843 
844  $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';
845 
846  if ( isset($idxoptions[$this->upperName]) )
847  $s .= $idxoptions[$this->upperName];
848 
849  if ( is_array($flds) )
850  $flds = implode(', ',$flds);
851  $s .= '(' . $flds . ')';
852  $sql[] = $s;
853 
854  return $sql;
855  }
856 
857  function _DropAutoIncrement($tabname)
858  {
859  return false;
860  }
861 
862  function _TableSQL($tabname,$lines,$pkey,$tableoptions)
863  {
864  $sql = array();
865 
866  if (isset($tableoptions['REPLACE']) || isset ($tableoptions['DROP'])) {
867  $sql[] = sprintf($this->dropTable,$tabname);
868  if ($this->autoIncrement) {
869  $sInc = $this->_DropAutoIncrement($tabname);
870  if ($sInc) $sql[] = $sInc;
871  }
872  if ( isset ($tableoptions['DROP']) ) {
873  return $sql;
874  }
875  }
876  $s = "CREATE TABLE $tabname (\n";
877  $s .= implode(",\n", $lines);
878  if (sizeof($pkey)>0) {
879  $s .= ",\n PRIMARY KEY (";
880  $s .= implode(", ",$pkey).")";
881  }
882  if (isset($tableoptions['CONSTRAINTS']))
883  $s .= "\n".$tableoptions['CONSTRAINTS'];
884 
885  if (isset($tableoptions[$this->upperName.'_CONSTRAINTS']))
886  $s .= "\n".$tableoptions[$this->upperName.'_CONSTRAINTS'];
887 
888  $s .= "\n)";
889  if (isset($tableoptions[$this->upperName])) $s .= $tableoptions[$this->upperName];
890  $sql[] = $s;
891 
892  return $sql;
893  }
894 
899  function _Triggers($tabname,$taboptions)
900  {
901  return array();
902  }
903 
907  function _Options($opts)
908  {
909  if (!is_array($opts)) return array();
910  $newopts = array();
911  foreach($opts as $k => $v) {
912  if (is_numeric($k)) $newopts[strtoupper($v)] = $v;
913  else $newopts[strtoupper($k)] = $v;
914  }
915  return $newopts;
916  }
917 
918 
919  function _getSizePrec($size)
920  {
921  $fsize = false;
922  $fprec = false;
923  $dotat = strpos($size,'.');
924  if ($dotat === false) $dotat = strpos($size,',');
925  if ($dotat === false) $fsize = $size;
926  else {
927  $fsize = substr($size,0,$dotat);
928  $fprec = substr($size,$dotat+1);
929  }
930  return array($fsize, $fprec);
931  }
932 
939  function ChangeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=false)
940  {
941  global $ADODB_FETCH_MODE;
942 
943  $save = $ADODB_FETCH_MODE;
944  $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
945  if ($this->connection->fetchMode !== false) $savem = $this->connection->SetFetchMode(false);
946 
947  // check table exists
948  $save_handler = $this->connection->raiseErrorFn;
949  $this->connection->raiseErrorFn = '';
950  $cols = $this->MetaColumns($tablename);
951  $this->connection->raiseErrorFn = $save_handler;
952 
953  if (isset($savem)) $this->connection->SetFetchMode($savem);
954  $ADODB_FETCH_MODE = $save;
955 
956  if ( empty($cols)) {
957  return $this->CreateTableSQL($tablename, $flds, $tableoptions);
958  }
959 
960  if (is_array($flds)) {
961  // Cycle through the update fields, comparing
962  // existing fields to fields to update.
963  // if the Metatype and size is exactly the
964  // same, ignore - by Mark Newham
965  $holdflds = array();
966  foreach($flds as $k=>$v) {
967  if ( isset($cols[$k]) && is_object($cols[$k]) ) {
968  // If already not allowing nulls, then don't change
969  $obj = $cols[$k];
970  if (isset($obj->not_null) && $obj->not_null)
971  $v = str_replace('NOT NULL','',$v);
972  if (isset($obj->auto_increment) && $obj->auto_increment && empty($v['AUTOINCREMENT']))
973  $v = str_replace('AUTOINCREMENT','',$v);
974 
975  $c = $cols[$k];
976  $ml = $c->max_length;
977  $mt = $this->MetaType($c->type,$ml);
978 
979  if (isset($c->scale)) $sc = $c->scale;
980  else $sc = 99; // always force change if scale not known.
981 
982  if ($sc == -1) $sc = false;
983  list($fsize, $fprec) = $this->_getSizePrec($v['SIZE']);
984 
985  if ($ml == -1) $ml = '';
986  if ($mt == 'X') $ml = $v['SIZE'];
987  if (($mt != $v['TYPE']) || ($ml != $fsize || $sc != $fprec) || (isset($v['AUTOINCREMENT']) && $v['AUTOINCREMENT'] != $obj->auto_increment)) {
988  $holdflds[$k] = $v;
989  }
990  } else {
991  $holdflds[$k] = $v;
992  }
993  }
994  $flds = $holdflds;
995  }
996 
997 
998  // already exists, alter table instead
999  list($lines,$pkey,$idxs) = $this->_GenFields($flds);
1000  // genfields can return FALSE at times
1001  if ($lines == null) $lines = array();
1002  $alter = 'ALTER TABLE ' . $this->TableName($tablename);
1003  $sql = array();
1004 
1005  foreach ( $lines as $id => $v ) {
1006  if ( isset($cols[$id]) && is_object($cols[$id]) ) {
1007 
1008  $flds = Lens_ParseArgs($v,',');
1009 
1010  // We are trying to change the size of the field, if not allowed, simply ignore the request.
1011  // $flds[1] holds the type, $flds[2] holds the size -postnuke addition
1012  if ($flds && in_array(strtoupper(substr($flds[0][1],0,4)),$this->invalidResizeTypes4)
1013  && (isset($flds[0][2]) && is_numeric($flds[0][2]))) {
1014  if ($this->debug) ADOConnection::outp(sprintf("<h3>%s cannot be changed to %s currently</h3>", $flds[0][0], $flds[0][1]));
1015  #echo "<h3>$this->alterCol cannot be changed to $flds currently</h3>";
1016  continue;
1017  }
1018  $sql[] = $alter . $this->alterCol . ' ' . $v;
1019  } else {
1020  $sql[] = $alter . $this->addCol . ' ' . $v;
1021  }
1022  }
1023 
1024  if ($dropOldFlds) {
1025  foreach ( $cols as $id => $v )
1026  if ( !isset($lines[$id]) )
1027  $sql[] = $alter . $this->dropCol . ' ' . $v->name;
1028  }
1029  return $sql;
1030  }
1031 } // class
Lens_ParseTest()
_GenFields($flds, $widespacing=false)
ChangeTableSQL($tablename, $flds, $tableoptions=false, $dropOldFlds=false)
_CreateSuffix($fname, &$ftype, $fnotnull, $fdefault, $fautoinc, $fconstraint, $funsigned)
if(!function_exists('ctype_alnum')) Lens_ParseArgs($args, $endstmtchar=',', $tokenchars='_.-')
MetaColumns($tab, $upper=true, $schema=false)
$sql
Definition: server.php:82
AlterColumnSQL($tabname, $flds, $tableflds='', $tableoptions='')
MetaIndexes($table, $primary=false, $owner=false)
DropIndexSQL($idxname, $tabname=NULL)
CreateIndexSQL($idxname, $tabname, $flds, $idxoptions=false)
DropColumnSQL($tabname, $flds, $tableflds='', $tableoptions='')
SetCommentSQL($table, $col, $cmt)
_TableSQL($tabname, $lines, $pkey, $tableoptions)
AddColumnSQL($tabname, $flds)
$conn
Definition: server.php:79
die
Definition: index.php:6
_DropAutoIncrement($tabname)
_array_change_key_case($an_array)
CreateDatabase($dbname, $options=false)
MetaType($t, $len=-1, $fieldobj=false)
_Triggers($tabname, $taboptions)
CreateTableSQL($tabname, $flds, $tableoptions=array())
RenameColumnSQL($tabname, $oldcolumn, $newcolumn, $flds='')
_IndexSQL($idxname, $tabname, $flds, $idxoptions)
_GetSize($ftype, $ty, $fsize, $fprec)
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel=E_DEBUG)
RenameTableSQL($tabname, $newname)
GetCommentSQL($table, $col)
MetaPrimaryKeys($tab, $owner=false, $intkey=false)
NameQuote($name=NULL, $allowBrackets=false)
ExecuteSQLArray($sql, $continueOnError=true)