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