xmlschema или какво ново относно базата данни на Moodle

xmlschema или какво ново относно базата данни на Moodle

от Daniel Denev -
Number of replies: 8

Виж файла adodb-xmlschema.inc.php

01302                                {
01303         
01304         $this->mgq = get_magic_quotes_runtime();
01305         set_magic_quotes_runtime(0);
01306         
01307         $this->db =& $db;
01308         $this->debug = $this->db->debug;
01309         $this->dict = NewDataDictionary( $this->db );
01310         $this->sqlArray = array();
01311         $this->schemaVersion = XMLS_SCHEMA_VERSION;
01312         $this->executeInline( XMLS_EXECUTE_INLINE );
01313         $this->continueOnError( XMLS_CONTINUE_ON_ERROR );
01314         $this->setUpgradeMethod();
01315     }

adoSchema::_file_get_contents ( $ path )
01722     {
01723         if (function_exists('file_get_contents')) return file_get_contents($path);
01724         return join('',file($path));
01725     }

XML Callback to process start elements
01643                                                       {
01644         switch( strtoupper( $tag ) ) {
01645             case 'TABLE':
01646                 $this->obj = new dbTable( $this, $attributes );
01647                 xml_set_object( $parser, $this->obj );
01648                 break;
01649             case 'SQL':
01650                 if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
01651                     $this->obj = new dbQuerySet( $this, $attributes );
01652                     xml_set_object( $parser, $this->obj );
01653                 }
01654                 break;
01655             default:
01656                 // print_r( array( $tag, $attributes ) );
01657         }
01658         
01659     }
02121                                    {
02122         if( is_array( $sql ) ) {
02123             foreach( $sql as $line ) {
02124                 $this->addSQL( $line );
02125             }
02126             
02127             return TRUE;
02128         }
02129         
02130         if( is_string( $sql ) ) {
02131             $this->sqlArray[] = $sql;
02132             
02133             // if executeInline is enabled, and either no errors have occurred or continueOnError is enabled, execute SQL.
02134             if( $this->ExecuteInline() && ( $this->success == 2 || $this->ContinueOnError() ) ) {
02135                 $saved = $this->db->debug;
02136                 $this->db->debug = $this->debug;
02137                 $ok = $this->db->Execute( $sql );
02138                 $this->db->debug = $saved;
02139                 
02140                 if( !$ok ) {
02141                     if( $this->debug ) {
02142                         ADOConnection::outp( $this->db->ErrorMsg() );
02143                     }
02144                     
02145                     $this->success = 1;
02146                 }
02147             }
02148             
02149             return TRUE;
02150         }
02151         
02152         return FALSE;
02153     }

Clears the array of generated SQL
02109                         {
02110         $this->sqlArray = array();
02111     }


                        
In reply to Daniel Denev

Re: xmlschema или какво ново относно базата данни на Moodle

