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