TYPO3 CMS  TYPO3_6-2
adodb-xmlschema03.inc.php
Go to the documentation of this file.
1 <?php
2 // Copyright (c) 2004-2005 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.3' );
75 }
76 
80 if( !defined( 'XMLS_DEFAULT_SCHEMA_VERSION' ) ) {
81  define( 'XMLS_DEFAULT_SCHEMA_VERSION', '0.1' );
82 }
83 
89 if( !defined( 'XMLS_MODE_INSERT' ) ) {
90  define( 'XMLS_MODE_INSERT', 0 );
91 }
92 if( !defined( 'XMLS_MODE_UPDATE' ) ) {
93  define( 'XMLS_MODE_UPDATE', 1 );
94 }
95 if( !defined( 'XMLS_MODE_IGNORE' ) ) {
96  define( 'XMLS_MODE_IGNORE', 2 );
97 }
98 if( !defined( 'XMLS_EXISTING_DATA' ) ) {
99  define( 'XMLS_EXISTING_DATA', XMLS_MODE_INSERT );
100 }
101 
105 if( !defined( 'XMLS_DEFAULT_UPGRADE_METHOD' ) ) {
106  define( 'XMLS_DEFAULT_UPGRADE_METHOD', 'ALTER' );
107 }
108 
112 if( !defined( '_ADODB_LAYER' ) ) {
113  require( 'adodb.inc.php' );
114  require( 'adodb-datadict.inc.php' );
115 }
116 
124 class dbObject {
125 
129  var $parent;
130 
134  var $currentElement;
135 
139  function dbObject( &$parent, $attributes = NULL ) {
140  $this->parent = $parent;
141  }
142 
148  function _tag_open( &$parser, $tag, $attributes ) {
149 
150  }
151 
157  function _tag_cdata( &$parser, $cdata ) {
158 
159  }
160 
166  function _tag_close( &$parser, $tag ) {
167 
168  }
169 
170  function create(&$xmls) {
171  return array();
172  }
173 
177  function destroy() {
178  unset( $this );
179  }
180 
188  function supportedPlatform( $platform = NULL ) {
189  return is_object( $this->parent ) ? $this->parent->supportedPlatform( $platform ) : TRUE;
190  }
191 
198  function prefix( $name = '' ) {
199  return is_object( $this->parent ) ? $this->parent->prefix( $name ) : $name;
200  }
201 
208  function FieldID( $field ) {
209  return strtoupper( preg_replace( '/^`(.+)`$/', '$1', $field ) );
210  }
211 }
212 
224 class dbTable extends dbObject {
225 
229  var $name;
230 
234  var $fields = array();
235 
239  var $indexes = array();
240 
244  var $opts = array();
245 
249  var $current_field;
250 
255  var $drop_table;
256 
261  var $drop_field = array();
262 
267  var $currentPlatform = true;
268 
269 
276  function dbTable( &$parent, $attributes = NULL ) {
277  $this->parent = $parent;
278  $this->name = $this->prefix($attributes['NAME']);
279  }
280 
287  function _tag_open( &$parser, $tag, $attributes ) {
288  $this->currentElement = strtoupper( $tag );
289 
290  switch( $this->currentElement ) {
291  case 'INDEX':
292  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
293  xml_set_object( $parser, $this->addIndex( $attributes ) );
294  }
295  break;
296  case 'DATA':
297  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
298  xml_set_object( $parser, $this->addData( $attributes ) );
299  }
300  break;
301  case 'DROP':
302  $this->drop();
303  break;
304  case 'FIELD':
305  // Add a field
306  $fieldName = $attributes['NAME'];
307  $fieldType = $attributes['TYPE'];
308  $fieldSize = isset( $attributes['SIZE'] ) ? $attributes['SIZE'] : NULL;
309  $fieldOpts = !empty( $attributes['OPTS'] ) ? $attributes['OPTS'] : NULL;
310 
311  $this->addField( $fieldName, $fieldType, $fieldSize, $fieldOpts );
312  break;
313  case 'KEY':
314  case 'NOTNULL':
315  case 'AUTOINCREMENT':
316  case 'DEFDATE':
317  case 'DEFTIMESTAMP':
318  case 'UNSIGNED':
319  // Add a field option
320  $this->addFieldOpt( $this->current_field, $this->currentElement );
321  break;
322  case 'DEFAULT':
323  // Add a field option to the table object
324 
325  // Work around ADOdb datadict issue that misinterprets empty strings.
326  if( $attributes['VALUE'] == '' ) {
327  $attributes['VALUE'] = " '' ";
328  }
329 
330  $this->addFieldOpt( $this->current_field, $this->currentElement, $attributes['VALUE'] );
331  break;
332  case 'OPT':
333  case 'CONSTRAINT':
334  // Accept platform-specific options
335  $this->currentPlatform = ( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) );
336  break;
337  default:
338  // print_r( array( $tag, $attributes ) );
339  }
340  }
341 
347  function _tag_cdata( &$parser, $cdata ) {
348  switch( $this->currentElement ) {
349  // Table/field constraint
350  case 'CONSTRAINT':
351  if( isset( $this->current_field ) ) {
352  $this->addFieldOpt( $this->current_field, $this->currentElement, $cdata );
353  } else {
354  $this->addTableOpt( $cdata );
355  }
356  break;
357  // Table/field option
358  case 'OPT':
359  if( isset( $this->current_field ) ) {
360  $this->addFieldOpt( $this->current_field, $cdata );
361  } else {
362  $this->addTableOpt( $cdata );
363  }
364  break;
365  default:
366 
367  }
368  }
369 
375  function _tag_close( &$parser, $tag ) {
376  $this->currentElement = '';
377 
378  switch( strtoupper( $tag ) ) {
379  case 'TABLE':
380  $this->parent->addSQL( $this->create( $this->parent ) );
381  xml_set_object( $parser, $this->parent );
382  $this->destroy();
383  break;
384  case 'FIELD':
385  unset($this->current_field);
386  break;
387  case 'OPT':
388  case 'CONSTRAINT':
389  $this->currentPlatform = true;
390  break;
391  default:
392 
393  }
394  }
395 
402  function addIndex( $attributes ) {
403  $name = strtoupper( $attributes['NAME'] );
404  $this->indexes[$name] = new dbIndex( $this, $attributes );
405  return $this->indexes[$name];
406  }
407 
414  function addData( $attributes ) {
415  if( !isset( $this->data ) ) {
416  $this->data = new dbData( $this, $attributes );
417  }
418  return $this->data;
419  }
420 
450  function addField( $name, $type, $size = NULL, $opts = NULL ) {
451  $field_id = $this->FieldID( $name );
452 
453  // Set the field index so we know where we are
454  $this->current_field = $field_id;
455 
456  // Set the field name (required)
457  $this->fields[$field_id]['NAME'] = $name;
458 
459  // Set the field type (required)
460  $this->fields[$field_id]['TYPE'] = $type;
461 
462  // Set the field size (optional)
463  if( isset( $size ) ) {
464  $this->fields[$field_id]['SIZE'] = $size;
465  }
466 
467  // Set the field options
468  if( isset( $opts ) ) {
469  $this->fields[$field_id]['OPTS'] = array($opts);
470  } else {
471  $this->fields[$field_id]['OPTS'] = array();
472  }
473  }
474 
486  function addFieldOpt( $field, $opt, $value = NULL ) {
487  if( $this->currentPlatform ) {
488  if( !isset( $value ) ) {
489  $this->fields[$this->FieldID( $field )]['OPTS'][] = $opt;
490  // Add the option and value
491  } else {
492  $this->fields[$this->FieldID( $field )]['OPTS'][] = array( $opt => $value );
493  }
494  }
495  }
496 
506  function addTableOpt( $opt ) {
507  if(isset($this->currentPlatform)) {
508  $this->opts[$this->parent->db->databaseType] = $opt;
509  }
510  return $this->opts;
511  }
512 
513 
520  function create( &$xmls ) {
521  $sql = array();
522 
523  // drop any existing indexes
524  if( is_array( $legacy_indexes = $xmls->dict->MetaIndexes( $this->name ) ) ) {
525  foreach( $legacy_indexes as $index => $index_details ) {
526  $sql[] = $xmls->dict->DropIndexSQL( $index, $this->name );
527  }
528  }
529 
530  // remove fields to be dropped from table object
531  foreach( $this->drop_field as $field ) {
532  unset( $this->fields[$field] );
533  }
534 
535  // if table exists
536  if( is_array( $legacy_fields = $xmls->dict->MetaColumns( $this->name ) ) ) {
537  // drop table
538  if( $this->drop_table ) {
539  $sql[] = $xmls->dict->DropTableSQL( $this->name );
540 
541  return $sql;
542  }
543 
544  // drop any existing fields not in schema
545  foreach( $legacy_fields as $field_id => $field ) {
546  if( !isset( $this->fields[$field_id] ) ) {
547  $sql[] = $xmls->dict->DropColumnSQL( $this->name, $field->name );
548  }
549  }
550  // if table doesn't exist
551  } else {
552  if( $this->drop_table ) {
553  return $sql;
554  }
555 
556  $legacy_fields = array();
557  }
558 
559  // Loop through the field specifier array, building the associative array for the field options
560  $fldarray = array();
561 
562  foreach( $this->fields as $field_id => $finfo ) {
563  // Set an empty size if it isn't supplied
564  if( !isset( $finfo['SIZE'] ) ) {
565  $finfo['SIZE'] = '';
566  }
567 
568  // Initialize the field array with the type and size
569  $fldarray[$field_id] = array(
570  'NAME' => $finfo['NAME'],
571  'TYPE' => $finfo['TYPE'],
572  'SIZE' => $finfo['SIZE']
573  );
574 
575  // Loop through the options array and add the field options.
576  if( isset( $finfo['OPTS'] ) ) {
577  foreach( $finfo['OPTS'] as $opt ) {
578  // Option has an argument.
579  if( is_array( $opt ) ) {
580  $key = key( $opt );
581  $value = $opt[key( $opt )];
582  @$fldarray[$field_id][$key] .= $value;
583  // Option doesn't have arguments
584  } else {
585  $fldarray[$field_id][$opt] = $opt;
586  }
587  }
588  }
589  }
590 
591  if( empty( $legacy_fields ) ) {
592  // Create the new table
593  $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
594  logMsg( end( $sql ), 'Generated CreateTableSQL' );
595  } else {
596  // Upgrade an existing table
597  logMsg( "Upgrading {$this->name} using '{$xmls->upgrade}'" );
598  switch( $xmls->upgrade ) {
599  // Use ChangeTableSQL
600  case 'ALTER':
601  logMsg( 'Generated ChangeTableSQL (ALTERing table)' );
602  $sql[] = $xmls->dict->ChangeTableSQL( $this->name, $fldarray, $this->opts );
603  break;
604  case 'REPLACE':
605  logMsg( 'Doing upgrade REPLACE (testing)' );
606  $sql[] = $xmls->dict->DropTableSQL( $this->name );
607  $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
608  break;
609  // ignore table
610  default:
611  return array();
612  }
613  }
614 
615  foreach( $this->indexes as $index ) {
616  $sql[] = $index->create( $xmls );
617  }
618 
619  if( isset( $this->data ) ) {
620  $sql[] = $this->data->create( $xmls );
621  }
622 
623  return $sql;
624  }
625 
629  function drop() {
630  if( isset( $this->current_field ) ) {
631  // Drop the current field
632  logMsg( "Dropping field '{$this->current_field}' from table '{$this->name}'" );
633  // $this->drop_field[$this->current_field] = $xmls->dict->DropColumnSQL( $this->name, $this->current_field );
634  $this->drop_field[$this->current_field] = $this->current_field;
635  } else {
636  // Drop the current table
637  logMsg( "Dropping table '{$this->name}'" );
638  // $this->drop_table = $xmls->dict->DropTableSQL( $this->name );
639  $this->drop_table = TRUE;
640  }
641  }
642 }
643 
655 class dbIndex extends dbObject {
656 
660  var $name;
661 
665  var $opts = array();
666 
670  var $columns = array();
671 
676  var $drop = FALSE;
677 
686  function dbIndex( &$parent, $attributes = NULL ) {
687  $this->parent = $parent;
688 
689  $this->name = $this->prefix ($attributes['NAME']);
690  }
691 
700  function _tag_open( &$parser, $tag, $attributes ) {
701  $this->currentElement = strtoupper( $tag );
702 
703  switch( $this->currentElement ) {
704  case 'DROP':
705  $this->drop();
706  break;
707  case 'CLUSTERED':
708  case 'BITMAP':
709  case 'UNIQUE':
710  case 'FULLTEXT':
711  case 'HASH':
712  // Add index Option
713  $this->addIndexOpt( $this->currentElement );
714  break;
715  default:
716  // print_r( array( $tag, $attributes ) );
717  }
718  }
719 
727  function _tag_cdata( &$parser, $cdata ) {
728  switch( $this->currentElement ) {
729  // Index field name
730  case 'COL':
731  $this->addField( $cdata );
732  break;
733  default:
734 
735  }
736  }
737 
743  function _tag_close( &$parser, $tag ) {
744  $this->currentElement = '';
745 
746  switch( strtoupper( $tag ) ) {
747  case 'INDEX':
748  xml_set_object( $parser, $this->parent );
749  break;
750  }
751  }
752 
759  function addField( $name ) {
760  $this->columns[$this->FieldID( $name )] = $name;
761 
762  // Return the field list
763  return $this->columns;
764  }
765 
772  function addIndexOpt( $opt ) {
773  $this->opts[] = $opt;
774 
775  // Return the options list
776  return $this->opts;
777  }
778 
785  function create( &$xmls ) {
786  if( $this->drop ) {
787  return NULL;
788  }
789 
790  // eliminate any columns that aren't in the table
791  foreach( $this->columns as $id => $col ) {
792  if( !isset( $this->parent->fields[$id] ) ) {
793  unset( $this->columns[$id] );
794  }
795  }
796 
797  return $xmls->dict->CreateIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts );
798  }
799 
803  function drop() {
804  $this->drop = TRUE;
805  }
806 }
807 
817 class dbData extends dbObject {
818 
819  var $data = array();
820 
821  var $row;
822 
831  function dbData( &$parent, $attributes = NULL ) {
832  $this->parent = $parent;
833  }
834 
843  function _tag_open( &$parser, $tag, $attributes ) {
844  $this->currentElement = strtoupper( $tag );
845 
846  switch( $this->currentElement ) {
847  case 'ROW':
848  $this->row = count( $this->data );
849  $this->data[$this->row] = array();
850  break;
851  case 'F':
852  $this->addField($attributes);
853  default:
854  // print_r( array( $tag, $attributes ) );
855  }
856  }
857 
865  function _tag_cdata( &$parser, $cdata ) {
866  switch( $this->currentElement ) {
867  // Index field name
868  case 'F':
869  $this->addData( $cdata );
870  break;
871  default:
872 
873  }
874  }
875 
881  function _tag_close( &$parser, $tag ) {
882  $this->currentElement = '';
883 
884  switch( strtoupper( $tag ) ) {
885  case 'DATA':
886  xml_set_object( $parser, $this->parent );
887  break;
888  }
889  }
890 
897  function addField( $attributes ) {
898  // check we're in a valid row
899  if( !isset( $this->row ) || !isset( $this->data[$this->row] ) ) {
900  return;
901  }
902 
903  // Set the field index so we know where we are
904  if( isset( $attributes['NAME'] ) ) {
905  $this->current_field = $this->FieldID( $attributes['NAME'] );
906  } else {
907  $this->current_field = count( $this->data[$this->row] );
908  }
909 
910  // initialise data
911  if( !isset( $this->data[$this->row][$this->current_field] ) ) {
912  $this->data[$this->row][$this->current_field] = '';
913  }
914  }
915 
922  function addData( $cdata ) {
923  // check we're in a valid field
924  if ( isset( $this->data[$this->row][$this->current_field] ) ) {
925  // add data to field
926  $this->data[$this->row][$this->current_field] .= $cdata;
927  }
928  }
929 
936  function create( &$xmls ) {
937  $table = $xmls->dict->TableName($this->parent->name);
938  $table_field_count = count($this->parent->fields);
939  $tables = $xmls->db->MetaTables();
940  $sql = array();
941 
942  $ukeys = $xmls->db->MetaPrimaryKeys( $table );
943  if( !empty( $this->parent->indexes ) and !empty( $ukeys ) ) {
944  foreach( $this->parent->indexes as $indexObj ) {
945  if( !in_array( $indexObj->name, $ukeys ) ) $ukeys[] = $indexObj->name;
946  }
947  }
948 
949  // eliminate any columns that aren't in the table
950  foreach( $this->data as $row ) {
951  $table_fields = $this->parent->fields;
952  $fields = array();
953  $rawfields = array(); // Need to keep some of the unprocessed data on hand.
954 
955  foreach( $row as $field_id => $field_data ) {
956  if( !array_key_exists( $field_id, $table_fields ) ) {
957  if( is_numeric( $field_id ) ) {
958  $field_id = reset( array_keys( $table_fields ) );
959  } else {
960  continue;
961  }
962  }
963 
964  $name = $table_fields[$field_id]['NAME'];
965 
966  switch( $table_fields[$field_id]['TYPE'] ) {
967  case 'I':
968  case 'I1':
969  case 'I2':
970  case 'I4':
971  case 'I8':
972  $fields[$name] = intval($field_data);
973  break;
974  case 'C':
975  case 'C2':
976  case 'X':
977  case 'X2':
978  default:
979  $fields[$name] = $xmls->db->qstr( $field_data );
980  $rawfields[$name] = $field_data;
981  }
982 
983  unset($table_fields[$field_id]);
984 
985  }
986 
987  // check that at least 1 column is specified
988  if( empty( $fields ) ) {
989  continue;
990  }
991 
992  // check that no required columns are missing
993  if( count( $fields ) < $table_field_count ) {
994  foreach( $table_fields as $field ) {
995  if( isset( $field['OPTS'] ) and ( in_array( 'NOTNULL', $field['OPTS'] ) || in_array( 'KEY', $field['OPTS'] ) ) && !in_array( 'AUTOINCREMENT', $field['OPTS'] ) ) {
996  continue(2);
997  }
998  }
999  }
1000 
1001  // The rest of this method deals with updating existing data records.
1002 
1003  if( !in_array( $table, $tables ) or ( $mode = $xmls->existingData() ) == XMLS_MODE_INSERT ) {
1004  // Table doesn't yet exist, so it's safe to insert.
1005  logMsg( "$table doesn't exist, inserting or mode is INSERT" );
1006  $sql[] = 'INSERT INTO '. $table .' ('. implode( ',', array_keys( $fields ) ) .') VALUES ('. implode( ',', $fields ) .')';
1007  continue;
1008  }
1009 
1010  // Prepare to test for potential violations. Get primary keys and unique indexes
1011  $mfields = array_merge( $fields, $rawfields );
1012  $keyFields = array_intersect( $ukeys, array_keys( $mfields ) );
1013 
1014  if( empty( $ukeys ) or count( $keyFields ) == 0 ) {
1015  // No unique keys in schema, so safe to insert
1016  logMsg( "Either schema or data has no unique keys, so safe to insert" );
1017  $sql[] = 'INSERT INTO '. $table .' ('. implode( ',', array_keys( $fields ) ) .') VALUES ('. implode( ',', $fields ) .')';
1018  continue;
1019  }
1020 
1021  // Select record containing matching unique keys.
1022  $where = '';
1023  foreach( $ukeys as $key ) {
1024  if( isset( $mfields[$key] ) and $mfields[$key] ) {
1025  if( $where ) $where .= ' AND ';
1026  $where .= $key . ' = ' . $xmls->db->qstr( $mfields[$key] );
1027  }
1028  }
1029  $records = $xmls->db->Execute( 'SELECT * FROM ' . $table . ' WHERE ' . $where );
1030  switch( $records->RecordCount() ) {
1031  case 0:
1032  // No matching record, so safe to insert.
1033  logMsg( "No matching records. Inserting new row with unique data" );
1034  $sql[] = $xmls->db->GetInsertSQL( $records, $mfields );
1035  break;
1036  case 1:
1037  // Exactly one matching record, so we can update if the mode permits.
1038  logMsg( "One matching record..." );
1039  if( $mode == XMLS_MODE_UPDATE ) {
1040  logMsg( "...Updating existing row from unique data" );
1041  $sql[] = $xmls->db->GetUpdateSQL( $records, $mfields );
1042  }
1043  break;
1044  default:
1045  // More than one matching record; the result is ambiguous, so we must ignore the row.
1046  logMsg( "More than one matching record. Ignoring row." );
1047  }
1048  }
1049  return $sql;
1050  }
1051 }
1052 
1059 class dbQuerySet extends dbObject {
1060 
1064  var $queries = array();
1065 
1069  var $query;
1070 
1074  var $prefixKey = '';
1075 
1079  var $prefixMethod = 'AUTO';
1080 
1087  function dbQuerySet( &$parent, $attributes = NULL ) {
1088  $this->parent = $parent;
1089 
1090  // Overrides the manual prefix key
1091  if( isset( $attributes['KEY'] ) ) {
1092  $this->prefixKey = $attributes['KEY'];
1093  }
1094 
1095  $prefixMethod = isset( $attributes['PREFIXMETHOD'] ) ? strtoupper( trim( $attributes['PREFIXMETHOD'] ) ) : '';
1096 
1097  // Enables or disables automatic prefix prepending
1098  switch( $prefixMethod ) {
1099  case 'AUTO':
1100  $this->prefixMethod = 'AUTO';
1101  break;
1102  case 'MANUAL':
1103  $this->prefixMethod = 'MANUAL';
1104  break;
1105  case 'NONE':
1106  $this->prefixMethod = 'NONE';
1107  break;
1108  }
1109  }
1110 
1117  function _tag_open( &$parser, $tag, $attributes ) {
1118  $this->currentElement = strtoupper( $tag );
1119 
1120  switch( $this->currentElement ) {
1121  case 'QUERY':
1122  // Create a new query in a SQL queryset.
1123  // Ignore this query set if a platform is specified and it's different than the
1124  // current connection platform.
1125  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
1126  $this->newQuery();
1127  } else {
1128  $this->discardQuery();
1129  }
1130  break;
1131  default:
1132  // print_r( array( $tag, $attributes ) );
1133  }
1134  }
1135 
1139  function _tag_cdata( &$parser, $cdata ) {
1140  switch( $this->currentElement ) {
1141  // Line of queryset SQL data
1142  case 'QUERY':
1143  $this->buildQuery( $cdata );
1144  break;
1145  default:
1146 
1147  }
1148  }
1149 
1155  function _tag_close( &$parser, $tag ) {
1156  $this->currentElement = '';
1157 
1158  switch( strtoupper( $tag ) ) {
1159  case 'QUERY':
1160  // Add the finished query to the open query set.
1161  $this->addQuery();
1162  break;
1163  case 'SQL':
1164  $this->parent->addSQL( $this->create( $this->parent ) );
1165  xml_set_object( $parser, $this->parent );
1166  $this->destroy();
1167  break;
1168  default:
1169 
1170  }
1171  }
1172 
1178  function newQuery() {
1179  $this->query = '';
1180 
1181  return TRUE;
1182  }
1183 
1189  function discardQuery() {
1190  unset( $this->query );
1191 
1192  return TRUE;
1193  }
1194 
1201  function buildQuery( $sql = NULL ) {
1202  if( !isset( $this->query ) OR empty( $sql ) ) {
1203  return FALSE;
1204  }
1205 
1206  $this->query .= $sql;
1207 
1208  return $this->query;
1209  }
1210 
1216  function addQuery() {
1217  if( !isset( $this->query ) ) {
1218  return FALSE;
1219  }
1220 
1221  $this->queries[] = $return = trim($this->query);
1222 
1223  unset( $this->query );
1224 
1225  return $return;
1226  }
1227 
1234  function create( &$xmls ) {
1235  foreach( $this->queries as $id => $query ) {
1236  switch( $this->prefixMethod ) {
1237  case 'AUTO':
1238  // Enable auto prefix replacement
1239 
1240  // Process object prefix.
1241  // Evaluate SQL statements to prepend prefix to objects
1242  $query = $this->prefixQuery( '/^\s*((?is)INSERT\s+(INTO\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
1243  $query = $this->prefixQuery( '/^\s*((?is)UPDATE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
1244  $query = $this->prefixQuery( '/^\s*((?is)DELETE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
1245 
1246  // SELECT statements aren't working yet
1247  #$data = preg_replace( '/(?ias)(^\s*SELECT\s+.*\s+FROM)\s+(\W\s*,?\s*)+((?i)\s+WHERE.*$)/', "\1 $prefix\2 \3", $data );
1248 
1249  case 'MANUAL':
1250  // If prefixKey is set and has a value then we use it to override the default constant XMLS_PREFIX.
1251  // If prefixKey is not set, we use the default constant XMLS_PREFIX
1252  if( isset( $this->prefixKey ) AND( $this->prefixKey !== '' ) ) {
1253  // Enable prefix override
1254  $query = str_replace( $this->prefixKey, $xmls->objectPrefix, $query );
1255  } else {
1256  // Use default replacement
1257  $query = str_replace( XMLS_PREFIX , $xmls->objectPrefix, $query );
1258  }
1259  }
1260 
1261  $this->queries[$id] = trim( $query );
1262  }
1263 
1264  // Return the query set array
1265  return $this->queries;
1266  }
1267 
1276  function prefixQuery( $regex, $query, $prefix = NULL ) {
1277  if( !isset( $prefix ) ) {
1278  return $query;
1279  }
1280 
1281  if( preg_match( $regex, $query, $match ) ) {
1282  $preamble = $match[1];
1283  $postamble = $match[5];
1284  $objectList = explode( ',', $match[3] );
1285  // $prefix = $prefix . '_';
1286 
1287  $prefixedList = '';
1288 
1289  foreach( $objectList as $object ) {
1290  if( $prefixedList !== '' ) {
1291  $prefixedList .= ', ';
1292  }
1293 
1294  $prefixedList .= $prefix . trim( $object );
1295  }
1296 
1297  $query = $preamble . ' ' . $prefixedList . ' ' . $postamble;
1298  }
1299 
1300  return $query;
1301  }
1302 }
1303 
1317 class adoSchema {
1318 
1323  var $sqlArray;
1324 
1329  var $db;
1330 
1335  var $dict;
1336 
1341  var $currentElement = '';
1342 
1347  var $upgrade = '';
1348 
1353  var $objectPrefix = '';
1354 
1359  var $mgq;
1360 
1365  var $debug;
1366 
1371  var $versionRegex = '/<schema.*?( version="([^"]*)")?.*?>/';
1372 
1377  var $schemaVersion;
1378 
1382  var $success;
1383 
1387  var $executeInline;
1388 
1392  var $continueOnError;
1393 
1398 
1408  function adoSchema( $db ) {
1409  // Initialize the environment
1410  $this->mgq = get_magic_quotes_runtime();
1411  #set_magic_quotes_runtime(0);
1412  ini_set("magic_quotes_runtime", 0);
1413 
1414  $this->db = $db;
1415  $this->debug = $this->db->debug;
1416  $this->dict = NewDataDictionary( $this->db );
1417  $this->sqlArray = array();
1418  $this->schemaVersion = XMLS_SCHEMA_VERSION;
1419  $this->executeInline( XMLS_EXECUTE_INLINE );
1420  $this->continueOnError( XMLS_CONTINUE_ON_ERROR );
1421  $this->existingData( XMLS_EXISTING_DATA );
1422  $this->setUpgradeMethod();
1423  }
1424 
1441  function SetUpgradeMethod( $method = '' ) {
1442  if( !is_string( $method ) ) {
1443  return FALSE;
1444  }
1445 
1446  $method = strtoupper( $method );
1447 
1448  // Handle the upgrade methods
1449  switch( $method ) {
1450  case 'ALTER':
1451  $this->upgrade = $method;
1452  break;
1453  case 'REPLACE':
1454  $this->upgrade = $method;
1455  break;
1456  case 'BEST':
1457  $this->upgrade = 'ALTER';
1458  break;
1459  case 'NONE':
1460  $this->upgrade = 'NONE';
1461  break;
1462  default:
1463  // Use default if no legitimate method is passed.
1464  $this->upgrade = XMLS_DEFAULT_UPGRADE_METHOD;
1465  }
1466 
1467  return $this->upgrade;
1468  }
1469 
1489  function ExistingData( $mode = NULL ) {
1490  if( is_int( $mode ) ) {
1491  switch( $mode ) {
1492  case XMLS_MODE_UPDATE:
1493  $mode = XMLS_MODE_UPDATE;
1494  break;
1495  case XMLS_MODE_IGNORE:
1496  $mode = XMLS_MODE_IGNORE;
1497  break;
1498  case XMLS_MODE_INSERT:
1499  $mode = XMLS_MODE_INSERT;
1500  break;
1501  default:
1502  $mode = XMLS_EXISTING_DATA;
1503  break;
1504  }
1505  $this->existingData = $mode;
1506  }
1507 
1508  return $this->existingData;
1509  }
1510 
1524  function ExecuteInline( $mode = NULL ) {
1525  if( is_bool( $mode ) ) {
1526  $this->executeInline = $mode;
1527  }
1528 
1529  return $this->executeInline;
1530  }
1531 
1545  function ContinueOnError( $mode = NULL ) {
1546  if( is_bool( $mode ) ) {
1547  $this->continueOnError = $mode;
1548  }
1549 
1550  return $this->continueOnError;
1551  }
1552 
1566  function ParseSchema( $filename, $returnSchema = FALSE ) {
1567  return $this->ParseSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
1568  }
1569 
1591  function ParseSchemaFile( $filename, $returnSchema = FALSE ) {
1592  // Open the file
1593  if( !($fp = fopen( $filename, 'r' )) ) {
1594  logMsg( 'Unable to open file' );
1595  return FALSE;
1596  }
1597 
1598  // do version detection here
1599  if( $this->SchemaFileVersion( $filename ) != $this->schemaVersion ) {
1600  logMsg( 'Invalid Schema Version' );
1601  return FALSE;
1602  }
1603 
1604  if( $returnSchema ) {
1605  $xmlstring = '';
1606  while( $data = fread( $fp, 4096 ) ) {
1607  $xmlstring .= $data . "\n";
1608  }
1609  return $xmlstring;
1610  }
1611 
1612  $this->success = 2;
1613 
1614  $xmlParser = $this->create_parser();
1615  // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
1616  $previousValueOfEntityLoader = libxml_disable_entity_loader(TRUE);
1617 
1618  // Process the file
1619  while( $data = fread( $fp, 4096 ) ) {
1620  if( !xml_parse( $xmlParser, $data, feof( $fp ) ) ) {
1621  die( sprintf(
1622  "XML error: %s at line %d",
1623  xml_error_string( xml_get_error_code( $xmlParser) ),
1624  xml_get_current_line_number( $xmlParser)
1625  ) );
1626  }
1627  }
1628 
1629  libxml_disable_entity_loader($previousValueOfEntityLoader);
1630  xml_parser_free( $xmlParser );
1631 
1632  return $this->sqlArray;
1633  }
1634 
1646  function ParseSchemaString( $xmlstring, $returnSchema = FALSE ) {
1647  if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
1648  logMsg( 'Empty or Invalid Schema' );
1649  return FALSE;
1650  }
1651 
1652  // do version detection here
1653  if( $this->SchemaStringVersion( $xmlstring ) != $this->schemaVersion ) {
1654  logMsg( 'Invalid Schema Version' );
1655  return FALSE;
1656  }
1657 
1658  if( $returnSchema ) {
1659  return $xmlstring;
1660  }
1661 
1662  $this->success = 2;
1663 
1664  $xmlParser = $this->create_parser();
1665  // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
1666  $previousValueOfEntityLoader = libxml_disable_entity_loader(TRUE);
1667 
1668  if( !xml_parse( $xmlParser, $xmlstring, TRUE ) ) {
1669  die( sprintf(
1670  "XML error: %s at line %d",
1671  xml_error_string( xml_get_error_code( $xmlParser) ),
1672  xml_get_current_line_number( $xmlParser)
1673  ) );
1674  }
1675 
1676  libxml_disable_entity_loader($previousValueOfEntityLoader);
1677  xml_parser_free( $xmlParser );
1678 
1679  return $this->sqlArray;
1680  }
1681 
1693  function RemoveSchema( $filename, $returnSchema = FALSE ) {
1694  return $this->RemoveSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
1695  }
1696 
1708  function RemoveSchemaString( $schema, $returnSchema = FALSE ) {
1709 
1710  // grab current version
1711  if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
1712  return FALSE;
1713  }
1714 
1715  return $this->ParseSchemaString( $this->TransformSchema( $schema, 'remove-' . $version), $returnSchema );
1716  }
1717 
1731  function ExecuteSchema( $sqlArray = NULL, $continueOnErr = NULL ) {
1732  if( !is_bool( $continueOnErr ) ) {
1733  $continueOnErr = $this->ContinueOnError();
1734  }
1735 
1736  if( !isset( $sqlArray ) ) {
1737  $sqlArray = $this->sqlArray;
1738  }
1739 
1740  if( !is_array( $sqlArray ) ) {
1741  $this->success = 0;
1742  } else {
1743  $this->success = $this->dict->ExecuteSQLArray( $sqlArray, $continueOnErr );
1744  }
1745 
1746  return $this->success;
1747  }
1748 
1758  function PrintSQL( $format = 'NONE' ) {
1759  $sqlArray = null;
1760  return $this->getSQL( $format, $sqlArray );
1761  }
1762 
1772  function SaveSQL( $filename = './schema.sql' ) {
1773 
1774  if( !isset( $sqlArray ) ) {
1775  $sqlArray = $this->sqlArray;
1776  }
1777  if( !isset( $sqlArray ) ) {
1778  return FALSE;
1779  }
1780 
1781  $fp = fopen( $filename, "w" );
1782 
1783  foreach( $sqlArray as $key => $query ) {
1784  fwrite( $fp, $query . ";\n" );
1785  }
1786  fclose( $fp );
1787  }
1788 
1796  function create_parser() {
1797  // Create the parser
1798  $xmlParser = xml_parser_create();
1799  xml_set_object( $xmlParser, $this );
1800 
1801  // Initialize the XML callback functions
1802  xml_set_element_handler( $xmlParser, '_tag_open', '_tag_close' );
1803  xml_set_character_data_handler( $xmlParser, '_tag_cdata' );
1804 
1805  return $xmlParser;
1806  }
1807 
1813  function _tag_open( &$parser, $tag, $attributes ) {
1814  switch( strtoupper( $tag ) ) {
1815  case 'TABLE':
1816  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
1817  $this->obj = new dbTable( $this, $attributes );
1818  xml_set_object( $parser, $this->obj );
1819  }
1820  break;
1821  case 'SQL':
1822  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
1823  $this->obj = new dbQuerySet( $this, $attributes );
1824  xml_set_object( $parser, $this->obj );
1825  }
1826  break;
1827  default:
1828  // print_r( array( $tag, $attributes ) );
1829  }
1830 
1831  }
1832 
1838  function _tag_cdata( &$parser, $cdata ) {
1839  }
1840 
1847  function _tag_close( &$parser, $tag ) {
1848 
1849  }
1850 
1867  function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
1868 
1869  // grab current version
1870  if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
1871  return FALSE;
1872  }
1873 
1874  if( !isset ($newVersion) ) {
1875  $newVersion = $this->schemaVersion;
1876  }
1877 
1878  if( $version == $newVersion ) {
1879  $result = $schema;
1880  } else {
1881  $result = $this->TransformSchema( $schema, 'convert-' . $version . '-' . $newVersion);
1882  }
1883 
1884  if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
1885  fwrite( $fp, $result );
1886  fclose( $fp );
1887  }
1888 
1889  return $result;
1890  }
1891 
1892  /*
1893  // compat for pre-4.3 - jlim
1894  function _file_get_contents($path)
1895  {
1896  if (function_exists('file_get_contents')) return file_get_contents($path);
1897  return join('',file($path));
1898  }*/
1899 
1916  function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
1917 
1918  // grab current version
1919  if( !( $version = $this->SchemaFileVersion( $filename ) ) ) {
1920  return FALSE;
1921  }
1922 
1923  if( !isset ($newVersion) ) {
1924  $newVersion = $this->schemaVersion;
1925  }
1926 
1927  if( $version == $newVersion ) {
1928  $result = _file_get_contents( $filename );
1929 
1930  // remove unicode BOM if present
1931  if( substr( $result, 0, 3 ) == sprintf( '%c%c%c', 239, 187, 191 ) ) {
1932  $result = substr( $result, 3 );
1933  }
1934  } else {
1935  $result = $this->TransformSchema( $filename, 'convert-' . $version . '-' . $newVersion, 'file' );
1936  }
1937 
1938  if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
1939  fwrite( $fp, $result );
1940  fclose( $fp );
1941  }
1942 
1943  return $result;
1944  }
1945 
1946  function TransformSchema( $schema, $xsl, $schematype='string' )
1947  {
1948  // Fail if XSLT extension is not available
1949  if( ! function_exists( 'xslt_create' ) ) {
1950  return FALSE;
1951  }
1952 
1953  $xsl_file = dirname( __FILE__ ) . '/xsl/' . $xsl . '.xsl';
1954 
1955  // look for xsl
1956  if( !is_readable( $xsl_file ) ) {
1957  return FALSE;
1958  }
1959 
1960  switch( $schematype )
1961  {
1962  case 'file':
1963  if( !is_readable( $schema ) ) {
1964  return FALSE;
1965  }
1966 
1967  $schema = _file_get_contents( $schema );
1968  break;
1969  case 'string':
1970  default:
1971  if( !is_string( $schema ) ) {
1972  return FALSE;
1973  }
1974  }
1975 
1976  $arguments = array (
1977  '/_xml' => $schema,
1978  '/_xsl' => _file_get_contents( $xsl_file )
1979  );
1980 
1981  // create an XSLT processor
1982  $xh = xslt_create ();
1983 
1984  // set error handler
1985  xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler'));
1986 
1987  // process the schema
1988  $result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
1989 
1990  xslt_free ($xh);
1991 
1992  return $result;
1993  }
1994 
2005  function xslt_error_handler( $parser, $errno, $level, $fields ) {
2006  if( is_array( $fields ) ) {
2007  $msg = array(
2008  'Message Type' => ucfirst( $fields['msgtype'] ),
2009  'Message Code' => $fields['code'],
2010  'Message' => $fields['msg'],
2011  'Error Number' => $errno,
2012  'Level' => $level
2013  );
2014 
2015  switch( $fields['URI'] ) {
2016  case 'arg:/_xml':
2017  $msg['Input'] = 'XML';
2018  break;
2019  case 'arg:/_xsl':
2020  $msg['Input'] = 'XSL';
2021  break;
2022  default:
2023  $msg['Input'] = $fields['URI'];
2024  }
2025 
2026  $msg['Line'] = $fields['line'];
2027  } else {
2028  $msg = array(
2029  'Message Type' => 'Error',
2030  'Error Number' => $errno,
2031  'Level' => $level,
2032  'Fields' => var_export( $fields, TRUE )
2033  );
2034  }
2035 
2036  $error_details = $msg['Message Type'] . ' in XSLT Transformation' . "\n"
2037  . '<table>' . "\n";
2038 
2039  foreach( $msg as $label => $details ) {
2040  $error_details .= '<tr><td><b>' . $label . ': </b></td><td>' . htmlentities( $details ) . '</td></tr>' . "\n";
2041  }
2042 
2043  $error_details .= '</table>';
2044 
2045  trigger_error( $error_details, E_USER_ERROR );
2046  }
2047 
2057  function SchemaFileVersion( $filename ) {
2058  // Open the file
2059  if( !($fp = fopen( $filename, 'r' )) ) {
2060  // die( 'Unable to open file' );
2061  return FALSE;
2062  }
2063 
2064  // Process the file
2065  while( $data = fread( $fp, 4096 ) ) {
2066  if( preg_match( $this->versionRegex, $data, $matches ) ) {
2067  return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
2068  }
2069  }
2070 
2071  return FALSE;
2072  }
2073 
2083  function SchemaStringVersion( $xmlstring ) {
2084  if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
2085  return FALSE;
2086  }
2087 
2088  if( preg_match( $this->versionRegex, $xmlstring, $matches ) ) {
2089  return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
2090  }
2091 
2092  return FALSE;
2093  }
2094 
2108  function ExtractSchema( $data = FALSE, $indent = ' ', $prefix = '' , $stripprefix=false) {
2109  $old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM );
2110 
2111  $schema = '<?xml version="1.0"?>' . "\n"
2112  . '<schema version="' . $this->schemaVersion . '">' . "\n";
2113 
2114  if( is_array( $tables = $this->db->MetaTables( 'TABLES' , ($prefix) ? $prefix.'%' : '') ) ) {
2115  foreach( $tables as $table ) {
2116  if ($stripprefix) $table = str_replace(str_replace('\\_', '_', $pfx ), '', $table);
2117  $schema .= $indent . '<table name="' . htmlentities( $table ) . '">' . "\n";
2118 
2119  // grab details from database
2120  $rs = $this->db->Execute( 'SELECT * FROM ' . $table . ' WHERE -1' );
2121  $fields = $this->db->MetaColumns( $table );
2122  $indexes = $this->db->MetaIndexes( $table );
2123 
2124  if( is_array( $fields ) ) {
2125  foreach( $fields as $details ) {
2126  $extra = '';
2127  $content = array();
2128 
2129  if( isset($details->max_length) && $details->max_length > 0 ) {
2130  $extra .= ' size="' . $details->max_length . '"';
2131  }
2132 
2133  if( isset($details->primary_key) && $details->primary_key ) {
2134  $content[] = '<KEY/>';
2135  } elseif( isset($details->not_null) && $details->not_null ) {
2136  $content[] = '<NOTNULL/>';
2137  }
2138 
2139  if( isset($details->has_default) && $details->has_default ) {
2140  $content[] = '<DEFAULT value="' . htmlentities( $details->default_value ) . '"/>';
2141  }
2142 
2143  if( isset($details->auto_increment) && $details->auto_increment ) {
2144  $content[] = '<AUTOINCREMENT/>';
2145  }
2146 
2147  if( isset($details->unsigned) && $details->unsigned ) {
2148  $content[] = '<UNSIGNED/>';
2149  }
2150 
2151  // this stops the creation of 'R' columns,
2152  // AUTOINCREMENT is used to create auto columns
2153  $details->primary_key = 0;
2154  $type = $rs->MetaType( $details );
2155 
2156  $schema .= str_repeat( $indent, 2 ) . '<field name="' . htmlentities( $details->name ) . '" type="' . $type . '"' . $extra;
2157 
2158  if( !empty( $content ) ) {
2159  $schema .= ">\n" . str_repeat( $indent, 3 )
2160  . implode( "\n" . str_repeat( $indent, 3 ), $content ) . "\n"
2161  . str_repeat( $indent, 2 ) . '</field>' . "\n";
2162  } else {
2163  $schema .= "/>\n";
2164  }
2165  }
2166  }
2167 
2168  if( is_array( $indexes ) ) {
2169  foreach( $indexes as $index => $details ) {
2170  $schema .= str_repeat( $indent, 2 ) . '<index name="' . $index . '">' . "\n";
2171 
2172  if( $details['unique'] ) {
2173  $schema .= str_repeat( $indent, 3 ) . '<UNIQUE/>' . "\n";
2174  }
2175 
2176  foreach( $details['columns'] as $column ) {
2177  $schema .= str_repeat( $indent, 3 ) . '<col>' . htmlentities( $column ) . '</col>' . "\n";
2178  }
2179 
2180  $schema .= str_repeat( $indent, 2 ) . '</index>' . "\n";
2181  }
2182  }
2183 
2184  if( $data ) {
2185  $rs = $this->db->Execute( 'SELECT * FROM ' . $table );
2186 
2187  if( is_object( $rs ) && !$rs->EOF ) {
2188  $schema .= str_repeat( $indent, 2 ) . "<data>\n";
2189 
2190  while( $row = $rs->FetchRow() ) {
2191  foreach( $row as $key => $val ) {
2192  if ( $val != htmlentities( $val ) ) {
2193  $row[$key] = '<![CDATA[' . $val . ']]>';
2194  }
2195  }
2196 
2197  $schema .= str_repeat( $indent, 3 ) . '<row><f>' . implode( '</f><f>', $row ) . "</f></row>\n";
2198  }
2199 
2200  $schema .= str_repeat( $indent, 2 ) . "</data>\n";
2201  }
2202  }
2203 
2204  $schema .= $indent . "</table>\n";
2205  }
2206  }
2207 
2208  $this->db->SetFetchMode( $old_mode );
2209 
2210  $schema .= '</schema>';
2211  return $schema;
2212  }
2213 
2224  function SetPrefix( $prefix = '', $underscore = TRUE ) {
2225  switch( TRUE ) {
2226  // clear prefix
2227  case empty( $prefix ):
2228  logMsg( 'Cleared prefix' );
2229  $this->objectPrefix = '';
2230  return TRUE;
2231  // prefix too long
2232  case strlen( $prefix ) > XMLS_PREFIX_MAXLEN:
2233  // prefix contains invalid characters
2234  case !preg_match( '/^[a-z][a-z0-9_]+$/i', $prefix ):
2235  logMsg( 'Invalid prefix: ' . $prefix );
2236  return FALSE;
2237  }
2238 
2239  if( $underscore AND substr( $prefix, -1 ) != '_' ) {
2240  $prefix .= '_';
2241  }
2242 
2243  // prefix valid
2244  logMsg( 'Set prefix: ' . $prefix );
2245  $this->objectPrefix = $prefix;
2246  return TRUE;
2247  }
2248 
2257  function prefix( $name = '' ) {
2258  // if prefix is set
2259  if( !empty( $this->objectPrefix ) ) {
2260  // Prepend the object prefix to the table name
2261  // prepend after quote if used
2262  return preg_replace( '/^(`?)(.+)$/', '$1' . $this->objectPrefix . '$2', $name );
2263  }
2264 
2265  // No prefix set. Use name provided.
2266  return $name;
2267  }
2268 
2277  function supportedPlatform( $platform = NULL ) {
2278  if( !empty( $platform ) ) {
2279  $regex = '/(^|\|)' . $this->db->databaseType . '(\||$)/i';
2280 
2281  if( preg_match( '/^- /', $platform ) ) {
2282  if (preg_match ( $regex, substr( $platform, 2 ) ) ) {
2283  logMsg( 'Platform ' . $platform . ' is NOT supported' );
2284  return FALSE;
2285  }
2286  } else {
2287  if( !preg_match ( $regex, $platform ) ) {
2288  logMsg( 'Platform ' . $platform . ' is NOT supported' );
2289  return FALSE;
2290  }
2291  }
2292  }
2293 
2294  logMsg( 'Platform ' . $platform . ' is supported' );
2295  return TRUE;
2296  }
2297 
2303  function clearSQL() {
2304  $this->sqlArray = array();
2305  }
2306 
2315  function addSQL( $sql = NULL ) {
2316  if( is_array( $sql ) ) {
2317  foreach( $sql as $line ) {
2318  $this->addSQL( $line );
2319  }
2320 
2321  return TRUE;
2322  }
2323 
2324  if( is_string( $sql ) ) {
2325  $this->sqlArray[] = $sql;
2326 
2327  // if executeInline is enabled, and either no errors have occurred or continueOnError is enabled, execute SQL.
2328  if( $this->ExecuteInline() && ( $this->success == 2 || $this->ContinueOnError() ) ) {
2329  $saved = $this->db->debug;
2330  $this->db->debug = $this->debug;
2331  $ok = $this->db->Execute( $sql );
2332  $this->db->debug = $saved;
2333 
2334  if( !$ok ) {
2335  if( $this->debug ) {
2336  ADOConnection::outp( $this->db->ErrorMsg() );
2337  }
2338 
2339  $this->success = 1;
2340  }
2341  }
2342 
2343  return TRUE;
2344  }
2345 
2346  return FALSE;
2347  }
2348 
2357  function getSQL( $format = NULL, $sqlArray = NULL ) {
2358  if( !is_array( $sqlArray ) ) {
2359  $sqlArray = $this->sqlArray;
2360  }
2361 
2362  if( !is_array( $sqlArray ) ) {
2363  return FALSE;
2364  }
2365 
2366  switch( strtolower( $format ) ) {
2367  case 'string':
2368  case 'text':
2369  return !empty( $sqlArray ) ? implode( ";\n\n", $sqlArray ) . ';' : '';
2370  case'html':
2371  return !empty( $sqlArray ) ? nl2br( htmlentities( implode( ";\n\n", $sqlArray ) . ';' ) ) : '';
2372  }
2373 
2374  return $this->sqlArray;
2375  }
2376 
2383  function Destroy() {
2384  ini_set("magic_quotes_runtime", $this->mgq );
2385  #set_magic_quotes_runtime( $this->mgq );
2386  unset( $this );
2387  }
2388 }
2389 
2395 function logMsg( $msg, $title = NULL, $force = FALSE ) {
2396  if( XMLS_DEBUG or $force ) {
2397  echo '<pre>';
2398 
2399  if( isset( $title ) ) {
2400  echo '<h3>' . htmlentities( $title ) . '</h3>';
2401  }
2402 
2403  if( @is_object( $this ) ) {
2404  echo '[' . get_class( $this ) . '] ';
2405  }
2406 
2407  print_r( $msg );
2408 
2409  echo '</pre>';
2410  }
2411 }
dbTable(&$parent, $attributes=NULL)
SchemaFileVersion( $filename)
_tag_open(&$parser, $tag, $attributes)
ExecuteSchema( $sqlArray=NULL, $continueOnErr=NULL)
_tag_close(&$parser, $tag)
RemoveSchemaString( $schema, $returnSchema=FALSE)
_file_get_contents($file)
ConvertSchemaFile( $filename, $newVersion=NULL, $newFile=NULL)
$sql
Definition: server.php:82
ParseSchemaFile( $filename, $returnSchema=FALSE)
if(!defined('ADODB_ERROR_HANDLER_TYPE')) define('ADODB_ERROR_HANDLER_TYPE' E_USER_ERROR
if(isset($_REQUEST['nrows'])) else $rs
Definition: server.php:92
ContinueOnError( $mode=NULL)
_tag_close(&$parser, $tag)
RemoveSchema( $filename, $returnSchema=FALSE)
logMsg( $msg, $title=NULL, $force=FALSE)
supportedPlatform( $platform=NULL)
_tag_open(&$parser, $tag, $attributes)
_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)
dbIndex(&$parent, $attributes=NULL)
ConvertSchemaString( $schema, $newVersion=NULL, $newFile=NULL)
die
Definition: index.php:6
_tag_cdata(&$parser, $cdata)
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)
ExistingData( $mode=NULL)
_tag_cdata(&$parser, $cdata)
_tag_close(&$parser, $tag)
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
SetPrefix( $prefix='', $underscore=TRUE)
addData( $attributes)
dbObject(&$parent, $attributes=NULL)
_tag_cdata(&$parser, $cdata)
SchemaStringVersion( $xmlstring)
TransformSchema( $schema, $xsl, $schematype='string')
ExtractSchema( $data=FALSE, $indent=' ', $prefix='', $stripprefix=false)
dbData(&$parent, $attributes=NULL)
_tag_open(&$parser, $tag, $attributes)
ParseSchema( $filename, $returnSchema=FALSE)
_tag_open(&$parser, $tag, $attributes)
ParseSchemaString( $xmlstring, $returnSchema=FALSE)
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel=E_DEBUG)
ExecuteInline( $mode=NULL)
addField( $attributes)
_tag_cdata(&$parser, $cdata)
dbQuerySet(&$parent, $attributes=NULL)
buildQuery( $sql=NULL)
_tag_close(&$parser, $tag)
PrintSQL( $format='NONE')
SetUpgradeMethod( $method='')