<?php /*~ simpleddlparser.inc.php
.---------------------------------------------------------------------------.
|  Software: MySQL Database Upgrade Library based on A Simple DML Parser    |
|   Version: 0.1                                                            |
|   Contact: via http://www.uniwits.com/contact                             |
|      Info: http://www.uniwits.com/                                        |
|   Support: http://www.uniwits.com/support                                 |
| ------------------------------------------------------------------------- |
|     Admin: Yuxiang Mao (project admininistrator)                          |
|   Authors: Yuxiang Mao (Uniwits) contact@uniwits.com                      |
|   Founder: Yuxiang Mao                                                    |
| Copyright (c) 2010-2012, Yuxiang Mao. All Rights Reserved.                |
| ------------------------------------------------------------------------- |
|   License: Distributed under Uniwits Shareware License (USL)              |
|            http://www.uniwits.com/licenses/shareware/                     |
| This program is distributed as a part of software provided by Uniwits     |
| System WITHOUT ANY WARRANTY; without even the implied warranty of         |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                      |
| ------------------------------------------------------------------------- |
*/ function parse_db_DML($sqltext) { $alltokens=tokenize_sql($sqltext); $nsidxs=filter_nonspace_token_idxs($alltokens); for ($nstokens_pre=array(),$ni=0;$ni<sizeof($nsidxs);$ni++) $nstokens_pre[]=&$alltokens[$nsidxs[$ni]]; fix_tokenlist($nstokens_pre); $nsidxs=filter_nonspace_token_idxs($alltokens); for ($nstokens=array(),$ni=0;$ni<sizeof($nsidxs);$ni++) $nstokens[]=&$alltokens[$nsidxs[$ni]]; $statements=turn_into_all_statements($nstokens); $dbstructure=parse_table_structure($nstokens,$statements); return array( 'alltokens'=>$alltokens, 'nstokens'=>$nstokens, 'nsidxs'=>$nsidxs, 'dbstructure'=>$dbstructure, 'statements'=>$statements ); } function tablestructure_to_fieldmap($tablestructure,$tokens) { $fieldmap=array(); $keymap=array(); foreach ($tablestructure['fields'] as $field) { if (compare_tokenlist($tokens,array('KEY'),0,$field)==0) $keymap[$tokens[$field[1]]['content']]=$field; else if (compare_tokenlist($tokens,array('PRIMARY','KEY'),0,$field)==0) $keymap[null]=$field; else if (compare_tokenlist($tokens,array('UNIQUE','KEY'),0,$field)==0) $keymap[$tokens[$field[2]]['content']]=$field; else if (compare_tokenlist($tokens,array('FULLTEXT','KEY'),0,$field)==0) $keymap[$tokens[$field[2]]['content']]=$field; else $fieldmap[$tokens[$field[0]]['content']]=$field; } return array('fieldmap'=>$fieldmap,'keymap'=>$keymap); } function generate_fix_table_sql($tokens_new,$tokens_old,$table_name,$table_new,$table_old,$delete_table=false) { if (!$table_old) return array(statements_as_string($tokens_new,array($table_new['createstatement']),null,' ','')); if (!$table_new) if ($delete_table) return array('DROP TABLE IF EXISTS '.$table_name); else return array(); $structmap_new=tablestructure_to_fieldmap($table_new,$tokens_new); $structmap_old=tablestructure_to_fieldmap($table_old,$tokens_old); $sqls=array(); $fieldnames=array_merge(array_keys($structmap_new['fieldmap']+$structmap_old['fieldmap'])); $fieldname_prev_new=false; foreach ($fieldnames as $fieldname) { $field_new=$structmap_new['fieldmap'][$fieldname]; $field_old=$structmap_old['fieldmap'][$fieldname]; if (!$field_new) { array_push($sqls,'ALTER TABLE '.$table_name.' DROP '.$fieldname); } else if (!$field_old) { array_push( $sqls, 'ALTER TABLE '.$table_name.' ADD ' .statements_as_string($tokens_new,array($field_new),null,' ','') .' ' .($fieldname_prev_new?'AFTER '.$fieldname_prev_new:'FIRST') ); } else if (compare_tokenlist(array_select_by_key($tokens_new,$field_new),array_select_by_key($tokens_old,$field_old))!=0) { array_push( $sqls, 'ALTER TABLE '.$table_name.' MODIFY ' .statements_as_string($tokens_new,array($field_new),null,' ','') .' ' .($fieldname_prev_new?'AFTER '.$fieldname_prev_new:'FIRST') ); } $fieldname_prev_new=$fieldname; } $keynames=array_merge(array_keys($structmap_new['keymap']+$structmap_old['keymap'])); foreach ($keynames as $keyname) { $key_new=$structmap_new['keymap'][$keyname]; $key_old=$structmap_old['keymap'][$keyname]; if (!$key_new) { array_push($sqls,'ALTER TABLE '.$table_name.' DROP KEY '.$keyname); } else if (!$key_old) { array_push($sqls,'ALTER TABLE '.$table_name.' ADD '.statements_as_string($tokens_new,array($key_new),null,' ','')); } else if (compare_tokenlist(array_select_by_key($tokens_new,$key_new),array_select_by_key($tokens_old,$key_old))!=0) { array_push($sqls,'ALTER TABLE '.$table_name.' DROP KEY '.$keyname); array_push($sqls,'ALTER TABLE '.$table_name.' ADD '.statements_as_string($tokens_new,array($key_new),null,' ','')); } } if ($table_new['properties']) { $sql=''; foreach ($table_new['properties'] as $prop=>$value) { if (strcasecmp($prop,'AUTO_INCREMENT')==0) continue; if ($value!=$table_old['properties'][$prop]) { if ($sql) $sql.=' '; $sql.=$prop.($value===null?'':'='.$value); } } if ($sql) { $sql='ALTER TABLE '.$table_name.' '.$sql; array_push($sqls,$sql); } } return $sqls; } function generate_fix_db_sql($parseresult_new,$parseresult_old,$delete_tables=false) { $tableview_names=array_keys($parseresult_new['dbstructure']+$parseresult_old['dbstructure']); $dml_fixtables=array(); $dml_dropviews=array(); $dml_createviews=array(); $dml_dropfunctions=array(); $dml_createfunctions=array(); $dml_dropprocedures=array(); $dml_createprocedures=array(); foreach ($tableview_names as $name) { $tablestructure_new=$parseresult_new['dbstructure'][$name]; $tablestructure_old=$parseresult_old['dbstructure'][$name]; if ($tablestructure_new['type']=='TABLE' || $tablestructure_old['type']=='TABLE') { $sqls=generate_fix_table_sql($parseresult_new['nstokens'],$parseresult_old['nstokens'],$name,$tablestructure_new,$tablestructure_old,$delete_tables); if ($sqls) $dml_fixtables=array_merge($dml_fixtables,$sqls); } else if ($tablestructure_new['type']=='VIEW' || $tablestructure_old['type']=='VIEW') { $dml_dropviews[$name]='DROP VIEW IF EXISTS '.$name; if ($tablestructure_new) { $sql=statements_as_string($parseresult_new['nstokens'],array($tablestructure_new['createstatement']),null,' ',''); if (strncasecmp($sql,'CREATE OR REPLACE ',18)!=0) $sql='CREATE OR REPLACE'.substr($sql,6); $dml_createviews[$name]=$sql; } } else if (in_array('PROCEDURE',array($tablestructure_new['type'],$tablestructure_old['type']))) { $dml_dropprocedures[$name]='DROP PROCEDURE IF EXISTS '.$name; if ($tablestructure_new) { $sql=statements_as_string($parseresult_new['nstokens'],array($tablestructure_new['createstatement']),null,' ',''); $dml_createprocedures[$name]=$sql; } } else if (in_array('FUNCTION',array($tablestructure_new['type'],$tablestructure_old['type']))) { $dml_dropfunctions[$name]='DROP FUNCTION IF EXISTS '.$name; if ($tablestructure_new) { $sql=statements_as_string($parseresult_new['nstokens'],array($tablestructure_new['createstatement']),null,' ',''); $dml_createfunctions[$name]=$sql; } } } return array( 'fixtables'=>$dml_fixtables, 'dropviews'=>$dml_dropviews, 'createviews'=>sort_dml_createviews($dml_createviews), 'dropfunctions'=>$dml_dropfunctions, 'createfunctions'=>$dml_createfunctions, 'dropprocedures'=>$dml_dropprocedures, 'createprocedures'=>$dml_createprocedures, ); } function sort_dml_createviews($dml_createviews) { $dependency=array(); $donetable=array(); foreach ($dml_createviews as $name=>$sql) $dependency[$name]=array(); foreach ($dml_createviews as $name=>$tmp) { foreach ($dml_createviews as $vn=>$sql) { if ($vn==$name) continue; if (strpos($sql,$name)!==false) array_push($dependency[$vn],$name); } } $order=array(); $changed=true; while ($changed) { $changed=false; foreach ($dependency as $name=>$dependson) { if ($donetable[$name]) continue; $outable=true; foreach ($dependson as $doname) if (!$donetable[$doname]) { $outable=false; break; } if ($outable) { array_push($order,$name); $donetable[$name]=true; $changed=true; } } } return array_select_by_key($dml_createviews,array_keys($donetable)); } function tokenize_sql($sqltext) { $curpos=0; $tokenlist=array(); while ( tokenize_id($sqltext,$startpos,$tokenlist) || tokenize_comment($sqltext,$startpos,$tokenlist) || tokenize_space($sqltext,$startpos,$tokenlist) || tokenize_string($sqltext,$startpos,$tokenlist) || tokenize_number($sqltext,$startpos,$tokenlist) || tokenize_puncts($sqltext,$startpos,$tokenlist) || false); if ($startpos<strlen($sqltext)) { trigger_error('Error near: '.htmlspecialchars(substr($sqltext,$startpos,200))); return false; } return $tokenlist; } function filter_nonspace_token_idxs($tokenlist) { $nsidxs=array(); for ($ti=0;$ti<sizeof($tokenlist);$ti++) if ($tokenlist[$ti]['type']!='space') array_push($nsidxs,$ti); return $nsidxs; } function fix_tokenlist(&$tokens) { $sqlsecuritydefiner=array('SQL','SECURITY','DEFINER'); $definereq=array('DEFINER','='); $algorithmeqmerge=array('ALGORITHM','=','MERGE'); $tokenslocal=$tokens; for ($ti=0;$ti<sizeof($tokenslocal);$ti++) { if (compare_tokenlist($tokenslocal,$sqlsecuritydefiner,$ti)==0) $tokens[$ti+2]['content']='INVOKER'; else if (compare_tokenlist($tokenslocal,$definereq,$ti)==0) { $tokens[$ti]['type']='space'; $tokens[$ti+1]['type']='space'; $tokens[$ti+2]['type']='space'; $tokens[$ti+3]['type']='space'; $tokens[$ti+4]['type']='space'; } else if (compare_tokenlist($tokenslocal,$algorithmeqmerge,$ti)==0) { $tokens[$ti+2]['content']='UNDEFINED'; } } } function compare_tokenlist($tokenlist,$tokens,$startidx=0,$idxlist=null) { $tki=0; $tli=$startidx; $tlilimit=$idxlist?sizeof($idxlist):sizeof($tokenlist); for (;$tki<sizeof($tokens) && $tli<$tlilimit;$tki++,$tli++) { $usetli=$idxlist?$idxlist[$tli]:$tli; if (is_array($tokens[$tki])) $cr=strcasecmp($tokenlist[$usetli]['content'],$tokens[$tki]['content']); else $cr=strcasecmp($tokenlist[$usetli]['content'],$tokens[$tki]); if ($cr) return $cr; } return 0; } function turn_into_all_statements($nstokens) { $statements=array(); $nextpos=0; $delimiter=';'; while ($idxs=next_statement_idxs($nstokens,$nextpos,$delimiter)) array_push($statements,$idxs); return $statements; } function skip_to_token($tokens,&$tkidx,$tokencontents,$idxlist=null) { $idxlimit=$idxlist?sizeof($idxlist):sizeof($tokens); while ($tkidx<$idxlimit) { $useidx=$idxlist?$idxlist[$tkidx]:$tkidx; if (is_array($tokencontents)) { foreach ($tokencontents as $tk) if ($tokens[$useidx]['content']==$tk) return true; } else { if ($tokens[$useidx]['content']==$tokencontents) return true; } $tkidx++; } return false; } function ignore_tokens($tokens,&$tkidx,$ignoredcontents,$idxlist=null) { $idxlimit=$idxlist?sizeof($idxlist):sizeof($tokens); while ($tkidx<$idxlimit) { $useidx=$idxlist?$idxlist[$tkidx]:$tkidx; if (is_array($ignoredcontents)) { $found=false; foreach ($ignoredcontents as $tk) if ($tokens[$useidx]['content']==$tk) { $found=true; break; } if (!$found) return true; } else { if ($tokens[$useidx]['content']!=$ignoredcontents) return true; } $tkidx++; } return false; } function parse_table_structure($tokens,$statements) { $typecontents=array('TABLE','VIEW','FUNCTION','PROCEDURE'); $ignoredcontents=array('IF','EXISTS','NOT','SQL','ALGORITHM','=','UNDEFINED','SECURITY',' INVOKER'); $dbstructure=array(); for ($si=0;$si<sizeof($statements);$si++) { $statement=$statements[$si]; $tkidx=0; $objid=false; $objtype=false; $objaction=false; if (compare_tokenlist($tokens,array('DROP'),0,$statement)==0) { skip_to_token($tokens,$tkidx,$typecontents,$statement); $objtype=strtoupper($tokens[$statement[$tkidx]]['content']); $tkidx++; ignore_tokens($tokens,$tkidx,$ignoredcontents,$statement); $objid=$tokens[$statement[$tkidx]]['content']; if ($tkidx+2<sizeof($statements) && $tokens[$statement[$tkidx+1]]['content']=='.') $objid=$tokens[$statement[$tkidx+=2]]['content']; $objaction='DROP'; } else if (compare_tokenlist($tokens,array('CREATE'),0,$statement)==0) { skip_to_token($tokens,$tkidx,$typecontents,$statement); $objtype=strtoupper($tokens[$statement[$tkidx]]['content']); $tkidx++; ignore_tokens($tokens,$tkidx,$ignoredcontents,$statement); $objid=$tokens[$statement[$tkidx]]['content']; if ($tkidx+2<sizeof($statements) && $tokens[$statement[$tkidx+1]]['content']=='.') $objid=$tokens[$statement[$tkidx+=2]]['content']; $objaction='CREATE'; } if ($objaction=='DROP'); else if ($objaction=='CREATE' && $objtype=='TABLE') { skip_to_token($tokens,$tkidx,'(',$statement); $pdepth=0; $fields=array(); $curfield=array(); for ($tkidx++;$tkidx<sizeof($statement) && ($pdepth || $tokens[$statement[$tkidx]]['content']!=')');$tkidx++) { if ($tokens[$statement[$tkidx]]['content']=='(') $pdepth++; else if ($tokens[$statement[$tkidx]]['content']==')') $pdepth--; if (!$pdepth && $tokens[$statement[$tkidx]]['content']==',') { if ($curfield) { array_push($fields,$curfield); $curfield=array(); } } else array_push($curfield,$statement[$tkidx]); } if ($curfield) array_push($fields,$curfield); $properties=array(); for ($tkidx++;$tkidx<sizeof($statement);$tkidx++) { if ($tokens[$statement[$tkidx]]['type']=='id') { if ($tkidx+2<sizeof($statement) && $tokens[$statement[$tkidx+1]]['content']=='=') { $properties[$tokens[$statement[$tkidx]]['content']]=$tokens[$statement[$tkidx+2]]['content']; $tkidx+=2; } else $properties[$tokens[$statement[$tkidx]]['content']]=null; } else if (compare_tokenlist($tokens,array(';'),$tkidx,$statement)==0); else { trigger_error('Error: unrecognized property "'.$tokens[$statement[$tkidx]]['content'].'"'); break; } } unset($dbstructure[$objid]); $sbody=$statement; if ($tokens[$sbody[sizeof($sbody)-1]]['content']==';') array_pop($sbody); $dbstructure[$objid]=array( 'type'=>$objtype, 'fields'=>$fields, 'createstatement'=>$sbody, 'properties'=>$properties ); } else if ($objaction=='CREATE' && in_array($objtype,array('VIEW','FUNCTION','PROCEDURE'))) { unset($dbstructure[$objid]); $sbody=$statement; if ($objtype=='VIEW') { if ($tokens[$sbody[sizeof($sbody)-1]]['content']==';') array_pop($sbody); } else if ($tokens[$sbody[sizeof($sbody)-1]]['content']=='$$') array_pop($sbody); $dbstructure[$objid]=array( 'type'=>$objtype, 'createstatement'=>$sbody, ); } } return $dbstructure; } function export_tables_by_prefix($dbconn,$tableprefix) { $exportsql=''; $sql="SELECT DATABASE()"; $dbname=$dbconn->query_value($sql); $sql="SHOW TABLES"; $tablenames=$dbconn->query_value_array($sql); foreach ($tablenames as $tablename) { if (strcasecmp($tableprefix,substr($tablename,0,strlen($tableprefix)))!=0) continue; $sql="SHOW CREATE TABLE `".str_replace('`','``',$tablename)."`"; $createsqls=$dbconn->query_row_assoc($sql); if ($createsqls['View']) $exportsql.=$createsqls['Create View'].";\n"; else if ($createsqls['Table']) $exportsql.=$createsqls['Create Table'].";\n"; } $exportsql.="DELIMITER $$\n"; $sql="SHOW FUNCTION STATUS"; $functioninfos=$dbconn->query_allrows_assoc($sql); foreach ($functioninfos as $functioninfo) { if ($dbname!=$functioninfo['Db']) continue; if (strcasecmp($tableprefix,substr($functioninfo['Name'],0,strlen($tableprefix)))!=0) continue; $sql="SHOW CREATE FUNCTION `".str_replace('`','``',$functioninfo['Name'])."`"; $createsqls=$dbconn->query_row_assoc($sql); $exportsql.=$createsqls['Create Function']."$$\n"; } $sql="SHOW PROCEDURE STATUS"; $functioninfos=$dbconn->query_allrows_assoc($sql); foreach ($functioninfos as $functioninfo) { if ($dbname!=$functioninfo['Db']) continue; if (strcasecmp($tableprefix,substr($functioninfo['Name'],0,strlen($tableprefix)))!=0) continue; $sql="SHOW CREATE PROCEDURE `".str_replace('`','``',$functioninfo['Name'])."`"; $createsqls=$dbconn->query_row_assoc($sql); $exportsql.=$createsqls['Create Procedure']."$$\n"; } $exportsql.="DELIMITER ;\n"; $exportsql=str_replace('`'.str_replace('`','``',$dbname).'`','',$exportsql); return $exportsql; } function next_statement_idxs($nstokens,&$nextpos,&$delimiter) { $idxs=array(); $initial=true; if (!$delimiter) $delimiter=';'; while ($nextpos<sizeof($nstokens)) { if ($initial) { if (strcasecmp($nstokens[$nextpos]['content'],'DELIMITER')==0) { $delimiter=$nstokens[$nextpos+1]['content']; $idxs=array($nextpos++,$nextpos++); break; } $initial=false; } array_push($idxs,$nextpos); if ($nstokens[$nextpos++]['content']==$delimiter) break; } return $idxs; } function tokenize_id($sqltext,&$startpos,&$tokenlist) { $id=''; if (ctype_alpha($sqltext[$startpos]) || $sqltext[$startpos]=='_') { do { $id.=$sqltext[$startpos++]; if ($startpos>=strlen($sqltext)) break; } while ( $startpos<strlen($sqltext) && (ctype_alnum($sqltext[$startpos]) || $sqltext[$startpos]=='_') ); } else if ($sqltext[$startpos]=='`') { do { $id.=$sqltext[$startpos++]; while ($sqltext[$startpos]=='`' && $startpos+1<strlen($sqltext) && $sqltext[$startpos+1]=='`') { $id.='``'; $startpos+=2; } } while ($startpos<strlen($sqltext) && $sqltext[$startpos]!='`'); if ($startpos<strlen($sqltext)) $id.=$sqltext[$startpos++]; } if ($id) { array_push($tokenlist, array( 'type'=>'id', 'content'=>$id ) ); return true; } return false; } function tokenize_comment($sqltext,&$startpos,&$tokenlist) { if (substr($sqltext,$startpos,2)=='--') { $endpos=strpos($sqltext,"\n",$startpos+2); if (!$endpos) $endpos=strlen($sqltext); else $endpos++; array_push($tokenlist, array( 'type'=>'space', 'content'=>substr($sqltext,$startpos,$endpos-$startpos) ) ); $startpos=$endpos; return true; } return false; } function tokenize_space($sqltext,&$startpos,&$tokenlist) { $space=''; while ( $startpos<strlen($sqltext) && (ctype_space($sqltext[$startpos]) || ctype_cntrl($sqltext[$startpos]))) { $space.=$sqltext[$startpos]; $startpos++; } if ($space) { array_push($tokenlist, array( 'type'=>'space', 'content'=>$space ) ); return true; } return false; } function tokenize_string($sqltext,&$startpos,&$tokenlist) { $string=''; if ($sqltext[$startpos]=="'" || $sqltext[$startpos]=='"') { $quot=$sqltext[$startpos]; do { $string.=$sqltext[$startpos++]; while ($sqltext[$startpos]==$quot && $startpos+1<strlen($sqltext) && $sqltext[$startpos+1]==$quot) { $string.=$quot.$quot; $startpos+=2; } } while ($startpos<strlen($sqltext) && $sqltext[$startpos]!=$quot); if ($startpos<strlen($sqltext)) $string.=$sqltext[$startpos++]; } if ($string) { array_push($tokenlist, array( 'type'=>'string', 'content'=>$string ) ); return true; } return false; } function tokenize_number($sqltext,&$startpos,&$tokenlist) { $number=''; $numlen=0; if ($sqltext[$startpos]=='+' || $sqltext[$startpos]=='-') { if (is_numeric(substr($sqltext,$startpos,2))) { $number=substr($sqltext,$startpos,2); $numlen=2; } } else if (substr($sqltext,$startpos,2)=='0x' || substr($sqltext,$startpos,2)=='0X') { if (ctype_xdigit(substr($sqltext,$startpos+2,1))) { $number=substr($sqltext,$startpos,3); $numlen=3; } } while ($startpos+$numlen<strlen($sqltext) && is_numeric(substr($sqltext,$startpos,$numlen+1))) $numlen++; if ($numlen) { array_push($tokenlist, array( 'type'=>'number', 'content'=>substr($sqltext,$startpos,$numlen) ) ); $startpos+=$numlen; return true; } return false; } function tokenize_puncts($sqltext,&$startpos,&$tokenlist) { $len=strspn($sqltext,'+-=/*$<>&|~^.@:%!',$startpos); if (!$len) { $len=strspn($sqltext,'();,',$startpos); if ($len) $len=1; } if ($len) { array_push($tokenlist, array( 'type'=>'puncts', 'content'=>substr($sqltext,$startpos,$len) ) ); $startpos+=$len; return true; } return false; } function statements_as_string($tokens,$statements,$idxmap=null,$insertsep='',$linebreak="\n") { $out=false; for ($si=0;$si<sizeof($statements);$si++) { $statement=$statements[$si]; $prevtype=false; for ($tii=0;$tii<sizeof($statement);$tii++) { $thisidx=$idxmap?$idxmap[$statement[$tii]]:$statement[$tii]; $thistype=$tokens[$thisidx]['type']; if ($tii) if ($thisidx-$lastidx>1 || $thistype=='id' || $thistype=='string' || $thistype=='number' && $prevtype=='id') $out.=$insertsep; $out.=$tokens[$thisidx]['content']; $lastidx=$thisidx; $prevtype=$thistype; } $out.=$linebreak; } return $out; } function upgrade_database($dbconn,$sqls_newdb,$tableprefix,$delete_tables=false) { $sqltext_olddb=export_tables_by_prefix($dbconn,$tableprefix); $parseresult_new=parse_db_DML($sqls_newdb); $parseresult_old=parse_db_DML($sqltext_olddb); $upgradesqls=generate_fix_db_sql($parseresult_new,$parseresult_old); foreach ($upgradesqls['fixtables'] as $sql) $dbconn->real_query($sql,'error.db.upgrade'); foreach ($upgradesqls['dropfunctions'] as $sql) $dbconn->real_query($sql,'error.db.upgrade'); foreach ($upgradesqls['createfunctions'] as $sql) $dbconn->real_query($sql,'error.db.upgrade'); foreach ($upgradesqls['dropprocedures'] as $sql) $dbconn->real_query($sql,'error.db.upgrade'); foreach ($upgradesqls['createprocedures'] as $sql) $dbconn->real_query($sql,'error.db.upgrade'); foreach ($upgradesqls['createviews'] as $sql) $dbconn->real_query($sql,'error.db.upgrade'); } ?>