от Daniel Denev -
 adodb-xmlschema.inc.php- Richard Tango- Lowy 
   1  <?PHP
   2   /* ******************************************************************************
   3      Released under both BSD license and Lesser GPL library license. 
   4       Whenever there is any discrepancy between the two licenses, 
   5       the BSD license will take precedence. 
   6  *******************************************************************************/
   7  /**
   8   * xmlschema is a class that allows the user to quickly and easily
   9   * build a database on any ADOdb-supported platform using a simple
  10   * XML schema.
  11   *
  12   * @author             Richard Tango-Lowy
  13   * @version         $Revision$
  14   * @copyright    Copyright (c) 2003 ars Cognita Inc., all rights reserved
  15   *
  16   * @package        xmlschema
  17   */
  18  /**
  19    * Include the main ADODB library
  20    */
  21  if (!defined( '_ADODB_LAYER' ) ) {
  22      require ( 'adodb.inc.php' );
  23  }
  24  
  25  /**
  26   * Creates a table object in ADOdb's datadict format
  27   *
  28   * This class stores information about a database table. As charactaristics
  29   * of the table are loaded from the external source, methods and properties
  30   * of this class are used to build up the table description in ADOdb's
  31  *  datadict format.
  32   *
  33   * @package xmlschema
  34   * @access private
  35   */
  36  class dbTable {
  37      
  38      /**
  39      * @var string    Table name
  40      */
  41      var $tableName;
  42      
  43      /**
  44      * @var array    Field specifier: Meta-information about each field
  45      */
  46      var $fieldSpec;
  47      
  48      /**
  49      * @var array    Table options: Table-level options
  50      */
  51      var $tableOpts;
  52      
  53      /**
  54      * @var string    Field index: Keeps track of which field is currently being processed
  55      */
  56      var $currentField;
  57      
  58      /**
  59      * Constructor. Iniitializes a new table object.
  60      *
  61      * @param string    $name        Table name
  62      */
  63  	function dbTable( $name ) {
  64          $this->tableName = $name;
  65      }
  66      
  67      /**
  68      * Adds a field to a table object
  69      *
  70      * $name is the name of the table to which the field should be added. 
  71      * $type is an ADODB datadict field type. The following field types
  72      * are supported as of ADODB 3.40:
  73      *     - C:  varchar
  74      *    - X:  CLOB (character large object) or largest varchar size
  75      *       if CLOB is not supported
  76      *    - C2: Multibyte varchar
  77      *    - X2: Multibyte CLOB
  78      *    - B:  BLOB (binary large object)
  79      *    - D:  Date (some databases do not support this, and we return a datetime type)
  80      *    - T:  Datetime or Timestamp
  81      *    - L:  Integer field suitable for storing booleans (0 or 1)
  82      *    - I:  Integer (mapped to I4)
  83      *    - I1: 1-byte integer
  84      *    - I2: 2-byte integer
  85      *    - I4: 4-byte integer
  86      *    - I8: 8-byte integer
  87      *    - F:  Floating point number
  88      *    - N:  Numeric or decimal number
  89      *
  90      * @param string $name    Name of the table to which the field will be added.
  91      * @param string $type        ADODB datadict field type.
  92      * @param string $size        Field size
  93      * @param array $opts        Field options array
  94      * @return array    Field specifier array
  95      */
  96  	function addField( $name, $type, $size = NULL, $opts = NULL ) {
  97      
  98          // Set the field index so we know where we are
  99          $this->currentField = $name;
 100          
 101          // Set the field type (required)
 102          $this->fieldSpec[$name]['TYPE'] = $type;
 103          
 104          // Set the field size (optional)
 105          if( isset( $size ) ) {
 106              $this->fieldSpec[$name]['SIZE'] = $size;
 107          }
 108          
 109          // Set the field options
 110          if( isset( $opts ) ) $this->fieldSpec[$name]['OPTS'] = $opts;
 111          
 112          // Return array containing field specifier
 113          return $this->fieldSpec;
 114      }
 115      
 116      /**
 117      * Adds a field option to the current field specifier
 118      *
 119      * This method adds a field option allowed by the ADOdb datadict 
 120      * and appends it to the given field.
 121      *
 122      * @param string $field        Field name
 123      * @param string $opt        ADOdb field option
 124      * @param mixed $value    Field option value
 125      * @return array    Field specifier array
 126      */
 127  	function addFieldOpt( $field, $opt, $value = NULL ) {
 128          
 129          // Add the option to the field specifier
 130          if(  $value === NULL ) { // No value, so add only the option
 131              $this->fieldSpec[$field]['OPTS'][] = $opt;
 132          } else { // Add the option and value
 133              $this->fieldSpec[$field]['OPTS'][] = array( "$opt" => "$value" );
 134          }
 135      
 136          // Return array containing field specifier
 137          return $this->fieldSpec;
 138      }
 139      
 140      /**
 141      * Adds an option to the table
 142      *
 143      *This method takes a comma-separated list of table-level options
 144      * and appends them to the table object.
 145      *
 146      * @param string $opt        Table option
 147      * @return string    Option list
 148      */
 149  	function addTableOpt( $opt ) {
 150      
 151          $optlist = &$this->tableOpts;
 152          $optlist ? $optlist .= ", $opt" : $optlist = $opt;
 153          
 154          // Return the options list
 155          return $optlist;
 156      }
 157      
 158      /**
 159      * Generates the SQL that will create the table in the database
 160      *
 161      * Returns SQL that will create the table represented by the object.
 162      *
 163      * @param object $dict        ADOdb data dictionary
 164      * @return array    Array containing table creation SQL
 165      */
 166  	function create( $dict ) {
 167      
 168          // Loop through the field specifier array, building the associative array for the field options
 169          $fldarray = array();
 170          $i = 0;
 171          
 172          foreach( $this->fieldSpec as $field => $finfo ) {
 173              $i++;
 174              
 175              // Set an empty size if it isn't supplied
 176              if( !isset( $finfo['SIZE'] ) ) $finfo['SIZE'] = '';
 177              
 178              // Initialize the field array with the type and size
 179              $fldarray[$i] = array( $field, $finfo['TYPE'], $finfo['SIZE'] );
 180              
 181              // Loop through the options array and add the field options. 
 182              $opts = $finfo['OPTS'];
 183              if( $opts ) {
 184                  foreach( $finfo['OPTS'] as $opt ) {
 185                      
 186                      if( is_array( $opt ) ) { // Option has an argument.
 187                          $key = key( $opt );
 188                          $value = $opt[key( $opt ) ];
 189                          $fldarray[$i][$key] = $value;
 190                      } else { // Option doesn't have arguments
 191                          array_push( $fldarray[$i], $opt );
 192                      }
 193                  }
 194              }
 195          }
 196          
 197          // Build table array
 198          $sqlArray = $dict->CreateTableSQL( $this->tableName, $fldarray, $this->tableOpts );
 199          
 200          // Return the array containing the SQL to create the table
 201          return $sqlArray;
 202      }
 203      
 204      /**
 205      * Destructor
 206      */
 207  	function destroy() {
 208          unset( $this );
 209      }
 210  }
 211  
 212  /**
 213  * Creates an index object in ADOdb's datadict format
 214  *
 215  * This class stores information about a database index. As charactaristics
 216  * of the index are loaded from the external source, methods and properties
 217  * of this class are used to build up the index description in ADOdb's
 218  * datadict format.
 219  *
 220  * @package xmlschema
 221  * @access private
 222  */
 223  class dbIndex {
 224      
 225      /**
 226      * @var string    Index name
 227      */
 228      var $indexName;
 229      
 230      /**
 231      * @var string    Name of the table this index is attached to
 232      */
 233      var $tableName;
 234      
 235      /**
 236      * @var array    Indexed fields: Table columns included in this index
 237      */
 238      var $fields;
 239      
 240      /**
 241      * Constructor. Initialize the index and table names.
 242      *
 243      * @param string $name    Index name
 244      * @param string $table        Name of indexed table
 245      */
 246  	function dbIndex( $name, $table ) {
 247          $this->indexName = $name;
 248          $this->tableName = $table;
 249      }
 250      
 251      /**
 252      * Adds a field to the index
 253      * 
 254      * This method adds the specified column to an index.
 255      *
 256      * @param string $name        Field name
 257      * @return string    Field list
 258      */
 259  	function addField( $name ) {
 260          $fieldlist = &$this->fields;
 261          $fieldlist ? $fieldlist .=" , $name" : $fieldlist = $name;
 262          
 263          // Return the field list
 264          return $fieldlist;
 265      }
 266      
 267      /**
 268      * Generates the SQL that will create the index in the database
 269      *
 270      * Returns SQL that will create the index represented by the object.
 271      *
 272      * @param object $dict    ADOdb data dictionary object
 273      * @return array    Array containing index creation SQL
 274      */
 275  	function create( $dict ) {
 276      
 277          // Build table array
 278          $sqlArray = $dict->CreateIndexSQL( $this->indexName, $this->tableName, $this->fields );
 279          
 280          // Return the array containing the SQL to create the table
 281          return $sqlArray;
 282      }
 283      
 284      /**
 285      * Destructor
 286      */
 287  	function destroy() {
 288          unset( $this );
 289      }
 290  }
 291  
 292  /**
 293  * Creates the SQL to execute a list of provided SQL queries
 294  *
 295  * This class compiles a list of SQL queries specified in the external file.
 296  *
 297  * @package xmlschema
 298  * @access private
 299  */
 300  class dbQuerySet {
 301      
 302      /**
 303      * @var array    List of SQL queries
 304      */
 305      var $querySet;
 306      
 307      /**
 308      * @var string    String used to build of a query line by line
 309      */
 310      var $query;
 311      
 312      /**
 313      * Constructor. Initializes the queries array
 314      */
 315  	function dbQuerySet() {
 316          $this->querySet = array();
 317          $this->query = '';
 318      }
 319      
 320      /** 
 321      * Appends a line to a query that is being built line by line
 322      *
 323      * $param string $data    Line of SQL data or NULL to initialize a new query
 324      */
 325  	function buildQuery( $data = NULL ) {
 326          isset( $data ) ? $this->query .= " " . trim( $data ) : $this->query = '';
 327      }
 328      
 329      /**
 330      * Adds a completed query to the query list
 331      *
 332      * @return string    SQL of added query
 333      */
 334  	function addQuery() {
 335          
 336          // Push the query onto the query set array
 337          $finishedQuery = $this->query;
 338          array_push( $this->querySet, $finishedQuery );
 339          
 340          // Return the query set array
 341          return $finishedQuery;
 342      }
 343      
 344      /**
 345      * Creates and returns the current query set
 346      *
 347      * @return array Query set
 348      */
 349  	function create() {
 350          return $this->querySet;
 351      }
 352      
 353      /**
 354      * Destructor
 355      */
 356  	function destroy() {
 357          unset( $this );
 358      }
 359  }
 360  
 361  
 362  /**
 363  * Loads and parses an XML file, creating an array of "ready-to-run" SQL statements
 364  * 
 365  * This class is used to load and parse the XML file, to create an array of SQL statements
 366  * that can be used to build a database, and to build the database using the SQL array.
 367  *
 368  * @package xmlschema
 369  */
 370  class adoSchema {
 371      
 372      /**
 373      * @var array    Array containing SQL queries to generate all objects
 374      */
 375      var $sqlArray;
 376      
 377      /**
 378      * @var object    XML Parser object
 379      */
 380      var $xmlParser;
 381      
 382      /**
 383      * @var object    ADOdb connection object
 384      */
 385      var $dbconn;
 386      
 387      /**
 388      * @var string    Database type (platform)
 389      */
 390      var $dbType;
 391      
 392      /**
 393      * @var object    ADOdb Data Dictionary
 394      */
 395      var $dict;
 396      
 397      /**
 398      * @var object    Temporary dbTable object
 399      * @access private
 400      */
 401      var $table;
 402      
 403      /**
 404      * @var object    Temporary dbIndex object
 405      * @access private
 406      */
 407      var $index;
 408      
 409      /**
 410      * @var object    Temporary dbQuerySet object
 411      * @access private
 412      */
 413      var $querySet;
 414      
 415      /**
 416      * @var string Current XML element
 417      * @access private
 418      */
 419      var $currentElement;
 420      
 421      /**
 422      * @var long    Original Magic Quotes Runtime value
 423      * @access private
 424      */
 425      var $mgq;
 426      
 427      /**
 428      * Constructor. Initializes the xmlschema object
 429      *
 430      * @param object $dbconn        ADOdb connection object
 431      */
 432  	function adoSchema( $dbconn ) {
 433          
 434          // Initialize the environment
 435          $this->mgq = get_magic_quotes_runtime();
 436          set_magic_quotes_runtime(0);    
 437          
 438          $this->dbconn    =  &$dbconn;
 439          $this->dbType = $dbconn->databaseType;
 440          $this->sqlArray = array();
 441          
 442          // Create an ADOdb dictionary object
 443          $this->dict = NewDataDictionary( $dbconn );
 444      }
 445      
 446      /**
 447      * Loads and parses an XML file
 448      *
 449      * This method accepts a path to an xmlschema-compliant XML file,
 450      * loads it, parses it, and uses it to create the SQL to generate the objects
 451      * described by the XML file.
 452      *
 453      * @param string $file        XML file
 454      * @return array    Array of SQL queries, ready to execute
 455      */
 456  	function ParseSchema( $file ) {
 457      
 458          // Create the parser
 459          $this->xmlParser = &$xmlParser;
 460          $xmlParser = xml_parser_create();
 461          xml_set_object( $xmlParser, &$this );
 462          
 463          // Initialize the XML callback functions
 464          xml_set_element_handler( $xmlParser, "_xmlcb_startElement", "_xmlcb_endElement" );
 465          xml_set_character_data_handler( $xmlParser, "_xmlcb_cData" );
 466          
 467          // Open the file
 468          if( !( $fp = fopen( $file, "r" ) ) ) {
 469              die( "Unable to open file" );
 470          }
 471          
 472          // Process the file
 473          while( $data = fread( $fp, 4096 ) ) {
 474              if( !xml_parse( $xmlParser, $data, feof( $fp ) ) ) {
 475                  die( sprint( "XML error: %s at line %d",
 476                      xml_error_string( xml_get_error_code( $xmlParser ) ),
 477                      xml_get_current_line_number( $xmlParser ) ) );
 478              }
 479          }
 480          
 481          // Return the array of queries
 482          return $this->sqlArray;
 483      }
 484      
 485      /**
 486      * Loads a schema into the database
 487      *
 488      * Accepts an array of SQL queries generated by the parser 
 489      * and executes them.
 490      *
 491      * @param array $sqlArray    Array of SQL statements
 492      * @param boolean $continueOnErr    Don't fail out if an error is encountered
 493      * @return integer    0 if failed, 1 if errors, 2 if successful
 494      */
 495  	function ExecuteSchema( $sqlArray, $continueOnErr =  TRUE ) {
 496          $err = $this->dict->ExecuteSQLArray( $sqlArray, $continueOnErr );
 497          
 498          // Return the success code
 499          return $err;
 500      }
 501      
 502      /**
 503      * XML Callback to process start elements
 504      *
 505      * @access private
 506      */
 507  	function _xmlcb_startElement( $parser, $name, $attrs ) {
 508          
 509          $dbType = $this->dbType;
 510          if( isset( $this->table ) ) $table = &$this->table;
 511          if( isset( $this->index ) ) $index = &$this->index;
 512          if( isset( $this->querySet ) ) $querySet = &$this->querySet;
 513          $this->currentElement = $name;
 514          
 515          // Process the element. Ignore unimportant elements.
 516          if( in_array( trim( $name ),  array( "SCHEMA", "DESCR", "COL", "CONSTRAINT" ) ) ) {
 517              return FALSE;
 518          }
 519          
 520          switch( $name ) {
 521                  
 522              case "TABLE":    // Table element
 523                  if( $this->supportedPlatform( $attrs['PLATFORM'] ) ) {
 524                      $this->table = new dbTable( $attrs['NAME'] );
 525                  } else {
 526                      unset( $this->table );
 527                  }
 528                  break;
 529                  
 530              case "FIELD":    // Table field
 531                  if( isset( $this->table ) ) {
 532                      $fieldName = $attrs['NAME'];
 533                      $fieldType = $attrs['TYPE'];
 534                      isset( $attrs['SIZE'] ) ? $fieldSize = $attrs['SIZE'] : $fieldSize = NULL;
 535                      isset( $attrs['OPTS'] ) ? $fieldOpts = $attrs['OPTS'] : $fieldOpts = NULL;
 536                      $this->table->addField( $fieldName, $fieldType, $fieldSize, $fieldOpts );
 537                  }
 538                  break;
 539                  
 540              case "KEY":    // Table field option
 541                  if( isset( $this->table ) ) {
 542                      $this->table->addFieldOpt( $this->table->currentField, 'KEY' );
 543                  }
 544                  break;
 545                  
 546              case "NOTNULL":    // Table field option
 547                  if( isset( $this->table ) ) {
 548                      $this->table->addFieldOpt( $this->table->currentField, 'NOTNULL' );
 549                  }
 550                  break;
 551                  
 552              case "AUTOINCREMENT":    // Table field option
 553                  if( isset( $this->table ) ) {
 554                      $this->table->addFieldOpt( $this->table->currentField, 'AUTOINCREMENT' );
 555                  }
 556                  break;
 557                  
 558              case "DEFAULT":    // Table field option
 559                  if( isset( $this->table ) ) {
 560                      $this->table->addFieldOpt( $this->table->currentField, 'DEFAULT', $attrs['VALUE'] );
 561                  }
 562                  break;
 563                  
 564              case "INDEX":    // Table index
 565                  if( $this->supportedPlatform( $attrs['PLATFORM'] ) ) {
 566                      $this->index = new dbIndex( $attrs['NAME'], $attrs['TABLE'] );
 567                  } else {
 568                      if( isset( $this->index ) ) unset( $this->index );
 569                  }
 570                  break;
 571                  
 572              case "SQL":    // Freeform SQL queryset
 573                  if( $this->supportedPlatform( $attrs['PLATFORM'] ) ) {
 574                      $this->querySet = new dbQuerySet( $attrs );
 575                  } else {
 576                      if( isset( $this->querySet ) ) unset( $this->querySet );
 577                  }
 578                  break;
 579                  
 580              case "QUERY":    // Queryset SQL query
 581                  if( isset( $this->querySet ) ) {
 582                      // Ignore this query set if a platform is specified and it's different than the 
 583                      // current connection platform.
 584                      if( $this->supportedPlatform( $attrs['PLATFORM'] ) ) {
 585                          $this->querySet->buildQuery();
 586                      } else {
 587                          if( isset( $this->querySet->query ) ) unset( $this->querySet->query );
 588                      }
 589                  }
 590                  break;
 591                  
 592              default:
 593                  print "OPENING ELEMENT '$name'<BR/>\n";
 594          }    
 595      }
 596  
 597      /**
 598      * XML Callback to process cDATA elements
 599      *
 600      * @access private
 601      */
 602  	function _xmlcb_cData( $parser, $data ) {
 603          
 604          $element = &$this->currentElement;
 605          
 606          if( trim( $data ) == "" ) return;
 607          
 608          // Process the data depending on the element
 609          switch( $element ) {
 610          
 611              case "COL":    // Index column
 612                  if( isset( $this->index ) ) $this->index->addField( $data );
 613                  break;
 614                  
 615              case "DESCR":    // Description element
 616                  // Display the description information
 617                  if( isset( $this->table ) ) {
 618                      $name = "({$this->table->tableName}):  ";
 619                  } elseif( isset( $this->index ) ) {
 620                      $name = "({$this->index->indexName}):  ";
 621                  } else {
 622                      $name = "";
 623                  }
 624                  print "<LI> $name $data\n";
 625                  break;
 626              
 627              case "QUERY":    // Query SQL data
 628                  if( isset( $this->querySet ) and isset( $this->querySet->query ) ) $this->querySet->buildQuery( $data );
 629                  break;
 630              
 631              case "CONSTRAINT":    // Table constraint
 632                  if( isset( $this->table ) ) $this->table->addTableOpt( $data );
 633                  break;
 634                  
 635              default:
 636                  print "<UL><LI>CDATA ($element) $data</UL>\n";
 637          }
 638      }
 639  
 640      /**
 641      * XML Callback to process end elements
 642      *
 643      * @access private
 644      */
 645  	function _xmlcb_endElement( $parser, $name ) {
 646          
 647          // Process the element. Ignore unimportant elements.
 648          if( in_array( trim( $name ), 
 649              array(     "SCHEMA", "DESCR", "KEY", "AUTOINCREMENT", "FIELD",
 650                          "DEFAULT", "NOTNULL", "CONSTRAINT", "COL" ) ) ) {
 651              return FALSE;
 652          }
 653          
 654          switch( trim( $name ) ) {
 655              
 656              case "TABLE":    // Table element
 657                  if( isset( $this->table ) ) {
 658                      $tableSQL = $this->table->create( $this->dict );
 659                      array_push( $this->sqlArray, $tableSQL[0] );
 660                      $this->table->destroy();
 661                  }
 662                  break;
 663                  
 664              case "INDEX":    // Index element
 665                  if( isset( $this->index ) ) {
 666                      $indexSQL = $this->index->create( $this->dict );
 667                      array_push( $this->sqlArray, $indexSQL[0] );
 668                      $this->index->destroy();
 669                  }
 670                  break;
 671              
 672              case "QUERY":    // Queryset element
 673                  if( isset( $this->querySet ) and isset( $this->querySet->query ) ) $this->querySet->addQuery();
 674                  break;
 675              
 676              case "SQL":    // Query SQL element
 677                  if( isset( $this->querySet ) ) {
 678                      $querySQL = $this->querySet->create();
 679                      $this->sqlArray = array_merge( $this->sqlArray, $querySQL );;
 680                      $this->querySet->destroy();
 681                  }
 682                  break;
 683                  
 684              default:
 685                  print "<LI>CLOSING $name</UL>\n";
 686          }
 687      }
 688      
 689      /**
 690      * Checks if element references a specific platform
 691      *
 692      * Returns TRUE is no platform is specified or if we are currently
 693      * using the specified platform.
 694      *
 695      * @param string    $platform    Requested platform
 696      * @return boolean    TRUE if platform check succeeds
 697      *
 698      * @access private
 699      */
 700  	function supportedPlatform( $platform = NULL ) {
 701  
 702          $dbType = $this->dbType;
 703          $regex = "/^(\w*\|)*" . $dbType . "(\|\w*)*$/";
 704          
 705          if( !isset( $platform ) or 
 706              preg_match( $regex, $platform ) ) {
 707              return TRUE;
 708          } else {
 709              return FALSE;
 710          }
 711      }
 712      
 713      /**
 714      * Destructor
 715      */
 716  	function Destroy() {
 717          xml_parser_free( $this->xmlParser );
 718          set_magic_quotes_runtime( $this->mgq );
 719          unset( $this );
 720      }
 721  }
 722  ?>
