TYPO3 CMS  TYPO3_7-6
adodb-xmlschema.inc.php
Go to the documentation of this file.
1 <?php
2 // Copyright (c) 2004 ars Cognita Inc., all rights reserved
3 /* ******************************************************************************
4  Released under both BSD license and Lesser GPL library license.
5  Whenever there is any discrepancy between the two licenses,
6  the BSD license will take precedence.
7 *******************************************************************************/
21 function _file_get_contents($file)
22 {
23  if (function_exists('file_get_contents')) return file_get_contents($file);
24 
25  $f = fopen($file,'r');
26  if (!$f) return '';
27  $t = '';
28 
29  while ($s = fread($f,100000)) $t .= $s;
30  fclose($f);
31  return $t;
32 }
33 
34 
38 if( !defined( 'XMLS_DEBUG' ) ) {
39  define( 'XMLS_DEBUG', FALSE );
40 }
41 
45 if( !defined( 'XMLS_PREFIX' ) ) {
46  define( 'XMLS_PREFIX', '%%P' );
47 }
48 
52 if( !defined( 'XMLS_PREFIX_MAXLEN' ) ) {
53  define( 'XMLS_PREFIX_MAXLEN', 10 );
54 }
55 
59 if( !defined( 'XMLS_EXECUTE_INLINE' ) ) {
60  define( 'XMLS_EXECUTE_INLINE', FALSE );
61 }
62 
66 if( !defined( 'XMLS_CONTINUE_ON_ERROR' ) ) {
67  define( 'XMLS_CONTINUE_ON_ERROR', FALSE );
68 }
69 
73 if( !defined( 'XMLS_SCHEMA_VERSION' ) ) {
74  define( 'XMLS_SCHEMA_VERSION', '0.2' );
75 }
76 
80 if( !defined( 'XMLS_DEFAULT_SCHEMA_VERSION' ) ) {
81  define( 'XMLS_DEFAULT_SCHEMA_VERSION', '0.1' );
82 }
83 
87 if( !defined( 'XMLS_DEFAULT_UPGRADE_METHOD' ) ) {
88  define( 'XMLS_DEFAULT_UPGRADE_METHOD', 'ALTER' );
89 }
90 
94 if( !defined( '_ADODB_LAYER' ) ) {
95  require( 'adodb.inc.php' );
96  require( 'adodb-datadict.inc.php' );
97 }
98 
106 class dbObject {
107 
111  var $parent;
112 
117 
121  function __construct( &$parent, $attributes = NULL ) {
122  $this->parent = $parent;
123  }
124 
130  function _tag_open( &$parser, $tag, $attributes ) {
131 
132  }
133 
139  function _tag_cdata( &$parser, $cdata ) {
140 
141  }
142 
148  function _tag_close( &$parser, $tag ) {
149 
150  }
151 
152  function create(&$xmls) {
153  return array();
154  }
155 
159  function destroy() {
160  }
161 
169  function supportedPlatform( $platform = NULL ) {
170  return is_object( $this->parent ) ? $this->parent->supportedPlatform( $platform ) : TRUE;
171  }
172 
179  function prefix( $name = '' ) {
180  return is_object( $this->parent ) ? $this->parent->prefix( $name ) : $name;
181  }
182 
189  function FieldID( $field ) {
190  return strtoupper( preg_replace( '/^`(.+)`$/', '$1', $field ) );
191  }
192 }
193 
205 class dbTable extends dbObject {
206 
210  var $name;
211 
215  var $fields = array();
216 
220  var $indexes = array();
221 
225  var $opts = array();
226 
231 
237 
242  var $drop_field = array();
243 
250  function __construct( &$parent, $attributes = NULL ) {
251  $this->parent = $parent;
252  $this->name = $this->prefix($attributes['NAME']);
253  }
254 
261  function _tag_open( &$parser, $tag, $attributes ) {
262  $this->currentElement = strtoupper( $tag );
263 
264  switch( $this->currentElement ) {
265  case 'INDEX':
266  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
267  xml_set_object( $parser, $this->addIndex( $attributes ) );
268  }
269  break;
270  case 'DATA':
271  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
272  xml_set_object( $parser, $this->addData( $attributes ) );
273  }
274  break;
275  case 'DROP':
276  $this->drop();
277  break;
278  case 'FIELD':
279  // Add a field
280  $fieldName = $attributes['NAME'];
281  $fieldType = $attributes['TYPE'];
282  $fieldSize = isset( $attributes['SIZE'] ) ? $attributes['SIZE'] : NULL;
283  $fieldOpts = isset( $attributes['OPTS'] ) ? $attributes['OPTS'] : NULL;
284 
285  $this->addField( $fieldName, $fieldType, $fieldSize, $fieldOpts );
286  break;
287  case 'KEY':
288  case 'NOTNULL':
289  case 'AUTOINCREMENT':
290  // Add a field option
291  $this->addFieldOpt( $this->current_field, $this->currentElement );
292  break;
293  case 'DEFAULT':
294  // Add a field option to the table object
295 
296  // Work around ADOdb datadict issue that misinterprets empty strings.
297  if( $attributes['VALUE'] == '' ) {
298  $attributes['VALUE'] = " '' ";
299  }
300 
301  $this->addFieldOpt( $this->current_field, $this->currentElement, $attributes['VALUE'] );
302  break;
303  case 'DEFDATE':
304  case 'DEFTIMESTAMP':
305  // Add a field option to the table object
306  $this->addFieldOpt( $this->current_field, $this->currentElement );
307  break;
308  default:
309  // print_r( array( $tag, $attributes ) );
310  }
311  }
312 
318  function _tag_cdata( &$parser, $cdata ) {
319  switch( $this->currentElement ) {
320  // Table constraint
321  case 'CONSTRAINT':
322  if( isset( $this->current_field ) ) {
323  $this->addFieldOpt( $this->current_field, $this->currentElement, $cdata );
324  } else {
325  $this->addTableOpt( $cdata );
326  }
327  break;
328  // Table option
329  case 'OPT':
330  $this->addTableOpt( $cdata );
331  break;
332  default:
333 
334  }
335  }
336 
342  function _tag_close( &$parser, $tag ) {
343  $this->currentElement = '';
344 
345  switch( strtoupper( $tag ) ) {
346  case 'TABLE':
347  $this->parent->addSQL( $this->create( $this->parent ) );
348  xml_set_object( $parser, $this->parent );
349  $this->destroy();
350  break;
351  case 'FIELD':
352  unset($this->current_field);
353  break;
354 
355  }
356  }
357 
364  function addIndex( $attributes ) {
365  $name = strtoupper( $attributes['NAME'] );
366  $this->indexes[$name] = new dbIndex( $this, $attributes );
367  return $this->indexes[$name];
368  }
369 
376  function addData( $attributes ) {
377  if( !isset( $this->data ) ) {
378  $this->data = new dbData( $this, $attributes );
379  }
380  return $this->data;
381  }
382 
412  function addField( $name, $type, $size = NULL, $opts = NULL ) {
413  $field_id = $this->FieldID( $name );
414 
415  // Set the field index so we know where we are
416  $this->current_field = $field_id;
417 
418  // Set the field name (required)
419  $this->fields[$field_id]['NAME'] = $name;
420 
421  // Set the field type (required)
422  $this->fields[$field_id]['TYPE'] = $type;
423 
424  // Set the field size (optional)
425  if( isset( $size ) ) {
426  $this->fields[$field_id]['SIZE'] = $size;
427  }
428 
429  // Set the field options
430  if( isset( $opts ) ) {
431  $this->fields[$field_id]['OPTS'][] = $opts;
432  }
433  }
434 
446  function addFieldOpt( $field, $opt, $value = NULL ) {
447  if( !isset( $value ) ) {
448  $this->fields[$this->FieldID( $field )]['OPTS'][] = $opt;
449  // Add the option and value
450  } else {
451  $this->fields[$this->FieldID( $field )]['OPTS'][] = array( $opt => $value );
452  }
453  }
454 
464  function addTableOpt( $opt ) {
465  if(isset($this->currentPlatform)) {
466  $this->opts[$this->parent->db->databaseType] = $opt;
467  }
468  return $this->opts;
469  }
470 
471 
478  function create( &$xmls ) {
479  $sql = array();
480 
481  // drop any existing indexes
482  if( is_array( $legacy_indexes = $xmls->dict->MetaIndexes( $this->name ) ) ) {
483  foreach( $legacy_indexes as $index => $index_details ) {
484  $sql[] = $xmls->dict->DropIndexSQL( $index, $this->name );
485  }
486  }
487 
488  // remove fields to be dropped from table object
489  foreach( $this->drop_field as $field ) {
490  unset( $this->fields[$field] );
491  }
492 
493  // if table exists
494  if( is_array( $legacy_fields = $xmls->dict->MetaColumns( $this->name ) ) ) {
495  // drop table
496  if( $this->drop_table ) {
497  $sql[] = $xmls->dict->DropTableSQL( $this->name );
498 
499  return $sql;
500  }
501 
502  // drop any existing fields not in schema
503  foreach( $legacy_fields as $field_id => $field ) {
504  if( !isset( $this->fields[$field_id] ) ) {
505  $sql[] = $xmls->dict->DropColumnSQL( $this->name, '`'.$field->name.'`' );
506  }
507  }
508  // if table doesn't exist
509  } else {
510  if( $this->drop_table ) {
511  return $sql;
512  }
513 
514  $legacy_fields = array();
515  }
516 
517  // Loop through the field specifier array, building the associative array for the field options
518  $fldarray = array();
519 
520  foreach( $this->fields as $field_id => $finfo ) {
521  // Set an empty size if it isn't supplied
522  if( !isset( $finfo['SIZE'] ) ) {
523  $finfo['SIZE'] = '';
524  }
525 
526  // Initialize the field array with the type and size
527  $fldarray[$field_id] = array(
528  'NAME' => $finfo['NAME'],
529  'TYPE' => $finfo['TYPE'],
530  'SIZE' => $finfo['SIZE']
531  );
532 
533  // Loop through the options array and add the field options.
534  if( isset( $finfo['OPTS'] ) ) {
535  foreach( $finfo['OPTS'] as $opt ) {
536  // Option has an argument.
537  if( is_array( $opt ) ) {
538  $key = key( $opt );
539  $value = $opt[key( $opt )];
540  @$fldarray[$field_id][$key] .= $value;
541  // Option doesn't have arguments
542  } else {
543  $fldarray[$field_id][$opt] = $opt;
544  }
545  }
546  }
547  }
548 
549  if( empty( $legacy_fields ) ) {
550  // Create the new table
551  $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
552  logMsg( end( $sql ), 'Generated CreateTableSQL' );
553  } else {
554  // Upgrade an existing table
555  logMsg( "Upgrading {$this->name} using '{$xmls->upgrade}'" );
556  switch( $xmls->upgrade ) {
557  // Use ChangeTableSQL
558  case 'ALTER':
559  logMsg( 'Generated ChangeTableSQL (ALTERing table)' );
560  $sql[] = $xmls->dict->ChangeTableSQL( $this->name, $fldarray, $this->opts );
561  break;
562  case 'REPLACE':
563  logMsg( 'Doing upgrade REPLACE (testing)' );
564  $sql[] = $xmls->dict->DropTableSQL( $this->name );
565  $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
566  break;
567  // ignore table
568  default:
569  return array();
570  }
571  }
572 
573  foreach( $this->indexes as $index ) {
574  $sql[] = $index->create( $xmls );
575  }
576 
577  if( isset( $this->data ) ) {
578  $sql[] = $this->data->create( $xmls );
579  }
580 
581  return $sql;
582  }
583 
587  function drop() {
588  if( isset( $this->current_field ) ) {
589  // Drop the current field
590  logMsg( "Dropping field '{$this->current_field}' from table '{$this->name}'" );
591  // $this->drop_field[$this->current_field] = $xmls->dict->DropColumnSQL( $this->name, $this->current_field );
592  $this->drop_field[$this->current_field] = $this->current_field;
593  } else {
594  // Drop the current table
595  logMsg( "Dropping table '{$this->name}'" );
596  // $this->drop_table = $xmls->dict->DropTableSQL( $this->name );
597  $this->drop_table = TRUE;
598  }
599  }
600 }
601 
613 class dbIndex extends dbObject {
614 
618  var $name;
619 
623  var $opts = array();
624 
628  var $columns = array();
629 
634  var $drop = FALSE;
635 
644  function __construct( &$parent, $attributes = NULL ) {
645  $this->parent = $parent;
646 
647  $this->name = $this->prefix ($attributes['NAME']);
648  }
649 
658  function _tag_open( &$parser, $tag, $attributes ) {
659  $this->currentElement = strtoupper( $tag );
660 
661  switch( $this->currentElement ) {
662  case 'DROP':
663  $this->drop();
664  break;
665  case 'CLUSTERED':
666  case 'BITMAP':
667  case 'UNIQUE':
668  case 'FULLTEXT':
669  case 'HASH':
670  // Add index Option
671  $this->addIndexOpt( $this->currentElement );
672  break;
673  default:
674  // print_r( array( $tag, $attributes ) );
675  }
676  }
677 
685  function _tag_cdata( &$parser, $cdata ) {
686  switch( $this->currentElement ) {
687  // Index field name
688  case 'COL':
689  $this->addField( $cdata );
690  break;
691  default:
692 
693  }
694  }
695 
701  function _tag_close( &$parser, $tag ) {
702  $this->currentElement = '';
703 
704  switch( strtoupper( $tag ) ) {
705  case 'INDEX':
706  xml_set_object( $parser, $this->parent );
707  break;
708  }
709  }
710 
717  function addField( $name ) {
718  $this->columns[$this->FieldID( $name )] = $name;
719 
720  // Return the field list
721  return $this->columns;
722  }
723 
730  function addIndexOpt( $opt ) {
731  $this->opts[] = $opt;
732 
733  // Return the options list
734  return $this->opts;
735  }
736 
743  function create( &$xmls ) {
744  if( $this->drop ) {
745  return NULL;
746  }
747 
748  // eliminate any columns that aren't in the table
749  foreach( $this->columns as $id => $col ) {
750  if( !isset( $this->parent->fields[$id] ) ) {
751  unset( $this->columns[$id] );
752  }
753  }
754 
755  return $xmls->dict->CreateIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts );
756  }
757 
761  function drop() {
762  $this->drop = TRUE;
763  }
764 }
765 
774 class dbData extends dbObject {
775 
776  var $data = array();
777 
778  var $row;
779 
788  function __construct( &$parent, $attributes = NULL ) {
789  $this->parent = $parent;
790  }
791 
800  function _tag_open( &$parser, $tag, $attributes ) {
801  $this->currentElement = strtoupper( $tag );
802 
803  switch( $this->currentElement ) {
804  case 'ROW':
805  $this->row = count( $this->data );
806  $this->data[$this->row] = array();
807  break;
808  case 'F':
809  $this->addField($attributes);
810  default:
811  // print_r( array( $tag, $attributes ) );
812  }
813  }
814 
822  function _tag_cdata( &$parser, $cdata ) {
823  switch( $this->currentElement ) {
824  // Index field name
825  case 'F':
826  $this->addData( $cdata );
827  break;
828  default:
829 
830  }
831  }
832 
838  function _tag_close( &$parser, $tag ) {
839  $this->currentElement = '';
840 
841  switch( strtoupper( $tag ) ) {
842  case 'DATA':
843  xml_set_object( $parser, $this->parent );
844  break;
845  }
846  }
847 
854  function addField( $attributes ) {
855  if( isset( $attributes['NAME'] ) ) {
856  $name = $attributes['NAME'];
857  } else {
858  $name = count($this->data[$this->row]);
859  }
860 
861  // Set the field index so we know where we are
862  $this->current_field = $this->FieldID( $name );
863  }
864 
871  function addData( $cdata ) {
872  if( !isset( $this->data[$this->row] ) ) {
873  $this->data[$this->row] = array();
874  }
875 
876  if( !isset( $this->data[$this->row][$this->current_field] ) ) {
877  $this->data[$this->row][$this->current_field] = '';
878  }
879 
880  $this->data[$this->row][$this->current_field] .= $cdata;
881  }
882 
889  function create( &$xmls ) {
890  $table = $xmls->dict->TableName($this->parent->name);
891  $table_field_count = count($this->parent->fields);
892  $sql = array();
893 
894  // eliminate any columns that aren't in the table
895  foreach( $this->data as $row ) {
896  $table_fields = $this->parent->fields;
897  $fields = array();
898 
899  foreach( $row as $field_id => $field_data ) {
900  if( !array_key_exists( $field_id, $table_fields ) ) {
901  if( is_numeric( $field_id ) ) {
902  $field_id = reset( array_keys( $table_fields ) );
903  } else {
904  continue;
905  }
906  }
907 
908  $name = $table_fields[$field_id]['NAME'];
909 
910  switch( $table_fields[$field_id]['TYPE'] ) {
911  case 'C':
912  case 'C2':
913  case 'X':
914  case 'X2':
915  $fields[$name] = $xmls->db->qstr( $field_data );
916  break;
917  case 'I':
918  case 'I1':
919  case 'I2':
920  case 'I4':
921  case 'I8':
922  $fields[$name] = intval($field_data);
923  break;
924  default:
925  $fields[$name] = $field_data;
926  }
927 
928  unset($table_fields[$field_id]);
929  }
930 
931  // check that at least 1 column is specified
932  if( empty( $fields ) ) {
933  continue;
934  }
935 
936  // check that no required columns are missing
937  if( count( $fields ) < $table_field_count ) {
938  foreach( $table_fields as $field ) {
939  if (isset( $field['OPTS'] ))
940  if( ( in_array( 'NOTNULL', $field['OPTS'] ) || in_array( 'KEY', $field['OPTS'] ) ) && !in_array( 'AUTOINCREMENT', $field['OPTS'] ) ) {
941  continue(2);
942  }
943  }
944  }
945 
946  $sql[] = 'INSERT INTO '. $table .' ('. implode( ',', array_keys( $fields ) ) .') VALUES ('. implode( ',', $fields ) .')';
947  }
948 
949  return $sql;
950  }
951 }
952 
959 class dbQuerySet extends dbObject {
960 
964  var $queries = array();
965 
969  var $query;
970 
974  var $prefixKey = '';
975 
979  var $prefixMethod = 'AUTO';
980 
987  function __construct( &$parent, $attributes = NULL ) {
988  $this->parent = $parent;
989 
990  // Overrides the manual prefix key
991  if( isset( $attributes['KEY'] ) ) {
992  $this->prefixKey = $attributes['KEY'];
993  }
994 
995  $prefixMethod = isset( $attributes['PREFIXMETHOD'] ) ? strtoupper( trim( $attributes['PREFIXMETHOD'] ) ) : '';
996 
997  // Enables or disables automatic prefix prepending
998  switch( $prefixMethod ) {
999  case 'AUTO':
1000  $this->prefixMethod = 'AUTO';
1001  break;
1002  case 'MANUAL':
1003  $this->prefixMethod = 'MANUAL';
1004  break;
1005  case 'NONE':
1006  $this->prefixMethod = 'NONE';
1007  break;
1008  }
1009  }
1010 
1017  function _tag_open( &$parser, $tag, $attributes ) {
1018  $this->currentElement = strtoupper( $tag );
1019 
1020  switch( $this->currentElement ) {
1021  case 'QUERY':
1022  // Create a new query in a SQL queryset.
1023  // Ignore this query set if a platform is specified and it's different than the
1024  // current connection platform.
1025  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
1026  $this->newQuery();
1027  } else {
1028  $this->discardQuery();
1029  }
1030  break;
1031  default:
1032  // print_r( array( $tag, $attributes ) );
1033  }
1034  }
1035 
1039  function _tag_cdata( &$parser, $cdata ) {
1040  switch( $this->currentElement ) {
1041  // Line of queryset SQL data
1042  case 'QUERY':
1043  $this->buildQuery( $cdata );
1044  break;
1045  default:
1046 
1047  }
1048  }
1049 
1055  function _tag_close( &$parser, $tag ) {
1056  $this->currentElement = '';
1057 
1058  switch( strtoupper( $tag ) ) {
1059  case 'QUERY':
1060  // Add the finished query to the open query set.
1061  $this->addQuery();
1062  break;
1063  case 'SQL':
1064  $this->parent->addSQL( $this->create( $this->parent ) );
1065  xml_set_object( $parser, $this->parent );
1066  $this->destroy();
1067  break;
1068  default:
1069 
1070  }
1071  }
1072 
1078  function newQuery() {
1079  $this->query = '';
1080 
1081  return TRUE;
1082  }
1083 
1089  function discardQuery() {
1090  unset( $this->query );
1091 
1092  return TRUE;
1093  }
1094 
1101  function buildQuery( $sql = NULL ) {
1102  if( !isset( $this->query ) OR empty( $sql ) ) {
1103  return FALSE;
1104  }
1105 
1106  $this->query .= $sql;
1107 
1108  return $this->query;
1109  }
1110 
1116  function addQuery() {
1117  if( !isset( $this->query ) ) {
1118  return FALSE;
1119  }
1120 
1121  $this->queries[] = $return = trim($this->query);
1122 
1123  unset( $this->query );
1124 
1125  return $return;
1126  }
1127 
1134  function create( &$xmls ) {
1135  foreach( $this->queries as $id => $query ) {
1136  switch( $this->prefixMethod ) {
1137  case 'AUTO':
1138  // Enable auto prefix replacement
1139 
1140  // Process object prefix.
1141  // Evaluate SQL statements to prepend prefix to objects
1142  $query = $this->prefixQuery( '/^\s*((?is)INSERT\s+(INTO\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
1143  $query = $this->prefixQuery( '/^\s*((?is)UPDATE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
1144  $query = $this->prefixQuery( '/^\s*((?is)DELETE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
1145 
1146  // SELECT statements aren't working yet
1147  #$data = preg_replace( '/(?ias)(^\s*SELECT\s+.*\s+FROM)\s+(\W\s*,?\s*)+((?i)\s+WHERE.*$)/', "\1 $prefix\2 \3", $data );
1148 
1149  case 'MANUAL':
1150  // If prefixKey is set and has a value then we use it to override the default constant XMLS_PREFIX.
1151  // If prefixKey is not set, we use the default constant XMLS_PREFIX
1152  if( isset( $this->prefixKey ) AND( $this->prefixKey !== '' ) ) {
1153  // Enable prefix override
1154  $query = str_replace( $this->prefixKey, $xmls->objectPrefix, $query );
1155  } else {
1156  // Use default replacement
1157  $query = str_replace( XMLS_PREFIX , $xmls->objectPrefix, $query );
1158  }
1159  }
1160 
1161  $this->queries[$id] = trim( $query );
1162  }
1163 
1164  // Return the query set array
1165  return $this->queries;
1166  }
1167 
1176  function prefixQuery( $regex, $query, $prefix = NULL ) {
1177  if( !isset( $prefix ) ) {
1178  return $query;
1179  }
1180 
1181  if( preg_match( $regex, $query, $match ) ) {
1182  $preamble = $match[1];
1183  $postamble = $match[5];
1184  $objectList = explode( ',', $match[3] );
1185  // $prefix = $prefix . '_';
1186 
1187  $prefixedList = '';
1188 
1189  foreach( $objectList as $object ) {
1190  if( $prefixedList !== '' ) {
1191  $prefixedList .= ', ';
1192  }
1193 
1194  $prefixedList .= $prefix . trim( $object );
1195  }
1196 
1197  $query = $preamble . ' ' . $prefixedList . ' ' . $postamble;
1198  }
1199 
1200  return $query;
1201  }
1202 }
1203 
1217 class adoSchema {
1218 
1224 
1229  var $db;
1230 
1235  var $dict;
1236 
1242 
1247  var $upgrade = '';
1248 
1253  var $objectPrefix = '';
1254 
1259  var $mgq;
1260 
1265  var $debug;
1266 
1271  var $versionRegex = '/<schema.*?( version="([^"]*)")?.*?>/';
1272 
1278 
1283 
1288 
1293 
1303  function __construct( $db ) {
1304  // Initialize the environment
1305  $this->mgq = get_magic_quotes_runtime();
1306  ini_set("magic_quotes_runtime", 0);
1307  #set_magic_quotes_runtime(0);
1308 
1309  $this->db = $db;
1310  $this->debug = $this->db->debug;
1311  $this->dict = NewDataDictionary( $this->db );
1312  $this->sqlArray = array();
1313  $this->schemaVersion = XMLS_SCHEMA_VERSION;
1314  $this->executeInline( XMLS_EXECUTE_INLINE );
1315  $this->continueOnError( XMLS_CONTINUE_ON_ERROR );
1316  $this->setUpgradeMethod();
1317  }
1318 
1335  function SetUpgradeMethod( $method = '' ) {
1336  if( !is_string( $method ) ) {
1337  return FALSE;
1338  }
1339 
1340  $method = strtoupper( $method );
1341 
1342  // Handle the upgrade methods
1343  switch( $method ) {
1344  case 'ALTER':
1345  $this->upgrade = $method;
1346  break;
1347  case 'REPLACE':
1348  $this->upgrade = $method;
1349  break;
1350  case 'BEST':
1351  $this->upgrade = 'ALTER';
1352  break;
1353  case 'NONE':
1354  $this->upgrade = 'NONE';
1355  break;
1356  default:
1357  // Use default if no legitimate method is passed.
1358  $this->upgrade = XMLS_DEFAULT_UPGRADE_METHOD;
1359  }
1360 
1361  return $this->upgrade;
1362  }
1363 
1377  function ExecuteInline( $mode = NULL ) {
1378  if( is_bool( $mode ) ) {
1379  $this->executeInline = $mode;
1380  }
1381 
1382  return $this->executeInline;
1383  }
1384 
1398  function ContinueOnError( $mode = NULL ) {
1399  if( is_bool( $mode ) ) {
1400  $this->continueOnError = $mode;
1401  }
1402 
1403  return $this->continueOnError;
1404  }
1405 
1417  function ParseSchema( $filename, $returnSchema = FALSE ) {
1418  return $this->ParseSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
1419  }
1420 
1434  function ParseSchemaFile( $filename, $returnSchema = FALSE ) {
1435  // Open the file
1436  if( !($fp = fopen( $filename, 'r' )) ) {
1437  // die( 'Unable to open file' );
1438  return FALSE;
1439  }
1440 
1441  // do version detection here
1442  if( $this->SchemaFileVersion( $filename ) != $this->schemaVersion ) {
1443  return FALSE;
1444  }
1445 
1446  if ( $returnSchema )
1447  {
1448  $xmlstring = '';
1449  while( $data = fread( $fp, 100000 ) ) {
1450  $xmlstring .= $data;
1451  }
1452  return $xmlstring;
1453  }
1454 
1455  $this->success = 2;
1456 
1457  $xmlParser = $this->create_parser();
1458  // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
1459  $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
1460 
1461  // Process the file
1462  while( $data = fread( $fp, 4096 ) ) {
1463  if( !xml_parse( $xmlParser, $data, feof( $fp ) ) ) {
1464  die( sprintf(
1465  "XML error: %s at line %d",
1466  xml_error_string( xml_get_error_code( $xmlParser) ),
1467  xml_get_current_line_number( $xmlParser)
1468  ) );
1469  }
1470  }
1471 
1472  libxml_disable_entity_loader($previousValueOfEntityLoader);
1473  xml_parser_free( $xmlParser );
1474 
1475  return $this->sqlArray;
1476  }
1477 
1489  function ParseSchemaString( $xmlstring, $returnSchema = FALSE ) {
1490  if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
1491  return FALSE;
1492  }
1493 
1494  // do version detection here
1495  if( $this->SchemaStringVersion( $xmlstring ) != $this->schemaVersion ) {
1496  return FALSE;
1497  }
1498 
1499  if ( $returnSchema )
1500  {
1501  return $xmlstring;
1502  }
1503 
1504  $this->success = 2;
1505 
1506  $xmlParser = $this->create_parser();
1507  // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
1508  $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
1509 
1510  if( !xml_parse( $xmlParser, $xmlstring, TRUE ) ) {
1511  die( sprintf(
1512  "XML error: %s at line %d",
1513  xml_error_string( xml_get_error_code( $xmlParser) ),
1514  xml_get_current_line_number( $xmlParser)
1515  ) );
1516  }
1517 
1518  libxml_disable_entity_loader($previousValueOfEntityLoader);
1519  xml_parser_free( $xmlParser );
1520 
1521  return $this->sqlArray;
1522  }
1523 
1535  function RemoveSchema( $filename, $returnSchema = FALSE ) {
1536  return $this->RemoveSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
1537  }
1538 
1550  function RemoveSchemaString( $schema, $returnSchema = FALSE ) {
1551 
1552  // grab current version
1553  if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
1554  return FALSE;
1555  }
1556 
1557  return $this->ParseSchemaString( $this->TransformSchema( $schema, 'remove-' . $version), $returnSchema );
1558  }
1559 
1573  function ExecuteSchema( $sqlArray = NULL, $continueOnErr = NULL ) {
1574  if( !is_bool( $continueOnErr ) ) {
1575  $continueOnErr = $this->ContinueOnError();
1576  }
1577 
1578  if( !isset( $sqlArray ) ) {
1579  $sqlArray = $this->sqlArray;
1580  }
1581 
1582  if( !is_array( $sqlArray ) ) {
1583  $this->success = 0;
1584  } else {
1585  $this->success = $this->dict->ExecuteSQLArray( $sqlArray, $continueOnErr );
1586  }
1587 
1588  return $this->success;
1589  }
1590 
1600  function PrintSQL( $format = 'NONE' ) {
1601  $sqlArray = null;
1602  return $this->getSQL( $format, $sqlArray );
1603  }
1604 
1614  function SaveSQL( $filename = './schema.sql' ) {
1615 
1616  if( !isset( $sqlArray ) ) {
1617  $sqlArray = $this->sqlArray;
1618  }
1619  if( !isset( $sqlArray ) ) {
1620  return FALSE;
1621  }
1622 
1623  $fp = fopen( $filename, "w" );
1624 
1625  foreach( $sqlArray as $key => $query ) {
1626  fwrite( $fp, $query . ";\n" );
1627  }
1628  fclose( $fp );
1629  }
1630 
1638  function create_parser() {
1639  // Create the parser
1640  $xmlParser = xml_parser_create();
1641  xml_set_object( $xmlParser, $this );
1642 
1643  // Initialize the XML callback functions
1644  xml_set_element_handler( $xmlParser, '_tag_open', '_tag_close' );
1645  xml_set_character_data_handler( $xmlParser, '_tag_cdata' );
1646 
1647  return $xmlParser;
1648  }
1649 
1655  function _tag_open( &$parser, $tag, $attributes ) {
1656  switch( strtoupper( $tag ) ) {
1657  case 'TABLE':
1658  $this->obj = new dbTable( $this, $attributes );
1659  xml_set_object( $parser, $this->obj );
1660  break;
1661  case 'SQL':
1662  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
1663  $this->obj = new dbQuerySet( $this, $attributes );
1664  xml_set_object( $parser, $this->obj );
1665  }
1666  break;
1667  default:
1668  // print_r( array( $tag, $attributes ) );
1669  }
1670 
1671  }
1672 
1678  function _tag_cdata( &$parser, $cdata ) {
1679  }
1680 
1687  function _tag_close( &$parser, $tag ) {
1688 
1689  }
1690 
1707  function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
1708 
1709  // grab current version
1710  if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
1711  return FALSE;
1712  }
1713 
1714  if( !isset ($newVersion) ) {
1715  $newVersion = $this->schemaVersion;
1716  }
1717 
1718  if( $version == $newVersion ) {
1719  $result = $schema;
1720  } else {
1721  $result = $this->TransformSchema( $schema, 'convert-' . $version . '-' . $newVersion);
1722  }
1723 
1724  if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
1725  fwrite( $fp, $result );
1726  fclose( $fp );
1727  }
1728 
1729  return $result;
1730  }
1731 
1732  // compat for pre-4.3 - jlim
1733  function _file_get_contents($path)
1734  {
1735  if (function_exists('file_get_contents')) return file_get_contents($path);
1736  return join('',file($path));
1737  }
1738 
1755  function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
1756 
1757  // grab current version
1758  if( !( $version = $this->SchemaFileVersion( $filename ) ) ) {
1759  return FALSE;
1760  }
1761 
1762  if( !isset ($newVersion) ) {
1763  $newVersion = $this->schemaVersion;
1764  }
1765 
1766  if( $version == $newVersion ) {
1767  $result = _file_get_contents( $filename );
1768 
1769  // remove unicode BOM if present
1770  if( substr( $result, 0, 3 ) == sprintf( '%c%c%c', 239, 187, 191 ) ) {
1771  $result = substr( $result, 3 );
1772  }
1773  } else {
1774  $result = $this->TransformSchema( $filename, 'convert-' . $version . '-' . $newVersion, 'file' );
1775  }
1776 
1777  if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
1778  fwrite( $fp, $result );
1779  fclose( $fp );
1780  }
1781 
1782  return $result;
1783  }
1784 
1785  function TransformSchema( $schema, $xsl, $schematype='string' )
1786  {
1787  // Fail if XSLT extension is not available
1788  if( ! function_exists( 'xslt_create' ) ) {
1789  return FALSE;
1790  }
1791 
1792  $xsl_file = dirname( __FILE__ ) . '/xsl/' . $xsl . '.xsl';
1793 
1794  // look for xsl
1795  if( !is_readable( $xsl_file ) ) {
1796  return FALSE;
1797  }
1798 
1799  switch( $schematype )
1800  {
1801  case 'file':
1802  if( !is_readable( $schema ) ) {
1803  return FALSE;
1804  }
1805 
1806  $schema = _file_get_contents( $schema );
1807  break;
1808  case 'string':
1809  default:
1810  if( !is_string( $schema ) ) {
1811  return FALSE;
1812  }
1813  }
1814 
1815  $arguments = array (
1816  '/_xml' => $schema,
1817  '/_xsl' => _file_get_contents( $xsl_file )
1818  );
1819 
1820  // create an XSLT processor
1821  $xh = xslt_create ();
1822 
1823  // set error handler
1824  xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler'));
1825 
1826  // process the schema
1827  $result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
1828 
1829  xslt_free ($xh);
1830 
1831  return $result;
1832  }
1833 
1844  function xslt_error_handler( $parser, $errno, $level, $fields ) {
1845  if( is_array( $fields ) ) {
1846  $msg = array(
1847  'Message Type' => ucfirst( $fields['msgtype'] ),
1848  'Message Code' => $fields['code'],
1849  'Message' => $fields['msg'],
1850  'Error Number' => $errno,
1851  'Level' => $level
1852  );
1853 
1854  switch( $fields['URI'] ) {
1855  case 'arg:/_xml':
1856  $msg['Input'] = 'XML';
1857  break;
1858  case 'arg:/_xsl':
1859  $msg['Input'] = 'XSL';
1860  break;
1861  default:
1862  $msg['Input'] = $fields['URI'];
1863  }
1864 
1865  $msg['Line'] = $fields['line'];
1866  } else {
1867  $msg = array(
1868  'Message Type' => 'Error',
1869  'Error Number' => $errno,
1870  'Level' => $level,
1871  'Fields' => var_export( $fields, TRUE )
1872  );
1873  }
1874 
1875  $error_details = $msg['Message Type'] . ' in XSLT Transformation' . "\n"
1876  . '<table>' . "\n";
1877 
1878  foreach( $msg as $label => $details ) {
1879  $error_details .= '<tr><td><b>' . $label . ': </b></td><td>' . htmlentities( $details ) . '</td></tr>' . "\n";
1880  }
1881 
1882  $error_details .= '</table>';
1883 
1884  trigger_error( $error_details, E_USER_ERROR );
1885  }
1886 
1896  function SchemaFileVersion( $filename ) {
1897  // Open the file
1898  if( !($fp = fopen( $filename, 'r' )) ) {
1899  // die( 'Unable to open file' );
1900  return FALSE;
1901  }
1902 
1903  // Process the file
1904  while( $data = fread( $fp, 4096 ) ) {
1905  if( preg_match( $this->versionRegex, $data, $matches ) ) {
1906  return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
1907  }
1908  }
1909 
1910  return FALSE;
1911  }
1912 
1922  function SchemaStringVersion( $xmlstring ) {
1923  if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
1924  return FALSE;
1925  }
1926 
1927  if( preg_match( $this->versionRegex, $xmlstring, $matches ) ) {
1928  return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
1929  }
1930 
1931  return FALSE;
1932  }
1933 
1944  function ExtractSchema( $data = FALSE ) {
1945  $old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM );
1946 
1947  $schema = '<?xml version="1.0"?>' . "\n"
1948  . '<schema version="' . $this->schemaVersion . '">' . "\n";
1949 
1950  if( is_array( $tables = $this->db->MetaTables( 'TABLES' ) ) ) {
1951  foreach( $tables as $table ) {
1952  $schema .= ' <table name="' . $table . '">' . "\n";
1953 
1954  // grab details from database
1955  $rs = $this->db->Execute( 'SELECT * FROM ' . $table . ' WHERE 1=1' );
1956  $fields = $this->db->MetaColumns( $table );
1957  $indexes = $this->db->MetaIndexes( $table );
1958 
1959  if( is_array( $fields ) ) {
1960  foreach( $fields as $details ) {
1961  $extra = '';
1962  $content = array();
1963 
1964  if( $details->max_length > 0 ) {
1965  $extra .= ' size="' . $details->max_length . '"';
1966  }
1967 
1968  if( $details->primary_key ) {
1969  $content[] = '<KEY/>';
1970  } elseif( $details->not_null ) {
1971  $content[] = '<NOTNULL/>';
1972  }
1973 
1974  if( $details->has_default ) {
1975  $content[] = '<DEFAULT value="' . $details->default_value . '"/>';
1976  }
1977 
1978  if( $details->auto_increment ) {
1979  $content[] = '<AUTOINCREMENT/>';
1980  }
1981 
1982  // this stops the creation of 'R' columns,
1983  // AUTOINCREMENT is used to create auto columns
1984  $details->primary_key = 0;
1985  $type = $rs->MetaType( $details );
1986 
1987  $schema .= ' <field name="' . $details->name . '" type="' . $type . '"' . $extra . '>';
1988 
1989  if( !empty( $content ) ) {
1990  $schema .= "\n " . implode( "\n ", $content ) . "\n ";
1991  }
1992 
1993  $schema .= '</field>' . "\n";
1994  }
1995  }
1996 
1997  if( is_array( $indexes ) ) {
1998  foreach( $indexes as $index => $details ) {
1999  $schema .= ' <index name="' . $index . '">' . "\n";
2000 
2001  if( $details['unique'] ) {
2002  $schema .= ' <UNIQUE/>' . "\n";
2003  }
2004 
2005  foreach( $details['columns'] as $column ) {
2006  $schema .= ' <col>' . $column . '</col>' . "\n";
2007  }
2008 
2009  $schema .= ' </index>' . "\n";
2010  }
2011  }
2012 
2013  if( $data ) {
2014  $rs = $this->db->Execute( 'SELECT * FROM ' . $table );
2015 
2016  if( is_object( $rs ) ) {
2017  $schema .= ' <data>' . "\n";
2018 
2019  while( $row = $rs->FetchRow() ) {
2020  foreach( $row as $key => $val ) {
2021  $row[$key] = htmlentities($val);
2022  }
2023 
2024  $schema .= ' <row><f>' . implode( '</f><f>', $row ) . '</f></row>' . "\n";
2025  }
2026 
2027  $schema .= ' </data>' . "\n";
2028  }
2029  }
2030 
2031  $schema .= ' </table>' . "\n";
2032  }
2033  }
2034 
2035  $this->db->SetFetchMode( $old_mode );
2036 
2037  $schema .= '</schema>';
2038  return $schema;
2039  }
2040 
2051  function SetPrefix( $prefix = '', $underscore = TRUE ) {
2052  switch( TRUE ) {
2053  // clear prefix
2054  case empty( $prefix ):
2055  logMsg( 'Cleared prefix' );
2056  $this->objectPrefix = '';
2057  return TRUE;
2058  // prefix too long
2059  case strlen( $prefix ) > XMLS_PREFIX_MAXLEN:
2060  // prefix contains invalid characters
2061  case !preg_match( '/^[a-z][a-z0-9_]+$/i', $prefix ):
2062  logMsg( 'Invalid prefix: ' . $prefix );
2063  return FALSE;
2064  }
2065 
2066  if( $underscore AND substr( $prefix, -1 ) != '_' ) {
2067  $prefix .= '_';
2068  }
2069 
2070  // prefix valid
2071  logMsg( 'Set prefix: ' . $prefix );
2072  $this->objectPrefix = $prefix;
2073  return TRUE;
2074  }
2075 
2084  function prefix( $name = '' ) {
2085  // if prefix is set
2086  if( !empty( $this->objectPrefix ) ) {
2087  // Prepend the object prefix to the table name
2088  // prepend after quote if used
2089  return preg_replace( '/^(`?)(.+)$/', '$1' . $this->objectPrefix . '$2', $name );
2090  }
2091 
2092  // No prefix set. Use name provided.
2093  return $name;
2094  }
2095 
2104  function supportedPlatform( $platform = NULL ) {
2105  $regex = '/^(\w*\|)*' . $this->db->databaseType . '(\|\w*)*$/';
2106 
2107  if( !isset( $platform ) OR preg_match( $regex, $platform ) ) {
2108  logMsg( "Platform $platform is supported" );
2109  return TRUE;
2110  } else {
2111  logMsg( "Platform $platform is NOT supported" );
2112  return FALSE;
2113  }
2114  }
2115 
2121  function clearSQL() {
2122  $this->sqlArray = array();
2123  }
2124 
2133  function addSQL( $sql = NULL ) {
2134  if( is_array( $sql ) ) {
2135  foreach( $sql as $line ) {
2136  $this->addSQL( $line );
2137  }
2138 
2139  return TRUE;
2140  }
2141 
2142  if( is_string( $sql ) ) {
2143  $this->sqlArray[] = $sql;
2144 
2145  // if executeInline is enabled, and either no errors have occurred or continueOnError is enabled, execute SQL.
2146  if( $this->ExecuteInline() && ( $this->success == 2 || $this->ContinueOnError() ) ) {
2147  $saved = $this->db->debug;
2148  $this->db->debug = $this->debug;
2149  $ok = $this->db->Execute( $sql );
2150  $this->db->debug = $saved;
2151 
2152  if( !$ok ) {
2153  if( $this->debug ) {
2154  ADOConnection::outp( $this->db->ErrorMsg() );
2155  }
2156 
2157  $this->success = 1;
2158  }
2159  }
2160 
2161  return TRUE;
2162  }
2163 
2164  return FALSE;
2165  }
2166 
2175  function getSQL( $format = NULL, $sqlArray = NULL ) {
2176  if( !is_array( $sqlArray ) ) {
2177  $sqlArray = $this->sqlArray;
2178  }
2179 
2180  if( !is_array( $sqlArray ) ) {
2181  return FALSE;
2182  }
2183 
2184  switch( strtolower( $format ) ) {
2185  case 'string':
2186  case 'text':
2187  return !empty( $sqlArray ) ? implode( ";\n\n", $sqlArray ) . ';' : '';
2188  case'html':
2189  return !empty( $sqlArray ) ? nl2br( htmlentities( implode( ";\n\n", $sqlArray ) . ';' ) ) : '';
2190  }
2191 
2192  return $this->sqlArray;
2193  }
2194 
2201  function Destroy() {
2202  ini_set("magic_quotes_runtime", $this->mgq );
2203  #set_magic_quotes_runtime( $this->mgq );
2204  }
2205 }
2206 
2212 function logMsg( $msg, $title = NULL, $force = FALSE ) {
2213  if( XMLS_DEBUG or $force ) {
2214  echo '<pre>';
2215 
2216  if( isset( $title ) ) {
2217  echo '<h3>' . htmlentities( $title ) . '</h3>';
2218  }
2219 
2220  if( is_object( $this ) ) {
2221  echo '[' . get_class( $this ) . '] ';
2222  }
2223 
2224  print_r( $msg );
2225 
2226  echo '</pre>';
2227  }
2228 }
SchemaFileVersion( $filename)
_tag_open(&$parser, $tag, $attributes)
ExecuteSchema( $sqlArray=NULL, $continueOnErr=NULL)
_tag_close(&$parser, $tag)
RemoveSchemaString( $schema, $returnSchema=FALSE)
__construct(&$parent, $attributes=NULL)
ConvertSchemaFile( $filename, $newVersion=NULL, $newFile=NULL)
ParseSchemaFile( $filename, $returnSchema=FALSE)
if(isset($_REQUEST['nrows'])) else $rs
Definition: server.php:94
if(!defined('ADODB_ERROR_HANDLER_TYPE')) define('ADODB_ERROR_HANDLER_TYPE' E_USER_ERROR
_file_get_contents($file)
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel='E_DEBUG')
ContinueOnError( $mode=NULL)
_tag_close(&$parser, $tag)
RemoveSchema( $filename, $returnSchema=FALSE)
supportedPlatform( $platform=NULL)
_tag_open(&$parser, $tag, $attributes)
addSQL( $sql=NULL)
_tag_open(&$parser, $tag, $attributes)
_tag_cdata(&$parser, $cdata)
_tag_close(&$parser, $tag)
SaveSQL( $filename='./schema.sql')
supportedPlatform( $platform=NULL)
_tag_close(&$parser, $tag)
addIndex( $attributes)
prefixQuery( $regex, $query, $prefix=NULL)
_tag_cdata(&$parser, $cdata)
ConvertSchemaString( $schema, $newVersion=NULL, $newFile=NULL)
__construct(&$parent, $attributes=NULL)
prefix( $name='')
_tag_cdata(&$parser, $cdata)
__construct(&$parent, $attributes=NULL)
getSQL( $format=NULL, $sqlArray=NULL)
addFieldOpt( $field, $opt, $value=NULL)
_tag_open(&$parser, $tag, $attributes)
xslt_error_handler( $parser, $errno, $level, $fields)
addField( $name, $type, $size=NULL, $opts=NULL)
__construct(&$parent, $attributes=NULL)
_tag_cdata(&$parser, $cdata)
_tag_close(&$parser, $tag)
SetPrefix( $prefix='', $underscore=TRUE)
addData( $attributes)
_tag_cdata(&$parser, $cdata)
SchemaStringVersion( $xmlstring)
TransformSchema( $schema, $xsl, $schematype='string')
_tag_open(&$parser, $tag, $attributes)
ParseSchema( $filename, $returnSchema=FALSE)
_tag_open(&$parser, $tag, $attributes)
ParseSchemaString( $xmlstring, $returnSchema=FALSE)
addData( $cdata)
ExecuteInline( $mode=NULL)
ExtractSchema( $data=FALSE)
addField( $attributes)
__construct(&$parent, $attributes=NULL)
_tag_cdata(&$parser, $cdata)
buildQuery( $sql=NULL)
logMsg( $msg, $title=NULL, $force=FALSE)
$sql
Definition: server.php:84
_tag_close(&$parser, $tag)
PrintSQL( $format='NONE')
SetUpgradeMethod( $method='')