|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00016 /* 00017 Test script for parser 00018 */ 00019 00020 // security - hide paths 00021 if (!defined('ADODB_DIR')) die(); 00022 00023 function Lens_ParseTest() 00024 { 00025 $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"; 00026 print "<p>$str</p>"; 00027 $a= Lens_ParseArgs($str); 00028 print "<pre>"; 00029 print_r($a); 00030 print "</pre>"; 00031 } 00032 00033 00034 if (!function_exists('ctype_alnum')) { 00035 function ctype_alnum($text) { 00036 return preg_match('/^[a-z0-9]*$/i', $text); 00037 } 00038 } 00039 00040 //Lens_ParseTest(); 00041 00054 function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-') 00055 { 00056 $pos = 0; 00057 $intoken = false; 00058 $stmtno = 0; 00059 $endquote = false; 00060 $tokens = array(); 00061 $tokens[$stmtno] = array(); 00062 $max = strlen($args); 00063 $quoted = false; 00064 $tokarr = array(); 00065 00066 while ($pos < $max) { 00067 $ch = substr($args,$pos,1); 00068 switch($ch) { 00069 case ' ': 00070 case "\t": 00071 case "\n": 00072 case "\r": 00073 if (!$quoted) { 00074 if ($intoken) { 00075 $intoken = false; 00076 $tokens[$stmtno][] = implode('',$tokarr); 00077 } 00078 break; 00079 } 00080 00081 $tokarr[] = $ch; 00082 break; 00083 00084 case '`': 00085 if ($intoken) $tokarr[] = $ch; 00086 case '(': 00087 case ')': 00088 case '"': 00089 case "'": 00090 00091 if ($intoken) { 00092 if (empty($endquote)) { 00093 $tokens[$stmtno][] = implode('',$tokarr); 00094 if ($ch == '(') $endquote = ')'; 00095 else $endquote = $ch; 00096 $quoted = true; 00097 $intoken = true; 00098 $tokarr = array(); 00099 } else if ($endquote == $ch) { 00100 $ch2 = substr($args,$pos+1,1); 00101 if ($ch2 == $endquote) { 00102 $pos += 1; 00103 $tokarr[] = $ch2; 00104 } else { 00105 $quoted = false; 00106 $intoken = false; 00107 $tokens[$stmtno][] = implode('',$tokarr); 00108 $endquote = ''; 00109 } 00110 } else 00111 $tokarr[] = $ch; 00112 00113 }else { 00114 00115 if ($ch == '(') $endquote = ')'; 00116 else $endquote = $ch; 00117 $quoted = true; 00118 $intoken = true; 00119 $tokarr = array(); 00120 if ($ch == '`') $tokarr[] = '`'; 00121 } 00122 break; 00123 00124 default: 00125 00126 if (!$intoken) { 00127 if ($ch == $endstmtchar) { 00128 $stmtno += 1; 00129 $tokens[$stmtno] = array(); 00130 break; 00131 } 00132 00133 $intoken = true; 00134 $quoted = false; 00135 $endquote = false; 00136 $tokarr = array(); 00137 00138 } 00139 00140 if ($quoted) $tokarr[] = $ch; 00141 else if (ctype_alnum($ch) || strpos($tokenchars,$ch) !== false) $tokarr[] = $ch; 00142 else { 00143 if ($ch == $endstmtchar) { 00144 $tokens[$stmtno][] = implode('',$tokarr); 00145 $stmtno += 1; 00146 $tokens[$stmtno] = array(); 00147 $intoken = false; 00148 $tokarr = array(); 00149 break; 00150 } 00151 $tokens[$stmtno][] = implode('',$tokarr); 00152 $tokens[$stmtno][] = $ch; 00153 $intoken = false; 00154 } 00155 } 00156 $pos += 1; 00157 } 00158 if ($intoken) $tokens[$stmtno][] = implode('',$tokarr); 00159 00160 return $tokens; 00161 } 00162 00163 00164 class ADODB_DataDict { 00165 var $connection; 00166 var $debug = false; 00167 var $dropTable = 'DROP TABLE %s'; 00168 var $renameTable = 'RENAME TABLE %s TO %s'; 00169 var $dropIndex = 'DROP INDEX %s'; 00170 var $addCol = ' ADD'; 00171 var $alterCol = ' ALTER COLUMN'; 00172 var $dropCol = ' DROP COLUMN'; 00173 var $renameColumn = 'ALTER TABLE %s RENAME COLUMN %s TO %s'; // table, old-column, new-column, column-definitions (not used by default) 00174 var $nameRegex = '\w'; 00175 var $nameRegexBrackets = 'a-zA-Z0-9_\(\)'; 00176 var $schema = false; 00177 var $serverInfo = array(); 00178 var $autoIncrement = false; 00179 var $dataProvider; 00180 var $invalidResizeTypes4 = array('CLOB','BLOB','TEXT','DATE','TIME'); // for changetablesql 00181 var $blobSize = 100; 00182 00183 00184 function GetCommentSQL($table,$col) 00185 { 00186 return false; 00187 } 00188 00189 function SetCommentSQL($table,$col,$cmt) 00190 { 00191 return false; 00192 } 00193 00194 function MetaTables() 00195 { 00196 if (!$this->connection->IsConnected()) return array(); 00197 return $this->connection->MetaTables(); 00198 } 00199 00200 function MetaColumns($tab, $upper=true, $schema=false) 00201 { 00202 if (!$this->connection->IsConnected()) return array(); 00203 return $this->connection->MetaColumns($this->TableName($tab), $upper, $schema); 00204 } 00205 00206 function MetaPrimaryKeys($tab,$owner=false,$intkey=false) 00207 { 00208 if (!$this->connection->IsConnected()) return array(); 00209 return $this->connection->MetaPrimaryKeys($this->TableName($tab), $owner, $intkey); 00210 } 00211 00212 function MetaIndexes($table, $primary = false, $owner = false) 00213 { 00214 if (!$this->connection->IsConnected()) return array(); 00215 return $this->connection->MetaIndexes($this->TableName($table), $primary, $owner); 00216 } 00217 00218 function MetaType($t,$len=-1,$fieldobj=false) 00219 { 00220 static $typeMap = array( 00221 'VARCHAR' => 'C', 00222 'VARCHAR2' => 'C', 00223 'CHAR' => 'C', 00224 'C' => 'C', 00225 'STRING' => 'C', 00226 'NCHAR' => 'C', 00227 'NVARCHAR' => 'C', 00228 'VARYING' => 'C', 00229 'BPCHAR' => 'C', 00230 'CHARACTER' => 'C', 00231 'INTERVAL' => 'C', # Postgres 00232 'MACADDR' => 'C', # postgres 00233 'VAR_STRING' => 'C', # mysql 00234 ## 00235 'LONGCHAR' => 'X', 00236 'TEXT' => 'X', 00237 'NTEXT' => 'X', 00238 'M' => 'X', 00239 'X' => 'X', 00240 'CLOB' => 'X', 00241 'NCLOB' => 'X', 00242 'LVARCHAR' => 'X', 00243 ## 00244 'BLOB' => 'B', 00245 'IMAGE' => 'B', 00246 'BINARY' => 'B', 00247 'VARBINARY' => 'B', 00248 'LONGBINARY' => 'B', 00249 'B' => 'B', 00250 ## 00251 'YEAR' => 'D', // mysql 00252 'DATE' => 'D', 00253 'D' => 'D', 00254 ## 00255 'UNIQUEIDENTIFIER' => 'C', # MS SQL Server 00256 ## 00257 'TIME' => 'T', 00258 'TIMESTAMP' => 'T', 00259 'DATETIME' => 'T', 00260 'TIMESTAMPTZ' => 'T', 00261 'SMALLDATETIME' => 'T', 00262 'T' => 'T', 00263 'TIMESTAMP WITHOUT TIME ZONE' => 'T', // postgresql 00264 ## 00265 'BOOL' => 'L', 00266 'BOOLEAN' => 'L', 00267 'BIT' => 'L', 00268 'L' => 'L', 00269 ## 00270 'COUNTER' => 'R', 00271 'R' => 'R', 00272 'SERIAL' => 'R', // ifx 00273 'INT IDENTITY' => 'R', 00274 ## 00275 'INT' => 'I', 00276 'INT2' => 'I', 00277 'INT4' => 'I', 00278 'INT8' => 'I', 00279 'INTEGER' => 'I', 00280 'INTEGER UNSIGNED' => 'I', 00281 'SHORT' => 'I', 00282 'TINYINT' => 'I', 00283 'SMALLINT' => 'I', 00284 'I' => 'I', 00285 ## 00286 'LONG' => 'N', // interbase is numeric, oci8 is blob 00287 'BIGINT' => 'N', // this is bigger than PHP 32-bit integers 00288 'DECIMAL' => 'N', 00289 'DEC' => 'N', 00290 'REAL' => 'N', 00291 'DOUBLE' => 'N', 00292 'DOUBLE PRECISION' => 'N', 00293 'SMALLFLOAT' => 'N', 00294 'FLOAT' => 'N', 00295 'NUMBER' => 'N', 00296 'NUM' => 'N', 00297 'NUMERIC' => 'N', 00298 'MONEY' => 'N', 00299 00300 ## informix 9.2 00301 'SQLINT' => 'I', 00302 'SQLSERIAL' => 'I', 00303 'SQLSMINT' => 'I', 00304 'SQLSMFLOAT' => 'N', 00305 'SQLFLOAT' => 'N', 00306 'SQLMONEY' => 'N', 00307 'SQLDECIMAL' => 'N', 00308 'SQLDATE' => 'D', 00309 'SQLVCHAR' => 'C', 00310 'SQLCHAR' => 'C', 00311 'SQLDTIME' => 'T', 00312 'SQLINTERVAL' => 'N', 00313 'SQLBYTES' => 'B', 00314 'SQLTEXT' => 'X', 00315 ## informix 10 00316 "SQLINT8" => 'I8', 00317 "SQLSERIAL8" => 'I8', 00318 "SQLNCHAR" => 'C', 00319 "SQLNVCHAR" => 'C', 00320 "SQLLVARCHAR" => 'X', 00321 "SQLBOOL" => 'L' 00322 ); 00323 00324 if (!$this->connection->IsConnected()) { 00325 $t = strtoupper($t); 00326 if (isset($typeMap[$t])) return $typeMap[$t]; 00327 return 'N'; 00328 } 00329 return $this->connection->MetaType($t,$len,$fieldobj); 00330 } 00331 00332 function NameQuote($name = NULL,$allowBrackets=false) 00333 { 00334 if (!is_string($name)) { 00335 return FALSE; 00336 } 00337 00338 $name = trim($name); 00339 00340 if ( !is_object($this->connection) ) { 00341 return $name; 00342 } 00343 00344 $quote = $this->connection->nameQuote; 00345 00346 // if name is of the form `name`, quote it 00347 if ( preg_match('/^`(.+)`$/', $name, $matches) ) { 00348 return $quote . $matches[1] . $quote; 00349 } 00350 00351 // if name contains special characters, quote it 00352 $regex = ($allowBrackets) ? $this->nameRegexBrackets : $this->nameRegex; 00353 00354 if ( !preg_match('/^[' . $regex . ']+$/', $name) ) { 00355 return $quote . $name . $quote; 00356 } 00357 00358 return $name; 00359 } 00360 00361 function TableName($name) 00362 { 00363 if ( $this->schema ) { 00364 return $this->NameQuote($this->schema) .'.'. $this->NameQuote($name); 00365 } 00366 return $this->NameQuote($name); 00367 } 00368 00369 // Executes the sql array returned by GetTableSQL and GetIndexSQL 00370 function ExecuteSQLArray($sql, $continueOnError = true) 00371 { 00372 $rez = 2; 00373 $conn = $this->connection; 00374 $saved = $conn->debug; 00375 foreach($sql as $line) { 00376 00377 if ($this->debug) $conn->debug = true; 00378 $ok = $conn->Execute($line); 00379 $conn->debug = $saved; 00380 if (!$ok) { 00381 if ($this->debug) ADOConnection::outp($conn->ErrorMsg()); 00382 if (!$continueOnError) return 0; 00383 $rez = 1; 00384 } 00385 } 00386 return $rez; 00387 } 00388 00407 function ActualType($meta) 00408 { 00409 return $meta; 00410 } 00411 00412 function CreateDatabase($dbname,$options=false) 00413 { 00414 $options = $this->_Options($options); 00415 $sql = array(); 00416 00417 $s = 'CREATE DATABASE ' . $this->NameQuote($dbname); 00418 if (isset($options[$this->upperName])) 00419 $s .= ' '.$options[$this->upperName]; 00420 00421 $sql[] = $s; 00422 return $sql; 00423 } 00424 00425 /* 00426 Generates the SQL to create index. Returns an array of sql strings. 00427 */ 00428 function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false) 00429 { 00430 if (!is_array($flds)) { 00431 $flds = explode(',',$flds); 00432 } 00433 00434 foreach($flds as $key => $fld) { 00435 # some indexes can use partial fields, eg. index first 32 chars of "name" with NAME(32) 00436 $flds[$key] = $this->NameQuote($fld,$allowBrackets=true); 00437 } 00438 00439 return $this->_IndexSQL($this->NameQuote($idxname), $this->TableName($tabname), $flds, $this->_Options($idxoptions)); 00440 } 00441 00442 function DropIndexSQL ($idxname, $tabname = NULL) 00443 { 00444 return array(sprintf($this->dropIndex, $this->NameQuote($idxname), $this->TableName($tabname))); 00445 } 00446 00447 function SetSchema($schema) 00448 { 00449 $this->schema = $schema; 00450 } 00451 00452 function AddColumnSQL($tabname, $flds) 00453 { 00454 $tabname = $this->TableName ($tabname); 00455 $sql = array(); 00456 list($lines,$pkey,$idxs) = $this->_GenFields($flds); 00457 // genfields can return FALSE at times 00458 if ($lines == null) $lines = array(); 00459 $alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' '; 00460 foreach($lines as $v) { 00461 $sql[] = $alter . $v; 00462 } 00463 if (is_array($idxs)) { 00464 foreach($idxs as $idx => $idxdef) { 00465 $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']); 00466 $sql = array_merge($sql, $sql_idxs); 00467 } 00468 } 00469 return $sql; 00470 } 00471 00483 function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') 00484 { 00485 $tabname = $this->TableName ($tabname); 00486 $sql = array(); 00487 list($lines,$pkey,$idxs) = $this->_GenFields($flds); 00488 // genfields can return FALSE at times 00489 if ($lines == null) $lines = array(); 00490 $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' '; 00491 foreach($lines as $v) { 00492 $sql[] = $alter . $v; 00493 } 00494 if (is_array($idxs)) { 00495 foreach($idxs as $idx => $idxdef) { 00496 $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']); 00497 $sql = array_merge($sql, $sql_idxs); 00498 } 00499 00500 } 00501 return $sql; 00502 } 00503 00514 function RenameColumnSQL($tabname,$oldcolumn,$newcolumn,$flds='') 00515 { 00516 $tabname = $this->TableName ($tabname); 00517 if ($flds) { 00518 list($lines,$pkey,$idxs) = $this->_GenFields($flds); 00519 // genfields can return FALSE at times 00520 if ($lines == null) $lines = array(); 00521 list(,$first) = each($lines); 00522 list(,$column_def) = preg_split("/[\t ]+/",$first,2); 00523 } 00524 return array(sprintf($this->renameColumn,$tabname,$this->NameQuote($oldcolumn),$this->NameQuote($newcolumn),$column_def)); 00525 } 00526 00538 function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='') 00539 { 00540 $tabname = $this->TableName ($tabname); 00541 if (!is_array($flds)) $flds = explode(',',$flds); 00542 $sql = array(); 00543 $alter = 'ALTER TABLE ' . $tabname . $this->dropCol . ' '; 00544 foreach($flds as $v) { 00545 $sql[] = $alter . $this->NameQuote($v); 00546 } 00547 return $sql; 00548 } 00549 00550 function DropTableSQL($tabname) 00551 { 00552 return array (sprintf($this->dropTable, $this->TableName($tabname))); 00553 } 00554 00555 function RenameTableSQL($tabname,$newname) 00556 { 00557 return array (sprintf($this->renameTable, $this->TableName($tabname),$this->TableName($newname))); 00558 } 00559 00563 function CreateTableSQL($tabname, $flds, $tableoptions=array()) 00564 { 00565 list($lines,$pkey,$idxs) = $this->_GenFields($flds, true); 00566 // genfields can return FALSE at times 00567 if ($lines == null) $lines = array(); 00568 00569 $taboptions = $this->_Options($tableoptions); 00570 $tabname = $this->TableName ($tabname); 00571 $sql = $this->_TableSQL($tabname,$lines,$pkey,$taboptions); 00572 00573 // ggiunta - 2006/10/12 - KLUDGE: 00574 // if we are on autoincrement, and table options includes REPLACE, the 00575 // autoincrement sequence has already been dropped on table creation sql, so 00576 // we avoid passing REPLACE to trigger creation code. This prevents 00577 // creating sql that double-drops the sequence 00578 if ($this->autoIncrement && isset($taboptions['REPLACE'])) 00579 unset($taboptions['REPLACE']); 00580 $tsql = $this->_Triggers($tabname,$taboptions); 00581 foreach($tsql as $s) $sql[] = $s; 00582 00583 if (is_array($idxs)) { 00584 foreach($idxs as $idx => $idxdef) { 00585 $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']); 00586 $sql = array_merge($sql, $sql_idxs); 00587 } 00588 } 00589 00590 return $sql; 00591 } 00592 00593 00594 00595 function _GenFields($flds,$widespacing=false) 00596 { 00597 if (is_string($flds)) { 00598 $padding = ' '; 00599 $txt = $flds.$padding; 00600 $flds = array(); 00601 $flds0 = Lens_ParseArgs($txt,','); 00602 $hasparam = false; 00603 foreach($flds0 as $f0) { 00604 $f1 = array(); 00605 foreach($f0 as $token) { 00606 switch (strtoupper($token)) { 00607 case 'INDEX': 00608 $f1['INDEX'] = ''; 00609 // fall through intentionally 00610 case 'CONSTRAINT': 00611 case 'DEFAULT': 00612 $hasparam = $token; 00613 break; 00614 default: 00615 if ($hasparam) $f1[$hasparam] = $token; 00616 else $f1[] = $token; 00617 $hasparam = false; 00618 break; 00619 } 00620 } 00621 // 'index' token without a name means single column index: name it after column 00622 if (array_key_exists('INDEX', $f1) && $f1['INDEX'] == '') { 00623 $f1['INDEX'] = isset($f0['NAME']) ? $f0['NAME'] : $f0[0]; 00624 // check if column name used to create an index name was quoted 00625 if (($f1['INDEX'][0] == '"' || $f1['INDEX'][0] == "'" || $f1['INDEX'][0] == "`") && 00626 ($f1['INDEX'][0] == substr($f1['INDEX'], -1))) { 00627 $f1['INDEX'] = $f1['INDEX'][0].'idx_'.substr($f1['INDEX'], 1, -1).$f1['INDEX'][0]; 00628 } 00629 else 00630 $f1['INDEX'] = 'idx_'.$f1['INDEX']; 00631 } 00632 // reset it, so we don't get next field 1st token as INDEX... 00633 $hasparam = false; 00634 00635 $flds[] = $f1; 00636 00637 } 00638 } 00639 $this->autoIncrement = false; 00640 $lines = array(); 00641 $pkey = array(); 00642 $idxs = array(); 00643 foreach($flds as $fld) { 00644 $fld = _array_change_key_case($fld); 00645 00646 $fname = false; 00647 $fdefault = false; 00648 $fautoinc = false; 00649 $ftype = false; 00650 $fsize = false; 00651 $fprec = false; 00652 $fprimary = false; 00653 $fnoquote = false; 00654 $fdefts = false; 00655 $fdefdate = false; 00656 $fconstraint = false; 00657 $fnotnull = false; 00658 $funsigned = false; 00659 $findex = ''; 00660 $funiqueindex = false; 00661 00662 //----------------- 00663 // Parse attributes 00664 foreach($fld as $attr => $v) { 00665 if ($attr == 2 && is_numeric($v)) $attr = 'SIZE'; 00666 else if (is_numeric($attr) && $attr > 1 && !is_numeric($v)) $attr = strtoupper($v); 00667 00668 switch($attr) { 00669 case '0': 00670 case 'NAME': $fname = $v; break; 00671 case '1': 00672 case 'TYPE': $ty = $v; $ftype = $this->ActualType(strtoupper($v)); break; 00673 00674 case 'SIZE': 00675 $dotat = strpos($v,'.'); if ($dotat === false) $dotat = strpos($v,','); 00676 if ($dotat === false) $fsize = $v; 00677 else { 00678 $fsize = substr($v,0,$dotat); 00679 $fprec = substr($v,$dotat+1); 00680 } 00681 break; 00682 case 'UNSIGNED': $funsigned = true; break; 00683 case 'AUTOINCREMENT': 00684 case 'AUTO': $fautoinc = true; $fnotnull = true; break; 00685 case 'KEY': 00686 // a primary key col can be non unique in itself (if key spans many cols...) 00687 case 'PRIMARY': $fprimary = $v; $fnotnull = true; /*$funiqueindex = true;*/ break; 00688 case 'DEF': 00689 case 'DEFAULT': $fdefault = $v; break; 00690 case 'NOTNULL': $fnotnull = $v; break; 00691 case 'NOQUOTE': $fnoquote = $v; break; 00692 case 'DEFDATE': $fdefdate = $v; break; 00693 case 'DEFTIMESTAMP': $fdefts = $v; break; 00694 case 'CONSTRAINT': $fconstraint = $v; break; 00695 // let INDEX keyword create a 'very standard' index on column 00696 case 'INDEX': $findex = $v; break; 00697 case 'UNIQUE': $funiqueindex = true; break; 00698 } //switch 00699 } // foreach $fld 00700 00701 //-------------------- 00702 // VALIDATE FIELD INFO 00703 if (!strlen($fname)) { 00704 if ($this->debug) ADOConnection::outp("Undefined NAME"); 00705 return false; 00706 } 00707 00708 $fid = strtoupper(preg_replace('/^`(.+)`$/', '$1', $fname)); 00709 $fname = $this->NameQuote($fname); 00710 00711 if (!strlen($ftype)) { 00712 if ($this->debug) ADOConnection::outp("Undefined TYPE for field '$fname'"); 00713 return false; 00714 } else { 00715 $ftype = strtoupper($ftype); 00716 } 00717 00718 $ftype = $this->_GetSize($ftype, $ty, $fsize, $fprec); 00719 00720 if ($ty == 'X' || $ty == 'X2' || $ty == 'B') $fnotnull = false; // some blob types do not accept nulls 00721 00722 if ($fprimary) $pkey[] = $fname; 00723 00724 // some databases do not allow blobs to have defaults 00725 if ($ty == 'X') $fdefault = false; 00726 00727 // build list of indexes 00728 if ($findex != '') { 00729 if (array_key_exists($findex, $idxs)) { 00730 $idxs[$findex]['cols'][] = ($fname); 00731 if (in_array('UNIQUE', $idxs[$findex]['opts']) != $funiqueindex) { 00732 if ($this->debug) ADOConnection::outp("Index $findex defined once UNIQUE and once not"); 00733 } 00734 if ($funiqueindex && !in_array('UNIQUE', $idxs[$findex]['opts'])) 00735 $idxs[$findex]['opts'][] = 'UNIQUE'; 00736 } 00737 else 00738 { 00739 $idxs[$findex] = array(); 00740 $idxs[$findex]['cols'] = array($fname); 00741 if ($funiqueindex) 00742 $idxs[$findex]['opts'] = array('UNIQUE'); 00743 else 00744 $idxs[$findex]['opts'] = array(); 00745 } 00746 } 00747 00748 //-------------------- 00749 // CONSTRUCT FIELD SQL 00750 if ($fdefts) { 00751 if (substr($this->connection->databaseType,0,5) == 'mysql') { 00752 $ftype = 'TIMESTAMP'; 00753 } else { 00754 $fdefault = $this->connection->sysTimeStamp; 00755 } 00756 } else if ($fdefdate) { 00757 if (substr($this->connection->databaseType,0,5) == 'mysql') { 00758 $ftype = 'TIMESTAMP'; 00759 } else { 00760 $fdefault = $this->connection->sysDate; 00761 } 00762 } else if ($fdefault !== false && !$fnoquote) { 00763 if ($ty == 'C' or $ty == 'X' or 00764 ( substr($fdefault,0,1) != "'" && !is_numeric($fdefault))) { 00765 00766 if (($ty == 'D' || $ty == 'T') && strtolower($fdefault) != 'null') { 00767 // convert default date into database-aware code 00768 if ($ty == 'T') 00769 { 00770 $fdefault = $this->connection->DBTimeStamp($fdefault); 00771 } 00772 else 00773 { 00774 $fdefault = $this->connection->DBDate($fdefault); 00775 } 00776 } 00777 else 00778 if (strlen($fdefault) != 1 && substr($fdefault,0,1) == ' ' && substr($fdefault,strlen($fdefault)-1) == ' ') 00779 $fdefault = trim($fdefault); 00780 else if (strtolower($fdefault) != 'null') 00781 $fdefault = $this->connection->qstr($fdefault); 00782 } 00783 } 00784 $suffix = $this->_CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned); 00785 00786 // add index creation 00787 if ($widespacing) $fname = str_pad($fname,24); 00788 00789 // check for field names appearing twice 00790 if (array_key_exists($fid, $lines)) { 00791 ADOConnection::outp("Field '$fname' defined twice"); 00792 } 00793 00794 $lines[$fid] = $fname.' '.$ftype.$suffix; 00795 00796 if ($fautoinc) $this->autoIncrement = true; 00797 } // foreach $flds 00798 00799 return array($lines,$pkey,$idxs); 00800 } 00801 00807 function _GetSize($ftype, $ty, $fsize, $fprec) 00808 { 00809 if (strlen($fsize) && $ty != 'X' && $ty != 'B' && strpos($ftype,'(') === false) { 00810 $ftype .= "(".$fsize; 00811 if (strlen($fprec)) $ftype .= ",".$fprec; 00812 $ftype .= ')'; 00813 } 00814 return $ftype; 00815 } 00816 00817 00818 // return string must begin with space 00819 function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned) 00820 { 00821 $suffix = ''; 00822 if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault"; 00823 if ($fnotnull) $suffix .= ' NOT NULL'; 00824 if ($fconstraint) $suffix .= ' '.$fconstraint; 00825 return $suffix; 00826 } 00827 00828 function _IndexSQL($idxname, $tabname, $flds, $idxoptions) 00829 { 00830 $sql = array(); 00831 00832 if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) { 00833 $sql[] = sprintf ($this->dropIndex, $idxname); 00834 if ( isset($idxoptions['DROP']) ) 00835 return $sql; 00836 } 00837 00838 if ( empty ($flds) ) { 00839 return $sql; 00840 } 00841 00842 $unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : ''; 00843 00844 $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' '; 00845 00846 if ( isset($idxoptions[$this->upperName]) ) 00847 $s .= $idxoptions[$this->upperName]; 00848 00849 if ( is_array($flds) ) 00850 $flds = implode(', ',$flds); 00851 $s .= '(' . $flds . ')'; 00852 $sql[] = $s; 00853 00854 return $sql; 00855 } 00856 00857 function _DropAutoIncrement($tabname) 00858 { 00859 return false; 00860 } 00861 00862 function _TableSQL($tabname,$lines,$pkey,$tableoptions) 00863 { 00864 $sql = array(); 00865 00866 if (isset($tableoptions['REPLACE']) || isset ($tableoptions['DROP'])) { 00867 $sql[] = sprintf($this->dropTable,$tabname); 00868 if ($this->autoIncrement) { 00869 $sInc = $this->_DropAutoIncrement($tabname); 00870 if ($sInc) $sql[] = $sInc; 00871 } 00872 if ( isset ($tableoptions['DROP']) ) { 00873 return $sql; 00874 } 00875 } 00876 $s = "CREATE TABLE $tabname (\n"; 00877 $s .= implode(",\n", $lines); 00878 if (sizeof($pkey)>0) { 00879 $s .= ",\n PRIMARY KEY ("; 00880 $s .= implode(", ",$pkey).")"; 00881 } 00882 if (isset($tableoptions['CONSTRAINTS'])) 00883 $s .= "\n".$tableoptions['CONSTRAINTS']; 00884 00885 if (isset($tableoptions[$this->upperName.'_CONSTRAINTS'])) 00886 $s .= "\n".$tableoptions[$this->upperName.'_CONSTRAINTS']; 00887 00888 $s .= "\n)"; 00889 if (isset($tableoptions[$this->upperName])) $s .= $tableoptions[$this->upperName]; 00890 $sql[] = $s; 00891 00892 return $sql; 00893 } 00894 00899 function _Triggers($tabname,$taboptions) 00900 { 00901 return array(); 00902 } 00903 00907 function _Options($opts) 00908 { 00909 if (!is_array($opts)) return array(); 00910 $newopts = array(); 00911 foreach($opts as $k => $v) { 00912 if (is_numeric($k)) $newopts[strtoupper($v)] = $v; 00913 else $newopts[strtoupper($k)] = $v; 00914 } 00915 return $newopts; 00916 } 00917 00918 00919 function _getSizePrec($size) 00920 { 00921 $fsize = false; 00922 $fprec = false; 00923 $dotat = strpos($size,'.'); 00924 if ($dotat === false) $dotat = strpos($size,','); 00925 if ($dotat === false) $fsize = $size; 00926 else { 00927 $fsize = substr($size,0,$dotat); 00928 $fprec = substr($size,$dotat+1); 00929 } 00930 return array($fsize, $fprec); 00931 } 00932 00939 function ChangeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=false) 00940 { 00941 global $ADODB_FETCH_MODE; 00942 00943 $save = $ADODB_FETCH_MODE; 00944 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; 00945 if ($this->connection->fetchMode !== false) $savem = $this->connection->SetFetchMode(false); 00946 00947 // check table exists 00948 $save_handler = $this->connection->raiseErrorFn; 00949 $this->connection->raiseErrorFn = ''; 00950 $cols = $this->MetaColumns($tablename); 00951 $this->connection->raiseErrorFn = $save_handler; 00952 00953 if (isset($savem)) $this->connection->SetFetchMode($savem); 00954 $ADODB_FETCH_MODE = $save; 00955 00956 if ( empty($cols)) { 00957 return $this->CreateTableSQL($tablename, $flds, $tableoptions); 00958 } 00959 00960 if (is_array($flds)) { 00961 // Cycle through the update fields, comparing 00962 // existing fields to fields to update. 00963 // if the Metatype and size is exactly the 00964 // same, ignore - by Mark Newham 00965 $holdflds = array(); 00966 foreach($flds as $k=>$v) { 00967 if ( isset($cols[$k]) && is_object($cols[$k]) ) { 00968 // If already not allowing nulls, then don't change 00969 $obj = $cols[$k]; 00970 if (isset($obj->not_null) && $obj->not_null) 00971 $v = str_replace('NOT NULL','',$v); 00972 if (isset($obj->auto_increment) && $obj->auto_increment && empty($v['AUTOINCREMENT'])) 00973 $v = str_replace('AUTOINCREMENT','',$v); 00974 00975 $c = $cols[$k]; 00976 $ml = $c->max_length; 00977 $mt = $this->MetaType($c->type,$ml); 00978 00979 if (isset($c->scale)) $sc = $c->scale; 00980 else $sc = 99; // always force change if scale not known. 00981 00982 if ($sc == -1) $sc = false; 00983 list($fsize, $fprec) = $this->_getSizePrec($v['SIZE']); 00984 00985 if ($ml == -1) $ml = ''; 00986 if ($mt == 'X') $ml = $v['SIZE']; 00987 if (($mt != $v['TYPE']) || ($ml != $fsize || $sc != $fprec) || (isset($v['AUTOINCREMENT']) && $v['AUTOINCREMENT'] != $obj->auto_increment)) { 00988 $holdflds[$k] = $v; 00989 } 00990 } else { 00991 $holdflds[$k] = $v; 00992 } 00993 } 00994 $flds = $holdflds; 00995 } 00996 00997 00998 // already exists, alter table instead 00999 list($lines,$pkey,$idxs) = $this->_GenFields($flds); 01000 // genfields can return FALSE at times 01001 if ($lines == null) $lines = array(); 01002 $alter = 'ALTER TABLE ' . $this->TableName($tablename); 01003 $sql = array(); 01004 01005 foreach ( $lines as $id => $v ) { 01006 if ( isset($cols[$id]) && is_object($cols[$id]) ) { 01007 01008 $flds = Lens_ParseArgs($v,','); 01009 01010 // We are trying to change the size of the field, if not allowed, simply ignore the request. 01011 // $flds[1] holds the type, $flds[2] holds the size -postnuke addition 01012 if ($flds && in_array(strtoupper(substr($flds[0][1],0,4)),$this->invalidResizeTypes4) 01013 && (isset($flds[0][2]) && is_numeric($flds[0][2]))) { 01014 if ($this->debug) ADOConnection::outp(sprintf("<h3>%s cannot be changed to %s currently</h3>", $flds[0][0], $flds[0][1])); 01015 #echo "<h3>$this->alterCol cannot be changed to $flds currently</h3>"; 01016 continue; 01017 } 01018 $sql[] = $alter . $this->alterCol . ' ' . $v; 01019 } else { 01020 $sql[] = $alter . $this->addCol . ' ' . $v; 01021 } 01022 } 01023 01024 if ($dropOldFlds) { 01025 foreach ( $cols as $id => $v ) 01026 if ( !isset($lines[$id]) ) 01027 $sql[] = $alter . $this->dropCol . ' ' . $v->name; 01028 } 01029 return $sql; 01030 } 01031 } // class 01032 ?>