In reply to Daniel Denev

Re: xmlschema или какво ново относно базата данни на Moodle

от Snezhina Velcheva -
In reply to Snezhina Velcheva

Re: xmlschema или какво ново относно базата данни на Moodle

от Daniel Denev -

   Бази данни, AXMLS Схема, библиотеки ... => 1.7

ADOdb1.7

   Интересен въпрос е миграцията базата на Moodle към Oracle. Още в началото бих искал да уточня няколко неща. Oracle е платен сървър и аз лично не одобрявам тази идея но това си е мое мнение и никого не ангажирам с него. Като ПЛАТЕН такъв не мога да отрека, че е много добър. Все пак Moodle е отворен код. Мартин е дал възможност на много хора да работят по проекта ползвайки предимно бази данни на MySQL отново свободна платформа. Мартин Догиамас е (няма да крия)  мой идол, от тази гледна точка считам за неуместно намесата на компании като Oracle. Второто нещо което бих искал да уточня е, че въпроса не е толкова в това какъв е сървъра за базите данни, а каква е тяхната организация. Много често оптимизацията, разработката, синхронизацията, проектирането и там всичкко останало се нарича backend developmend.

DBDesigner_ERDiagram.png

На фигурата са показани ключовите таблици от базата на Moodle, user и course, както и на някой други по-важни релации. В действителност картинката е с много по-големи размери (1584 на 1753) и итеглянето и е възможно. DBDesigner_ERDiagram

 

