TYPO3 CMS  TYPO3_7-6
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 __construct( &$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  }
179 
187  function supportedPlatform( $platform = NULL ) {
188  return is_object( $this->parent ) ? $this->parent->supportedPlatform( $platform ) : TRUE;
189  }
190 
197  function prefix( $name = '' ) {
198  return is_object( $this->parent ) ? $this->parent->prefix( $name ) : $name;
199  }
200 
207  function FieldID( $field ) {
208  return strtoupper( preg_replace( '/^`(.+)`$/', '$1', $field ) );
209  }
210 }
211 
223 class dbTable extends dbObject {
224 
228  var $name;
229 
233  var $fields = array();
234 
238  var $indexes = array();
239 
243  var $opts = array();
244 
248  var $current_field;
249 
254  var $drop_table;
255 
260  var $drop_field = array();
261 
266  var $currentPlatform = true;
267 
268 
275  function __construct( &$parent, $attributes = NULL ) {
276  $this->parent = $parent;
277  $this->name = $this->prefix($attributes['NAME']);
278  }
279 
286  function _tag_open( &$parser, $tag, $attributes ) {
287  $this->currentElement = strtoupper( $tag );
288 
289  switch( $this->currentElement ) {
290  case 'INDEX':
291  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
292  xml_set_object( $parser, $this->addIndex( $attributes ) );
293  }
294  break;
295  case 'DATA':
296  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
297  xml_set_object( $parser, $this->addData( $attributes ) );
298  }
299  break;
300  case 'DROP':
301  $this->drop();
302  break;
303  case 'FIELD':
304  // Add a field
305  $fieldName = $attributes['NAME'];
306  $fieldType = $attributes['TYPE'];
307  $fieldSize = isset( $attributes['SIZE'] ) ? $attributes['SIZE'] : NULL;
308  $fieldOpts = !empty( $attributes['OPTS'] ) ? $attributes['OPTS'] : NULL;
309 
310  $this->addField( $fieldName, $fieldType, $fieldSize, $fieldOpts );
311  break;
312  case 'KEY':
313  case 'NOTNULL':
314  case 'AUTOINCREMENT':
315  case 'DEFDATE':
316  case 'DEFTIMESTAMP':
317  case 'UNSIGNED':
318  // Add a field option
319  $this->addFieldOpt( $this->current_field, $this->currentElement );
320  break;
321  case 'DEFAULT':
322  // Add a field option to the table object
323 
324  // Work around ADOdb datadict issue that misinterprets empty strings.
325  if( $attributes['VALUE'] == '' ) {
326  $attributes['VALUE'] = " '' ";
327  }
328 
329  $this->addFieldOpt( $this->current_field, $this->currentElement, $attributes['VALUE'] );
330  break;
331  case 'OPT':
332  case 'CONSTRAINT':
333  // Accept platform-specific options
334  $this->currentPlatform = ( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) );
335  break;
336  default:
337  // print_r( array( $tag, $attributes ) );
338  }
339  }
340 
346  function _tag_cdata( &$parser, $cdata ) {
347  switch( $this->currentElement ) {
348  // Table/field constraint
349  case 'CONSTRAINT':
350  if( isset( $this->current_field ) ) {
351  $this->addFieldOpt( $this->current_field, $this->currentElement, $cdata );
352  } else {
353  $this->addTableOpt( $cdata );
354  }
355  break;
356  // Table/field option
357  case 'OPT':
358  if( isset( $this->current_field ) ) {
359  $this->addFieldOpt( $this->current_field, $cdata );
360  } else {
361  $this->addTableOpt( $cdata );
362  }
363  break;
364  default:
365 
366  }
367  }
368 
374  function _tag_close( &$parser, $tag ) {
375  $this->currentElement = '';
376 
377  switch( strtoupper( $tag ) ) {
378  case 'TABLE':
379  $this->parent->addSQL( $this->create( $this->parent ) );
380  xml_set_object( $parser, $this->parent );
381  $this->destroy();
382  break;
383  case 'FIELD':
384  unset($this->current_field);
385  break;
386  case 'OPT':
387  case 'CONSTRAINT':
388  $this->currentPlatform = true;
389  break;
390  default:
391 
392  }
393  }
394 
401  function addIndex( $attributes ) {
402  $name = strtoupper( $attributes['NAME'] );
403  $this->indexes[$name] = new dbIndex( $this, $attributes );
404  return $this->indexes[$name];
405  }
406 
413  function addData( $attributes ) {
414  if( !isset( $this->data ) ) {
415  $this->data = new dbData( $this, $attributes );
416  }
417  return $this->data;
418  }
419 
449  function addField( $name, $type, $size = NULL, $opts = NULL ) {
450  $field_id = $this->FieldID( $name );
451 
452  // Set the field index so we know where we are
453  $this->current_field = $field_id;
454 
455  // Set the field name (required)
456  $this->fields[$field_id]['NAME'] = $name;
457 
458  // Set the field type (required)
459  $this->fields[$field_id]['TYPE'] = $type;
460 
461  // Set the field size (optional)
462  if( isset( $size ) ) {
463  $this->fields[$field_id]['SIZE'] = $size;
464  }
465 
466  // Set the field options
467  if( isset( $opts ) ) {
468  $this->fields[$field_id]['OPTS'] = array($opts);
469  } else {
470  $this->fields[$field_id]['OPTS'] = array();
471  }
472  }
473 
485  function addFieldOpt( $field, $opt, $value = NULL ) {
486  if( $this->currentPlatform ) {
487  if( !isset( $value ) ) {
488  $this->fields[$this->FieldID( $field )]['OPTS'][] = $opt;
489  // Add the option and value
490  } else {
491  $this->fields[$this->FieldID( $field )]['OPTS'][] = array( $opt => $value );
492  }
493  }
494  }
495 
505  function addTableOpt( $opt ) {
506  if(isset($this->currentPlatform)) {
507  $this->opts[$this->parent->db->databaseType] = $opt;
508  }
509  return $this->opts;
510  }
511 
512 
519  function create( &$xmls ) {
520  $sql = array();
521 
522  // drop any existing indexes
523  if( is_array( $legacy_indexes = $xmls->dict->MetaIndexes( $this->name ) ) ) {
524  foreach( $legacy_indexes as $index => $index_details ) {
525  $sql[] = $xmls->dict->DropIndexSQL( $index, $this->name );
526  }
527  }
528 
529  // remove fields to be dropped from table object
530  foreach( $this->drop_field as $field ) {
531  unset( $this->fields[$field] );
532  }
533 
534  // if table exists
535  if( is_array( $legacy_fields = $xmls->dict->MetaColumns( $this->name ) ) ) {
536  // drop table
537  if( $this->drop_table ) {
538  $sql[] = $xmls->dict->DropTableSQL( $this->name );
539 
540  return $sql;
541  }
542 
543  // drop any existing fields not in schema
544  foreach( $legacy_fields as $field_id => $field ) {
545  if( !isset( $this->fields[$field_id] ) ) {
546  $sql[] = $xmls->dict->DropColumnSQL( $this->name, $field->name );
547  }
548  }
549  // if table doesn't exist
550  } else {
551  if( $this->drop_table ) {
552  return $sql;
553  }
554 
555  $legacy_fields = array();
556  }
557 
558  // Loop through the field specifier array, building the associative array for the field options
559  $fldarray = array();
560 
561  foreach( $this->fields as $field_id => $finfo ) {
562  // Set an empty size if it isn't supplied
563  if( !isset( $finfo['SIZE'] ) ) {
564  $finfo['SIZE'] = '';
565  }
566 
567  // Initialize the field array with the type and size
568  $fldarray[$field_id] = array(
569  'NAME' => $finfo['NAME'],
570  'TYPE' => $finfo['TYPE'],
571  'SIZE' => $finfo['SIZE']
572  );
573 
574  // Loop through the options array and add the field options.
575  if( isset( $finfo['OPTS'] ) ) {
576  foreach( $finfo['OPTS'] as $opt ) {
577  // Option has an argument.
578  if( is_array( $opt ) ) {
579  $key = key( $opt );
580  $value = $opt[key( $opt )];
581  @$fldarray[$field_id][$key] .= $value;
582  // Option doesn't have arguments
583  } else {
584  $fldarray[$field_id][$opt] = $opt;
585  }
586  }
587  }
588  }
589 
590  if( empty( $legacy_fields ) ) {
591  // Create the new table
592  $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
593  logMsg( end( $sql ), 'Generated CreateTableSQL' );
594  } else {
595  // Upgrade an existing table
596  logMsg( "Upgrading {$this->name} using '{$xmls->upgrade}'" );
597  switch( $xmls->upgrade ) {
598  // Use ChangeTableSQL
599  case 'ALTER':
600  logMsg( 'Generated ChangeTableSQL (ALTERing table)' );
601  $sql[] = $xmls->dict->ChangeTableSQL( $this->name, $fldarray, $this->opts );
602  break;
603  case 'REPLACE':
604  logMsg( 'Doing upgrade REPLACE (testing)' );
605  $sql[] = $xmls->dict->DropTableSQL( $this->name );
606  $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
607  break;
608  // ignore table
609  default:
610  return array();
611  }
612  }
613 
614  foreach( $this->indexes as $index ) {
615  $sql[] = $index->create( $xmls );
616  }
617 
618  if( isset( $this->data ) ) {
619  $sql[] = $this->data->create( $xmls );
620  }
621 
622  return $sql;
623  }
624 
628  function drop() {
629  if( isset( $this->current_field ) ) {
630  // Drop the current field
631  logMsg( "Dropping field '{$this->current_field}' from table '{$this->name}'" );
632  // $this->drop_field[$this->current_field] = $xmls->dict->DropColumnSQL( $this->name, $this->current_field );
633  $this->drop_field[$this->current_field] = $this->current_field;
634  } else {
635  // Drop the current table
636  logMsg( "Dropping table '{$this->name}'" );
637  // $this->drop_table = $xmls->dict->DropTableSQL( $this->name );
638  $this->drop_table = TRUE;
639  }
640  }
641 }
642 
654 class dbIndex extends dbObject {
655 
659  var $name;
660 
664  var $opts = array();
665 
669  var $columns = array();
670 
675  var $drop = FALSE;
676 
685  function __construct( &$parent, $attributes = NULL ) {
686  $this->parent = $parent;
687 
688  $this->name = $this->prefix ($attributes['NAME']);
689  }
690 
699  function _tag_open( &$parser, $tag, $attributes ) {
700  $this->currentElement = strtoupper( $tag );
701 
702  switch( $this->currentElement ) {
703  case 'DROP':
704  $this->drop();
705  break;
706  case 'CLUSTERED':
707  case 'BITMAP':
708  case 'UNIQUE':
709  case 'FULLTEXT':
710  case 'HASH':
711  // Add index Option
712  $this->addIndexOpt( $this->currentElement );
713  break;
714  default:
715  // print_r( array( $tag, $attributes ) );
716  }
717  }
718 
726  function _tag_cdata( &$parser, $cdata ) {
727  switch( $this->currentElement ) {
728  // Index field name
729  case 'COL':
730  $this->addField( $cdata );
731  break;
732  default:
733 
734  }
735  }
736 
742  function _tag_close( &$parser, $tag ) {
743  $this->currentElement = '';
744 
745  switch( strtoupper( $tag ) ) {
746  case 'INDEX':
747  xml_set_object( $parser, $this->parent );
748  break;
749  }
750  }
751 
758  function addField( $name ) {
759  $this->columns[$this->FieldID( $name )] = $name;
760 
761  // Return the field list
762  return $this->columns;
763  }
764 
771  function addIndexOpt( $opt ) {
772  $this->opts[] = $opt;
773 
774  // Return the options list
775  return $this->opts;
776  }
777 
784  function create( &$xmls ) {
785  if( $this->drop ) {
786  return NULL;
787  }
788 
789  // eliminate any columns that aren't in the table
790  foreach( $this->columns as $id => $col ) {
791  if( !isset( $this->parent->fields[$id] ) ) {
792  unset( $this->columns[$id] );
793  }
794  }
795 
796  return $xmls->dict->CreateIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts );
797  }
798 
802  function drop() {
803  $this->drop = TRUE;
804  }
805 }
806 
816 class dbData extends dbObject {
817 
818  var $data = array();
819 
820  var $row;
821 
830  function __construct( &$parent, $attributes = NULL ) {
831  $this->parent = $parent;
832  }
833 
842  function _tag_open( &$parser, $tag, $attributes ) {
843  $this->currentElement = strtoupper( $tag );
844 
845  switch( $this->currentElement ) {
846  case 'ROW':
847  $this->row = count( $this->data );
848  $this->data[$this->row] = array();
849  break;
850  case 'F':
851  $this->addField($attributes);
852  default:
853  // print_r( array( $tag, $attributes ) );
854  }
855  }
856 
864  function _tag_cdata( &$parser, $cdata ) {
865  switch( $this->currentElement ) {
866  // Index field name
867  case 'F':
868  $this->addData( $cdata );
869  break;
870  default:
871 
872  }
873  }
874 
880  function _tag_close( &$parser, $tag ) {
881  $this->currentElement = '';
882 
883  switch( strtoupper( $tag ) ) {
884  case 'DATA':
885  xml_set_object( $parser, $this->parent );
886  break;
887  }
888  }
889 
896  function addField( $attributes ) {
897  // check we're in a valid row
898  if( !isset( $this->row ) || !isset( $this->data[$this->row] ) ) {
899  return;
900  }
901 
902  // Set the field index so we know where we are
903  if( isset( $attributes['NAME'] ) ) {
904  $this->current_field = $this->FieldID( $attributes['NAME'] );
905  } else {
906  $this->current_field = count( $this->data[$this->row] );
907  }
908 
909  // initialise data
910  if( !isset( $this->data[$this->row][$this->current_field] ) ) {
911  $this->data[$this->row][$this->current_field] = '';
912  }
913  }
914 
921  function addData( $cdata ) {
922  // check we're in a valid field
923  if ( isset( $this->data[$this->row][$this->current_field] ) ) {
924  // add data to field
925  $this->data[$this->row][$this->current_field] .= $cdata;
926  }
927  }
928 
935  function create( &$xmls ) {
936  $table = $xmls->dict->TableName($this->parent->name);
937  $table_field_count = count($this->parent->fields);
938  $tables = $xmls->db->MetaTables();
939  $sql = array();
940 
941  $ukeys = $xmls->db->MetaPrimaryKeys( $table );
942  if( !empty( $this->parent->indexes ) and !empty( $ukeys ) ) {
943  foreach( $this->parent->indexes as $indexObj ) {
944  if( !in_array( $indexObj->name, $ukeys ) ) $ukeys[] = $indexObj->name;
945  }
946  }
947 
948  // eliminate any columns that aren't in the table
949  foreach( $this->data as $row ) {
950  $table_fields = $this->parent->fields;
951  $fields = array();
952  $rawfields = array(); // Need to keep some of the unprocessed data on hand.
953 
954  foreach( $row as $field_id => $field_data ) {
955  if( !array_key_exists( $field_id, $table_fields ) ) {
956  if( is_numeric( $field_id ) ) {
957  $field_id = reset( array_keys( $table_fields ) );
958  } else {
959  continue;
960  }
961  }
962 
963  $name = $table_fields[$field_id]['NAME'];
964 
965  switch( $table_fields[$field_id]['TYPE'] ) {
966  case 'I':
967  case 'I1':
968  case 'I2':
969  case 'I4':
970  case 'I8':
971  $fields[$name] = intval($field_data);
972  break;
973  case 'C':
974  case 'C2':
975  case 'X':
976  case 'X2':
977  default:
978  $fields[$name] = $xmls->db->qstr( $field_data );
979  $rawfields[$name] = $field_data;
980  }
981 
982  unset($table_fields[$field_id]);
983 
984  }
985 
986  // check that at least 1 column is specified
987  if( empty( $fields ) ) {
988  continue;
989  }
990 
991  // check that no required columns are missing
992  if( count( $fields ) < $table_field_count ) {
993  foreach( $table_fields as $field ) {
994  if( isset( $field['OPTS'] ) and ( in_array( 'NOTNULL', $field['OPTS'] ) || in_array( 'KEY', $field['OPTS'] ) ) && !in_array( 'AUTOINCREMENT', $field['OPTS'] ) ) {
995  continue(2);
996  }
997  }
998  }
999 
1000  // The rest of this method deals with updating existing data records.
1001 
1002  if( !in_array( $table, $tables ) or ( $mode = $xmls->existingData() ) == XMLS_MODE_INSERT ) {
1003  // Table doesn't yet exist, so it's safe to insert.
1004  logMsg( "$table doesn't exist, inserting or mode is INSERT" );
1005  $sql[] = 'INSERT INTO '. $table .' ('. implode( ',', array_keys( $fields ) ) .') VALUES ('. implode( ',', $fields ) .')';
1006  continue;
1007  }
1008 
1009  // Prepare to test for potential violations. Get primary keys and unique indexes
1010  $mfields = array_merge( $fields, $rawfields );
1011  $keyFields = array_intersect( $ukeys, array_keys( $mfields ) );
1012 
1013  if( empty( $ukeys ) or count( $keyFields ) == 0 ) {
1014  // No unique keys in schema, so safe to insert
1015  logMsg( "Either schema or data has no unique keys, so safe to insert" );
1016  $sql[] = 'INSERT INTO '. $table .' ('. implode( ',', array_keys( $fields ) ) .') VALUES ('. implode( ',', $fields ) .')';
1017  continue;
1018  }
1019 
1020  // Select record containing matching unique keys.
1021  $where = '';
1022  foreach( $ukeys as $key ) {
1023  if( isset( $mfields[$key] ) and $mfields[$key] ) {
1024  if( $where ) $where .= ' AND ';
1025  $where .= $key . ' = ' . $xmls->db->qstr( $mfields[$key] );
1026  }
1027  }
1028  $records = $xmls->db->Execute( 'SELECT * FROM ' . $table . ' WHERE ' . $where );
1029  switch( $records->RecordCount() ) {
1030  case 0:
1031  // No matching record, so safe to insert.
1032  logMsg( "No matching records. Inserting new row with unique data" );
1033  $sql[] = $xmls->db->GetInsertSQL( $records, $mfields );
1034  break;
1035  case 1:
1036  // Exactly one matching record, so we can update if the mode permits.
1037  logMsg( "One matching record..." );
1038  if( $mode == XMLS_MODE_UPDATE ) {
1039  logMsg( "...Updating existing row from unique data" );
1040  $sql[] = $xmls->db->GetUpdateSQL( $records, $mfields );
1041  }
1042  break;
1043  default:
1044  // More than one matching record; the result is ambiguous, so we must ignore the row.
1045  logMsg( "More than one matching record. Ignoring row." );
1046  }
1047  }
1048  return $sql;
1049  }
1050 }
1051 
1058 class dbQuerySet extends dbObject {
1059 
1063  var $queries = array();
1064 
1068  var $query;
1069 
1073  var $prefixKey = '';
1074 
1078  var $prefixMethod = 'AUTO';
1079 
1086  function __construct( &$parent, $attributes = NULL ) {
1087  $this->parent = $parent;
1088 
1089  // Overrides the manual prefix key
1090  if( isset( $attributes['KEY'] ) ) {
1091  $this->prefixKey = $attributes['KEY'];
1092  }
1093 
1094  $prefixMethod = isset( $attributes['PREFIXMETHOD'] ) ? strtoupper( trim( $attributes['PREFIXMETHOD'] ) ) : '';
1095 
1096  // Enables or disables automatic prefix prepending
1097  switch( $prefixMethod ) {
1098  case 'AUTO':
1099  $this->prefixMethod = 'AUTO';
1100  break;
1101  case 'MANUAL':
1102  $this->prefixMethod = 'MANUAL';
1103  break;
1104  case 'NONE':
1105  $this->prefixMethod = 'NONE';
1106  break;
1107  }
1108  }
1109 
1116  function _tag_open( &$parser, $tag, $attributes ) {
1117  $this->currentElement = strtoupper( $tag );
1118 
1119  switch( $this->currentElement ) {
1120  case 'QUERY':
1121  // Create a new query in a SQL queryset.
1122  // Ignore this query set if a platform is specified and it's different than the
1123  // current connection platform.
1124  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
1125  $this->newQuery();
1126  } else {
1127  $this->discardQuery();
1128  }
1129  break;
1130  default:
1131  // print_r( array( $tag, $attributes ) );
1132  }
1133  }
1134 
1138  function _tag_cdata( &$parser, $cdata ) {
1139  switch( $this->currentElement ) {
1140  // Line of queryset SQL data
1141  case 'QUERY':
1142  $this->buildQuery( $cdata );
1143  break;
1144  default:
1145 
1146  }
1147  }
1148 
1154  function _tag_close( &$parser, $tag ) {
1155  $this->currentElement = '';
1156 
1157  switch( strtoupper( $tag ) ) {
1158  case 'QUERY':
1159  // Add the finished query to the open query set.
1160  $this->addQuery();
1161  break;
1162  case 'SQL':
1163  $this->parent->addSQL( $this->create( $this->parent ) );
1164  xml_set_object( $parser, $this->parent );
1165  $this->destroy();
1166  break;
1167  default:
1168 
1169  }
1170  }
1171 
1177  function newQuery() {
1178  $this->query = '';
1179 
1180  return TRUE;
1181  }
1182 
1188  function discardQuery() {
1189  unset( $this->query );
1190 
1191  return TRUE;
1192  }
1193 
1200  function buildQuery( $sql = NULL ) {
1201  if( !isset( $this->query ) OR empty( $sql ) ) {
1202  return FALSE;
1203  }
1204 
1205  $this->query .= $sql;
1206 
1207  return $this->query;
1208  }
1209 
1215  function addQuery() {
1216  if( !isset( $this->query ) ) {
1217  return FALSE;
1218  }
1219 
1220  $this->queries[] = $return = trim($this->query);
1221 
1222  unset( $this->query );
1223 
1224  return $return;
1225  }
1226 
1233  function create( &$xmls ) {
1234  foreach( $this->queries as $id => $query ) {
1235  switch( $this->prefixMethod ) {
1236  case 'AUTO':
1237  // Enable auto prefix replacement
1238 
1239  // Process object prefix.
1240  // Evaluate SQL statements to prepend prefix to objects
1241  $query = $this->prefixQuery( '/^\s*((?is)INSERT\s+(INTO\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
1242  $query = $this->prefixQuery( '/^\s*((?is)UPDATE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
1243  $query = $this->prefixQuery( '/^\s*((?is)DELETE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
1244 
1245  // SELECT statements aren't working yet
1246  #$data = preg_replace( '/(?ias)(^\s*SELECT\s+.*\s+FROM)\s+(\W\s*,?\s*)+((?i)\s+WHERE.*$)/', "\1 $prefix\2 \3", $data );
1247 
1248  case 'MANUAL':
1249  // If prefixKey is set and has a value then we use it to override the default constant XMLS_PREFIX.
1250  // If prefixKey is not set, we use the default constant XMLS_PREFIX
1251  if( isset( $this->prefixKey ) AND( $this->prefixKey !== '' ) ) {
1252  // Enable prefix override
1253  $query = str_replace( $this->prefixKey, $xmls->objectPrefix, $query );
1254  } else {
1255  // Use default replacement
1256  $query = str_replace( XMLS_PREFIX , $xmls->objectPrefix, $query );
1257  }
1258  }
1259 
1260  $this->queries[$id] = trim( $query );
1261  }
1262 
1263  // Return the query set array
1264  return $this->queries;
1265  }
1266 
1275  function prefixQuery( $regex, $query, $prefix = NULL ) {
1276  if( !isset( $prefix ) ) {
1277  return $query;
1278  }
1279 
1280  if( preg_match( $regex, $query, $match ) ) {
1281  $preamble = $match[1];
1282  $postamble = $match[5];
1283  $objectList = explode( ',', $match[3] );
1284  // $prefix = $prefix . '_';
1285 
1286  $prefixedList = '';
1287 
1288  foreach( $objectList as $object ) {
1289  if( $prefixedList !== '' ) {
1290  $prefixedList .= ', ';
1291  }
1292 
1293  $prefixedList .= $prefix . trim( $object );
1294  }
1295 
1296  $query = $preamble . ' ' . $prefixedList . ' ' . $postamble;
1297  }
1298 
1299  return $query;
1300  }
1301 }
1302 
1316 class adoSchema {
1317 
1322  var $sqlArray;
1323 
1328  var $db;
1329 
1334  var $dict;
1335 
1340  var $currentElement = '';
1341 
1346  var $upgrade = '';
1347 
1352  var $objectPrefix = '';
1353 
1358  var $mgq;
1359 
1364  var $debug;
1365 
1370  var $versionRegex = '/<schema.*?( version="([^"]*)")?.*?>/';
1371 
1376  var $schemaVersion;
1377 
1381  var $success;
1382 
1386  var $executeInline;
1387 
1391  var $continueOnError;
1392 
1397 
1407  function __construct( $db ) {
1408  // Initialize the environment
1409  $this->mgq = get_magic_quotes_runtime();
1410  #set_magic_quotes_runtime(0);
1411  ini_set("magic_quotes_runtime", 0);
1412 
1413  $this->db = $db;
1414  $this->debug = $this->db->debug;
1415  $this->dict = NewDataDictionary( $this->db );
1416  $this->sqlArray = array();
1417  $this->schemaVersion = XMLS_SCHEMA_VERSION;
1418  $this->executeInline( XMLS_EXECUTE_INLINE );
1419  $this->continueOnError( XMLS_CONTINUE_ON_ERROR );
1420  $this->existingData( XMLS_EXISTING_DATA );
1421  $this->setUpgradeMethod();
1422  }
1423 
1440  function SetUpgradeMethod( $method = '' ) {
1441  if( !is_string( $method ) ) {
1442  return FALSE;
1443  }
1444 
1445  $method = strtoupper( $method );
1446 
1447  // Handle the upgrade methods
1448  switch( $method ) {
1449  case 'ALTER':
1450  $this->upgrade = $method;
1451  break;
1452  case 'REPLACE':
1453  $this->upgrade = $method;
1454  break;
1455  case 'BEST':
1456  $this->upgrade = 'ALTER';
1457  break;
1458  case 'NONE':
1459  $this->upgrade = 'NONE';
1460  break;
1461  default:
1462  // Use default if no legitimate method is passed.
1463  $this->upgrade = XMLS_DEFAULT_UPGRADE_METHOD;
1464  }
1465 
1466  return $this->upgrade;
1467  }
1468 
1488  function ExistingData( $mode = NULL ) {
1489  if( is_int( $mode ) ) {
1490  switch( $mode ) {
1491  case XMLS_MODE_UPDATE:
1492  $mode = XMLS_MODE_UPDATE;
1493  break;
1494  case XMLS_MODE_IGNORE:
1495  $mode = XMLS_MODE_IGNORE;
1496  break;
1497  case XMLS_MODE_INSERT:
1498  $mode = XMLS_MODE_INSERT;
1499  break;
1500  default:
1501  $mode = XMLS_EXISTING_DATA;
1502  break;
1503  }
1504  $this->existingData = $mode;
1505  }
1506 
1507  return $this->existingData;
1508  }
1509 
1523  function ExecuteInline( $mode = NULL ) {
1524  if( is_bool( $mode ) ) {
1525  $this->executeInline = $mode;
1526  }
1527 
1528  return $this->executeInline;
1529  }
1530 
1544  function ContinueOnError( $mode = NULL ) {
1545  if( is_bool( $mode ) ) {
1546  $this->continueOnError = $mode;
1547  }
1548 
1549  return $this->continueOnError;
1550  }
1551 
1565  function ParseSchema( $filename, $returnSchema = FALSE ) {
1566  return $this->ParseSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
1567  }
1568 
1590  function ParseSchemaFile( $filename, $returnSchema = FALSE ) {
1591  // Open the file
1592  if( !($fp = fopen( $filename, 'r' )) ) {
1593  logMsg( 'Unable to open file' );
1594  return FALSE;
1595  }
1596 
1597  // do version detection here
1598  if( $this->SchemaFileVersion( $filename ) != $this->schemaVersion ) {
1599  logMsg( 'Invalid Schema Version' );
1600  return FALSE;
1601  }
1602 
1603  if( $returnSchema ) {
1604  $xmlstring = '';
1605  while( $data = fread( $fp, 4096 ) ) {
1606  $xmlstring .= $data . "\n";
1607  }
1608  return $xmlstring;
1609  }
1610 
1611  $this->success = 2;
1612 
1613  $xmlParser = $this->create_parser();
1614  // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
1615  $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
1616 
1617  // Process the file
1618  while( $data = fread( $fp, 4096 ) ) {
1619  if( !xml_parse( $xmlParser, $data, feof( $fp ) ) ) {
1620  die( sprintf(
1621  "XML error: %s at line %d",
1622  xml_error_string( xml_get_error_code( $xmlParser) ),
1623  xml_get_current_line_number( $xmlParser)
1624  ) );
1625  }
1626  }
1627 
1628  libxml_disable_entity_loader($previousValueOfEntityLoader);
1629  xml_parser_free( $xmlParser );
1630 
1631  return $this->sqlArray;
1632  }
1633 
1645  function ParseSchemaString( $xmlstring, $returnSchema = FALSE ) {
1646  if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
1647  logMsg( 'Empty or Invalid Schema' );
1648  return FALSE;
1649  }
1650 
1651  // do version detection here
1652  if( $this->SchemaStringVersion( $xmlstring ) != $this->schemaVersion ) {
1653  logMsg( 'Invalid Schema Version' );
1654  return FALSE;
1655  }
1656 
1657  if( $returnSchema ) {
1658  return $xmlstring;
1659  }
1660 
1661  $this->success = 2;
1662 
1663  $xmlParser = $this->create_parser();
1664  // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
1665  $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
1666 
1667  if( !xml_parse( $xmlParser, $xmlstring, TRUE ) ) {
1668  die( sprintf(
1669  "XML error: %s at line %d",
1670  xml_error_string( xml_get_error_code( $xmlParser) ),
1671  xml_get_current_line_number( $xmlParser)
1672  ) );
1673  }
1674 
1675  libxml_disable_entity_loader($previousValueOfEntityLoader);
1676  xml_parser_free( $xmlParser );
1677 
1678  return $this->sqlArray;
1679  }
1680 
1692  function RemoveSchema( $filename, $returnSchema = FALSE ) {
1693  return $this->RemoveSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
1694  }
1695 
1707  function RemoveSchemaString( $schema, $returnSchema = FALSE ) {
1708 
1709  // grab current version
1710  if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
1711  return FALSE;
1712  }
1713 
1714  return $this->ParseSchemaString( $this->TransformSchema( $schema, 'remove-' . $version), $returnSchema );
1715  }
1716 
1730  function ExecuteSchema( $sqlArray = NULL, $continueOnErr = NULL ) {
1731  if( !is_bool( $continueOnErr ) ) {
1732  $continueOnErr = $this->ContinueOnError();
1733  }
1734 
1735  if( !isset( $sqlArray ) ) {
1736  $sqlArray = $this->sqlArray;
1737  }
1738 
1739  if( !is_array( $sqlArray ) ) {
1740  $this->success = 0;
1741  } else {
1742  $this->success = $this->dict->ExecuteSQLArray( $sqlArray, $continueOnErr );
1743  }
1744 
1745  return $this->success;
1746  }
1747 
1757  function PrintSQL( $format = 'NONE' ) {
1758  $sqlArray = null;
1759  return $this->getSQL( $format, $sqlArray );
1760  }
1761 
1771  function SaveSQL( $filename = './schema.sql' ) {
1772 
1773  if( !isset( $sqlArray ) ) {
1774  $sqlArray = $this->sqlArray;
1775  }
1776  if( !isset( $sqlArray ) ) {
1777  return FALSE;
1778  }
1779 
1780  $fp = fopen( $filename, "w" );
1781 
1782  foreach( $sqlArray as $key => $query ) {
1783  fwrite( $fp, $query . ";\n" );
1784  }
1785  fclose( $fp );
1786  }
1787 
1795  function create_parser() {
1796  // Create the parser
1797  $xmlParser = xml_parser_create();
1798  xml_set_object( $xmlParser, $this );
1799 
1800  // Initialize the XML callback functions
1801  xml_set_element_handler( $xmlParser, '_tag_open', '_tag_close' );
1802  xml_set_character_data_handler( $xmlParser, '_tag_cdata' );
1803 
1804  return $xmlParser;
1805  }
1806 
1812  function _tag_open( &$parser, $tag, $attributes ) {
1813  switch( strtoupper( $tag ) ) {
1814  case 'TABLE':
1815  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
1816  $this->obj = new dbTable( $this, $attributes );
1817  xml_set_object( $parser, $this->obj );
1818  }
1819  break;
1820  case 'SQL':
1821  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
1822  $this->obj = new dbQuerySet( $this, $attributes );
1823  xml_set_object( $parser, $this->obj );
1824  }
1825  break;
1826  default:
1827  // print_r( array( $tag, $attributes ) );
1828  }
1829 
1830  }
1831 
1837  function _tag_cdata( &$parser, $cdata ) {
1838  }
1839 
1846  function _tag_close( &$parser, $tag ) {
1847 
1848  }
1849 
1866  function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
1867 
1868  // grab current version
1869  if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
1870  return FALSE;
1871  }
1872 
1873  if( !isset ($newVersion) ) {
1874  $newVersion = $this->schemaVersion;
1875  }
1876 
1877  if( $version == $newVersion ) {
1878  $result = $schema;
1879  } else {
1880  $result = $this->TransformSchema( $schema, 'convert-' . $version . '-' . $newVersion);
1881  }
1882 
1883  if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
1884  fwrite( $fp, $result );
1885  fclose( $fp );
1886  }
1887 
1888  return $result;
1889  }
1890 
1891  /*
1892  // compat for pre-4.3 - jlim
1893  function _file_get_contents($path)
1894  {
1895  if (function_exists('file_get_contents')) return file_get_contents($path);
1896  return join('',file($path));
1897  }*/
1898 
1915  function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
1916 
1917  // grab current version
1918  if( !( $version = $this->SchemaFileVersion( $filename ) ) ) {
1919  return FALSE;
1920  }
1921 
1922  if( !isset ($newVersion) ) {
1923  $newVersion = $this->schemaVersion;
1924  }
1925 
1926  if( $version == $newVersion ) {
1927  $result = _file_get_contents( $filename );
1928 
1929  // remove unicode BOM if present
1930  if( substr( $result, 0, 3 ) == sprintf( '%c%c%c', 239, 187, 191 ) ) {
1931  $result = substr( $result, 3 );
1932  }
1933  } else {
1934  $result = $this->TransformSchema( $filename, 'convert-' . $version . '-' . $newVersion, 'file' );
1935  }
1936 
1937  if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
1938  fwrite( $fp, $result );
1939  fclose( $fp );
1940  }
1941 
1942  return $result;
1943  }
1944 
1945  function TransformSchema( $schema, $xsl, $schematype='string' )
1946  {
1947  // Fail if XSLT extension is not available
1948  if( ! function_exists( 'xslt_create' ) ) {
1949  return FALSE;
1950  }
1951 
1952  $xsl_file = dirname( __FILE__ ) . '/xsl/' . $xsl . '.xsl';
1953 
1954  // look for xsl
1955  if( !is_readable( $xsl_file ) ) {
1956  return FALSE;
1957  }
1958 
1959  switch( $schematype )
1960  {
1961  case 'file':
1962  if( !is_readable( $schema ) ) {
1963  return FALSE;
1964  }
1965 
1966  $schema = _file_get_contents( $schema );
1967  break;
1968  case 'string':
1969  default:
1970  if( !is_string( $schema ) ) {
1971  return FALSE;
1972  }
1973  }
1974 
1975  $arguments = array (
1976  '/_xml' => $schema,
1977  '/_xsl' => _file_get_contents( $xsl_file )
1978  );
1979 
1980  // create an XSLT processor
1981  $xh = xslt_create ();
1982 
1983  // set error handler
1984  xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler'));
1985 
1986  // process the schema
1987  $result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
1988 
1989  xslt_free ($xh);
1990 
1991  return $result;
1992  }
1993 
2004  function xslt_error_handler( $parser, $errno, $level, $fields ) {
2005  if( is_array( $fields ) ) {
2006  $msg = array(
2007  'Message Type' => ucfirst( $fields['msgtype'] ),
2008  'Message Code' => $fields['code'],
2009  'Message' => $fields['msg'],
2010  'Error Number' => $errno,
2011  'Level' => $level
2012  );
2013 
2014  switch( $fields['URI'] ) {
2015  case 'arg:/_xml':
2016  $msg['Input'] = 'XML';
2017  break;
2018  case 'arg:/_xsl':
2019  $msg['Input'] = 'XSL';
2020  break;
2021  default:
2022  $msg['Input'] = $fields['URI'];
2023  }
2024 
2025  $msg['Line'] = $fields['line'];
2026  } else {
2027  $msg = array(
2028  'Message Type' => 'Error',
2029  'Error Number' => $errno,
2030  'Level' => $level,
2031  'Fields' => var_export( $fields, TRUE )
2032  );
2033  }
2034 
2035  $error_details = $msg['Message Type'] . ' in XSLT Transformation' . "\n"
2036  . '<table>' . "\n";
2037 
2038  foreach( $msg as $label => $details ) {
2039  $error_details .= '<tr><td><b>' . $label . ': </b></td><td>' . htmlentities( $details ) . '</td></tr>' . "\n";
2040  }
2041 
2042  $error_details .= '</table>';
2043 
2044  trigger_error( $error_details, E_USER_ERROR );
2045  }
2046 
2056  function SchemaFileVersion( $filename ) {
2057  // Open the file
2058  if( !($fp = fopen( $filename, 'r' )) ) {
2059  // die( 'Unable to open file' );
2060  return FALSE;
2061  }
2062 
2063  // Process the file
2064  while( $data = fread( $fp, 4096 ) ) {
2065  if( preg_match( $this->versionRegex, $data, $matches ) ) {
2066  return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
2067  }
2068  }
2069 
2070  return FALSE;
2071  }
2072 
2082  function SchemaStringVersion( $xmlstring ) {
2083  if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
2084  return FALSE;
2085  }
2086 
2087  if( preg_match( $this->versionRegex, $xmlstring, $matches ) ) {
2088  return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
2089  }
2090 
2091  return FALSE;
2092  }
2093 
2107  function ExtractSchema( $data = FALSE, $indent = ' ', $prefix = '' , $stripprefix=false) {
2108  $old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM );
2109 
2110  $schema = '<?xml version="1.0"?>' . "\n"
2111  . '<schema version="' . $this->schemaVersion . '">' . "\n";
2112  if( is_array( $tables = $this->db->MetaTables( 'TABLES' ,false ,($prefix) ? str_replace('_','\_',$prefix).'%' : '') ) ) {
2113  foreach( $tables as $table ) {
2114  $schema .= $indent
2115  . '<table name="'
2116  . htmlentities( $stripprefix ? str_replace($prefix, '', $table) : $table )
2117  . '">' . "\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  }
2387 }
2388 
2394 function logMsg( $msg, $title = NULL, $force = FALSE ) {
2395  if( XMLS_DEBUG or $force ) {
2396  echo '<pre>';
2397 
2398  if( isset( $title ) ) {
2399  echo '<h3>' . htmlentities( $title ) . '</h3>';
2400  }
2401 
2402  if( @is_object( $this ) ) {
2403  echo '[' . get_class( $this ) . '] ';
2404  }
2405 
2406  print_r( $msg );
2407 
2408  echo '</pre>';
2409  }
2410 }
SchemaFileVersion( $filename)
_tag_open(&$parser, $tag, $attributes)
ExecuteSchema( $sqlArray=NULL, $continueOnErr=NULL)
_tag_close(&$parser, $tag)
RemoveSchemaString( $schema, $returnSchema=FALSE)
_file_get_contents($file)
__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
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel='E_DEBUG')
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)
ConvertSchemaString( $schema, $newVersion=NULL, $newFile=NULL)
__construct(&$parent, $attributes=NULL)
_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)
ExistingData( $mode=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')
ExtractSchema( $data=FALSE, $indent=' ', $prefix='', $stripprefix=false)
_tag_open(&$parser, $tag, $attributes)
ParseSchema( $filename, $returnSchema=FALSE)
_tag_open(&$parser, $tag, $attributes)
ParseSchemaString( $xmlstring, $returnSchema=FALSE)
ExecuteInline( $mode=NULL)
addField( $attributes)
__construct(&$parent, $attributes=NULL)
_tag_cdata(&$parser, $cdata)
buildQuery( $sql=NULL)
$sql
Definition: server.php:84
_tag_close(&$parser, $tag)
PrintSQL( $format='NONE')
SetUpgradeMethod( $method='')