21 if (!defined(
'ADODB_DIR'))
die();
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";
34 if (!function_exists(
'ctype_alnum')) {
35 function ctype_alnum($text) {
36 return preg_match(
'/^[a-z0-9]*$/i', $text);
61 $tokens[$stmtno] = array();
67 $ch = substr($args,$pos,1);
76 $tokens[$stmtno][] = implode(
'',$tokarr);
85 if ($intoken) $tokarr[] = $ch;
92 if (empty($endquote)) {
93 $tokens[$stmtno][] = implode(
'',$tokarr);
94 if ($ch ==
'(') $endquote =
')';
99 }
else if ($endquote == $ch) {
100 $ch2 = substr($args,$pos+1,1);
101 if ($ch2 == $endquote) {
107 $tokens[$stmtno][] = implode(
'',$tokarr);
115 if ($ch ==
'(') $endquote =
')';
116 else $endquote = $ch;
120 if ($ch ==
'`') $tokarr[] =
'`';
127 if ($ch == $endstmtchar) {
129 $tokens[$stmtno] = array();
140 if ($quoted) $tokarr[] = $ch;
141 else if (ctype_alnum($ch) || strpos($tokenchars,$ch) !==
false) $tokarr[] = $ch;
143 if ($ch == $endstmtchar) {
144 $tokens[$stmtno][] = implode(
'',$tokarr);
146 $tokens[$stmtno] = array();
151 $tokens[$stmtno][] = implode(
'',$tokarr);
152 $tokens[$stmtno][] = $ch;
158 if ($intoken) $tokens[$stmtno][] = implode(
'',$tokarr);
196 if (!$this->connection->IsConnected())
return array();
197 return $this->connection->MetaTables();
202 if (!$this->connection->IsConnected())
return array();
203 return $this->connection->MetaColumns($this->
TableName($tab), $upper, $schema);
208 if (!$this->connection->IsConnected())
return array();
209 return $this->connection->MetaPrimaryKeys($this->
TableName($tab), $owner, $intkey);
214 if (!$this->connection->IsConnected())
return array();
215 return $this->connection->MetaIndexes($this->
TableName($table), $primary, $owner);
220 static $typeMap = array(
231 'INTERVAL' =>
'C', # Postgres
232 'MACADDR' =>
'C', # postgres
233 'VAR_STRING' =>
'C', # mysql
255 'UNIQUEIDENTIFIER' =>
'C', # MS SQL Server
260 'TIMESTAMPTZ' =>
'T',
261 'SMALLDATETIME' =>
'T',
263 'TIMESTAMP WITHOUT TIME ZONE' =>
'T',
273 'INT IDENTITY' =>
'R',
280 'INTEGER UNSIGNED' =>
'I',
292 'DOUBLE PRECISION' =>
'N',
312 'SQLINTERVAL' =>
'N',
317 "SQLSERIAL8" =>
'I8',
320 "SQLLVARCHAR" =>
'X',
324 if (!$this->connection->IsConnected()) {
326 if (isset($typeMap[$t]))
return $typeMap[$t];
329 return $this->connection->MetaType($t,$len,$fieldobj);
334 if (!is_string($name)) {
340 if ( !is_object($this->connection) ) {
344 $quote = $this->connection->nameQuote;
347 if ( preg_match(
'/^`(.+)`$/', $name, $matches) ) {
348 return $quote . $matches[1] . $quote;
352 $regex = ($allowBrackets) ? $this->nameRegexBrackets : $this->nameRegex;
354 if ( !preg_match(
'/^[' . $regex .
']+$/', $name) ) {
355 return $quote . $name . $quote;
363 if ( $this->schema ) {
374 $saved =
$conn->debug;
375 foreach(
$sql as $line) {
378 $ok =
$conn->Execute($line);
379 $conn->debug = $saved;
381 if ($this->
debug) ADOConnection::outp(
$conn->ErrorMsg());
382 if (!$continueOnError)
return 0;
414 $options = $this->
_Options($options);
417 $s =
'CREATE DATABASE ' . $this->
NameQuote($dbname);
418 if (isset($options[$this->upperName]))
419 $s .=
' '.$options[$this->upperName];
430 if (!is_array($flds)) {
431 $flds = explode(
',',$flds);
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);
444 return array(sprintf($this->dropIndex, $this->
NameQuote($idxname), $this->
TableName($tabname)));
456 list($lines,$pkey,$idxs) = $this->
_GenFields($flds);
458 if ($lines == null) $lines = array();
459 $alter =
'ALTER TABLE ' . $tabname . $this->addCol .
' ';
460 foreach($lines as $v) {
461 $sql[] = $alter . $v;
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);
487 list($lines,$pkey,$idxs) = $this->
_GenFields($flds);
489 if ($lines == null) $lines = array();
490 $alter =
'ALTER TABLE ' . $tabname . $this->alterCol .
' ';
491 foreach($lines as $v) {
492 $sql[] = $alter . $v;
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);
518 list($lines,$pkey,$idxs) = $this->
_GenFields($flds);
520 if ($lines == null) $lines = array();
521 list(,$first) = each($lines);
522 list(,$column_def) = preg_split(
"/[\t ]+/",$first,2);
524 return array(sprintf($this->renameColumn,$tabname,$this->
NameQuote($oldcolumn),$this->
NameQuote($newcolumn),$column_def));
541 if (!is_array($flds)) $flds = explode(
',',$flds);
543 $alter =
'ALTER TABLE ' . $tabname . $this->dropCol .
' ';
544 foreach($flds as $v) {
552 return array (sprintf($this->dropTable, $this->
TableName($tabname)));
557 return array (sprintf($this->renameTable, $this->
TableName($tabname),$this->
TableName($newname)));
565 list($lines,$pkey,$idxs) = $this->
_GenFields($flds,
true);
567 if ($lines == null) $lines = array();
569 $taboptions = $this->
_Options($tableoptions);
578 if ($this->autoIncrement && isset($taboptions[
'REPLACE']))
579 unset($taboptions[
'REPLACE']);
580 $tsql = $this->
_Triggers($tabname,$taboptions);
581 foreach($tsql as $s)
$sql[] = $s;
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);
597 if (is_string($flds)) {
599 $txt = $flds.$padding;
603 foreach($flds0 as $f0) {
605 foreach($f0 as $token) {
606 switch (strtoupper($token)) {
615 if ($hasparam) $f1[$hasparam] = $token;
622 if (array_key_exists(
'INDEX', $f1) && $f1[
'INDEX'] ==
'') {
623 $f1[
'INDEX'] = isset($f0[
'NAME']) ? $f0[
'NAME'] : $f0[0];
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];
630 $f1[
'INDEX'] =
'idx_'.$f1[
'INDEX'];
639 $this->autoIncrement =
false;
643 foreach($flds as $fld) {
656 $fconstraint =
false;
660 $funiqueindex =
false;
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);
670 case 'NAME': $fname = $v;
break;
672 case 'TYPE': $ty = $v; $ftype = $this->
ActualType(strtoupper($v));
break;
675 $dotat = strpos($v,
'.');
if ($dotat ===
false) $dotat = strpos($v,
',');
676 if ($dotat ===
false) $fsize = $v;
678 $fsize = substr($v,0,$dotat);
679 $fprec = substr($v,$dotat+1);
682 case 'UNSIGNED': $funsigned =
true;
break;
683 case 'AUTOINCREMENT':
684 case 'AUTO': $fautoinc =
true; $fnotnull =
true;
break;
687 case 'PRIMARY': $fprimary = $v; $fnotnull =
true;
break;
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;
696 case 'INDEX': $findex = $v;
break;
697 case 'UNIQUE': $funiqueindex =
true;
break;
703 if (!strlen($fname)) {
704 if ($this->
debug) ADOConnection::outp(
"Undefined NAME");
708 $fid = strtoupper(preg_replace(
'/^`(.+)`$/',
'$1', $fname));
711 if (!strlen($ftype)) {
712 if ($this->
debug) ADOConnection::outp(
"Undefined TYPE for field '$fname'");
715 $ftype = strtoupper($ftype);
718 $ftype = $this->
_GetSize($ftype, $ty, $fsize, $fprec);
720 if ($ty ==
'X' || $ty ==
'X2' || $ty ==
'B') $fnotnull =
false;
722 if ($fprimary) $pkey[] = $fname;
725 if ($ty ==
'X') $fdefault =
false;
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");
734 if ($funiqueindex && !in_array(
'UNIQUE', $idxs[$findex][
'opts']))
735 $idxs[$findex][
'opts'][] =
'UNIQUE';
739 $idxs[$findex] = array();
740 $idxs[$findex][
'cols'] = array($fname);
742 $idxs[$findex][
'opts'] = array(
'UNIQUE');
744 $idxs[$findex][
'opts'] = array();
751 if (substr($this->connection->databaseType,0,5) ==
'mysql') {
752 $ftype =
'TIMESTAMP';
754 $fdefault = $this->connection->sysTimeStamp;
756 }
else if ($fdefdate) {
757 if (substr($this->connection->databaseType,0,5) ==
'mysql') {
758 $ftype =
'TIMESTAMP';
760 $fdefault = $this->connection->sysDate;
762 }
else if ($fdefault !==
false && !$fnoquote) {
763 if ($ty ==
'C' or $ty ==
'X' or
764 ( substr($fdefault,0,1) !=
"'" && !is_numeric($fdefault))) {
766 if (($ty ==
'D' || $ty ==
'T') && strtolower($fdefault) !=
'null') {
770 $fdefault = $this->connection->DBTimeStamp($fdefault);
774 $fdefault = $this->connection->DBDate($fdefault);
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);
784 $suffix = $this->
_CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned);
787 if ($widespacing) $fname = str_pad($fname,24);
790 if (array_key_exists($fid, $lines)) {
791 ADOConnection::outp(
"Field '$fname' defined twice");
794 $lines[$fid] = $fname.
' '.$ftype.$suffix;
796 if ($fautoinc) $this->autoIncrement =
true;
799 return array($lines,$pkey,$idxs);
809 if (strlen($fsize) && $ty !=
'X' && $ty !=
'B' && strpos($ftype,
'(') ===
false) {
810 $ftype .=
"(".$fsize;
811 if (strlen($fprec)) $ftype .=
",".$fprec;
819 function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
822 if (strlen($fdefault)) $suffix .=
" DEFAULT $fdefault";
823 if ($fnotnull) $suffix .=
' NOT NULL';
824 if ($fconstraint) $suffix .=
' '.$fconstraint;
828 function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
832 if ( isset($idxoptions[
'REPLACE']) || isset($idxoptions[
'DROP']) ) {
833 $sql[] = sprintf ($this->dropIndex, $idxname);
834 if ( isset($idxoptions[
'DROP']) )
838 if ( empty ($flds) ) {
842 $unique = isset($idxoptions[
'UNIQUE']) ?
' UNIQUE' :
'';
844 $s =
'CREATE' . $unique .
' INDEX ' . $idxname .
' ON ' . $tabname .
' ';
846 if ( isset($idxoptions[$this->upperName]) )
847 $s .= $idxoptions[$this->upperName];
849 if ( is_array($flds) )
850 $flds = implode(
', ',$flds);
851 $s .=
'(' . $flds .
')';
866 if (isset($tableoptions[
'REPLACE']) || isset ($tableoptions[
'DROP'])) {
867 $sql[] = sprintf($this->dropTable,$tabname);
868 if ($this->autoIncrement) {
870 if ($sInc)
$sql[] = $sInc;
872 if ( isset ($tableoptions[
'DROP']) ) {
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).
")";
882 if (isset($tableoptions[
'CONSTRAINTS']))
883 $s .=
"\n".$tableoptions[
'CONSTRAINTS'];
885 if (isset($tableoptions[$this->upperName.
'_CONSTRAINTS']))
886 $s .=
"\n".$tableoptions[$this->upperName.
'_CONSTRAINTS'];
889 if (isset($tableoptions[$this->upperName])) $s .= $tableoptions[$this->upperName];
909 if (!is_array($opts))
return array();
911 foreach($opts as $k => $v) {
912 if (is_numeric($k)) $newopts[strtoupper($v)] = $v;
913 else $newopts[strtoupper($k)] = $v;
923 $dotat = strpos($size,
'.');
924 if ($dotat ===
false) $dotat = strpos($size,
',');
925 if ($dotat ===
false) $fsize = $size;
927 $fsize = substr($size,0,$dotat);
928 $fprec = substr($size,$dotat+1);
930 return array($fsize, $fprec);
939 function ChangeTableSQL($tablename, $flds, $tableoptions =
false, $dropOldFlds=
false)
941 global $ADODB_FETCH_MODE;
943 $save = $ADODB_FETCH_MODE;
944 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
945 if ($this->connection->fetchMode !==
false) $savem = $this->connection->SetFetchMode(
false);
948 $save_handler = $this->connection->raiseErrorFn;
949 $this->connection->raiseErrorFn =
'';
951 $this->connection->raiseErrorFn = $save_handler;
953 if (isset($savem)) $this->connection->SetFetchMode($savem);
954 $ADODB_FETCH_MODE = $save;
960 if (is_array($flds)) {
966 foreach($flds as $k=>$v) {
967 if ( isset($cols[$k]) && is_object($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);
976 $ml = $c->max_length;
977 $mt = $this->
MetaType($c->type,$ml);
979 if (isset($c->scale)) $sc = $c->scale;
982 if ($sc == -1) $sc =
false;
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)) {
999 list($lines,$pkey,$idxs) = $this->
_GenFields($flds);
1001 if ($lines == null) $lines = array();
1002 $alter =
'ALTER TABLE ' . $this->
TableName($tablename);
1005 foreach ( $lines as $id => $v ) {
1006 if ( isset($cols[$id]) && is_object($cols[$id]) ) {
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>"; 1018 $sql[] = $alter . $this->alterCol .
' ' . $v;
1020 $sql[] = $alter . $this->addCol .
' ' . $v;
1025 foreach ( $cols as $id => $v )
1026 if ( !isset($lines[$id]) )
1027 $sql[] = $alter . $this->dropCol .
' ' . $v->name;
_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)
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)
_DropAutoIncrement($tabname)
_array_change_key_case($an_array)
CreateDatabase($dbname, $options=false)
MetaType($t, $len=-1, $fieldobj=false)
_Triggers($tabname, $taboptions)
CreateTableSQL($tabname, $flds, $tableoptions=array())
RenameColumnSQL($tabname, $oldcolumn, $newcolumn, $flds='')
_IndexSQL($idxname, $tabname, $flds, $idxoptions)
_GetSize($ftype, $ty, $fsize, $fprec)
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel=E_DEBUG)
RenameTableSQL($tabname, $newname)
GetCommentSQL($table, $col)
MetaPrimaryKeys($tab, $owner=false, $intkey=false)
NameQuote($name=NULL, $allowBrackets=false)
ExecuteSQLArray($sql, $continueOnError=true)