moodle_db_key_user_course_tabls_rel_by_schemaball_db_schema_graph_tool.png

На фигурата са показани ключовите таблици от базата на Moodle, user и course, както и на някой други по-важни релации. В действителност картинката е с много по-големи размери (1000 на 1000) и итеглянето и е възможно. За тази визуализация е използван графичния инструмент Schemaball

 

 

moodle_db_tabl_rel_by_schemaball_db_schema_graph_tool.png

На фигурата са показани ключовите таблици от базата на Moodle, user и course, както и на някой други по-важни релации. В действителност картинката е с много по-големи размери (1000 на 1000) и итеглянето и е възможно. За тази визуализация е използван графичния инструмент Schemaball

 

a_tutor_database.gif

Аt- Аналогия

 

   Та мисълта ми беше по въпроса с организацията на релационния модел на базите данни в Moodle. Тук Петър Атанасов е абсолютно прав като казва, че въпроса с релациите, ограниченията, минимизацията, синхронизацията ... е МНОГО ВАЖЕН!!! Така естествено като една от първите задачи преди да се мисли за това къв да е сървъра за базата данни е по смисленно да се оптимизира вече съществуващата организация на таблиците и връзките между тях. Второ, в момента в рамките на 1.7 се разработва вариант при който ще се използва схема за базите данни която няма да зависи от това какъв е точно сървъра за базите данни. Преди доста време бях писал тук в някой от форумите за XML-лизацията на базата данни. Основна роля в процеса на неутралната база данни играят AXMLS Схемата и ADOdb. Третото нещо което ме вълнува и много бих искал да споделя е скоростта на търсене в такава база данни, както и миграбията на огромното количество модули разработени вече за MySQL.

   Едно от предстоящите нови неща които ще се случат в областта на бекенд дивелъпмънта (разработката на структурата и оптимизацията на базата данни в този слой на приложението) е новата функционалност даваща възможнос на Moodle да работи с много повече сървъри за бази данни от поддържаните в момента.
