adodb 최신버전으로 변경

<? 를 <?php 로 변경
This commit is contained in:
2018-01-11 19:28:35 +09:00
parent feff33715f
commit 7b3b674dee
450 changed files with 19425 additions and 32248 deletions
+359 -357
View File
@@ -1,9 +1,9 @@
<?php
// Copyright (c) 2004-2005 ars Cognita Inc., all rights reserved
/* ******************************************************************************
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
*******************************************************************************/
/**
* xmlschema is a class that allows the user to quickly and easily
@@ -17,15 +17,15 @@
* @package axmls
* @tutorial getting_started.pkg
*/
function _file_get_contents($file)
function _file_get_contents($file)
{
if (function_exists('file_get_contents')) return file_get_contents($file);
$f = fopen($file,'r');
if (!$f) return '';
$t = '';
while ($s = fread($f,100000)) $t .= $s;
fclose($f);
return $t;
@@ -122,62 +122,61 @@ if( !defined( '_ADODB_LAYER' ) ) {
* @access private
*/
class dbObject {
/**
* var object Parent
*/
var $parent;
/**
* var string current element
*/
var $currentElement;
/**
* NOP
*/
function dbObject( &$parent, $attributes = NULL ) {
function __construct( &$parent, $attributes = NULL ) {
$this->parent = $parent;
}
/**
* XML Callback to process start elements
*
* @access private
*/
function _tag_open( &$parser, $tag, $attributes ) {
}
/**
* XML Callback to process CDATA elements
*
* @access private
*/
function _tag_cdata( &$parser, $cdata ) {
}
/**
* XML Callback to process end elements
*
* @access private
*/
function _tag_close( &$parser, $tag ) {
}
function create() {
function create(&$xmls) {
return array();
}
/**
* Destroys the object
*/
function destroy() {
unset( $this );
}
/**
* Checks whether the specified RDBMS is supported by the current
* database object or its ranking ancestor.
@@ -188,7 +187,7 @@ class dbObject {
function supportedPlatform( $platform = NULL ) {
return is_object( $this->parent ) ? $this->parent->supportedPlatform( $platform ) : TRUE;
}
/**
* Returns the prefix set by the ranking ancestor of the database object.
*
@@ -198,7 +197,7 @@ class dbObject {
function prefix( $name = '' ) {
return is_object( $this->parent ) ? $this->parent->prefix( $name ) : $name;
}
/**
* Extracts a field ID from the specified field.
*
@@ -222,80 +221,82 @@ class dbObject {
* @access private
*/
class dbTable extends dbObject {
/**
* @var string Table name
*/
var $name;
/**
* @var array Field specifier: Meta-information about each field
*/
var $fields = array();
/**
* @var array List of table indexes.
*/
var $indexes = array();
/**
* @var array Table options: Table-level options
*/
var $opts = array();
/**
* @var string Field index: Keeps track of which field is currently being processed
*/
var $current_field;
/**
* @var boolean Mark table for destruction
* @access private
*/
var $drop_table;
/**
* @var boolean Mark field for destruction (not yet implemented)
* @access private
*/
var $drop_field = array();
/**
* @var array Platform-specific options
* @access private
*/
var $currentPlatform = true;
/**
* Iniitializes a new table object.
*
* @param string $prefix DB Object prefix
* @param array $attributes Array of table attributes.
*/
function dbTable( &$parent, $attributes = NULL ) {
function __construct( &$parent, $attributes = NULL ) {
$this->parent = $parent;
$this->name = $this->prefix($attributes['NAME']);
}
/**
* XML Callback to process start elements. Elements currently
* processed are: INDEX, DROP, FIELD, KEY, NOTNULL, AUTOINCREMENT & DEFAULT.
* XML Callback to process start elements. Elements currently
* processed are: INDEX, DROP, FIELD, KEY, NOTNULL, AUTOINCREMENT & DEFAULT.
*
* @access private
*/
function _tag_open( &$parser, $tag, $attributes ) {
$this->currentElement = strtoupper( $tag );
switch( $this->currentElement ) {
case 'INDEX':
if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
xml_set_object( $parser, $this->addIndex( $attributes ) );
$index = $this->addIndex( $attributes );
xml_set_object( $parser, $index );
}
break;
case 'DATA':
if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
xml_set_object( $parser, $this->addData( $attributes ) );
$data = $this->addData( $attributes );
xml_set_object( $parser, $data );
}
break;
case 'DROP':
@@ -307,7 +308,7 @@ class dbTable extends dbObject {
$fieldType = $attributes['TYPE'];
$fieldSize = isset( $attributes['SIZE'] ) ? $attributes['SIZE'] : NULL;
$fieldOpts = !empty( $attributes['OPTS'] ) ? $attributes['OPTS'] : NULL;
$this->addField( $fieldName, $fieldType, $fieldSize, $fieldOpts );
break;
case 'KEY':
@@ -321,12 +322,12 @@ class dbTable extends dbObject {
break;
case 'DEFAULT':
// Add a field option to the table object
// Work around ADOdb datadict issue that misinterprets empty strings.
if( $attributes['VALUE'] == '' ) {
$attributes['VALUE'] = " '' ";
}
$this->addFieldOpt( $this->current_field, $this->currentElement, $attributes['VALUE'] );
break;
case 'OPT':
@@ -338,7 +339,7 @@ class dbTable extends dbObject {
// print_r( array( $tag, $attributes ) );
}
}
/**
* XML Callback to process CDATA elements
*
@@ -363,10 +364,10 @@ class dbTable extends dbObject {
}
break;
default:
}
}
/**
* XML Callback to process end elements
*
@@ -374,7 +375,7 @@ class dbTable extends dbObject {
*/
function _tag_close( &$parser, $tag ) {
$this->currentElement = '';
switch( strtoupper( $tag ) ) {
case 'TABLE':
$this->parent->addSQL( $this->create( $this->parent ) );
@@ -392,7 +393,7 @@ class dbTable extends dbObject {
}
}
/**
* Adds an index to a table object
*
@@ -404,7 +405,7 @@ class dbTable extends dbObject {
$this->indexes[$name] = new dbIndex( $this, $attributes );
return $this->indexes[$name];
}
/**
* Adds data to a table object
*
@@ -417,11 +418,11 @@ class dbTable extends dbObject {
}
return $this->data;
}
/**
* Adds a field to a table object
*
* $name is the name of the table to which the field should be added.
* $name is the name of the table to which the field should be added.
* $type is an ADODB datadict field type. The following field types
* are supported as of ADODB 3.40:
* - C: varchar
@@ -449,21 +450,21 @@ class dbTable extends dbObject {
*/
function addField( $name, $type, $size = NULL, $opts = NULL ) {
$field_id = $this->FieldID( $name );
// Set the field index so we know where we are
$this->current_field = $field_id;
// Set the field name (required)
$this->fields[$field_id]['NAME'] = $name;
// Set the field type (required)
$this->fields[$field_id]['TYPE'] = $type;
// Set the field size (optional)
if( isset( $size ) ) {
$this->fields[$field_id]['SIZE'] = $size;
}
// Set the field options
if( isset( $opts ) ) {
$this->fields[$field_id]['OPTS'] = array($opts);
@@ -471,11 +472,11 @@ class dbTable extends dbObject {
$this->fields[$field_id]['OPTS'] = array();
}
}
/**
* Adds a field option to the current field specifier
*
* This method adds a field option allowed by the ADOdb datadict
* This method adds a field option allowed by the ADOdb datadict
* and appends it to the given field.
*
* @param string $field Field name
@@ -493,7 +494,7 @@ class dbTable extends dbObject {
}
}
}
/**
* Adds an option to the table
*
@@ -510,7 +511,7 @@ class dbTable extends dbObject {
return $this->opts;
}
/**
* Generates the SQL that will create the table in the database
*
@@ -519,28 +520,28 @@ class dbTable extends dbObject {
*/
function create( &$xmls ) {
$sql = array();
// drop any existing indexes
if( is_array( $legacy_indexes = $xmls->dict->MetaIndexes( $this->name ) ) ) {
foreach( $legacy_indexes as $index => $index_details ) {
$sql[] = $xmls->dict->DropIndexSQL( $index, $this->name );
}
}
// remove fields to be dropped from table object
foreach( $this->drop_field as $field ) {
unset( $this->fields[$field] );
}
// if table exists
if( is_array( $legacy_fields = $xmls->dict->MetaColumns( $this->name ) ) ) {
// drop table
if( $this->drop_table ) {
$sql[] = $xmls->dict->DropTableSQL( $this->name );
return $sql;
}
// drop any existing fields not in schema
foreach( $legacy_fields as $field_id => $field ) {
if( !isset( $this->fields[$field_id] ) ) {
@@ -552,27 +553,27 @@ class dbTable extends dbObject {
if( $this->drop_table ) {
return $sql;
}
$legacy_fields = array();
}
// Loop through the field specifier array, building the associative array for the field options
$fldarray = array();
foreach( $this->fields as $field_id => $finfo ) {
// Set an empty size if it isn't supplied
if( !isset( $finfo['SIZE'] ) ) {
$finfo['SIZE'] = '';
}
// Initialize the field array with the type and size
$fldarray[$field_id] = array(
'NAME' => $finfo['NAME'],
'TYPE' => $finfo['TYPE'],
'SIZE' => $finfo['SIZE']
);
// Loop through the options array and add the field options.
// Loop through the options array and add the field options.
if( isset( $finfo['OPTS'] ) ) {
foreach( $finfo['OPTS'] as $opt ) {
// Option has an argument.
@@ -587,7 +588,7 @@ class dbTable extends dbObject {
}
}
}
if( empty( $legacy_fields ) ) {
// Create the new table
$sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
@@ -611,18 +612,18 @@ class dbTable extends dbObject {
return array();
}
}
foreach( $this->indexes as $index ) {
$sql[] = $index->create( $xmls );
}
if( isset( $this->data ) ) {
$sql[] = $this->data->create( $xmls );
}
return $sql;
}
/**
* Marks a field or table for destruction
*/
@@ -653,28 +654,28 @@ class dbTable extends dbObject {
* @access private
*/
class dbIndex extends dbObject {
/**
* @var string Index name
*/
var $name;
/**
* @var array Index options: Index-level options
*/
var $opts = array();
/**
* @var array Indexed fields: Table columns included in this index
*/
var $columns = array();
/**
* @var boolean Mark index for destruction
* @access private
*/
var $drop = FALSE;
/**
* Initializes the new dbIndex object.
*
@@ -683,23 +684,23 @@ class dbIndex extends dbObject {
*
* @internal
*/
function dbIndex( &$parent, $attributes = NULL ) {
function __construct( &$parent, $attributes = NULL ) {
$this->parent = $parent;
$this->name = $this->prefix ($attributes['NAME']);
}
/**
* XML Callback to process start elements
*
* Processes XML opening tags.
* Elements currently processed are: DROP, CLUSTERED, BITMAP, UNIQUE, FULLTEXT & HASH.
* Processes XML opening tags.
* Elements currently processed are: DROP, CLUSTERED, BITMAP, UNIQUE, FULLTEXT & HASH.
*
* @access private
*/
function _tag_open( &$parser, $tag, $attributes ) {
$this->currentElement = strtoupper( $tag );
switch( $this->currentElement ) {
case 'DROP':
$this->drop();
@@ -716,7 +717,7 @@ class dbIndex extends dbObject {
// print_r( array( $tag, $attributes ) );
}
}
/**
* XML Callback to process CDATA elements
*
@@ -731,10 +732,10 @@ class dbIndex extends dbObject {
$this->addField( $cdata );
break;
default:
}
}
/**
* XML Callback to process end elements
*
@@ -742,14 +743,14 @@ class dbIndex extends dbObject {
*/
function _tag_close( &$parser, $tag ) {
$this->currentElement = '';
switch( strtoupper( $tag ) ) {
case 'INDEX':
xml_set_object( $parser, $this->parent );
break;
}
}
/**
* Adds a field to the index
*
@@ -758,11 +759,11 @@ class dbIndex extends dbObject {
*/
function addField( $name ) {
$this->columns[$this->FieldID( $name )] = $name;
// Return the field list
return $this->columns;
}
/**
* Adds options to the index
*
@@ -771,11 +772,11 @@ class dbIndex extends dbObject {
*/
function addIndexOpt( $opt ) {
$this->opts[] = $opt;
// Return the options list
return $this->opts;
}
/**
* Generates the SQL that will create the index in the database
*
@@ -786,17 +787,17 @@ class dbIndex extends dbObject {
if( $this->drop ) {
return NULL;
}
// eliminate any columns that aren't in the table
foreach( $this->columns as $id => $col ) {
if( !isset( $this->parent->fields[$id] ) ) {
unset( $this->columns[$id] );
}
}
return $xmls->dict->CreateIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts );
}
/**
* Marks an index for destruction
*/
@@ -815,11 +816,11 @@ class dbIndex extends dbObject {
* @access private
*/
class dbData extends dbObject {
var $data = array();
var $row;
/**
* Initializes the new dbData object.
*
@@ -828,21 +829,21 @@ class dbData extends dbObject {
*
* @internal
*/
function dbData( &$parent, $attributes = NULL ) {
function __construct( &$parent, $attributes = NULL ) {
$this->parent = $parent;
}
/**
* XML Callback to process start elements
*
* Processes XML opening tags.
* Elements currently processed are: ROW and F (field).
* Processes XML opening tags.
* Elements currently processed are: ROW and F (field).
*
* @access private
*/
function _tag_open( &$parser, $tag, $attributes ) {
$this->currentElement = strtoupper( $tag );
switch( $this->currentElement ) {
case 'ROW':
$this->row = count( $this->data );
@@ -854,7 +855,7 @@ class dbData extends dbObject {
// print_r( array( $tag, $attributes ) );
}
}
/**
* XML Callback to process CDATA elements
*
@@ -869,10 +870,10 @@ class dbData extends dbObject {
$this->addData( $cdata );
break;
default:
}
}
/**
* XML Callback to process end elements
*
@@ -880,14 +881,14 @@ class dbData extends dbObject {
*/
function _tag_close( &$parser, $tag ) {
$this->currentElement = '';
switch( strtoupper( $tag ) ) {
case 'DATA':
xml_set_object( $parser, $this->parent );
break;
}
}
/**
* Adds a field to the insert
*
@@ -899,20 +900,20 @@ class dbData extends dbObject {
if( !isset( $this->row ) || !isset( $this->data[$this->row] ) ) {
return;
}
// Set the field index so we know where we are
if( isset( $attributes['NAME'] ) ) {
$this->current_field = $this->FieldID( $attributes['NAME'] );
} else {
$this->current_field = count( $this->data[$this->row] );
}
// initialise data
if( !isset( $this->data[$this->row][$this->current_field] ) ) {
$this->data[$this->row][$this->current_field] = '';
}
}
/**
* Adds options to the index
*
@@ -926,7 +927,7 @@ class dbData extends dbObject {
$this->data[$this->row][$this->current_field] .= $cdata;
}
}
/**
* Generates the SQL that will add/update the data in the database
*
@@ -936,22 +937,22 @@ class dbData extends dbObject {
function create( &$xmls ) {
$table = $xmls->dict->TableName($this->parent->name);
$table_field_count = count($this->parent->fields);
$tables = $xmls->db->MetaTables();
$tables = $xmls->db->MetaTables();
$sql = array();
$ukeys = $xmls->db->MetaPrimaryKeys( $table );
if( !empty( $this->parent->indexes ) and !empty( $ukeys ) ) {
foreach( $this->parent->indexes as $indexObj ) {
if( !in_array( $indexObj->name, $ukeys ) ) $ukeys[] = $indexObj->name;
}
}
// eliminate any columns that aren't in the table
foreach( $this->data as $row ) {
$table_fields = $this->parent->fields;
$fields = array();
$rawfields = array(); // Need to keep some of the unprocessed data on hand.
foreach( $row as $field_id => $field_data ) {
if( !array_key_exists( $field_id, $table_fields ) ) {
if( is_numeric( $field_id ) ) {
@@ -960,9 +961,9 @@ class dbData extends dbObject {
continue;
}
}
$name = $table_fields[$field_id]['NAME'];
switch( $table_fields[$field_id]['TYPE'] ) {
case 'I':
case 'I1':
@@ -979,16 +980,16 @@ class dbData extends dbObject {
$fields[$name] = $xmls->db->qstr( $field_data );
$rawfields[$name] = $field_data;
}
unset($table_fields[$field_id]);
}
// check that at least 1 column is specified
if( empty( $fields ) ) {
continue;
}
// check that no required columns are missing
if( count( $fields ) < $table_field_count ) {
foreach( $table_fields as $field ) {
@@ -997,27 +998,27 @@ class dbData extends dbObject {
}
}
}
// The rest of this method deals with updating existing data records.
if( !in_array( $table, $tables ) or ( $mode = $xmls->existingData() ) == XMLS_MODE_INSERT ) {
// Table doesn't yet exist, so it's safe to insert.
logMsg( "$table doesn't exist, inserting or mode is INSERT" );
$sql[] = 'INSERT INTO '. $table .' ('. implode( ',', array_keys( $fields ) ) .') VALUES ('. implode( ',', $fields ) .')';
continue;
}
// Prepare to test for potential violations. Get primary keys and unique indexes
$mfields = array_merge( $fields, $rawfields );
$keyFields = array_intersect( $ukeys, array_keys( $mfields ) );
if( empty( $ukeys ) or count( $keyFields ) == 0 ) {
// No unique keys in schema, so safe to insert
logMsg( "Either schema or data has no unique keys, so safe to insert" );
$sql[] = 'INSERT INTO '. $table .' ('. implode( ',', array_keys( $fields ) ) .') VALUES ('. implode( ',', $fields ) .')';
continue;
}
// Select record containing matching unique keys.
$where = '';
foreach( $ukeys as $key ) {
@@ -1057,43 +1058,43 @@ class dbData extends dbObject {
* @access private
*/
class dbQuerySet extends dbObject {
/**
* @var array List of SQL queries
*/
var $queries = array();
/**
* @var string String used to build of a query line by line
*/
var $query;
/**
* @var string Query prefix key
*/
var $prefixKey = '';
/**
* @var boolean Auto prefix enable (TRUE)
*/
var $prefixMethod = 'AUTO';
/**
* Initializes the query set.
*
* @param object $parent Parent object
* @param array $attributes Attributes
*/
function dbQuerySet( &$parent, $attributes = NULL ) {
function __construct( &$parent, $attributes = NULL ) {
$this->parent = $parent;
// Overrides the manual prefix key
if( isset( $attributes['KEY'] ) ) {
$this->prefixKey = $attributes['KEY'];
}
$prefixMethod = isset( $attributes['PREFIXMETHOD'] ) ? strtoupper( trim( $attributes['PREFIXMETHOD'] ) ) : '';
// Enables or disables automatic prefix prepending
switch( $prefixMethod ) {
case 'AUTO':
@@ -1107,20 +1108,20 @@ class dbQuerySet extends dbObject {
break;
}
}
/**
* XML Callback to process start elements. Elements currently
* processed are: QUERY.
* XML Callback to process start elements. Elements currently
* processed are: QUERY.
*
* @access private
*/
function _tag_open( &$parser, $tag, $attributes ) {
$this->currentElement = strtoupper( $tag );
switch( $this->currentElement ) {
case 'QUERY':
// Create a new query in a SQL queryset.
// Ignore this query set if a platform is specified and it's different than the
// Ignore this query set if a platform is specified and it's different than the
// current connection platform.
if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
$this->newQuery();
@@ -1132,7 +1133,7 @@ class dbQuerySet extends dbObject {
// print_r( array( $tag, $attributes ) );
}
}
/**
* XML Callback to process CDATA elements
*/
@@ -1143,10 +1144,10 @@ class dbQuerySet extends dbObject {
$this->buildQuery( $cdata );
break;
default:
}
}
/**
* XML Callback to process end elements
*
@@ -1154,7 +1155,7 @@ class dbQuerySet extends dbObject {
*/
function _tag_close( &$parser, $tag ) {
$this->currentElement = '';
switch( strtoupper( $tag ) ) {
case 'QUERY':
// Add the finished query to the open query set.
@@ -1166,10 +1167,10 @@ class dbQuerySet extends dbObject {
$this->destroy();
break;
default:
}
}
/**
* Re-initializes the query.
*
@@ -1177,10 +1178,10 @@ class dbQuerySet extends dbObject {
*/
function newQuery() {
$this->query = '';
return TRUE;
}
/**
* Discards the existing query.
*
@@ -1188,11 +1189,11 @@ class dbQuerySet extends dbObject {
*/
function discardQuery() {
unset( $this->query );
return TRUE;
}
/**
/**
* Appends a line to a query that is being built line by line
*
* @param string $data Line of SQL data or NULL to initialize a new query
@@ -1202,12 +1203,12 @@ class dbQuerySet extends dbObject {
if( !isset( $this->query ) OR empty( $sql ) ) {
return FALSE;
}
$this->query .= $sql;
return $this->query;
}
/**
* Adds a completed query to the query list
*
@@ -1217,14 +1218,14 @@ class dbQuerySet extends dbObject {
if( !isset( $this->query ) ) {
return FALSE;
}
$this->queries[] = $return = trim($this->query);
unset( $this->query );
return $return;
}
/**
* Creates and returns the current query set
*
@@ -1236,16 +1237,16 @@ class dbQuerySet extends dbObject {
switch( $this->prefixMethod ) {
case 'AUTO':
// Enable auto prefix replacement
// Process object prefix.
// Evaluate SQL statements to prepend prefix to objects
$query = $this->prefixQuery( '/^\s*((?is)INSERT\s+(INTO\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
$query = $this->prefixQuery( '/^\s*((?is)UPDATE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
$query = $this->prefixQuery( '/^\s*((?is)DELETE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
// SELECT statements aren't working yet
#$data = preg_replace( '/(?ias)(^\s*SELECT\s+.*\s+FROM)\s+(\W\s*,?\s*)+((?i)\s+WHERE.*$)/', "\1 $prefix\2 \3", $data );
case 'MANUAL':
// If prefixKey is set and has a value then we use it to override the default constant XMLS_PREFIX.
// If prefixKey is not set, we use the default constant XMLS_PREFIX
@@ -1257,14 +1258,14 @@ class dbQuerySet extends dbObject {
$query = str_replace( XMLS_PREFIX , $xmls->objectPrefix, $query );
}
}
$this->queries[$id] = trim( $query );
}
// Return the query set array
return $this->queries;
}
/**
* Rebuilds the query with the prefix attached to any objects
*
@@ -1277,33 +1278,33 @@ class dbQuerySet extends dbObject {
if( !isset( $prefix ) ) {
return $query;
}
if( preg_match( $regex, $query, $match ) ) {
$preamble = $match[1];
$postamble = $match[5];
$objectList = explode( ',', $match[3] );
// $prefix = $prefix . '_';
$prefixedList = '';
foreach( $objectList as $object ) {
if( $prefixedList !== '' ) {
$prefixedList .= ', ';
}
$prefixedList .= $prefix . trim( $object );
}
$query = $preamble . ' ' . $prefixedList . ' ' . $postamble;
}
return $query;
}
}
/**
* Loads and parses an XML file, creating an array of "ready-to-run" SQL statements
*
*
* This class is used to load and parse the XML file, to create an array of SQL statements
* that can be used to build a database, and to build the database using the SQL array.
*
@@ -1315,87 +1316,87 @@ class dbQuerySet extends dbObject {
* @package axmls
*/
class adoSchema {
/**
* @var array Array containing SQL queries to generate all objects
* @access private
*/
var $sqlArray;
/**
* @var object ADOdb connection object
* @access private
*/
var $db;
/**
* @var object ADOdb Data Dictionary
* @access private
*/
var $dict;
/**
* @var string Current XML element
* @access private
*/
var $currentElement = '';
/**
* @var string If set (to 'ALTER' or 'REPLACE'), upgrade an existing database
* @access private
*/
var $upgrade = '';
/**
* @var string Optional object prefix
* @access private
*/
var $objectPrefix = '';
/**
* @var long Original Magic Quotes Runtime value
* @access private
*/
var $mgq;
/**
* @var long System debug
* @access private
*/
var $debug;
/**
* @var string Regular expression to find schema version
* @access private
*/
var $versionRegex = '/<schema.*?( version="([^"]*)")?.*?>/';
/**
* @var string Current schema version
* @access private
*/
var $schemaVersion;
/**
* @var int Success of last Schema execution
*/
var $success;
/**
* @var bool Execute SQL inline as it is generated
*/
var $executeInline;
/**
* @var bool Continue SQL execution if errors occur
*/
var $continueOnError;
/**
* @var int How to handle existing data rows (insert, update, or ignore)
*/
var $existingData;
/**
* Creates an adoSchema object
*
@@ -1405,11 +1406,12 @@ class adoSchema {
*
* @param object $db ADOdb database connection object.
*/
function adoSchema( &$db ) {
function __construct( $db ) {
// Initialize the environment
$this->mgq = get_magic_quotes_runtime();
set_magic_quotes_runtime(0);
#set_magic_quotes_runtime(0);
ini_set("magic_quotes_runtime", 0);
$this->db = $db;
$this->debug = $this->db->debug;
$this->dict = NewDataDictionary( $this->db );
@@ -1420,7 +1422,7 @@ class adoSchema {
$this->existingData( XMLS_EXISTING_DATA );
$this->setUpgradeMethod();
}
/**
* Sets the method to be used for upgrading an existing database
*
@@ -1441,9 +1443,9 @@ class adoSchema {
if( !is_string( $method ) ) {
return FALSE;
}
$method = strtoupper( $method );
// Handle the upgrade methods
switch( $method ) {
case 'ALTER':
@@ -1462,10 +1464,10 @@ class adoSchema {
// Use default if no legitimate method is passed.
$this->upgrade = XMLS_DEFAULT_UPGRADE_METHOD;
}
return $this->upgrade;
}
/**
* Specifies how to handle existing data row when there is a unique key conflict.
*
@@ -1474,7 +1476,7 @@ class adoSchema {
* data into an existing table with one or more primary keys or unique indexes.
* The existingData method takes one of three options: XMLS_MODE_INSERT attempts
* to always insert the data as a new row. In the event of a unique key violation,
* the database will generate an error. XMLS_MODE_UPDATE attempts to update the
* the database will generate an error. XMLS_MODE_UPDATE attempts to update the
* any existing rows with the new data based upon primary or unique key fields in
* the schema. If the data row in the schema specifies no unique fields, the row
* data will be inserted as a new row. XMLS_MODE_IGNORE specifies that any data rows
@@ -1503,10 +1505,10 @@ class adoSchema {
}
$this->existingData = $mode;
}
return $this->existingData;
}
/**
* Enables/disables inline SQL execution.
*
@@ -1524,10 +1526,10 @@ class adoSchema {
if( is_bool( $mode ) ) {
$this->executeInline = $mode;
}
return $this->executeInline;
}
/**
* Enables/disables SQL continue on error.
*
@@ -1545,10 +1547,10 @@ class adoSchema {
if( is_bool( $mode ) ) {
$this->continueOnError = $mode;
}
return $this->continueOnError;
}
/**
* Loads an XML schema from a file and converts it to SQL.
*
@@ -1565,7 +1567,7 @@ class adoSchema {
function ParseSchema( $filename, $returnSchema = FALSE ) {
return $this->ParseSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
}
/**
* Loads an XML schema from a file and converts it to SQL.
*
@@ -1593,13 +1595,13 @@ class adoSchema {
logMsg( 'Unable to open file' );
return FALSE;
}
// do version detection here
if( $this->SchemaFileVersion( $filename ) != $this->schemaVersion ) {
logMsg( 'Invalid Schema Version' );
return FALSE;
}
if( $returnSchema ) {
$xmlstring = '';
while( $data = fread( $fp, 4096 ) ) {
@@ -1607,11 +1609,11 @@ class adoSchema {
}
return $xmlstring;
}
$this->success = 2;
$xmlParser = $this->create_parser();
// Process the file
while( $data = fread( $fp, 4096 ) ) {
if( !xml_parse( $xmlParser, $data, feof( $fp ) ) ) {
@@ -1622,17 +1624,17 @@ class adoSchema {
) );
}
}
xml_parser_free( $xmlParser );
return $this->sqlArray;
}
/**
* Converts an XML schema string to SQL.
*
* Call this method to parse a string containing an XML schema (see the DTD for the proper format)
* and generate the SQL necessary to create the database described by the schema.
* and generate the SQL necessary to create the database described by the schema.
* @see ParseSchema()
*
* @param string $xmlstring XML schema string.
@@ -1644,21 +1646,21 @@ class adoSchema {
logMsg( 'Empty or Invalid Schema' );
return FALSE;
}
// do version detection here
if( $this->SchemaStringVersion( $xmlstring ) != $this->schemaVersion ) {
logMsg( 'Invalid Schema Version' );
return FALSE;
}
if( $returnSchema ) {
return $xmlstring;
}
$this->success = 2;
$xmlParser = $this->create_parser();
if( !xml_parse( $xmlParser, $xmlstring, TRUE ) ) {
die( sprintf(
"XML error: %s at line %d",
@@ -1666,12 +1668,12 @@ class adoSchema {
xml_get_current_line_number( $xmlParser)
) );
}
xml_parser_free( $xmlParser );
return $this->sqlArray;
}
/**
* Loads an XML schema from a file and converts it to uninstallation SQL.
*
@@ -1686,12 +1688,12 @@ class adoSchema {
function RemoveSchema( $filename, $returnSchema = FALSE ) {
return $this->RemoveSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
}
/**
* Converts an XML schema string to uninstallation SQL.
*
* Call this method to parse a string containing an XML schema (see the DTD for the proper format)
* and generate the SQL necessary to uninstall the database described by the schema.
* and generate the SQL necessary to uninstall the database described by the schema.
* @see RemoveSchema()
*
* @param string $schema XML schema string.
@@ -1699,20 +1701,20 @@ class adoSchema {
* @return array Array of SQL queries, ready to execute.
*/
function RemoveSchemaString( $schema, $returnSchema = FALSE ) {
// grab current version
if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
return FALSE;
}
return $this->ParseSchemaString( $this->TransformSchema( $schema, 'remove-' . $version), $returnSchema );
}
/**
* Applies the current XML schema to the database (post execution).
*
* Call this method to apply the current schema (generally created by calling
* ParseSchema() or ParseSchemaString() ) to the database (creating the tables, indexes,
* Call this method to apply the current schema (generally created by calling
* ParseSchema() or ParseSchemaString() ) to the database (creating the tables, indexes,
* and executing other SQL specified in the schema) after parsing.
* @see ParseSchema(), ParseSchemaString(), ExecuteInline()
*
@@ -1725,25 +1727,25 @@ class adoSchema {
if( !is_bool( $continueOnErr ) ) {
$continueOnErr = $this->ContinueOnError();
}
if( !isset( $sqlArray ) ) {
$sqlArray = $this->sqlArray;
}
if( !is_array( $sqlArray ) ) {
$this->success = 0;
} else {
$this->success = $this->dict->ExecuteSQLArray( $sqlArray, $continueOnErr );
}
return $this->success;
}
/**
* Returns the current SQL array.
* Returns the current SQL array.
*
* Call this method to fetch the array of SQL queries resulting from
* ParseSchema() or ParseSchemaString().
* Call this method to fetch the array of SQL queries resulting from
* ParseSchema() or ParseSchemaString().
*
* @param string $format Format: HTML, TEXT, or NONE (PHP array)
* @return array Array of SQL statements or FALSE if an error occurs
@@ -1752,7 +1754,7 @@ class adoSchema {
$sqlArray = null;
return $this->getSQL( $format, $sqlArray );
}
/**
* Saves the current SQL array to the local filesystem as a list of SQL queries.
*
@@ -1760,25 +1762,25 @@ class adoSchema {
* parsed XML schema) to the filesystem.
*
* @param string $filename Path and name where the file should be saved.
* @return boolean TRUE if save is successful, else FALSE.
* @return boolean TRUE if save is successful, else FALSE.
*/
function SaveSQL( $filename = './schema.sql' ) {
if( !isset( $sqlArray ) ) {
$sqlArray = $this->sqlArray;
}
if( !isset( $sqlArray ) ) {
return FALSE;
}
$fp = fopen( $filename, "w" );
foreach( $sqlArray as $key => $query ) {
fwrite( $fp, $query . ";\n" );
}
fclose( $fp );
}
/**
* Create an xml parser
*
@@ -1790,14 +1792,14 @@ class adoSchema {
// Create the parser
$xmlParser = xml_parser_create();
xml_set_object( $xmlParser, $this );
// Initialize the XML callback functions
xml_set_element_handler( $xmlParser, '_tag_open', '_tag_close' );
xml_set_character_data_handler( $xmlParser, '_tag_cdata' );
return $xmlParser;
}
/**
* XML Callback to process start elements
*
@@ -1820,9 +1822,9 @@ class adoSchema {
default:
// print_r( array( $tag, $attributes ) );
}
}
/**
* XML Callback to process CDATA elements
*
@@ -1830,7 +1832,7 @@ class adoSchema {
*/
function _tag_cdata( &$parser, $cdata ) {
}
/**
* XML Callback to process end elements
*
@@ -1838,16 +1840,16 @@ class adoSchema {
* @internal
*/
function _tag_close( &$parser, $tag ) {
}
/**
* Converts an XML schema string to the specified DTD version.
*
* Call this method to convert a string containing an XML schema to a different AXMLS
* DTD version. For instance, to convert a schema created for an pre-1.0 version for
* AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version
* parameter is specified, the schema will be converted to the current DTD version.
* DTD version. For instance, to convert a schema created for an pre-1.0 version for
* AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version
* parameter is specified, the schema will be converted to the current DTD version.
* If the newFile parameter is provided, the converted schema will be written to the specified
* file.
* @see ConvertSchemaFile()
@@ -1858,27 +1860,27 @@ class adoSchema {
* @return string Converted XML schema or FALSE if an error occurs.
*/
function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
// grab current version
if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
return FALSE;
}
if( !isset ($newVersion) ) {
$newVersion = $this->schemaVersion;
}
if( $version == $newVersion ) {
$result = $schema;
} else {
$result = $this->TransformSchema( $schema, 'convert-' . $version . '-' . $newVersion);
}
if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
fwrite( $fp, $result );
fclose( $fp );
}
return $result;
}
@@ -1889,14 +1891,14 @@ class adoSchema {
if (function_exists('file_get_contents')) return file_get_contents($path);
return join('',file($path));
}*/
/**
* Converts an XML schema file to the specified DTD version.
*
* Call this method to convert the specified XML schema file to a different AXMLS
* DTD version. For instance, to convert a schema created for an pre-1.0 version for
* AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version
* parameter is specified, the schema will be converted to the current DTD version.
* DTD version. For instance, to convert a schema created for an pre-1.0 version for
* AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version
* parameter is specified, the schema will be converted to the current DTD version.
* If the newFile parameter is provided, the converted schema will be written to the specified
* file.
* @see ConvertSchemaString()
@@ -1907,19 +1909,19 @@ class adoSchema {
* @return string Converted XML schema or FALSE if an error occurs.
*/
function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
// grab current version
if( !( $version = $this->SchemaFileVersion( $filename ) ) ) {
return FALSE;
}
if( !isset ($newVersion) ) {
$newVersion = $this->schemaVersion;
}
if( $version == $newVersion ) {
$result = _file_get_contents( $filename );
// remove unicode BOM if present
if( substr( $result, 0, 3 ) == sprintf( '%c%c%c', 239, 187, 191 ) ) {
$result = substr( $result, 3 );
@@ -1927,36 +1929,36 @@ class adoSchema {
} else {
$result = $this->TransformSchema( $filename, 'convert-' . $version . '-' . $newVersion, 'file' );
}
if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
fwrite( $fp, $result );
fclose( $fp );
}
return $result;
}
function TransformSchema( $schema, $xsl, $schematype='string' )
{
// Fail if XSLT extension is not available
if( ! function_exists( 'xslt_create' ) ) {
return FALSE;
}
$xsl_file = dirname( __FILE__ ) . '/xsl/' . $xsl . '.xsl';
// look for xsl
if( !is_readable( $xsl_file ) ) {
return FALSE;
}
switch( $schematype )
{
case 'file':
if( !is_readable( $schema ) ) {
return FALSE;
}
$schema = _file_get_contents( $schema );
break;
case 'string':
@@ -1965,26 +1967,26 @@ class adoSchema {
return FALSE;
}
}
$arguments = array (
'/_xml' => $schema,
'/_xsl' => _file_get_contents( $xsl_file )
);
// create an XSLT processor
$xh = xslt_create ();
// set error handler
xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler'));
// process the schema
$result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
$result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
xslt_free ($xh);
return $result;
}
/**
* Processes XSLT transformation errors
*
@@ -2004,7 +2006,7 @@ class adoSchema {
'Error Number' => $errno,
'Level' => $level
);
switch( $fields['URI'] ) {
case 'arg:/_xml':
$msg['Input'] = 'XML';
@@ -2015,7 +2017,7 @@ class adoSchema {
default:
$msg['Input'] = $fields['URI'];
}
$msg['Line'] = $fields['line'];
} else {
$msg = array(
@@ -2025,19 +2027,19 @@ class adoSchema {
'Fields' => var_export( $fields, TRUE )
);
}
$error_details = $msg['Message Type'] . ' in XSLT Transformation' . "\n"
. '<table>' . "\n";
foreach( $msg as $label => $details ) {
$error_details .= '<tr><td><b>' . $label . ': </b></td><td>' . htmlentities( $details ) . '</td></tr>' . "\n";
}
$error_details .= '</table>';
trigger_error( $error_details, E_USER_ERROR );
}
/**
* Returns the AXMLS Schema Version of the requested XML schema file.
*
@@ -2053,17 +2055,17 @@ class adoSchema {
// die( 'Unable to open file' );
return FALSE;
}
// Process the file
while( $data = fread( $fp, 4096 ) ) {
if( preg_match( $this->versionRegex, $data, $matches ) ) {
return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
}
}
return FALSE;
}
/**
* Returns the AXMLS Schema Version of the provided XML schema string.
*
@@ -2077,20 +2079,20 @@ class adoSchema {
if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
return FALSE;
}
if( preg_match( $this->versionRegex, $xmlstring, $matches ) ) {
return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
}
return FALSE;
}
/**
* Extracts an XML schema from an existing database.
*
* Call this method to create an XML schema string from an existing database.
* If the data parameter is set to TRUE, AXMLS will include the data from the database
* in the schema.
* in the schema.
*
* @param boolean $data Include data in schema dump
* @indent string indentation to use
@@ -2100,54 +2102,55 @@ class adoSchema {
*/
function ExtractSchema( $data = FALSE, $indent = ' ', $prefix = '' , $stripprefix=false) {
$old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM );
$schema = '<?xml version="1.0"?>' . "\n"
. '<schema version="' . $this->schemaVersion . '">' . "\n";
if( is_array( $tables = $this->db->MetaTables( 'TABLES' , ($prefix) ? $prefix.'%' : '') ) ) {
if( is_array( $tables = $this->db->MetaTables( 'TABLES' ,false ,($prefix) ? str_replace('_','\_',$prefix).'%' : '') ) ) {
foreach( $tables as $table ) {
if ($stripprefix) $table = str_replace(str_replace('\\_', '_', $pfx ), '', $table);
$schema .= $indent . '<table name="' . htmlentities( $table ) . '">' . "\n";
$schema .= $indent
. '<table name="'
. htmlentities( $stripprefix ? str_replace($prefix, '', $table) : $table )
. '">' . "\n";
// grab details from database
$rs = $this->db->Execute( 'SELECT * FROM ' . $table . ' WHERE -1' );
$fields = $this->db->MetaColumns( $table );
$indexes = $this->db->MetaIndexes( $table );
if( is_array( $fields ) ) {
foreach( $fields as $details ) {
$extra = '';
$content = array();
if( isset($details->max_length) && $details->max_length > 0 ) {
$extra .= ' size="' . $details->max_length . '"';
}
if( isset($details->primary_key) && $details->primary_key ) {
$content[] = '<KEY/>';
} elseif( isset($details->not_null) && $details->not_null ) {
$content[] = '<NOTNULL/>';
}
if( isset($details->has_default) && $details->has_default ) {
$content[] = '<DEFAULT value="' . htmlentities( $details->default_value ) . '"/>';
}
if( isset($details->auto_increment) && $details->auto_increment ) {
$content[] = '<AUTOINCREMENT/>';
}
if( isset($details->unsigned) && $details->unsigned ) {
$content[] = '<UNSIGNED/>';
}
// this stops the creation of 'R' columns,
// AUTOINCREMENT is used to create auto columns
$details->primary_key = 0;
$type = $rs->MetaType( $details );
$schema .= str_repeat( $indent, 2 ) . '<field name="' . htmlentities( $details->name ) . '" type="' . $type . '"' . $extra;
if( !empty( $content ) ) {
$schema .= ">\n" . str_repeat( $indent, 3 )
. implode( "\n" . str_repeat( $indent, 3 ), $content ) . "\n"
@@ -2157,57 +2160,57 @@ class adoSchema {
}
}
}
if( is_array( $indexes ) ) {
foreach( $indexes as $index => $details ) {
$schema .= str_repeat( $indent, 2 ) . '<index name="' . $index . '">' . "\n";
if( $details['unique'] ) {
$schema .= str_repeat( $indent, 3 ) . '<UNIQUE/>' . "\n";
}
foreach( $details['columns'] as $column ) {
$schema .= str_repeat( $indent, 3 ) . '<col>' . htmlentities( $column ) . '</col>' . "\n";
}
$schema .= str_repeat( $indent, 2 ) . '</index>' . "\n";
}
}
if( $data ) {
$rs = $this->db->Execute( 'SELECT * FROM ' . $table );
if( is_object( $rs ) && !$rs->EOF ) {
$schema .= str_repeat( $indent, 2 ) . "<data>\n";
while( $row = $rs->FetchRow() ) {
foreach( $row as $key => $val ) {
if ( $val != htmlentities( $val ) ) {
$row[$key] = '<![CDATA[' . $val . ']]>';
}
}
$schema .= str_repeat( $indent, 3 ) . '<row><f>' . implode( '</f><f>', $row ) . "</f></row>\n";
}
$schema .= str_repeat( $indent, 2 ) . "</data>\n";
}
}
$schema .= $indent . "</table>\n";
}
}
$this->db->SetFetchMode( $old_mode );
$schema .= '</schema>';
return $schema;
}
/**
* Sets a prefix for database objects
*
* Call this method to set a standard prefix that will be prepended to all database tables
* Call this method to set a standard prefix that will be prepended to all database tables
* and indices when the schema is parsed. Calling setPrefix with no arguments clears the prefix.
*
* @param string $prefix Prefix that will be prepended.
@@ -2228,17 +2231,17 @@ class adoSchema {
logMsg( 'Invalid prefix: ' . $prefix );
return FALSE;
}
if( $underscore AND substr( $prefix, -1 ) != '_' ) {
$prefix .= '_';
}
// prefix valid
logMsg( 'Set prefix: ' . $prefix );
$this->objectPrefix = $prefix;
return TRUE;
}
/**
* Returns an object name with the current prefix prepended.
*
@@ -2254,11 +2257,11 @@ class adoSchema {
// prepend after quote if used
return preg_replace( '/^(`?)(.+)$/', '$1' . $this->objectPrefix . '$2', $name );
}
// No prefix set. Use name provided.
return $name;
}
/**
* Checks if element references a specific platform
*
@@ -2270,7 +2273,7 @@ class adoSchema {
function supportedPlatform( $platform = NULL ) {
if( !empty( $platform ) ) {
$regex = '/(^|\|)' . $this->db->databaseType . '(\||$)/i';
if( preg_match( '/^- /', $platform ) ) {
if (preg_match ( $regex, substr( $platform, 2 ) ) ) {
logMsg( 'Platform ' . $platform . ' is NOT supported' );
@@ -2283,11 +2286,11 @@ class adoSchema {
}
}
}
logMsg( 'Platform ' . $platform . ' is supported' );
return TRUE;
}
/**
* Clears the array of generated SQL.
*
@@ -2296,7 +2299,7 @@ class adoSchema {
function clearSQL() {
$this->sqlArray = array();
}
/**
* Adds SQL into the SQL array.
*
@@ -2304,58 +2307,58 @@ class adoSchema {
* @return boolean TRUE if successful, else FALSE.
*
* @access private
*/
*/
function addSQL( $sql = NULL ) {
if( is_array( $sql ) ) {
foreach( $sql as $line ) {
$this->addSQL( $line );
}
return TRUE;
}
if( is_string( $sql ) ) {
$this->sqlArray[] = $sql;
// if executeInline is enabled, and either no errors have occurred or continueOnError is enabled, execute SQL.
if( $this->ExecuteInline() && ( $this->success == 2 || $this->ContinueOnError() ) ) {
$saved = $this->db->debug;
$this->db->debug = $this->debug;
$ok = $this->db->Execute( $sql );
$this->db->debug = $saved;
if( !$ok ) {
if( $this->debug ) {
ADOConnection::outp( $this->db->ErrorMsg() );
}
$this->success = 1;
}
}
return TRUE;
}
return FALSE;
}
/**
* Gets the SQL array in the specified format.
*
* @param string $format Format
* @return mixed SQL
*
*
* @access private
*/
function getSQL( $format = NULL, $sqlArray = NULL ) {
if( !is_array( $sqlArray ) ) {
$sqlArray = $this->sqlArray;
}
if( !is_array( $sqlArray ) ) {
return FALSE;
}
switch( strtolower( $format ) ) {
case 'string':
case 'text':
@@ -2363,10 +2366,10 @@ class adoSchema {
case'html':
return !empty( $sqlArray ) ? nl2br( htmlentities( implode( ";\n\n", $sqlArray ) . ';' ) ) : '';
}
return $this->sqlArray;
}
/**
* Destroys an adoSchema object.
*
@@ -2374,8 +2377,8 @@ class adoSchema {
* @deprecated adoSchema now cleans up automatically.
*/
function Destroy() {
set_magic_quotes_runtime( $this->mgq );
unset( $this );
ini_set("magic_quotes_runtime", $this->mgq );
#set_magic_quotes_runtime( $this->mgq );
}
}
@@ -2387,18 +2390,17 @@ class adoSchema {
function logMsg( $msg, $title = NULL, $force = FALSE ) {
if( XMLS_DEBUG or $force ) {
echo '<pre>';
if( isset( $title ) ) {
echo '<h3>' . htmlentities( $title ) . '</h3>';
}
if( @is_object( $this ) ) {
echo '[' . get_class( $this ) . '] ';
}
print_r( $msg );
echo '</pre>';
}
}
?>