"TYPO3 4.0.1: typo3_src-4.0.1/typo3/sysext/adodb/adodb/adodb-xmlschema03.inc.php Source File", "datetime" => "Sat Dec 2 19:22:24 2006", "date" => "2 Dec 2006", "doxygenversion" => "1.4.6", "projectname" => "TYPO3 4.0.1", "projectnumber" => "4.0.1" ); get_header($doxygen_vars); ?>
00001 <?php 00002 // Copyright (c) 2004-2005 ars Cognita Inc., all rights reserved 00003 /* ****************************************************************************** 00004 Released under both BSD license and Lesser GPL library license. 00005 Whenever there is any discrepancy between the two licenses, 00006 the BSD license will take precedence. 00007 *******************************************************************************/ 00021 function _file_get_contents($file) 00022 { 00023 if (function_exists('file_get_contents')) return file_get_contents($file); 00024 00025 $f = fopen($file,'r'); 00026 if (!$f) return ''; 00027 $t = ''; 00028 00029 while ($s = fread($f,100000)) $t .= $s; 00030 fclose($f); 00031 return $t; 00032 } 00033 00034 00038 if( !defined( 'XMLS_DEBUG' ) ) { 00039 define( 'XMLS_DEBUG', FALSE ); 00040 } 00041 00045 if( !defined( 'XMLS_PREFIX' ) ) { 00046 define( 'XMLS_PREFIX', '%%P' ); 00047 } 00048 00052 if( !defined( 'XMLS_PREFIX_MAXLEN' ) ) { 00053 define( 'XMLS_PREFIX_MAXLEN', 10 ); 00054 } 00055 00059 if( !defined( 'XMLS_EXECUTE_INLINE' ) ) { 00060 define( 'XMLS_EXECUTE_INLINE', FALSE ); 00061 } 00062 00066 if( !defined( 'XMLS_CONTINUE_ON_ERROR' ) ) { 00067 define( 'XMLS_CONTINUE_ON_ERROR', FALSE ); 00068 } 00069 00073 if( !defined( 'XMLS_SCHEMA_VERSION' ) ) { 00074 define( 'XMLS_SCHEMA_VERSION', '0.3' ); 00075 } 00076 00080 if( !defined( 'XMLS_DEFAULT_SCHEMA_VERSION' ) ) { 00081 define( 'XMLS_DEFAULT_SCHEMA_VERSION', '0.1' ); 00082 } 00083 00089 if( !defined( 'XMLS_MODE_INSERT' ) ) { 00090 define( 'XMLS_MODE_INSERT', 0 ); 00091 } 00092 if( !defined( 'XMLS_MODE_UPDATE' ) ) { 00093 define( 'XMLS_MODE_UPDATE', 1 ); 00094 } 00095 if( !defined( 'XMLS_MODE_IGNORE' ) ) { 00096 define( 'XMLS_MODE_IGNORE', 2 ); 00097 } 00098 if( !defined( 'XMLS_EXISTING_DATA' ) ) { 00099 define( 'XMLS_EXISTING_DATA', XMLS_MODE_INSERT ); 00100 } 00101 00105 if( !defined( 'XMLS_DEFAULT_UPGRADE_METHOD' ) ) { 00106 define( 'XMLS_DEFAULT_UPGRADE_METHOD', 'ALTER' ); 00107 } 00108 00112 if( !defined( '_ADODB_LAYER' ) ) { 00113 require( 'adodb.inc.php' ); 00114 require( 'adodb-datadict.inc.php' ); 00115 } 00116 00124 class dbObject { 00125 00129 var $parent; 00130 00134 var $currentElement; 00135 00139 function dbObject( &$parent, $attributes = NULL ) { 00140 $this->parent =& $parent; 00141 } 00142 00148 function _tag_open( &$parser, $tag, $attributes ) { 00149 00150 } 00151 00157 function _tag_cdata( &$parser, $cdata ) { 00158 00159 } 00160 00166 function _tag_close( &$parser, $tag ) { 00167 00168 } 00169 00170 function create() { 00171 return array(); 00172 } 00173 00177 function destroy() { 00178 unset( $this ); 00179 } 00180 00188 function supportedPlatform( $platform = NULL ) { 00189 return is_object( $this->parent ) ? $this->parent->supportedPlatform( $platform ) : TRUE; 00190 } 00191 00198 function prefix( $name = '' ) { 00199 return is_object( $this->parent ) ? $this->parent->prefix( $name ) : $name; 00200 } 00201 00208 function FieldID( $field ) { 00209 return strtoupper( preg_replace( '/^`(.+)`$/', '$1', $field ) ); 00210 } 00211 } 00212 00224 class dbTable extends dbObject { 00225 00229 var $name; 00230 00234 var $fields = array(); 00235 00239 var $indexes = array(); 00240 00244 var $opts = array(); 00245 00249 var $current_field; 00250 00255 var $drop_table; 00256 00261 var $drop_field = array(); 00262 00267 var $currentPlatform = true; 00268 00269 00276 function dbTable( &$parent, $attributes = NULL ) { 00277 $this->parent =& $parent; 00278 $this->name = $this->prefix($attributes['NAME']); 00279 } 00280 00287 function _tag_open( &$parser, $tag, $attributes ) { 00288 $this->currentElement = strtoupper( $tag ); 00289 00290 switch( $this->currentElement ) { 00291 case 'INDEX': 00292 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) { 00293 xml_set_object( $parser, $this->addIndex( $attributes ) ); 00294 } 00295 break; 00296 case 'DATA': 00297 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) { 00298 xml_set_object( $parser, $this->addData( $attributes ) ); 00299 } 00300 break; 00301 case 'DROP': 00302 $this->drop(); 00303 break; 00304 case 'FIELD': 00305 // Add a field 00306 $fieldName = $attributes['NAME']; 00307 $fieldType = $attributes['TYPE']; 00308 $fieldSize = isset( $attributes['SIZE'] ) ? $attributes['SIZE'] : NULL; 00309 $fieldOpts = !empty( $attributes['OPTS'] ) ? $attributes['OPTS'] : NULL; 00310 00311 $this->addField( $fieldName, $fieldType, $fieldSize, $fieldOpts ); 00312 break; 00313 case 'KEY': 00314 case 'NOTNULL': 00315 case 'AUTOINCREMENT': 00316 case 'DEFDATE': 00317 case 'DEFTIMESTAMP': 00318 case 'UNSIGNED': 00319 // Add a field option 00320 $this->addFieldOpt( $this->current_field, $this->currentElement ); 00321 break; 00322 case 'DEFAULT': 00323 // Add a field option to the table object 00324 00325 // Work around ADOdb datadict issue that misinterprets empty strings. 00326 if( $attributes['VALUE'] == '' ) { 00327 $attributes['VALUE'] = " '' "; 00328 } 00329 00330 $this->addFieldOpt( $this->current_field, $this->currentElement, $attributes['VALUE'] ); 00331 break; 00332 case 'OPT': 00333 case 'CONSTRAINT': 00334 // Accept platform-specific options 00335 $this->currentPlatform = ( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ); 00336 break; 00337 default: 00338 // print_r( array( $tag, $attributes ) ); 00339 } 00340 } 00341 00347 function _tag_cdata( &$parser, $cdata ) { 00348 switch( $this->currentElement ) { 00349 // Table/field constraint 00350 case 'CONSTRAINT': 00351 if( isset( $this->current_field ) ) { 00352 $this->addFieldOpt( $this->current_field, $this->currentElement, $cdata ); 00353 } else { 00354 $this->addTableOpt( $cdata ); 00355 } 00356 break; 00357 // Table/field option 00358 case 'OPT': 00359 if( isset( $this->current_field ) ) { 00360 $this->addFieldOpt( $this->current_field, $cdata ); 00361 } else { 00362 $this->addTableOpt( $cdata ); 00363 } 00364 break; 00365 default: 00366 00367 } 00368 } 00369 00375 function _tag_close( &$parser, $tag ) { 00376 $this->currentElement = ''; 00377 00378 switch( strtoupper( $tag ) ) { 00379 case 'TABLE': 00380 $this->parent->addSQL( $this->create( $this->parent ) ); 00381 xml_set_object( $parser, $this->parent ); 00382 $this->destroy(); 00383 break; 00384 case 'FIELD': 00385 unset($this->current_field); 00386 break; 00387 case 'OPT': 00388 case 'CONSTRAINT': 00389 $this->currentPlatform = true; 00390 break; 00391 default: 00392 00393 } 00394 } 00395 00402 function &addIndex( $attributes ) { 00403 $name = strtoupper( $attributes['NAME'] ); 00404 $this->indexes[$name] =& new dbIndex( $this, $attributes ); 00405 return $this->indexes[$name]; 00406 } 00407 00414 function &addData( $attributes ) { 00415 if( !isset( $this->data ) ) { 00416 $this->data =& new dbData( $this, $attributes ); 00417 } 00418 return $this->data; 00419 } 00420 00450 function addField( $name, $type, $size = NULL, $opts = NULL ) { 00451 $field_id = $this->FieldID( $name ); 00452 00453 // Set the field index so we know where we are 00454 $this->current_field = $field_id; 00455 00456 // Set the field name (required) 00457 $this->fields[$field_id]['NAME'] = $name; 00458 00459 // Set the field type (required) 00460 $this->fields[$field_id]['TYPE'] = $type; 00461 00462 // Set the field size (optional) 00463 if( isset( $size ) ) { 00464 $this->fields[$field_id]['SIZE'] = $size; 00465 } 00466 00467 // Set the field options 00468 if( isset( $opts ) ) { 00469 $this->fields[$field_id]['OPTS'] = array($opts); 00470 } else { 00471 $this->fields[$field_id]['OPTS'] = array(); 00472 } 00473 } 00474 00486 function addFieldOpt( $field, $opt, $value = NULL ) { 00487 if( $this->currentPlatform ) { 00488 if( !isset( $value ) ) { 00489 $this->fields[$this->FieldID( $field )]['OPTS'][] = $opt; 00490 // Add the option and value 00491 } else { 00492 $this->fields[$this->FieldID( $field )]['OPTS'][] = array( $opt => $value ); 00493 } 00494 } 00495 } 00496 00506 function addTableOpt( $opt ) { 00507 if( $this->currentPlatform ) { 00508 $this->opts[] = $opt; 00509 } 00510 return $this->opts; 00511 } 00512 00519 function create( &$xmls ) { 00520 $sql = array(); 00521 00522 // drop any existing indexes 00523 if( is_array( $legacy_indexes = $xmls->dict->MetaIndexes( $this->name ) ) ) { 00524 foreach( $legacy_indexes as $index => $index_details ) { 00525 $sql[] = $xmls->dict->DropIndexSQL( $index, $this->name ); 00526 } 00527 } 00528 00529 // remove fields to be dropped from table object 00530 foreach( $this->drop_field as $field ) { 00531 unset( $this->fields[$field] ); 00532 } 00533 00534 // if table exists 00535 if( is_array( $legacy_fields = $xmls->dict->MetaColumns( $this->name ) ) ) { 00536 // drop table 00537 if( $this->drop_table ) { 00538 $sql[] = $xmls->dict->DropTableSQL( $this->name ); 00539 00540 return $sql; 00541 } 00542 00543 // drop any existing fields not in schema 00544 foreach( $legacy_fields as $field_id => $field ) { 00545 if( !isset( $this->fields[$field_id] ) ) { 00546 $sql[] = $xmls->dict->DropColumnSQL( $this->name, $field->name ); 00547 } 00548 } 00549 // if table doesn't exist 00550 } else { 00551 if( $this->drop_table ) { 00552 return $sql; 00553 } 00554 00555 $legacy_fields = array(); 00556 } 00557 00558 // Loop through the field specifier array, building the associative array for the field options 00559 $fldarray = array(); 00560 00561 foreach( $this->fields as $field_id => $finfo ) { 00562 // Set an empty size if it isn't supplied 00563 if( !isset( $finfo['SIZE'] ) ) { 00564 $finfo['SIZE'] = ''; 00565 } 00566 00567 // Initialize the field array with the type and size 00568 $fldarray[$field_id] = array( 00569 'NAME' => $finfo['NAME'], 00570 'TYPE' => $finfo['TYPE'], 00571 'SIZE' => $finfo['SIZE'] 00572 ); 00573 00574 // Loop through the options array and add the field options. 00575 if( isset( $finfo['OPTS'] ) ) { 00576 foreach( $finfo['OPTS'] as $opt ) { 00577 // Option has an argument. 00578 if( is_array( $opt ) ) { 00579 $key = key( $opt ); 00580 $value = $opt[key( $opt )]; 00581 @$fldarray[$field_id][$key] .= $value; 00582 // Option doesn't have arguments 00583 } else { 00584 $fldarray[$field_id][$opt] = $opt; 00585 } 00586 } 00587 } 00588 } 00589 00590 if( empty( $legacy_fields ) ) { 00591 // Create the new table 00592 $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts ); 00593 logMsg( end( $sql ), 'Generated CreateTableSQL' ); 00594 } else { 00595 // Upgrade an existing table 00596 logMsg( "Upgrading {$this->name} using '{$xmls->upgrade}'" ); 00597 switch( $xmls->upgrade ) { 00598 // Use ChangeTableSQL 00599 case 'ALTER': 00600 logMsg( 'Generated ChangeTableSQL (ALTERing table)' ); 00601 $sql[] = $xmls->dict->ChangeTableSQL( $this->name, $fldarray, $this->opts ); 00602 break; 00603 case 'REPLACE': 00604 logMsg( 'Doing upgrade REPLACE (testing)' ); 00605 $sql[] = $xmls->dict->DropTableSQL( $this->name ); 00606 $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts ); 00607 break; 00608 // ignore table 00609 default: 00610 return array(); 00611 } 00612 } 00613 00614 foreach( $this->indexes as $index ) { 00615 $sql[] = $index->create( $xmls ); 00616 } 00617 00618 if( isset( $this->data ) ) { 00619 $sql[] = $this->data->create( $xmls ); 00620 } 00621 00622 return $sql; 00623 } 00624 00628 function drop() { 00629 if( isset( $this->current_field ) ) { 00630 // Drop the current field 00631 logMsg( "Dropping field '{$this->current_field}' from table '{$this->name}'" ); 00632 // $this->drop_field[$this->current_field] = $xmls->dict->DropColumnSQL( $this->name, $this->current_field ); 00633 $this->drop_field[$this->current_field] = $this->current_field; 00634 } else { 00635 // Drop the current table 00636 logMsg( "Dropping table '{$this->name}'" ); 00637 // $this->drop_table = $xmls->dict->DropTableSQL( $this->name ); 00638 $this->drop_table = TRUE; 00639 } 00640 } 00641 } 00642 00654 class dbIndex extends dbObject { 00655 00659 var $name; 00660 00664 var $opts = array(); 00665 00669 var $columns = array(); 00670 00675 var $drop = FALSE; 00676 00685 function dbIndex( &$parent, $attributes = NULL ) { 00686 $this->parent =& $parent; 00687 00688 $this->name = $this->prefix ($attributes['NAME']); 00689 } 00690 00699 function _tag_open( &$parser, $tag, $attributes ) { 00700 $this->currentElement = strtoupper( $tag ); 00701 00702 switch( $this->currentElement ) { 00703 case 'DROP': 00704 $this->drop(); 00705 break; 00706 case 'CLUSTERED': 00707 case 'BITMAP': 00708 case 'UNIQUE': 00709 case 'FULLTEXT': 00710 case 'HASH': 00711 // Add index Option 00712 $this->addIndexOpt( $this->currentElement ); 00713 break; 00714 default: 00715 // print_r( array( $tag, $attributes ) ); 00716 } 00717 } 00718 00726 function _tag_cdata( &$parser, $cdata ) { 00727 switch( $this->currentElement ) { 00728 // Index field name 00729 case 'COL': 00730 $this->addField( $cdata ); 00731 break; 00732 default: 00733 00734 } 00735 } 00736 00742 function _tag_close( &$parser, $tag ) { 00743 $this->currentElement = ''; 00744 00745 switch( strtoupper( $tag ) ) { 00746 case 'INDEX': 00747 xml_set_object( $parser, $this->parent ); 00748 break; 00749 } 00750 } 00751 00758 function addField( $name ) { 00759 $this->columns[$this->FieldID( $name )] = $name; 00760 00761 // Return the field list 00762 return $this->columns; 00763 } 00764 00771 function addIndexOpt( $opt ) { 00772 $this->opts[] = $opt; 00773 00774 // Return the options list 00775 return $this->opts; 00776 } 00777 00784 function create( &$xmls ) { 00785 if( $this->drop ) { 00786 return NULL; 00787 } 00788 00789 // eliminate any columns that aren't in the table 00790 foreach( $this->columns as $id => $col ) { 00791 if( !isset( $this->parent->fields[$id] ) ) { 00792 unset( $this->columns[$id] ); 00793 } 00794 } 00795 00796 return $xmls->dict->CreateIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts ); 00797 } 00798 00802 function drop() { 00803 $this->drop = TRUE; 00804 } 00805 } 00806 00816 class dbData extends dbObject { 00817 00818 var $data = array(); 00819 00820 var $row; 00821 00830 function dbData( &$parent, $attributes = NULL ) { 00831 $this->parent =& $parent; 00832 } 00833 00842 function _tag_open( &$parser, $tag, $attributes ) { 00843 $this->currentElement = strtoupper( $tag ); 00844 00845 switch( $this->currentElement ) { 00846 case 'ROW': 00847 $this->row = count( $this->data ); 00848 $this->data[$this->row] = array(); 00849 break; 00850 case 'F': 00851 $this->addField($attributes); 00852 default: 00853 // print_r( array( $tag, $attributes ) ); 00854 } 00855 } 00856 00864 function _tag_cdata( &$parser, $cdata ) { 00865 switch( $this->currentElement ) { 00866 // Index field name 00867 case 'F': 00868 $this->addData( $cdata ); 00869 break; 00870 default: 00871 00872 } 00873 } 00874 00880 function _tag_close( &$parser, $tag ) { 00881 $this->currentElement = ''; 00882 00883 switch( strtoupper( $tag ) ) { 00884 case 'DATA': 00885 xml_set_object( $parser, $this->parent ); 00886 break; 00887 } 00888 } 00889 00896 function addField( $attributes ) { 00897 // check we're in a valid row 00898 if( !isset( $this->row ) || !isset( $this->data[$this->row] ) ) { 00899 return; 00900 } 00901 00902 // Set the field index so we know where we are 00903 if( isset( $attributes['NAME'] ) ) { 00904 $this->current_field = $this->FieldID( $attributes['NAME'] ); 00905 } else { 00906 $this->current_field = count( $this->data[$this->row] ); 00907 } 00908 00909 // initialise data 00910 if( !isset( $this->data[$this->row][$this->current_field] ) ) { 00911 $this->data[$this->row][$this->current_field] = ''; 00912 } 00913 } 00914 00921 function addData( $cdata ) { 00922 // check we're in a valid field 00923 if ( isset( $this->data[$this->row][$this->current_field] ) ) { 00924 // add data to field 00925 $this->data[$this->row][$this->current_field] .= $cdata; 00926 } 00927 } 00928 00935 function create( &$xmls ) { 00936 $table = $xmls->dict->TableName($this->parent->name); 00937 $table_field_count = count($this->parent->fields); 00938 $tables = $xmls->db->MetaTables(); 00939 $sql = array(); 00940 00941 $ukeys = $xmls->db->MetaPrimaryKeys( $table ); 00942 if( !empty( $this->parent->indexes ) and !empty( $ukeys ) ) { 00943 foreach( $this->parent->indexes as $indexObj ) { 00944 if( !in_array( $indexObj->name, $ukeys ) ) $ukeys[] = $indexObj->name; 00945 } 00946 } 00947 00948 // eliminate any columns that aren't in the table 00949 foreach( $this->data as $row ) { 00950 $table_fields = $this->parent->fields; 00951 $fields = array(); 00952 $rawfields = array(); // Need to keep some of the unprocessed data on hand. 00953 00954 foreach( $row as $field_id => $field_data ) { 00955 if( !array_key_exists( $field_id, $table_fields ) ) { 00956 if( is_numeric( $field_id ) ) { 00957 $field_id = reset( array_keys( $table_fields ) ); 00958 } else { 00959 continue; 00960 } 00961 } 00962 00963 $name = $table_fields[$field_id]['NAME']; 00964 00965 switch( $table_fields[$field_id]['TYPE'] ) { 00966 case 'I': 00967 case 'I1': 00968 case 'I2': 00969 case 'I4': 00970 case 'I8': 00971 $fields[$name] = intval($field_data); 00972 break; 00973 case 'C': 00974 case 'C2': 00975 case 'X': 00976 case 'X2': 00977 default: 00978 $fields[$name] = $xmls->db->qstr( $field_data ); 00979 $rawfields[$name] = $field_data; 00980 } 00981 00982 unset($table_fields[$field_id]); 00983 00984 } 00985 00986 // check that at least 1 column is specified 00987 if( empty( $fields ) ) { 00988 continue; 00989 } 00990 00991 // check that no required columns are missing 00992 if( count( $fields ) < $table_field_count ) { 00993 foreach( $table_fields as $field ) { 00994 if( isset( $field['OPTS'] ) and ( in_array( 'NOTNULL', $field['OPTS'] ) || in_array( 'KEY', $field['OPTS'] ) ) && !in_array( 'AUTOINCREMENT', $field['OPTS'] ) ) { 00995 continue(2); 00996 } 00997 } 00998 } 00999 01000 // The rest of this method deals with updating existing data records. 01001 01002 if( !in_array( $table, $tables ) or ( $mode = $xmls->existingData() ) == XMLS_MODE_INSERT ) { 01003 // Table doesn't yet exist, so it's safe to insert. 01004 logMsg( "$table doesn't exist, inserting or mode is INSERT" ); 01005 $sql[] = 'INSERT INTO '. $table .' ('. implode( ',', array_keys( $fields ) ) .') VALUES ('. implode( ',', $fields ) .')'; 01006 continue; 01007 } 01008 01009 // Prepare to test for potential violations. Get primary keys and unique indexes 01010 $mfields = array_merge( $fields, $rawfields ); 01011 $keyFields = array_intersect( $ukeys, array_keys( $mfields ) ); 01012 01013 if( empty( $ukeys ) or count( $keyFields ) == 0 ) { 01014 // No unique keys in schema, so safe to insert 01015 logMsg( "Either schema or data has no unique keys, so safe to insert" ); 01016 $sql[] = 'INSERT INTO '. $table .' ('. implode( ',', array_keys( $fields ) ) .') VALUES ('. implode( ',', $fields ) .')'; 01017 continue; 01018 } 01019 01020 // Select record containing matching unique keys. 01021 $where = ''; 01022 foreach( $ukeys as $key ) { 01023 if( isset( $mfields[$key] ) and $mfields[$key] ) { 01024 if( $where ) $where .= ' AND '; 01025 $where .= $key . ' = ' . $xmls->db->qstr( $mfields[$key] ); 01026 } 01027 } 01028 $records = $xmls->db->Execute( 'SELECT * FROM ' . $table . ' WHERE ' . $where ); 01029 switch( $records->RecordCount() ) { 01030 case 0: 01031 // No matching record, so safe to insert. 01032 logMsg( "No matching records. Inserting new row with unique data" ); 01033 $sql[] = $xmls->db->GetInsertSQL( $records, $mfields ); 01034 break; 01035 case 1: 01036 // Exactly one matching record, so we can update if the mode permits. 01037 logMsg( "One matching record..." ); 01038 if( $mode == XMLS_MODE_UPDATE ) { 01039 logMsg( "...Updating existing row from unique data" ); 01040 $sql[] = $xmls->db->GetUpdateSQL( $records, $mfields ); 01041 } 01042 break; 01043 default: 01044 // More than one matching record; the result is ambiguous, so we must ignore the row. 01045 logMsg( "More than one matching record. Ignoring row." ); 01046 } 01047 } 01048 return $sql; 01049 } 01050 } 01051 01058 class dbQuerySet extends dbObject { 01059 01063 var $queries = array(); 01064 01068 var $query; 01069 01073 var $prefixKey = ''; 01074 01078 var $prefixMethod = 'AUTO'; 01079 01086 function dbQuerySet( &$parent, $attributes = NULL ) { 01087 $this->parent =& $parent; 01088 01089 // Overrides the manual prefix key 01090 if( isset( $attributes['KEY'] ) ) { 01091 $this->prefixKey = $attributes['KEY']; 01092 } 01093 01094 $prefixMethod = isset( $attributes['PREFIXMETHOD'] ) ? strtoupper( trim( $attributes['PREFIXMETHOD'] ) ) : ''; 01095 01096 // Enables or disables automatic prefix prepending 01097 switch( $prefixMethod ) { 01098 case 'AUTO': 01099 $this->prefixMethod = 'AUTO'; 01100 break; 01101 case 'MANUAL': 01102 $this->prefixMethod = 'MANUAL'; 01103 break; 01104 case 'NONE': 01105 $this->prefixMethod = 'NONE'; 01106 break; 01107 } 01108 } 01109 01116 function _tag_open( &$parser, $tag, $attributes ) { 01117 $this->currentElement = strtoupper( $tag ); 01118 01119 switch( $this->currentElement ) { 01120 case 'QUERY': 01121 // Create a new query in a SQL queryset. 01122 // Ignore this query set if a platform is specified and it's different than the 01123 // current connection platform. 01124 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) { 01125 $this->newQuery(); 01126 } else { 01127 $this->discardQuery(); 01128 } 01129 break; 01130 default: 01131 // print_r( array( $tag, $attributes ) ); 01132 } 01133 } 01134 01138 function _tag_cdata( &$parser, $cdata ) { 01139 switch( $this->currentElement ) { 01140 // Line of queryset SQL data 01141 case 'QUERY': 01142 $this->buildQuery( $cdata ); 01143 break; 01144 default: 01145 01146 } 01147 } 01148 01154 function _tag_close( &$parser, $tag ) { 01155 $this->currentElement = ''; 01156 01157 switch( strtoupper( $tag ) ) { 01158 case 'QUERY': 01159 // Add the finished query to the open query set. 01160 $this->addQuery(); 01161 break; 01162 case 'SQL': 01163 $this->parent->addSQL( $this->create( $this->parent ) ); 01164 xml_set_object( $parser, $this->parent ); 01165 $this->destroy(); 01166 break; 01167 default: 01168 01169 } 01170 } 01171 01177 function newQuery() { 01178 $this->query = ''; 01179 01180 return TRUE; 01181 } 01182 01188 function discardQuery() { 01189 unset( $this->query ); 01190 01191 return TRUE; 01192 } 01193 01200 function buildQuery( $sql = NULL ) { 01201 if( !isset( $this->query ) OR empty( $sql ) ) { 01202 return FALSE; 01203 } 01204 01205 $this->query .= $sql; 01206 01207 return $this->query; 01208 } 01209 01215 function addQuery() { 01216 if( !isset( $this->query ) ) { 01217 return FALSE; 01218 } 01219 01220 $this->queries[] = $return = trim($this->query); 01221 01222 unset( $this->query ); 01223 01224 return $return; 01225 } 01226 01233 function create( &$xmls ) { 01234 foreach( $this->queries as $id => $query ) { 01235 switch( $this->prefixMethod ) { 01236 case 'AUTO': 01237 // Enable auto prefix replacement 01238 01239 // Process object prefix. 01240 // Evaluate SQL statements to prepend prefix to objects 01241 $query = $this->prefixQuery( '/^\s*((?is)INSERT\s+(INTO\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix ); 01242 $query = $this->prefixQuery( '/^\s*((?is)UPDATE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix ); 01243 $query = $this->prefixQuery( '/^\s*((?is)DELETE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix ); 01244 01245 // SELECT statements aren't working yet 01246 #$data = preg_replace( '/(?ias)(^\s*SELECT\s+.*\s+FROM)\s+(\W\s*,?\s*)+((?i)\s+WHERE.*$)/', "\1 $prefix\2 \3", $data ); 01247 01248 case 'MANUAL': 01249 // If prefixKey is set and has a value then we use it to override the default constant XMLS_PREFIX. 01250 // If prefixKey is not set, we use the default constant XMLS_PREFIX 01251 if( isset( $this->prefixKey ) AND( $this->prefixKey !== '' ) ) { 01252 // Enable prefix override 01253 $query = str_replace( $this->prefixKey, $xmls->objectPrefix, $query ); 01254 } else { 01255 // Use default replacement 01256 $query = str_replace( XMLS_PREFIX , $xmls->objectPrefix, $query ); 01257 } 01258 } 01259 01260 $this->queries[$id] = trim( $query ); 01261 } 01262 01263 // Return the query set array 01264 return $this->queries; 01265 } 01266 01275 function prefixQuery( $regex, $query, $prefix = NULL ) { 01276 if( !isset( $prefix ) ) { 01277 return $query; 01278 } 01279 01280 if( preg_match( $regex, $query, $match ) ) { 01281 $preamble = $match[1]; 01282 $postamble = $match[5]; 01283 $objectList = explode( ',', $match[3] ); 01284 // $prefix = $prefix . '_'; 01285 01286 $prefixedList = ''; 01287 01288 foreach( $objectList as $object ) { 01289 if( $prefixedList !== '' ) { 01290 $prefixedList .= ', '; 01291 } 01292 01293 $prefixedList .= $prefix . trim( $object ); 01294 } 01295 01296 $query = $preamble . ' ' . $prefixedList . ' ' . $postamble; 01297 } 01298 01299 return $query; 01300 } 01301 } 01302 01316 class adoSchema { 01317 01322 var $sqlArray; 01323 01328 var $db; 01329 01334 var $dict; 01335 01340 var $currentElement = ''; 01341 01346 var $upgrade = ''; 01347 01352 var $objectPrefix = ''; 01353 01358 var $mgq; 01359 01364 var $debug; 01365 01370 var $versionRegex = '/<schema.*?( version="([^"]*)")?.*?>/'; 01371 01376 var $schemaVersion; 01377 01381 var $success; 01382 01386 var $executeInline; 01387 01391 var $continueOnError; 01392 01396 var $existingData; 01397 01407 function adoSchema( &$db ) { 01408 // Initialize the environment 01409 $this->mgq = get_magic_quotes_runtime(); 01410 set_magic_quotes_runtime(0); 01411 01412 $this->db =& $db; 01413 $this->debug = $this->db->debug; 01414 $this->dict = NewDataDictionary( $this->db ); 01415 $this->sqlArray = array(); 01416 $this->schemaVersion = XMLS_SCHEMA_VERSION; 01417 $this->executeInline( XMLS_EXECUTE_INLINE ); 01418 $this->continueOnError( XMLS_CONTINUE_ON_ERROR ); 01419 $this->existingData( XMLS_EXISTING_DATA ); 01420 $this->setUpgradeMethod(); 01421 } 01422 01439 function SetUpgradeMethod( $method = '' ) { 01440 if( !is_string( $method ) ) { 01441 return FALSE; 01442 } 01443 01444 $method = strtoupper( $method ); 01445 01446 // Handle the upgrade methods 01447 switch( $method ) { 01448 case 'ALTER': 01449 $this->upgrade = $method; 01450 break; 01451 case 'REPLACE': 01452 $this->upgrade = $method; 01453 break; 01454 case 'BEST': 01455 $this->upgrade = 'ALTER'; 01456 break; 01457 case 'NONE': 01458 $this->upgrade = 'NONE'; 01459 break; 01460 default: 01461 // Use default if no legitimate method is passed. 01462 $this->upgrade = XMLS_DEFAULT_UPGRADE_METHOD; 01463 } 01464 01465 return $this->upgrade; 01466 } 01467 01487 function ExistingData( $mode = NULL ) { 01488 if( is_int( $mode ) ) { 01489 switch( $mode ) { 01490 case XMLS_MODE_UPDATE: 01491 $mode = XMLS_MODE_UPDATE; 01492 break; 01493 case XMLS_MODE_IGNORE: 01494 $mode = XMLS_MODE_IGNORE; 01495 break; 01496 case XMLS_MODE_INSERT: 01497 $mode = XMLS_MODE_INSERT; 01498 break; 01499 default: 01500 $mode = XMLS_EXISITNG_DATA; 01501 break; 01502 } 01503 $this->existingData = $mode; 01504 } 01505 01506 return $this->existingData; 01507 } 01508 01522 function ExecuteInline( $mode = NULL ) { 01523 if( is_bool( $mode ) ) { 01524 $this->executeInline = $mode; 01525 } 01526 01527 return $this->executeInline; 01528 } 01529 01543 function ContinueOnError( $mode = NULL ) { 01544 if( is_bool( $mode ) ) { 01545 $this->continueOnError = $mode; 01546 } 01547 01548 return $this->continueOnError; 01549 } 01550 01564 function ParseSchema( $filename, $returnSchema = FALSE ) { 01565 return $this->ParseSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema ); 01566 } 01567 01589 function ParseSchemaFile( $filename, $returnSchema = FALSE ) { 01590 // Open the file 01591 if( !($fp = fopen( $filename, 'r' )) ) { 01592 logMsg( 'Unable to open file' ); 01593 return FALSE; 01594 } 01595 01596 // do version detection here 01597 if( $this->SchemaFileVersion( $filename ) != $this->schemaVersion ) { 01598 logMsg( 'Invalid Schema Version' ); 01599 return FALSE; 01600 } 01601 01602 if( $returnSchema ) { 01603 $xmlstring = ''; 01604 while( $data = fread( $fp, 4096 ) ) { 01605 $xmlstring .= $data . "\n"; 01606 } 01607 return $xmlstring; 01608 } 01609 01610 $this->success = 2; 01611 01612 $xmlParser = $this->create_parser(); 01613 01614 // Process the file 01615 while( $data = fread( $fp, 4096 ) ) { 01616 if( !xml_parse( $xmlParser, $data, feof( $fp ) ) ) { 01617 die( sprintf( 01618 "XML error: %s at line %d", 01619 xml_error_string( xml_get_error_code( $xmlParser) ), 01620 xml_get_current_line_number( $xmlParser) 01621 ) ); 01622 } 01623 } 01624 01625 xml_parser_free( $xmlParser ); 01626 01627 return $this->sqlArray; 01628 } 01629 01641 function ParseSchemaString( $xmlstring, $returnSchema = FALSE ) { 01642 if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) { 01643 logMsg( 'Empty or Invalid Schema' ); 01644 return FALSE; 01645 } 01646 01647 // do version detection here 01648 if( $this->SchemaStringVersion( $xmlstring ) != $this->schemaVersion ) { 01649 logMsg( 'Invalid Schema Version' ); 01650 return FALSE; 01651 } 01652 01653 if( $returnSchema ) { 01654 return $xmlstring; 01655 } 01656 01657 $this->success = 2; 01658 01659 $xmlParser = $this->create_parser(); 01660 01661 if( !xml_parse( $xmlParser, $xmlstring, TRUE ) ) { 01662 die( sprintf( 01663 "XML error: %s at line %d", 01664 xml_error_string( xml_get_error_code( $xmlParser) ), 01665 xml_get_current_line_number( $xmlParser) 01666 ) ); 01667 } 01668 01669 xml_parser_free( $xmlParser ); 01670 01671 return $this->sqlArray; 01672 } 01673 01685 function RemoveSchema( $filename, $returnSchema = FALSE ) { 01686 return $this->RemoveSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema ); 01687 } 01688 01700 function RemoveSchemaString( $schema, $returnSchema = FALSE ) { 01701 01702 // grab current version 01703 if( !( $version = $this->SchemaStringVersion( $schema ) ) ) { 01704 return FALSE; 01705 } 01706 01707 return $this->ParseSchemaString( $this->TransformSchema( $schema, 'remove-' . $version), $returnSchema ); 01708 } 01709 01723 function ExecuteSchema( $sqlArray = NULL, $continueOnErr = NULL ) { 01724 if( !is_bool( $continueOnErr ) ) { 01725 $continueOnErr = $this->ContinueOnError(); 01726 } 01727 01728 if( !isset( $sqlArray ) ) { 01729 $sqlArray = $this->sqlArray; 01730 } 01731 01732 if( !is_array( $sqlArray ) ) { 01733 $this->success = 0; 01734 } else { 01735 $this->success = $this->dict->ExecuteSQLArray( $sqlArray, $continueOnErr ); 01736 } 01737 01738 return $this->success; 01739 } 01740 01750 function PrintSQL( $format = 'NONE' ) { 01751 $sqlArray = null; 01752 return $this->getSQL( $format, $sqlArray ); 01753 } 01754 01764 function SaveSQL( $filename = './schema.sql' ) { 01765 01766 if( !isset( $sqlArray ) ) { 01767 $sqlArray = $this->sqlArray; 01768 } 01769 if( !isset( $sqlArray ) ) { 01770 return FALSE; 01771 } 01772 01773 $fp = fopen( $filename, "w" ); 01774 01775 foreach( $sqlArray as $key => $query ) { 01776 fwrite( $fp, $query . ";\n" ); 01777 } 01778 fclose( $fp ); 01779 } 01780 01788 function &create_parser() { 01789 // Create the parser 01790 $xmlParser = xml_parser_create(); 01791 xml_set_object( $xmlParser, $this ); 01792 01793 // Initialize the XML callback functions 01794 xml_set_element_handler( $xmlParser, '_tag_open', '_tag_close' ); 01795 xml_set_character_data_handler( $xmlParser, '_tag_cdata' ); 01796 01797 return $xmlParser; 01798 } 01799 01805 function _tag_open( &$parser, $tag, $attributes ) { 01806 switch( strtoupper( $tag ) ) { 01807 case 'TABLE': 01808 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) { 01809 $this->obj = new dbTable( $this, $attributes ); 01810 xml_set_object( $parser, $this->obj ); 01811 } 01812 break; 01813 case 'SQL': 01814 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) { 01815 $this->obj = new dbQuerySet( $this, $attributes ); 01816 xml_set_object( $parser, $this->obj ); 01817 } 01818 break; 01819 default: 01820 // print_r( array( $tag, $attributes ) ); 01821 } 01822 01823 } 01824 01830 function _tag_cdata( &$parser, $cdata ) { 01831 } 01832 01839 function _tag_close( &$parser, $tag ) { 01840 01841 } 01842 01859 function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) { 01860 01861 // grab current version 01862 if( !( $version = $this->SchemaStringVersion( $schema ) ) ) { 01863 return FALSE; 01864 } 01865 01866 if( !isset ($newVersion) ) { 01867 $newVersion = $this->schemaVersion; 01868 } 01869 01870 if( $version == $newVersion ) { 01871 $result = $schema; 01872 } else { 01873 $result = $this->TransformSchema( $schema, 'convert-' . $version . '-' . $newVersion); 01874 } 01875 01876 if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) { 01877 fwrite( $fp, $result ); 01878 fclose( $fp ); 01879 } 01880 01881 return $result; 01882 } 01883 01884 /* 01885 // compat for pre-4.3 - jlim 01886 function _file_get_contents($path) 01887 { 01888 if (function_exists('file_get_contents')) return file_get_contents($path); 01889 return join('',file($path)); 01890 }*/ 01891 01908 function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) { 01909 01910 // grab current version 01911 if( !( $version = $this->SchemaFileVersion( $filename ) ) ) { 01912 return FALSE; 01913 } 01914 01915 if( !isset ($newVersion) ) { 01916 $newVersion = $this->schemaVersion; 01917 } 01918 01919 if( $version == $newVersion ) { 01920 $result = _file_get_contents( $filename ); 01921 01922 // remove unicode BOM if present 01923 if( substr( $result, 0, 3 ) == sprintf( '%c%c%c', 239, 187, 191 ) ) { 01924 $result = substr( $result, 3 ); 01925 } 01926 } else { 01927 $result = $this->TransformSchema( $filename, 'convert-' . $version . '-' . $newVersion, 'file' ); 01928 } 01929 01930 if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) { 01931 fwrite( $fp, $result ); 01932 fclose( $fp ); 01933 } 01934 01935 return $result; 01936 } 01937 01938 function TransformSchema( $schema, $xsl, $schematype='string' ) 01939 { 01940 // Fail if XSLT extension is not available 01941 if( ! function_exists( 'xslt_create' ) ) { 01942 return FALSE; 01943 } 01944 01945 $xsl_file = dirname( __FILE__ ) . '/xsl/' . $xsl . '.xsl'; 01946 01947 // look for xsl 01948 if( !is_readable( $xsl_file ) ) { 01949 return FALSE; 01950 } 01951 01952 switch( $schematype ) 01953 { 01954 case 'file': 01955 if( !is_readable( $schema ) ) { 01956 return FALSE; 01957 } 01958 01959 $schema = _file_get_contents( $schema ); 01960 break; 01961 case 'string': 01962 default: 01963 if( !is_string( $schema ) ) { 01964 return FALSE; 01965 } 01966 } 01967 01968 $arguments = array ( 01969 '/_xml' => $schema, 01970 '/_xsl' => _file_get_contents( $xsl_file ) 01971 ); 01972 01973 // create an XSLT processor 01974 $xh = xslt_create (); 01975 01976 // set error handler 01977 xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler')); 01978 01979 // process the schema 01980 $result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments); 01981 01982 xslt_free ($xh); 01983 01984 return $result; 01985 } 01986 01997 function xslt_error_handler( $parser, $errno, $level, $fields ) { 01998 if( is_array( $fields ) ) { 01999 $msg = array( 02000 'Message Type' => ucfirst( $fields['msgtype'] ), 02001 'Message Code' => $fields['code'], 02002 'Message' => $fields['msg'], 02003 'Error Number' => $errno, 02004 'Level' => $level 02005 ); 02006 02007 switch( $fields['URI'] ) { 02008 case 'arg:/_xml': 02009 $msg['Input'] = 'XML'; 02010 break; 02011 case 'arg:/_xsl': 02012 $msg['Input'] = 'XSL'; 02013 break; 02014 default: 02015 $msg['Input'] = $fields['URI']; 02016 } 02017 02018 $msg['Line'] = $fields['line']; 02019 } else { 02020 $msg = array( 02021 'Message Type' => 'Error', 02022 'Error Number' => $errno, 02023 'Level' => $level, 02024 'Fields' => var_export( $fields, TRUE ) 02025 ); 02026 } 02027 02028 $error_details = $msg['Message Type'] . ' in XSLT Transformation' . "\n" 02029 . '<table>' . "\n"; 02030 02031 foreach( $msg as $label => $details ) { 02032 $error_details .= '<tr><td><b>' . $label . ': </b></td><td>' . htmlentities( $details ) . '</td></tr>' . "\n"; 02033 } 02034 02035 $error_details .= '</table>'; 02036 02037 trigger_error( $error_details, E_USER_ERROR ); 02038 } 02039 02049 function SchemaFileVersion( $filename ) { 02050 // Open the file 02051 if( !($fp = fopen( $filename, 'r' )) ) { 02052 // die( 'Unable to open file' ); 02053 return FALSE; 02054 } 02055 02056 // Process the file 02057 while( $data = fread( $fp, 4096 ) ) { 02058 if( preg_match( $this->versionRegex, $data, $matches ) ) { 02059 return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION; 02060 } 02061 } 02062 02063 return FALSE; 02064 } 02065 02075 function SchemaStringVersion( $xmlstring ) { 02076 if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) { 02077 return FALSE; 02078 } 02079 02080 if( preg_match( $this->versionRegex, $xmlstring, $matches ) ) { 02081 return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION; 02082 } 02083 02084 return FALSE; 02085 } 02086 02097 function ExtractSchema( $data = FALSE, $indent = ' ' ) { 02098 $old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM ); 02099 02100 $schema = '<?xml version="1.0"?>' . "\n" 02101 . '<schema version="' . $this->schemaVersion . '">' . "\n"; 02102 02103 if( is_array( $tables = $this->db->MetaTables( 'TABLES' ) ) ) { 02104 foreach( $tables as $table ) { 02105 $schema .= $indent . '<table name="' . htmlentities( $table ) . '">' . "\n"; 02106 02107 // grab details from database 02108 $rs = $this->db->Execute( 'SELECT * FROM ' . $table . ' WHERE -1' ); 02109 $fields = $this->db->MetaColumns( $table ); 02110 $indexes = $this->db->MetaIndexes( $table ); 02111 02112 if( is_array( $fields ) ) { 02113 foreach( $fields as $details ) { 02114 $extra = ''; 02115 $content = array(); 02116 02117 if( isset($details->max_length) && $details->max_length > 0 ) { 02118 $extra .= ' size="' . $details->max_length . '"'; 02119 } 02120 02121 if( isset($details->primary_key) && $details->primary_key ) { 02122 $content[] = '<KEY/>'; 02123 } elseif( isset($details->not_null) && $details->not_null ) { 02124 $content[] = '<NOTNULL/>'; 02125 } 02126 02127 if( isset($details->has_default) && $details->has_default ) { 02128 $content[] = '<DEFAULT value="' . htmlentities( $details->default_value ) . '"/>'; 02129 } 02130 02131 if( isset($details->auto_increment) && $details->auto_increment ) { 02132 $content[] = '<AUTOINCREMENT/>'; 02133 } 02134 02135 if( isset($details->unsigned) && $details->unsigned ) { 02136 $content[] = '<UNSIGNED/>'; 02137 } 02138 02139 // this stops the creation of 'R' columns, 02140 // AUTOINCREMENT is used to create auto columns 02141 $details->primary_key = 0; 02142 $type = $rs->MetaType( $details ); 02143 02144 $schema .= str_repeat( $indent, 2 ) . '<field name="' . htmlentities( $details->name ) . '" type="' . $type . '"' . $extra; 02145 02146 if( !empty( $content ) ) { 02147 $schema .= ">\n" . str_repeat( $indent, 3 ) 02148 . implode( "\n" . str_repeat( $indent, 3 ), $content ) . "\n" 02149 . str_repeat( $indent, 2 ) . '</field>' . "\n"; 02150 } else { 02151 $schema .= "/>\n"; 02152 } 02153 } 02154 } 02155 02156 if( is_array( $indexes ) ) { 02157 foreach( $indexes as $index => $details ) { 02158 $schema .= str_repeat( $indent, 2 ) . '<index name="' . $index . '">' . "\n"; 02159 02160 if( $details['unique'] ) { 02161 $schema .= str_repeat( $indent, 3 ) . '<UNIQUE/>' . "\n"; 02162 } 02163 02164 foreach( $details['columns'] as $column ) { 02165 $schema .= str_repeat( $indent, 3 ) . '<col>' . htmlentities( $column ) . '</col>' . "\n"; 02166 } 02167 02168 $schema .= str_repeat( $indent, 2 ) . '</index>' . "\n"; 02169 } 02170 } 02171 02172 if( $data ) { 02173 $rs = $this->db->Execute( 'SELECT * FROM ' . $table ); 02174 02175 if( is_object( $rs ) && !$rs->EOF ) { 02176 $schema .= str_repeat( $indent, 2 ) . "<data>\n"; 02177 02178 while( $row = $rs->FetchRow() ) { 02179 foreach( $row as $key => $val ) { 02180 if ( $val != htmlentities( $val ) ) { 02181 $row[$key] = '<![CDATA[' . $val . ']]>'; 02182 } 02183 } 02184 02185 $schema .= str_repeat( $indent, 3 ) . '<row><f>' . implode( '</f><f>', $row ) . "</f></row>\n"; 02186 } 02187 02188 $schema .= str_repeat( $indent, 2 ) . "</data>\n"; 02189 } 02190 } 02191 02192 $schema .= $indent . "</table>\n"; 02193 } 02194 } 02195 02196 $this->db->SetFetchMode( $old_mode ); 02197 02198 $schema .= '</schema>'; 02199 return $schema; 02200 } 02201 02212 function SetPrefix( $prefix = '', $underscore = TRUE ) { 02213 switch( TRUE ) { 02214 // clear prefix 02215 case empty( $prefix ): 02216 logMsg( 'Cleared prefix' ); 02217 $this->objectPrefix = ''; 02218 return TRUE; 02219 // prefix too long 02220 case strlen( $prefix ) > XMLS_PREFIX_MAXLEN: 02221 // prefix contains invalid characters 02222 case !preg_match( '/^[a-z][a-z0-9_]+$/i', $prefix ): 02223 logMsg( 'Invalid prefix: ' . $prefix ); 02224 return FALSE; 02225 } 02226 02227 if( $underscore AND substr( $prefix, -1 ) != '_' ) { 02228 $prefix .= '_'; 02229 } 02230 02231 // prefix valid 02232 logMsg( 'Set prefix: ' . $prefix ); 02233 $this->objectPrefix = $prefix; 02234 return TRUE; 02235 } 02236 02245 function prefix( $name = '' ) { 02246 // if prefix is set 02247 if( !empty( $this->objectPrefix ) ) { 02248 // Prepend the object prefix to the table name 02249 // prepend after quote if used 02250 return preg_replace( '/^(`?)(.+)$/', '$1' . $this->objectPrefix . '$2', $name ); 02251 } 02252 02253 // No prefix set. Use name provided. 02254 return $name; 02255 } 02256 02265 function supportedPlatform( $platform = NULL ) { 02266 if( !empty( $platform ) ) { 02267 $regex = '/(^|\|)' . $this->db->databaseType . '(\||$)/i'; 02268 02269 if( preg_match( '/^- /', $platform ) ) { 02270 if (preg_match ( $regex, substr( $platform, 2 ) ) ) { 02271 logMsg( 'Platform ' . $platform . ' is NOT supported' ); 02272 return FALSE; 02273 } 02274 } else { 02275 if( !preg_match ( $regex, $platform ) ) { 02276 logMsg( 'Platform ' . $platform . ' is NOT supported' ); 02277 return FALSE; 02278 } 02279 } 02280 } 02281 02282 logMsg( 'Platform ' . $platform . ' is supported' ); 02283 return TRUE; 02284 } 02285 02291 function clearSQL() { 02292 $this->sqlArray = array(); 02293 } 02294 02303 function addSQL( $sql = NULL ) { 02304 if( is_array( $sql ) ) { 02305 foreach( $sql as $line ) { 02306 $this->addSQL( $line ); 02307 } 02308 02309 return TRUE; 02310 } 02311 02312 if( is_string( $sql ) ) { 02313 $this->sqlArray[] = $sql; 02314 02315 // if executeInline is enabled, and either no errors have occurred or continueOnError is enabled, execute SQL. 02316 if( $this->ExecuteInline() && ( $this->success == 2 || $this->ContinueOnError() ) ) { 02317 $saved = $this->db->debug; 02318 $this->db->debug = $this->debug; 02319 $ok = $this->db->Execute( $sql ); 02320 $this->db->debug = $saved; 02321 02322 if( !$ok ) { 02323 if( $this->debug ) { 02324 ADOConnection::outp( $this->db->ErrorMsg() ); 02325 } 02326 02327 $this->success = 1; 02328 } 02329 } 02330 02331 return TRUE; 02332 } 02333 02334 return FALSE; 02335 } 02336 02345 function getSQL( $format = NULL, $sqlArray = NULL ) { 02346 if( !is_array( $sqlArray ) ) { 02347 $sqlArray = $this->sqlArray; 02348 } 02349 02350 if( !is_array( $sqlArray ) ) { 02351 return FALSE; 02352 } 02353 02354 switch( strtolower( $format ) ) { 02355 case 'string': 02356 case 'text': 02357 return !empty( $sqlArray ) ? implode( ";\n\n", $sqlArray ) . ';' : ''; 02358 case'html': 02359 return !empty( $sqlArray ) ? nl2br( htmlentities( implode( ";\n\n", $sqlArray ) . ';' ) ) : ''; 02360 } 02361 02362 return $this->sqlArray; 02363 } 02364 02371 function Destroy() { 02372 set_magic_quotes_runtime( $this->mgq ); 02373 unset( $this ); 02374 } 02375 } 02376 02382 function logMsg( $msg, $title = NULL, $force = FALSE ) { 02383 if( XMLS_DEBUG or $force ) { 02384 echo '<pre>'; 02385 02386 if( isset( $title ) ) { 02387 echo '<h3>' . htmlentities( $title ) . '</h3>'; 02388 } 02389 02390 if( @is_object( $this ) ) { 02391 echo '[' . get_class( $this ) . '] '; 02392 } 02393 02394 print_r( $msg ); 02395 02396 echo '</pre>'; 02397 } 02398 } 02399 ?>