RDBMS Системи за Управление на Релационни Бази Данни, като същевременно се предполага, че всичко работило коректно с MySQL и Oracle до момента ще продължи да си работи. Още от самото начало беше известно, че ядрото на Moodle поддържа ADOdb. Екипът на Moodle още миналата година проведе тестове за предварителна проверка коректно ли работят класовете за ADOdb. В процеса на работата се изясни как да се съчетаят тези четири системи за управление на  релационни бази данни всяка имаща своите си особенности и диалекти на поддържания език. По този начин местата на промените в кода сами си се показват. Това е естественно файлът datalib.php. От съществено значение е и как ще взаимодейства останалата част от кода на Moodle с библиотеките за бази дании.

 

MoodleDBStack.png

Стекът

   Изискванията които първоначално е необходимо да се изпълнят преди да бъде реализирана същинската цей, а именно Moodle да работи с много системи за управление на релационни бази данни RDBMS са: един слой за създаване и обновяване на базите данни (DDL или както му казват Data Definition Language)

Уточнение: DDL е език за дефиниране на данни. Един пример за чист DDL това е XML Схемата. Подмножество на SQL инструкциите от друг DDL. Използвайки този нов слой в Moodle разработчиците ще могат да изграждат структурите си в едина неутрална форма независеща от точната имплементация за конкретната системе за управление на релационни бази данни. Другото предварително изискване е един слой за транспортиране и управление на базите данни даващ възможност на разработчиците да правят заявки и да съхраняват информация в една неутрална, независеща от конкретната имплементация за RDBS. За целта се използва Data Manipulation Language (DML), всъщност DML си е набор от езици за обработка на данните в релационни бази данни. Една друга форма на DML е IMS/DL1.

   Организацията на функционалните възможости на езиците за манипулиране на данни се базира на първата дума в израза, което при SQL почти винаги си е глагол. Друго не-функционално предварително изискване е ясното обявяване на един опростен път за лесна миграция от предишните версии. До момента надграждането на Moodle усложняваше работата на разработчиците дори ако става дума на писане на инсталационни скриптове за добавяне на модул или плъг-ин (малки софтуерни добавки) . Новия подход е един файл за инсталиране и един файл за обновяване на модулите, блоковете, плъг-ините, филтлите и т.н.

   В новата версия 1.7 е залегнало вече изискването да се намали условното използване на код. Това означава местата във файловете на библиотеките с php класовете за базите данни където до момента е можело да участва потребителски код ще се намалят. Не на последно място разбира се от голямо значение е подробното документиране на дефинираните функции кактои на DDL и DML слоевете, та последото ще помогне на разработчиците правилно да се ориентират в задачите.Стекът на кода на Moodle 1.7 показва как последният ще си взаимодейства с основните RDBMS За взаимодействието си с базите данни се предвижда Moodle да използва два езика. За променяне и изтриване в базата данни ще се използва XMLDB, т.е. неутрални описателни файлове за данни. По-горе вече споменах за DDL. Неутралните SQL изрази за операциите с информацията в базата данни. По-горе вече говорих за DML.

   Използваните ключови думи подсказват, че двата езика, ще бъдат 100% еднакви, независимо от използваните RDBMS. Това е от части вярно и за XMLDB. Всеки от посочените езици ще използва свои собствени библиотеки. Библиотеката Moodle DDL Library (т.е. файла DDLlib.php) съдържа вички обекти на базата данни и осигурява на разработчиците една голяма степен на абстракция. Като вход ще приема дефинирани обекти и ще изпълнява командите за конкретно използваната RDBMS. Библиотеката Moodle DML Library (т.е. файла datalib.php) съдържа функциите за управлението на съдържанието на базата данни и е променена така, че да осигурява на разработчиците висока степен на абстракция. Като вход приема параметри и изпълнява изразите за конкретно използваната RDBMS. И двете посочени библиотеки за работата си използват библиотеката абстрактни класове ADOdb Database Abstraction Library за PHP. Последната ще получава всички заявки от тях, ще омуниира с база данни на някакъв сървър за бази данни (MySQL, PostgreSQL, Oracle или SQL*Server), ще получава резултатите от обработката и ще ги връща обратно към изпратилата ги библиотека. Разширяванито възможностите на Moodle за поддръжка на повече сървъри за бази данни и самия процес на миграция се свежда до фази и
