C:/lib/adodb/adodb-datadict.inc.php Quellcode

adodb-datadict.inc.php
gehe zur Dokumentation dieser Datei
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;
373  $conn = $this->connection;
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
1032 ?>




Korrekturen, Hinweise und Ergänzungen

Bitte scheuen Sie sich nicht und melden Sie, was auf dieser Seite sachlich falsch oder irreführend ist, was ergänzt werden sollte, was fehlt usw. Dazu bitte oben aus dem Menü Seite den Eintrag Support Forum wählen. Es ist eine kostenlose Anmeldung erforderlich, um Anmerkungen zu posten. Unpassende Postings, Spam usw. werden kommentarlos entfernt.