Help file for patient_select.php
[openemr.git] / library / adodb / adodb-xmlschema.inc.php
blobd34c171aaf6bcbbd784890bf9a778e74281b14bf
1 <?php
2 // Copyright (c) 2004 ars Cognita Inc., all rights reserved
3 /* ******************************************************************************
4 Released under both BSD license and Lesser GPL library license.
5 Whenever there is any discrepancy between the two licenses,
6 the BSD license will take precedence.
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
11 Redistributions of source code must retain the above copyright notice, this list
12 of conditions and the following disclaimer.
13 Redistributions in binary form must reproduce the above copyright notice, this l
14 ist of conditions and the following disclaimer in the documentation and/or other
15 materials provided with the distribution.
16 Neither the name of the ars Cognita, Inc., nor the names of its contributors may be used
17 to endorse or promote products derived from this software without specific prior
18 written permission.
20 DISCLAIMER:
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WA
23 RRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIREC
25 T, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR P
27 ROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWI
29 SE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE P
30 OSSIBILITY OF SUCH DAMAGE.
32 *******************************************************************************/
33 /**
34 * xmlschema is a class that allows the user to quickly and easily
35 * build a database on any ADOdb-supported platform using a simple
36 * XML schema.
38 * Last Editor: $Author$
39 * @author Richard Tango-Lowy & Dan Cech
40 * @version $Revision$
42 * @package axmls
43 * @tutorial getting_started.pkg
46 /**
47 * Debug on or off
49 if( !defined( 'XMLS_DEBUG' ) ) {
50 define( 'XMLS_DEBUG', FALSE );
53 /**
54 * Default prefix key
56 if( !defined( 'XMLS_PREFIX' ) ) {
57 define( 'XMLS_PREFIX', '%%P' );
60 /**
61 * Maximum length allowed for object prefix
63 if( !defined( 'XMLS_PREFIX_MAXLEN' ) ) {
64 define( 'XMLS_PREFIX_MAXLEN', 10 );
67 /**
68 * Execute SQL inline as it is generated
70 if( !defined( 'XMLS_EXECUTE_INLINE' ) ) {
71 define( 'XMLS_EXECUTE_INLINE', FALSE );
74 /**
75 * Continue SQL Execution if an error occurs?
77 if( !defined( 'XMLS_CONTINUE_ON_ERROR' ) ) {
78 define( 'XMLS_CONTINUE_ON_ERROR', FALSE );
81 /**
82 * Current Schema Version
84 if( !defined( 'XMLS_SCHEMA_VERSION' ) ) {
85 define( 'XMLS_SCHEMA_VERSION', '0.2' );
88 /**
89 * Default Schema Version. Used for Schemas without an explicit version set.
91 if( !defined( 'XMLS_DEFAULT_SCHEMA_VERSION' ) ) {
92 define( 'XMLS_DEFAULT_SCHEMA_VERSION', '0.1' );
95 /**
96 * Default Schema Version. Used for Schemas without an explicit version set.
98 if( !defined( 'XMLS_DEFAULT_UPGRADE_METHOD' ) ) {
99 define( 'XMLS_DEFAULT_UPGRADE_METHOD', 'ALTER' );
103 * Include the main ADODB library
105 if( !defined( '_ADODB_LAYER' ) ) {
106 require( 'adodb.inc.php' );
110 * Abstract DB Object. This class provides basic methods for database objects, such
111 * as tables and indexes.
113 * @package axmls
114 * @access private
116 class dbObject {
119 * var object Parent
121 var $parent;
124 * var string current element
126 var $currentElement;
129 * NOP
131 function dbObject( &$parent, $attributes = NULL ) {
132 $this->parent =& $parent;
136 * XML Callback to process start elements
138 * @access private
140 function _tag_open( &$parser, $tag, $attributes ) {
145 * XML Callback to process CDATA elements
147 * @access private
149 function _tag_cdata( &$parser, $cdata ) {
154 * XML Callback to process end elements
156 * @access private
158 function _tag_close( &$parser, $tag ) {
162 function create() {
163 return array();
167 * Destroys the object
169 function destroy() {
170 unset( $this );
174 * Checks whether the specified RDBMS is supported by the current
175 * database object or its ranking ancestor.
177 * @param string $platform RDBMS platform name (from ADODB platform list).
178 * @return boolean TRUE if RDBMS is supported; otherwise returns FALSE.
180 function supportedPlatform( $platform = NULL ) {
181 return is_object( $this->parent ) ? $this->parent->supportedPlatform( $platform ) : TRUE;
185 * Returns the prefix set by the ranking ancestor of the database object.
187 * @param string $name Prefix string.
188 * @return string Prefix.
190 function prefix( $name = '' ) {
191 return is_object( $this->parent ) ? $this->parent->prefix( $name ) : $name;
195 * Extracts a field ID from the specified field.
197 * @param string $field Field.
198 * @return string Field ID.
200 function FieldID( $field ) {
201 return strtoupper( preg_replace( '/^`(.+)`$/', '$1', $field ) );
206 * Creates a table object in ADOdb's datadict format
208 * This class stores information about a database table. As charactaristics
209 * of the table are loaded from the external source, methods and properties
210 * of this class are used to build up the table description in ADOdb's
211 * datadict format.
213 * @package axmls
214 * @access private
216 class dbTable extends dbObject {
219 * @var string Table name
221 var $name;
224 * @var array Field specifier: Meta-information about each field
226 var $fields = array();
229 * @var array List of table indexes.
231 var $indexes = array();
234 * @var array Table options: Table-level options
236 var $opts = array();
239 * @var string Field index: Keeps track of which field is currently being processed
241 var $current_field;
244 * @var boolean Mark table for destruction
245 * @access private
247 var $drop_table;
250 * @var boolean Mark field for destruction (not yet implemented)
251 * @access private
253 var $drop_field = array();
256 * Iniitializes a new table object.
258 * @param string $prefix DB Object prefix
259 * @param array $attributes Array of table attributes.
261 function dbTable( &$parent, $attributes = NULL ) {
262 $this->parent =& $parent;
263 $this->name = $this->prefix($attributes['NAME']);
267 * XML Callback to process start elements. Elements currently
268 * processed are: INDEX, DROP, FIELD, KEY, NOTNULL, AUTOINCREMENT & DEFAULT.
270 * @access private
272 function _tag_open( &$parser, $tag, $attributes ) {
273 $this->currentElement = strtoupper( $tag );
275 switch( $this->currentElement ) {
276 case 'INDEX':
277 xml_set_object( $parser, $this->addIndex( $attributes ) );
278 break;
279 case 'DROP':
280 $this->drop();
281 break;
282 case 'FIELD':
283 // Add a field
284 $fieldName = $attributes['NAME'];
285 $fieldType = $attributes['TYPE'];
286 $fieldSize = isset( $attributes['SIZE'] ) ? $attributes['SIZE'] : NULL;
287 $fieldOpts = isset( $attributes['OPTS'] ) ? $attributes['OPTS'] : NULL;
289 $this->addField( $fieldName, $fieldType, $fieldSize, $fieldOpts );
290 break;
291 case 'KEY':
292 case 'NOTNULL':
293 case 'AUTOINCREMENT':
294 // Add a field option
295 $this->addFieldOpt( $this->current_field, $this->currentElement );
296 break;
297 case 'DEFAULT':
298 // Add a field option to the table object
300 // Work around ADOdb datadict issue that misinterprets empty strings.
301 if( $attributes['VALUE'] == '' ) {
302 $attributes['VALUE'] = " '' ";
305 $this->addFieldOpt( $this->current_field, $this->currentElement, $attributes['VALUE'] );
306 break;
307 default:
308 // print_r( array( $tag, $attributes ) );
313 * XML Callback to process CDATA elements
315 * @access private
317 function _tag_cdata( &$parser, $cdata ) {
318 switch( $this->currentElement ) {
319 // Table constraint
320 case 'CONSTRAINT':
321 // Table option
322 case 'OPT':
323 $this->addTableOpt( $cdata );
324 break;
325 default:
331 * XML Callback to process end elements
333 * @access private
335 function _tag_close( &$parser, $tag ) {
336 $this->currentElement = '';
338 switch( strtoupper( $tag ) ) {
339 case 'TABLE':
340 $this->parent->addSQL( $this->create( $this->parent ) );
341 xml_set_object( $parser, $this->parent );
342 $this->destroy();
343 break;
348 * Adds an index to a table object
350 * @param array $attributes Index attributes
351 * @return object dbIndex object
353 function &addIndex( $attributes ) {
354 $name = strtoupper( $attributes['NAME'] );
355 $this->indexes[$name] =& new dbIndex( $this, $attributes );
356 return $this->indexes[$name];
360 * Adds a field to a table object
362 * $name is the name of the table to which the field should be added.
363 * $type is an ADODB datadict field type. The following field types
364 * are supported as of ADODB 3.40:
365 * - C: varchar
366 * - X: CLOB (character large object) or largest varchar size
367 * if CLOB is not supported
368 * - C2: Multibyte varchar
369 * - X2: Multibyte CLOB
370 * - B: BLOB (binary large object)
371 * - D: Date (some databases do not support this, and we return a datetime type)
372 * - T: Datetime or Timestamp
373 * - L: Integer field suitable for storing booleans (0 or 1)
374 * - I: Integer (mapped to I4)
375 * - I1: 1-byte integer
376 * - I2: 2-byte integer
377 * - I4: 4-byte integer
378 * - I8: 8-byte integer
379 * - F: Floating point number
380 * - N: Numeric or decimal number
382 * @param string $name Name of the table to which the field will be added.
383 * @param string $type ADODB datadict field type.
384 * @param string $size Field size
385 * @param array $opts Field options array
386 * @return array Field specifier array
388 function addField( $name, $type, $size = NULL, $opts = NULL ) {
389 $field_id = $this->FieldID( $name );
391 // Set the field index so we know where we are
392 $this->current_field = $field_id;
394 // Set the field name (required)
395 $this->fields[$field_id]['NAME'] = $name;
397 // Set the field type (required)
398 $this->fields[$field_id]['TYPE'] = $type;
400 // Set the field size (optional)
401 if( isset( $size ) ) {
402 $this->fields[$field_id]['SIZE'] = $size;
405 // Set the field options
406 if( isset( $opts ) ) {
407 $this->fields[$field_id]['OPTS'] = $opts;
412 * Adds a field option to the current field specifier
414 * This method adds a field option allowed by the ADOdb datadict
415 * and appends it to the given field.
417 * @param string $field Field name
418 * @param string $opt ADOdb field option
419 * @param mixed $value Field option value
420 * @return array Field specifier array
422 function addFieldOpt( $field, $opt, $value = NULL ) {
423 if( !isset( $value ) ) {
424 $this->fields[$this->FieldID( $field )]['OPTS'][] = $opt;
425 // Add the option and value
426 } else {
427 $this->fields[$this->FieldID( $field )]['OPTS'][] = array( $opt => $value );
432 * Adds an option to the table
434 * This method takes a comma-separated list of table-level options
435 * and appends them to the table object.
437 * @param string $opt Table option
438 * @return array Options
440 function addTableOpt( $opt ) {
441 $this->opts[] = $opt;
443 return $this->opts;
447 * Generates the SQL that will create the table in the database
449 * @param object $xmls adoSchema object
450 * @return array Array containing table creation SQL
452 function create( &$xmls ) {
453 $sql = array();
455 // drop any existing indexes
456 if( is_array( $legacy_indexes = $xmls->dict->MetaIndexes( $this->name ) ) ) {
457 foreach( $legacy_indexes as $index => $index_details ) {
458 $sql[] = $xmls->dict->DropIndexSQL( $index, $this->name );
462 // remove fields to be dropped from table object
463 foreach( $this->drop_field as $field ) {
464 unset( $this->fields[$field] );
467 // if table exists
468 if( is_array( $legacy_fields = $xmls->dict->MetaColumns( $this->name ) ) ) {
469 // drop table
470 if( $this->drop_table ) {
471 $sql[] = $xmls->dict->DropTableSQL( $this->name );
473 return $sql;
476 // drop any existing fields not in schema
477 foreach( $legacy_fields as $field_id => $field ) {
478 if( !isset( $this->fields[$field_id] ) ) {
479 $sql[] = $xmls->dict->DropColumnSQL( $this->name, '`'.$field->name.'`' );
482 // if table doesn't exist
483 } else {
484 if( $this->drop_table ) {
485 return $sql;
488 $legacy_fields = array();
491 // Loop through the field specifier array, building the associative array for the field options
492 $fldarray = array();
494 foreach( $this->fields as $field_id => $finfo ) {
495 // Set an empty size if it isn't supplied
496 if( !isset( $finfo['SIZE'] ) ) {
497 $finfo['SIZE'] = '';
500 // Initialize the field array with the type and size
501 $fldarray[$field_id] = array(
502 'NAME' => $finfo['NAME'],
503 'TYPE' => $finfo['TYPE'],
504 'SIZE' => $finfo['SIZE']
507 // Loop through the options array and add the field options.
508 if( isset( $finfo['OPTS'] ) ) {
509 foreach( $finfo['OPTS'] as $opt ) {
510 // Option has an argument.
511 if( is_array( $opt ) ) {
512 $key = key( $opt );
513 $value = $opt[key( $opt )];
514 $fldarray[$field_id][$key] = $value;
515 // Option doesn't have arguments
516 } else {
517 $fldarray[$field_id][$opt] = $opt;
523 if( empty( $legacy_fields ) ) {
524 // Create the new table
525 $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
526 logMsg( end( $sql ), 'Generated CreateTableSQL' );
527 } else {
528 // Upgrade an existing table
529 logMsg( "Upgrading {$this->name} using '{$xmls->upgrade}'" );
530 switch( $xmls->upgrade ) {
531 // Use ChangeTableSQL
532 case 'ALTER':
533 logMsg( 'Generated ChangeTableSQL (ALTERing table)' );
534 $sql[] = $xmls->dict->ChangeTableSQL( $this->name, $fldarray, $this->opts );
535 break;
536 case 'REPLACE':
537 logMsg( 'Doing upgrade REPLACE (testing)' );
538 $sql[] = $xmls->dict->DropTableSQL( $this->name );
539 $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
540 break;
541 // ignore table
542 default:
543 return array();
547 foreach( $this->indexes as $index ) {
548 $sql[] = $index->create( $xmls );
551 return $sql;
555 * Marks a field or table for destruction
557 function drop() {
558 if( isset( $this->current_field ) ) {
559 // Drop the current field
560 logMsg( "Dropping field '{$this->current_field}' from table '{$this->name}'" );
561 // $this->drop_field[$this->current_field] = $xmls->dict->DropColumnSQL( $this->name, $this->current_field );
562 $this->drop_field[$this->current_field] = $this->current_field;
563 } else {
564 // Drop the current table
565 logMsg( "Dropping table '{$this->name}'" );
566 // $this->drop_table = $xmls->dict->DropTableSQL( $this->name );
567 $this->drop_table = TRUE;
573 * Creates an index object in ADOdb's datadict format
575 * This class stores information about a database index. As charactaristics
576 * of the index are loaded from the external source, methods and properties
577 * of this class are used to build up the index description in ADOdb's
578 * datadict format.
580 * @package axmls
581 * @access private
583 class dbIndex extends dbObject {
586 * @var string Index name
588 var $name;
591 * @var array Index options: Index-level options
593 var $opts = array();
596 * @var array Indexed fields: Table columns included in this index
598 var $columns = array();
601 * @var boolean Mark index for destruction
602 * @access private
604 var $drop = FALSE;
607 * Initializes the new dbIndex object.
609 * @param object $parent Parent object
610 * @param array $attributes Attributes
612 * @internal
614 function dbIndex( &$parent, $attributes = NULL ) {
615 $this->parent =& $parent;
617 $this->name = $this->prefix ($attributes['NAME']);
621 * XML Callback to process start elements
623 * Processes XML opening tags.
624 * Elements currently processed are: DROP, CLUSTERED, BITMAP, UNIQUE, FULLTEXT & HASH.
626 * @access private
628 function _tag_open( &$parser, $tag, $attributes ) {
629 $this->currentElement = strtoupper( $tag );
631 switch( $this->currentElement ) {
632 case 'DROP':
633 $this->drop();
634 break;
635 case 'CLUSTERED':
636 case 'BITMAP':
637 case 'UNIQUE':
638 case 'FULLTEXT':
639 case 'HASH':
640 // Add index Option
641 $this->addIndexOpt( $this->currentElement );
642 break;
643 default:
644 // print_r( array( $tag, $attributes ) );
649 * XML Callback to process CDATA elements
651 * Processes XML cdata.
653 * @access private
655 function _tag_cdata( &$parser, $cdata ) {
656 switch( $this->currentElement ) {
657 // Index field name
658 case 'COL':
659 $this->addField( $cdata );
660 break;
661 default:
667 * XML Callback to process end elements
669 * @access private
671 function _tag_close( &$parser, $tag ) {
672 $this->currentElement = '';
674 switch( strtoupper( $tag ) ) {
675 case 'INDEX':
676 xml_set_object( $parser, $this->parent );
677 break;
682 * Adds a field to the index
684 * @param string $name Field name
685 * @return string Field list
687 function addField( $name ) {
688 $this->columns[$this->FieldID( $name )] = $name;
690 // Return the field list
691 return $this->columns;
695 * Adds options to the index
697 * @param string $opt Comma-separated list of index options.
698 * @return string Option list
700 function addIndexOpt( $opt ) {
701 $this->opts[] = $opt;
703 // Return the options list
704 return $this->opts;
708 * Generates the SQL that will create the index in the database
710 * @param object $xmls adoSchema object
711 * @return array Array containing index creation SQL
713 function create( &$xmls ) {
714 if( $this->drop ) {
715 return NULL;
718 // eliminate any columns that aren't in the table
719 foreach( $this->columns as $id => $col ) {
720 if( !isset( $this->parent->fields[$id] ) ) {
721 unset( $this->columns[$id] );
725 return $xmls->dict->CreateIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts );
729 * Marks an index for destruction
731 function drop() {
732 $this->drop = TRUE;
737 * Creates the SQL to execute a list of provided SQL queries
739 * @package axmls
740 * @access private
742 class dbQuerySet extends dbObject {
745 * @var array List of SQL queries
747 var $queries = array();
750 * @var string String used to build of a query line by line
752 var $query;
755 * @var string Query prefix key
757 var $prefixKey = '';
760 * @var boolean Auto prefix enable (TRUE)
762 var $prefixMethod = 'AUTO';
765 * Initializes the query set.
767 * @param object $parent Parent object
768 * @param array $attributes Attributes
770 function dbQuerySet( &$parent, $attributes = NULL ) {
771 $this->parent =& $parent;
773 // Overrides the manual prefix key
774 if( isset( $attributes['KEY'] ) ) {
775 $this->prefixKey = $attributes['KEY'];
778 $prefixMethod = isset( $attributes['PREFIXMETHOD'] ) ? strtoupper( trim( $attributes['PREFIXMETHOD'] ) ) : '';
780 // Enables or disables automatic prefix prepending
781 switch( $prefixMethod ) {
782 case 'AUTO':
783 $this->prefixMethod = 'AUTO';
784 break;
785 case 'MANUAL':
786 $this->prefixMethod = 'MANUAL';
787 break;
788 case 'NONE':
789 $this->prefixMethod = 'NONE';
790 break;
791 default:
792 $this->prefixMethod = 'AUTO';
797 * XML Callback to process start elements. Elements currently
798 * processed are: QUERY.
800 * @access private
802 function _tag_open( &$parser, $tag, $attributes ) {
803 $this->currentElement = strtoupper( $tag );
805 switch( $this->currentElement ) {
806 case 'QUERY':
807 // Create a new query in a SQL queryset.
808 // Ignore this query set if a platform is specified and it's different than the
809 // current connection platform.
810 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
811 $this->newQuery();
812 } else {
813 $this->discardQuery();
815 break;
816 default:
817 // print_r( array( $tag, $attributes ) );
822 * XML Callback to process CDATA elements
824 function _tag_cdata( &$parser, $cdata ) {
825 switch( $this->currentElement ) {
826 // Line of queryset SQL data
827 case 'QUERY':
828 $this->buildQuery( $cdata );
829 break;
830 default:
836 * XML Callback to process end elements
838 * @access private
840 function _tag_close( &$parser, $tag ) {
841 $this->currentElement = '';
843 switch( strtoupper( $tag ) ) {
844 case 'QUERY':
845 // Add the finished query to the open query set.
846 $this->addQuery();
847 break;
848 case 'SQL':
849 $this->parent->addSQL( $this->create( $this->parent ) );
850 xml_set_object( $parser, $this->parent );
851 $this->destroy();
852 break;
853 default:
859 * Re-initializes the query.
861 * @return boolean TRUE
863 function newQuery() {
864 $this->query = '';
866 return TRUE;
870 * Discards the existing query.
872 * @return boolean TRUE
874 function discardQuery() {
875 unset( $this->query );
877 return TRUE;
881 * Appends a line to a query that is being built line by line
883 * @param string $data Line of SQL data or NULL to initialize a new query
884 * @return string SQL query string.
886 function buildQuery( $sql = NULL ) {
887 if( !isset( $this->query ) ) {
888 return FALSE;
891 if( empty( $sql ) ) {
892 return FALSE;
895 if( !empty( $this->query ) ) {
896 $this->query .= ' ';
899 $this->query .= trim( $sql );
901 return $this->query;
905 * Adds a completed query to the query list
907 * @return string SQL of added query
909 function addQuery() {
910 if( !isset( $this->query ) ) {
911 return FALSE;
914 $this->queries[] = $this->query;
915 $return = $this->query;
917 unset( $this->query );
919 return $return;
923 * Creates and returns the current query set
925 * @param object $xmls adoSchema object
926 * @return array Query set
928 function create( &$xmls ) {
929 foreach( $this->queries as $id => $query ) {
930 switch( $this->prefixMethod ) {
931 case 'AUTO':
932 // Enable auto prefix replacement
934 // Process object prefix.
935 // Evaluate SQL statements to prepend prefix to objects
936 $query = $this->prefixQuery( '/^\s*((?is)INSERT\s+(INTO\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query );
937 $query = $this->prefixQuery( '/^\s*((?is)UPDATE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query );
938 $query = $this->prefixQuery( '/^\s*((?is)DELETE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query );
940 // SELECT statements aren't working yet
941 #$data = preg_replace( '/(?ias)(^\s*SELECT\s+.*\s+FROM)\s+(\W\s*,?\s*)+((?i)\s+WHERE.*$)/', "\1 $prefix\2 \3", $data );
943 case 'MANUAL':
944 // If prefixKey is set and has a value then we use it to override the default constant XMLS_PREFIX.
945 // If prefixKey is not set, we use the default constant XMLS_PREFIX
946 if( isset( $this->prefixKey ) AND( $this->prefixKey !== '' ) ) {
947 // Enable prefix override
948 $query = str_replace( $this->prefixKey, $xmls->objectPrefix, $query );
949 } else {
950 // Use default replacement
951 $query = str_replace( XMLS_PREFIX , $xmls->objectPrefix, $query );
955 $this->queries[$id] = trim( $query );
958 // Return the query set array
959 return $this->queries;
963 * Rebuilds the query with the prefix attached to any objects
965 * @param string $regex Regex used to add prefix
966 * @param string $query SQL query string
967 * @param string $prefix Prefix to be appended to tables, indices, etc.
968 * @return string Prefixed SQL query string.
970 function prefixQuery( $regex, $query, $prefix = NULL ) {
971 if( !isset( $prefix ) ) {
972 return $query;
975 if( preg_match( $regex, $query, $match ) ) {
976 $preamble = $match[1];
977 $postamble = $match[5];
978 $objectList = explode( ',', $match[3] );
979 // $prefix = $prefix . '_';
981 $prefixedList = '';
983 foreach( $objectList as $object ) {
984 if( $prefixedList !== '' ) {
985 $prefixedList .= ', ';
988 $prefixedList .= $prefix . trim( $object );
991 $query = $preamble . ' ' . $prefixedList . ' ' . $postamble;
994 return $query;
999 * Loads and parses an XML file, creating an array of "ready-to-run" SQL statements
1001 * This class is used to load and parse the XML file, to create an array of SQL statements
1002 * that can be used to build a database, and to build the database using the SQL array.
1004 * @tutorial getting_started.pkg
1006 * @author Richard Tango-Lowy & Dan Cech
1007 * @version $Revision$
1009 * @package axmls
1011 class adoSchema {
1014 * @var array Array containing SQL queries to generate all objects
1015 * @access private
1017 var $sqlArray;
1020 * @var object ADOdb connection object
1021 * @access private
1023 var $db;
1026 * @var object ADOdb Data Dictionary
1027 * @access private
1029 var $dict;
1032 * @var string Current XML element
1033 * @access private
1035 var $currentElement = '';
1038 * @var string If set (to 'ALTER' or 'REPLACE'), upgrade an existing database
1039 * @access private
1041 var $upgrade = '';
1044 * @var string Optional object prefix
1045 * @access private
1047 var $objectPrefix = '';
1050 * @var long Original Magic Quotes Runtime value
1051 * @access private
1053 var $mgq;
1056 * @var long System debug
1057 * @access private
1059 var $debug;
1062 * @var string Regular expression to find schema version
1063 * @access private
1065 var $versionRegex = '/<schema.*?( version="([^"]*)")?.*?>/';
1068 * @var string Current schema version
1069 * @access private
1071 var $schemaVersion;
1074 * @var int Success of last Schema execution
1076 var $success;
1079 * @var bool Execute SQL inline as it is generated
1081 var $executeInline;
1084 * @var bool Continue SQL execution if errors occur
1086 var $continueOnError;
1089 * Creates an adoSchema object
1091 * Creating an adoSchema object is the first step in processing an XML schema.
1092 * The only parameter is an ADOdb database connection object, which must already
1093 * have been created.
1095 * @param object $db ADOdb database connection object.
1097 function adoSchema( &$db ) {
1098 // Initialize the environment
1099 $this->mgq = get_magic_quotes_runtime();
1100 set_magic_quotes_runtime(0);
1102 $this->debug = $this->db->debug;
1103 $this->db =& $db;
1104 $this->dict = NewDataDictionary( $this->db );
1105 $this->sqlArray = array();
1106 $this->schemaVersion = XMLS_SCHEMA_VERSION;
1107 $this->executeInline( XMLS_EXECUTE_INLINE );
1108 $this->continueOnError( XMLS_CONTINUE_ON_ERROR );
1109 $this->setUpgradeMethod();
1113 * Sets the method to be used for upgrading an existing database
1115 * Use this method to specify how existing database objects should be upgraded.
1116 * The method option can be set to ALTER, REPLACE, BEST, or NONE. ALTER attempts to
1117 * alter each database object directly, REPLACE attempts to rebuild each object
1118 * from scratch, BEST attempts to determine the best upgrade method for each
1119 * object, and NONE disables upgrading.
1121 * This method is not yet used by AXMLS, but exists for backward compatibility.
1122 * The ALTER method is automatically assumed when the adoSchema object is
1123 * instantiated; other upgrade methods are not currently supported.
1125 * @param string $method Upgrade method (ALTER|REPLACE|BEST|NONE)
1126 * @returns string Upgrade method used
1128 function SetUpgradeMethod( $method = '' ) {
1129 if( !is_string( $method ) ) {
1130 return FALSE;
1133 $method = strtoupper( $method );
1135 // Handle the upgrade methods
1136 switch( $method ) {
1137 case 'ALTER':
1138 $this->upgrade = $method;
1139 break;
1140 case 'REPLACE':
1141 $this->upgrade = $method;
1142 break;
1143 case 'BEST':
1144 $this->upgrade = 'ALTER';
1145 break;
1146 case 'NONE':
1147 $this->upgrade = 'NONE';
1148 break;
1149 default:
1150 // Use default if no legitimate method is passed.
1151 $this->upgrade = XMLS_DEFAULT_UPGRADE_METHOD;
1154 return $this->upgrade;
1158 * Enables/disables inline SQL execution.
1160 * Call this method to enable or disable inline execution of the schema. If the mode is set to TRUE (inline execution),
1161 * AXMLS applies the SQL to the database immediately as each schema entity is parsed. If the mode
1162 * is set to FALSE (post execution), AXMLS parses the entire schema and you will need to call adoSchema::ExecuteSchema()
1163 * to apply the schema to the database.
1165 * @param bool $mode execute
1166 * @return bool current execution mode
1168 * @see ParseSchema(), ExecuteSchema()
1170 function ExecuteInline( $mode = NULL ) {
1171 if( is_bool( $mode ) ) {
1172 $this->executeInline = $mode;
1175 return $this->executeInline;
1179 * Enables/disables SQL continue on error.
1181 * Call this method to enable or disable continuation of SQL execution if an error occurs.
1182 * If the mode is set to TRUE (continue), AXMLS will continue to apply SQL to the database, even if an error occurs.
1183 * If the mode is set to FALSE (halt), AXMLS will halt execution of generated sql if an error occurs, though parsing
1184 * of the schema will continue.
1186 * @param bool $mode execute
1187 * @return bool current continueOnError mode
1189 * @see addSQL(), ExecuteSchema()
1191 function ContinueOnError( $mode = NULL ) {
1192 if( is_bool( $mode ) ) {
1193 $this->continueOnError = $mode;
1196 return $this->continueOnError;
1200 * Loads an XML schema from a file and converts it to SQL.
1202 * Call this method to load the specified schema (see the DTD for the proper format) from
1203 * the filesystem and generate the SQL necessary to create the database described.
1204 * @see ParseSchemaString()
1206 * @param string $file Name of XML schema file.
1207 * @return array Array of SQL queries, ready to execute
1209 function ParseSchema( $filename ) {
1210 return $this->ParseSchemaString( $this->ConvertSchemaFile ( $filename ) );
1214 * Loads an XML schema from a file and converts it to SQL.
1216 * Call this method to load the specified schema from a file (see the DTD for the proper format)
1217 * and generate the SQL necessary to create the database described by the schema.
1219 * @param string $file Name of XML schema file.
1220 * @return array Array of SQL queries, ready to execute.
1222 * @deprecated Replaced by adoSchema::ParseSchema() and adoSchema::ParseSchemaString()
1223 * @see ParseSchema(), ParseSchemaString()
1225 function ParseSchemaFile( $filename ) {
1226 // Open the file
1227 if( !($fp = fopen( $filename, 'r' )) ) {
1228 // die( 'Unable to open file' );
1229 return FALSE;
1232 // do version detection here
1233 if( $this->SchemaFileVersion( $filename ) != $this->schemaVersion ) {
1234 return FALSE;
1237 $xmlParser = $this->create_parser();
1239 // Process the file
1240 while( $data = fread( $fp, 4096 ) ) {
1241 if( !xml_parse( $xmlParser, $data, feof( $fp ) ) ) {
1242 die( sprintf(
1243 "XML error: %s at line %d",
1244 xml_error_string( xml_get_error_code( $xmlParser) ),
1245 xml_get_current_line_number( $xmlParser)
1246 ) );
1250 xml_parser_free( $xmlParser );
1252 return $this->sqlArray;
1256 * Converts an XML schema string to SQL.
1258 * Call this method to parse a string containing an XML schema (see the DTD for the proper format)
1259 * and generate the SQL necessary to create the database described by the schema.
1260 * @see ParseSchema()
1262 * @param string $xmlstring XML schema string.
1263 * @return array Array of SQL queries, ready to execute.
1265 function ParseSchemaString( $xmlstring ) {
1266 if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
1267 return FALSE;
1270 // do version detection here
1271 if( $this->SchemaStringVersion( $xmlstring ) != $this->schemaVersion ) {
1272 return FALSE;
1275 $xmlParser = $this->create_parser();
1277 $this->success = 2;
1279 if( !xml_parse( $xmlParser, $xmlstring, TRUE ) ) {
1280 die( sprintf(
1281 "XML error: %s at line %d",
1282 xml_error_string( xml_get_error_code( $xmlParser) ),
1283 xml_get_current_line_number( $xmlParser)
1284 ) );
1287 xml_parser_free( $xmlParser );
1288 return $this->sqlArray;
1292 * Applies the current XML schema to the database (post execution).
1294 * Call this method to apply the current schema (generally created by calling
1295 * ParseSchema() or ParseSchemaString() ) to the database (creating the tables, indexes,
1296 * and executing other SQL specified in the schema) after parsing.
1297 * @see ParseSchema(), ParseSchemaString(), ExecuteInline()
1299 * @param array $sqlArray Array of SQL statements that will be applied rather than
1300 * the current schema.
1301 * @param boolean $continueOnErr Continue to apply the schema even if an error occurs.
1302 * @returns integer 0 if failure, 1 if errors, 2 if successful.
1304 function ExecuteSchema( $sqlArray = NULL, $continueOnErr = NULL ) {
1305 if( !is_bool( $continueOnErr ) ) {
1306 $continueOnErr = $this->ContinueOnError();
1309 if( !isset( $sqlArray ) ) {
1310 $sqlArray = $this->sqlArray;
1313 if( !is_array( $sqlArray ) ) {
1314 $this->success = 0;
1315 } else {
1316 $this->success = $this->dict->ExecuteSQLArray( $sqlArray, $continueOnErr );
1319 return $this->success;
1323 * Returns the current SQL array.
1325 * Call this method to fetch the array of SQL queries resulting from
1326 * ParseSchema() or ParseSchemaString().
1328 * @param string $format Format: HTML, TEXT, or NONE (PHP array)
1329 * @return array Array of SQL statements or FALSE if an error occurs
1331 function PrintSQL( $format = 'NONE' ) {
1332 return $this->getSQL( $format, $sqlArray );
1336 * Saves the current SQL array to the local filesystem as a list of SQL queries.
1338 * Call this method to save the array of SQL queries (generally resulting from a
1339 * parsed XML schema) to the filesystem.
1341 * @param string $filename Path and name where the file should be saved.
1342 * @return boolean TRUE if save is successful, else FALSE.
1344 function SaveSQL( $filename = './schema.sql' ) {
1346 if( !isset( $sqlArray ) ) {
1347 $sqlArray = $this->sqlArray;
1349 if( !isset( $sqlArray ) ) {
1350 return FALSE;
1353 touch($filename); // php bug
1354 $fp = fopen( $filename, "w" );
1356 foreach( $sqlArray as $key => $query ) {
1357 fwrite( $fp, $query . ";\n" );
1359 fclose( $fp );
1363 * Create an xml parser
1365 * @return object PHP XML parser object
1367 * @access private
1369 function &create_parser() {
1370 // Create the parser
1371 $xmlParser = xml_parser_create();
1372 xml_set_object( $xmlParser, $this );
1374 // Initialize the XML callback functions
1375 xml_set_element_handler( $xmlParser, '_tag_open', '_tag_close' );
1376 xml_set_character_data_handler( $xmlParser, '_tag_cdata' );
1378 return $xmlParser;
1382 * XML Callback to process start elements
1384 * @access private
1386 function _tag_open( &$parser, $tag, $attributes ) {
1387 switch( strtoupper( $tag ) ) {
1388 case 'TABLE':
1389 $this->obj = new dbTable( $this, $attributes );
1390 xml_set_object( $parser, $this->obj );
1391 break;
1392 case 'SQL':
1393 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
1394 $this->obj = new dbQuerySet( $this, $attributes );
1395 xml_set_object( $parser, $this->obj );
1397 break;
1398 default:
1399 // print_r( array( $tag, $attributes ) );
1405 * XML Callback to process CDATA elements
1407 * @access private
1409 function _tag_cdata( &$parser, $cdata ) {
1413 * XML Callback to process end elements
1415 * @access private
1416 * @internal
1418 function _tag_close( &$parser, $tag ) {
1423 * Converts an XML schema string to the specified DTD version.
1425 * Call this method to convert a string containing an XML schema to a different AXMLS
1426 * DTD version. For instance, to convert a schema created for an pre-1.0 version for
1427 * AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version
1428 * parameter is specified, the schema will be converted to the current DTD version.
1429 * If the newFile parameter is provided, the converted schema will be written to the specified
1430 * file.
1431 * @see ConvertSchemaFile()
1433 * @param string $schema String containing XML schema that will be converted.
1434 * @param string $newVersion DTD version to convert to.
1435 * @param string $newFile File name of (converted) output file.
1436 * @return string Converted XML schema or FALSE if an error occurs.
1438 function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
1440 // grab current version
1441 if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
1442 return FALSE;
1445 if( !isset ($newVersion) ) {
1446 $newVersion = $this->schemaVersion;
1449 if( $version == $newVersion ) {
1450 $result = $schema;
1451 } else {
1452 // Fail if XSLT extension is not available
1453 if( ! function_exists( 'xslt_create' ) ) {
1454 return FALSE;
1457 $xsl_file = dirname( __FILE__ ) . '/xsl/convert-' . $version . '-' . $newVersion . '.xsl';
1459 // look for xsl
1460 if( !is_readable( $xsl_file ) ) {
1461 return FALSE;
1464 $arguments = array (
1465 '/_xml' => $schema,
1466 '/_xsl' => file_get_contents ($xsl_file)
1469 // create an XSLT processor
1470 $xh = xslt_create ();
1472 // set error handler
1473 xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler'));
1475 // process the schema
1476 $result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
1478 xslt_free ($xh);
1481 if( is_string ($newFile) ) {
1482 touch($newFile); // php bug
1483 if ( $fp = fopen( $newFile, 'w' ) ) {
1484 fwrite ($fp, $result);
1485 fclose ($fp);
1489 return $result;
1493 * Converts an XML schema file to the specified DTD version.
1495 * Call this method to convert the specified XML schema file to a different AXMLS
1496 * DTD version. For instance, to convert a schema created for an pre-1.0 version for
1497 * AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version
1498 * parameter is specified, the schema will be converted to the current DTD version.
1499 * If the newFile parameter is provided, the converted schema will be written to the specified
1500 * file.
1501 * @see ConvertSchemaString()
1503 * @param string $filename Name of XML schema file that will be converted.
1504 * @param string $newVersion DTD version to convert to.
1505 * @param string $newFile File name of (converted) output file.
1506 * @return string Converted XML schema or FALSE if an error occurs.
1508 function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
1510 // grab current version
1511 if( !( $version = $this->SchemaFileVersion( $filename ) ) ) {
1512 return FALSE;
1515 if( !isset ($newVersion) ) {
1516 $newVersion = $this->schemaVersion;
1519 if( $version == $newVersion ) {
1520 $result = file_get_contents( $filename );
1522 // remove unicode BOM if present
1523 if( substr( $result, 0, 3 ) == sprintf( '%c%c%c', 239, 187, 191 ) ) {
1524 $result = substr( $result, 3 );
1526 } else {
1527 // Fail if XSLT extension is not available
1528 if( ! function_exists( 'xslt_create' ) ) {
1529 return FALSE;
1532 $xsl_file = dirname( __FILE__ ) . '/xsl/convert-' . $version . '-' . $newVersion . '.xsl';
1534 // look for xsl
1535 if( !is_readable( $xsl_file ) ) {
1536 return FALSE;
1539 $arguments = array (
1540 '/_xml' => file_get_contents ($filename),
1541 '/_xsl' => file_get_contents ($xsl_file)
1544 // create an XSLT processor
1545 $xh = xslt_create ();
1547 // set error handler
1548 xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler'));
1550 // process the schema
1551 $result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
1553 xslt_free ($xh);
1556 if( is_string ($newFile) ) {
1557 touch($newFile); // php bug
1558 if ( $fp = fopen( $newFile, 'w' ) ) {
1559 fwrite ($fp, $result);
1560 fclose ($fp);
1564 return $result;
1568 * Processes XSLT transformation errors
1570 * @param object $parser XML parser object
1571 * @param integer $errno Error number
1572 * @param integer $level Error level
1573 * @param array $fields Error information fields
1575 * @access private
1577 function xslt_error_handler( $parser, $errno, $level, $fields ) {
1578 if( is_array( $fields ) ) {
1579 $msg = array(
1580 'Message Type' => ucfirst( $fields['msgtype'] ),
1581 'Message Code' => $fields['code'],
1582 'Message' => $fields['msg'],
1583 'Error Number' => $errno,
1584 'Level' => $level
1587 switch( $fields['URI'] ) {
1588 case 'arg:/_xml':
1589 $msg['Input'] = 'XML';
1590 break;
1591 case 'arg:/_xsl':
1592 $msg['Input'] = 'XSL';
1593 break;
1594 default:
1595 $msg['Input'] = $fields['URI'];
1598 $msg['Line'] = $fields['line'];
1599 } else {
1600 $msg = array(
1601 'Message Type' => 'Error',
1602 'Error Number' => $errno,
1603 'Level' => $level,
1604 'Fields' => var_export( $fields, TRUE )
1608 $error_details = $msg['Message Type'] . ' in XSLT Transformation' . "\n"
1609 . '<table>' . "\n";
1611 foreach( $msg as $label => $details ) {
1612 $error_details .= '<tr><td><b>' . $label . ': </b></td><td>' . htmlentities( $details ) . '</td></tr>' . "\n";
1615 $error_details .= '</table>';
1617 trigger_error( $error_details, E_USER_ERROR );
1621 * Returns the AXMLS Schema Version of the requested XML schema file.
1623 * Call this method to obtain the AXMLS DTD version of the requested XML schema file.
1624 * @see SchemaStringVersion()
1626 * @param string $filename AXMLS schema file
1627 * @return string Schema version number or FALSE on error
1629 function SchemaFileVersion( $filename ) {
1630 // Open the file
1631 if( !($fp = fopen( $filename, 'r' )) ) {
1632 // die( 'Unable to open file' );
1633 return FALSE;
1636 // Process the file
1637 while( $data = fread( $fp, 4096 ) ) {
1638 if( preg_match( $this->versionRegex, $data, $matches ) ) {
1639 return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
1643 return FALSE;
1647 * Returns the AXMLS Schema Version of the provided XML schema string.
1649 * Call this method to obtain the AXMLS DTD version of the provided XML schema string.
1650 * @see SchemaFileVersion()
1652 * @param string $xmlstring XML schema string
1653 * @return string Schema version number or FALSE on error
1655 function SchemaStringVersion( $xmlstring ) {
1656 if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
1657 return FALSE;
1660 if( preg_match( $this->versionRegex, $xmlstring, $matches ) ) {
1661 return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
1664 return FALSE;
1668 * Extracts an XML schema from an existing database.
1670 * Call this method to create an XML schema string from an existing database.
1671 * If the data parameter is set to TRUE, AXMLS will include the data from the database
1672 * in the schema.
1674 * @param boolean $data Include data in schema dump
1675 * @return string Generated XML schema
1677 function ExtractSchema( $data = FALSE ) {
1678 $old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM );
1680 $schema = '<?xml version="1.0"?>' . "\n"
1681 . '<schema version="' . $this->schemaVersion . '">' . "\n";
1683 if( is_array( $tables = $this->db->MetaTables( 'TABLES' ) ) ) {
1684 foreach( $tables as $table ) {
1685 $schema .= ' <table name="' . $table . '">' . "\n";
1687 // grab details from database
1688 $rs = $this->db->Execute( 'SELECT * FROM ' . $table . ' WHERE -1' );
1689 $fields = $this->db->MetaColumns( $table );
1690 $indexes = $this->db->MetaIndexes( $table );
1692 if( is_array( $fields ) ) {
1693 foreach( $fields as $details ) {
1694 $extra = '';
1695 $content = array();
1697 if( $details->max_length > 0 ) {
1698 $extra .= ' size="' . $details->max_length . '"';
1701 if( $details->primary_key ) {
1702 $content[] = '<PRIMARY/>';
1703 } elseif( $details->not_null ) {
1704 $content[] = '<NOTNULL/>';
1707 if( $details->has_default ) {
1708 $content[] = '<DEFAULT value="' . $details->default_value . '"/>';
1711 if( $details->auto_increment ) {
1712 $content[] = '<AUTOINCREMENT/>';
1715 // this stops the creation of 'R' columns,
1716 // AUTOINCREMENT is used to create auto columns
1717 $details->primary_key = 0;
1718 $type = $rs->MetaType( $details );
1720 $schema .= ' <field name="' . $details->name . '" type="' . $type . '"' . $extra . '>';
1722 if( !empty( $content ) ) {
1723 $schema .= "\n " . implode( "\n ", $content ) . "\n ";
1726 $schema .= '</field>' . "\n";
1730 if( is_array( $indexes ) ) {
1731 foreach( $indexes as $index => $details ) {
1732 $schema .= ' <index name="' . $index . '">' . "\n";
1734 if( $details['unique'] ) {
1735 $schema .= ' <UNIQUE/>' . "\n";
1738 foreach( $details['columns'] as $column ) {
1739 $schema .= ' <col>' . $column . '</col>' . "\n";
1742 $schema .= ' </index>' . "\n";
1746 if( $data ) {
1747 $rs = $this->db->Execute( 'SELECT * FROM ' . $table );
1749 if( is_object( $rs ) ) {
1750 $schema .= ' <data>' . "\n";
1752 while( $row = $rs->FetchRow() ) {
1753 $schema .= ' <row><f>' . implode( '</f><f>', $row ) . '</f></row>' . "\n";
1756 $schema .= ' </data>' . "\n";
1760 $schema .= ' </table>' . "\n";
1764 $this->db->SetFetchMode( $old_mode );
1766 $schema .= '</schema>';
1767 return $schema;
1771 * Sets a prefix for database objects
1773 * Call this method to set a standard prefix that will be prepended to all database tables
1774 * and indices when the schema is parsed. Calling setPrefix with no arguments clears the prefix.
1776 * @param string $prefix Prefix that will be prepended.
1777 * @param boolean $underscore If TRUE, automatically append an underscore character to the prefix.
1778 * @return boolean TRUE if successful, else FALSE
1780 function SetPrefix( $prefix = '', $underscore = TRUE ) {
1781 switch( TRUE ) {
1782 // clear prefix
1783 case empty( $prefix ):
1784 logMsg( 'Cleared prefix' );
1785 $this->objectPrefix = '';
1786 return TRUE;
1787 // prefix too long
1788 case strlen( $prefix ) > XMLS_PREFIX_MAXLEN:
1789 // prefix contains invalid characters
1790 case !preg_match( '/^[a-z][a-z0-9]+$/i', $prefix ):
1791 logMsg( 'Invalid prefix: ' . $prefix );
1792 return FALSE;
1795 if( $underscore AND substr( $prefix, -1 ) != '_' ) {
1796 $prefix .= '_';
1799 // prefix valid
1800 logMsg( 'Set prefix: ' . $prefix );
1801 $this->objectPrefix = $prefix;
1802 return TRUE;
1806 * Returns an object name with the current prefix prepended.
1808 * @param string $name Name
1809 * @return string Prefixed name
1811 * @access private
1813 function prefix( $name = '' ) {
1814 // if prefix is set
1815 if( !empty( $this->objectPrefix ) ) {
1816 // Prepend the object prefix to the table name
1817 // prepend after quote if used
1818 return preg_replace( '/^(`?)(.+)$/', '$1' . $this->objectPrefix . '$2', $name );
1821 // No prefix set. Use name provided.
1822 return $name;
1826 * Checks if element references a specific platform
1828 * @param string $platform Requested platform
1829 * @returns boolean TRUE if platform check succeeds
1831 * @access private
1833 function supportedPlatform( $platform = NULL ) {
1834 $regex = '/^(\w*\|)*' . $this->db->databaseType . '(\|\w*)*$/';
1836 if( !isset( $platform ) OR preg_match( $regex, $platform ) ) {
1837 logMsg( "Platform $platform is supported" );
1838 return TRUE;
1839 } else {
1840 logMsg( "Platform $platform is NOT supported" );
1841 return FALSE;
1846 * Clears the array of generated SQL.
1848 * @access private
1850 function clearSQL() {
1851 $this->sqlArray = array();
1855 * Adds SQL into the SQL array.
1857 * @param mixed $sql SQL to Add
1858 * @return boolean TRUE if successful, else FALSE.
1860 * @access private
1862 function addSQL( $sql = NULL ) {
1863 if( is_array( $sql ) ) {
1864 foreach( $sql as $line ) {
1865 $this->addSQL( $line );
1868 return TRUE;
1871 if( is_string( $sql ) ) {
1872 $this->sqlArray[] = $sql;
1874 // if executeInline is enabled, and either no errors have occurred or continueOnError is enabled, execute SQL.
1875 if( $this->ExecuteInline() && ( $this->success == 2 || $this->ContinueOnError() ) ) {
1876 $saved = $this->db->debug;
1877 $this->db->debug = $this->debug;
1878 $ok = $this->db->Execute( $sql );
1879 $this->db->debug = $saved;
1881 if( !$ok ) {
1882 if( $this->debug ) {
1883 ADOConnection::outp( $this->db->ErrorMsg() );
1886 $this->success = 1;
1890 return TRUE;
1893 return FALSE;
1897 * Gets the SQL array in the specified format.
1899 * @param string $format Format
1900 * @return mixed SQL
1902 * @access private
1904 function getSQL( $format = NULL, $sqlArray = NULL ) {
1905 if( !is_array( $sqlArray ) ) {
1906 $sqlArray = $this->sqlArray;
1909 if( !is_array( $sqlArray ) ) {
1910 return FALSE;
1913 switch( strtolower( $format ) ) {
1914 case 'string':
1915 case 'text':
1916 return !empty( $sqlArray ) ? implode( ";\n\n", $sqlArray ) . ';' : '';
1917 case'html':
1918 return !empty( $sqlArray ) ? nl2br( htmlentities( implode( ";\n\n", $sqlArray ) . ';' ) ) : '';
1921 return $this->sqlArray;
1925 * Destroys an adoSchema object.
1927 * Call this method to clean up after an adoSchema object that is no longer in use.
1928 * @deprecated adoSchema now cleans up automatically.
1930 function Destroy() {
1931 set_magic_quotes_runtime( $this->mgq );
1932 unset( $this );
1937 * Message logging function
1939 * @access private
1941 function logMsg( $msg, $title = NULL ) {
1942 if( XMLS_DEBUG ) {
1943 echo '<pre>';
1945 if( isset( $title ) ) {
1946 echo '<h3>' . htmlentities( $title ) . '</h3>';
1949 if( is_object( $this ) ) {
1950 echo '[' . get_class( $this ) . '] ';
1953 print_r( $msg );
1955 echo '</pre>';