подзадачи (както е при всеки един проект)

       1. Разделяне на файла datalib.php на три части. Този файл съдържа фунциите за SQL DDL (table_column()...), SQL DML (select, insert...) . Първата част DDLlib.php ще се изполва само в началото за целите на миграцията, втората си запазва името и поддърржа и управлява DML-ла, и третата част състояща се от няколко файла съдържащи функции НЕ свързани с ADOdb ще се разпредели между няколко файла които ще се намират в course/lib.php, user/lib.php..

       2. Промени в DML функциите: В основни линии това включва промяна в support LIMIT клаузите които са емулирани под Oracle, транспортиране и управление на CLOB/BLOB (large text/binary objects...)

        3. Необходима е сложна XML структура за дефиниране на всяка база данни, и цялата информация необхдима за преобразуването в използваеми DDL изрази за всяка RDBMS.

        4. Следващата задача е създаването на нови DDL функции необходими за инсталирането на произволен компонент за БД на Moodle, нови функции за създаване на таблици, индексиране.. Всичко това ще се намира във файла DDLlib.php.

        5. Необходима е промяна в процеса на инсталиране. За целта ще бъде въведен един нов XML файл който ще замени сега съществуващите *.sql файлове , сега съществуващите *php файлове ще бъдат заменени от един файл upgrade.php

        6. Последната задача е докуменнтирането на всичко описано по-горе.

   Описания по горе процес неминуемо ще е свързан с доста проблеми и подводни камъни. Създаването на функцията SelectLimit() осигуряваща универсална съвместимост с различни типове бази данни е един от проблемите. Извикването на последната функция при Oracle ще отвори работа защото се емулира от ADOdb , поради забавянето в резултат на клаузата LIMIT. За да може ADOdb да извлече желания прозорец му се налага да итерира през голям брой записи. Още в началото на този материал (погледнете в началото) споменах нещо за търсене в много на брой и дълги записи. Друг проблем е несъответствието на сега съществуващата конвенция за имена на обектите в базата данни с тази която ще е в ADOdb мплементацията. Какво да правим с тези обекти? За Oracle например при необходими id ще са необходими допълнителни механизми в insert_record() нещо като get sequence nextval, insert record... Относно Oracle (дано не бъда  обвинен в субективизъм) сериозни проблеми съществуват при вмъкването на CLOB/BLOB данни. Имам предвид двете стъпки INSERT empty_b/clob() и UPDATE

Донякъде решението е описано http://phplens.com/ADOdb/reference.functions.updateblob.html и тук http://phplens.com/ADOdb/reference.functions.updateclob.html
Още един проблем свързан с Oracle с полетата NOT NULL и вмъкването на values. Въобще не става! Да не говорим как са нещата при Oracle с регулярните
изрази.
Приложеният ZIP архив съдържа файловете касаещи написаното (v. 1.7+ )
 


XML database schema


Moodle 1.7 will be able to work with more RDBMS such as Oracle for example while maintaining everything working properly with MySQL. Moodle core supports ADOdb
internally. The tests was made to inspect how ADOdb was doing its work, and how the Moodle team could mix together all those 4 RDBMS, whose SQL dialects, although
pretty similar, have some differences and idiosyncrasies that force us to do some important changes to current Moodle database code (formerly datalib.php) and how it's
used by the rest of it.

Non-functional preliminary requirements:


- Provide one layer (new) for DB creation/upgrade (DDL)
- Provide one layer (existing) for DB handling (DML)
- Easy migration path from previous versions
- Simple, usable and effective install and upgrade
- Conditional code usage must be minimised
- Well documented

The Stack


The Moodle 1.7 stack shows how code will interact with underlying RDBMS.

The Roadmap:


Moodle code will use two languages to perform its DB actions. DDL and DML. Each one of this languages will use its own library. Moodle DDL Library (DDLlib.php) and
Moodle DML Library (datalib.php) respectively.

XMLDB Modifying DML functions

Uses of the LIMIT offset have to be changed. num clause to use the cross-db compatible SelectLimit() function must be modified.

XMLDB Roadmap

     1. Splitting datalib.php
     2. Modifying DML functions
     3. XML Defining one XML structure and handling it
     4. Creating new DDL functions
     5. Modifying the installation/upgrade process
     6. Documenting everything

XMLDB Splitting datalib.php

   Currently there are 94 functions defined in lib/datalib.php where most of them (50) are not directly related with DML or DDL statements at all but with some commonly used DB transactions (let's call them functional functions. The rest (44) are core functions (from the perspective of being general, used by any script, to access to any table info), used to access to DB (with 42 functions used to handle data - DML - and 2 functions used to handle objects - DDL).

The two approaches:

      1. Create two new libraries (DDLlib.php and DMLlib.php) and leave datalib.php for functional functions.
      2. Create one new library (dDDLib.php), 'leaving datalib.php for core functions and move functional functions to other libraries.

XMLDB column types

For Oracle: http://www.cs.umbc.edu/help/Oracle8/server.815/a68003/01_04blt.htm

XMLDB preliminary links Installation instructions for Refactored Oracle driver to use with PHP versions prior to 5.1.2 ) (За рефакторинг на код някой друг път намигване
Един полезен линк страница на PHP за Oracle- http://www.php.net/oci8

XMLDB Problems

    Regular expressions (Problems with Oracle (not available until 10g), Oracle 10g implements them using directly and one package existed since ages (Oracle 8i?) to handle them).

SQL Limit performance ( SelectLimit() calls under Oracle because it's emulated by ADOdb on those DBs, because their lack of support for the LIMIT clause).

Naming conventions (if previously created DB objects (indexes, unique indexes, sequences) naming schema doesn't fit with the implemented by ADOdb???



Приложеният ZIP архив съдържа файловете касаещи написаното (v. 1.7+ )

In reply to Daniel Denev

Re: xmlschema или какво ново относно базата данни на Moodle

от Kiril Ilarionov -
Да, звучи логично.

От практическа гледна точка,
това предполага като следваща
голяма стъпка напред =>
ОТДЕЛЯНЕТО на развойната среда
от експлоатацията.

Тогана сайтът за експлатация може да е само
от статични страници, в резултат на
XSLT справка от независимата XML база данни (БД).

Eдновременно с това тази XML БД
е потенциална основа за развитието на
Application Server работещ с разпределена БД,
т.е. много и различни DBMS, в т.ч. и RDBMS.

Резултатът е подобряване в пъти
на съотношението цена/производителност
за експлоатацията и на принципно нов потенциал
за разработка на педагогически софтуер.

В следващите 5-10 години
тези две подобрения щмогат да променят
значително пазара на образователните услуги.

С две думи практическите последици ще са сериозни.


In reply to Kiril Ilarionov

Re: xmlschema или какво ново относно базата данни на Moodle

от Daniel Denev -

засрамен(а) Здравей Кирил,

Написаното вероятно се отнася за постинга по-горе. Ако е наистина така - Благодаря! Твоят постинг е първият за новата година и съдейки по това къде е поставен - Във форума за програмисти - новата година явно такава и ще бъде - ще се пише код! А, честито! Просто това което ми се ще да спомена е, че в живота не всичко е програмиране! Последното казва един нещастник който дори не е само програмист!

Един Дидо засрамен(а) тъжен/тъжна

P.S. Чудя се колко човека в България познават софтуерната архитектура на Moodle
Ако има такива - "Вдигнете ръка" ако пък има от вас такива на които им се работи, за тази страна, ако поне на някого му пука за децата ни, дайте да видим какво да направим тъй щото да се формира някакъв български екип който да работи върху писането на софтуер за образованието. Как това да се синхронизира с Министерството на образованието, как да се подкрепи такава инициатива. АЗ ДО МОМЕНТА НЕ СЪМ СРЕЩАЛ МНОГО ХОРА ЗАПОЗНАТИ СЪС СОФТУЕРНАТА АРХИТЕКТУРА НА Moodle в България. КОИ СМЕ?????????
Уточнение: Moodle не означава e-Learning в света хората работят над много неща и най-вече НЕ САМИ!!!

In reply to Daniel Denev

Re: xmlschema или какво ново относно базата данни на Moodle

от Daniel Denev -
... вярвайте оставам с "грешното" впечатление, че на никого не му пука (или поне в милата ни татковина) за образованието, пък камо ли за новите технологии в него!!! "... Обучени са 1000 000 еди какви си специалисти, Направени са еди какви си проекти ..."  Трябва май да сменя станцията на радиото си и да спра да гледам телевизия! Толкова зле никога не е било!
In reply to Daniel Denev

Re: xmlschema или какво ново относно базата данни на Moodle

от Daniel Denev -

Дори да се хванем и да създадем софтуер - чудо независещ от базата данни, ВСЕ ТАЯ!!! Последното вече мога да кажа със сигурност след години ходене по мъките!!! Нищо неможе да се случи!!! НИЩО!!!  Оглеждам се наоколо и се чудя какво правя аз тук!?

Един абсолютен нещастник

In reply to Daniel Denev

Re: xmlschema или какво ново относно базата данни на Moodle

от Kiril Ilarionov -
Е Базата Данни на Moodle просто не е нормализирана
http://moodle.org/mod/forum/discuss.php?d=71691
както може да се прочете от горния линк.

Нещо което подозирах през последните 6 месеца.

Нормализирана или НЕ е нормализирана???
Това е ВЪПРОСЪТ!

smile