00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 include_once( 'lib/ezdbschema/classes/ezdbschemainterface.php' );
00037
00038 class eZMysqlSchema extends eZDBSchemaInterface
00039 {
00040
00041
00042
00043
00044
00045
00046
00047 function eZMysqlSchema( $params )
00048 {
00049 $this->eZDBSchemaInterface( $params );
00050 }
00051
00052
00053
00054
00055 function schema( $params = array() )
00056 {
00057 $params = array_merge( array( 'meta_data' => false,
00058 'format' => 'generic' ),
00059 $params );
00060 $schema = array();
00061
00062 if ( $this->Schema === false )
00063 {
00064 $tableArray = $this->DBInstance->arrayQuery( "SHOW TABLES" );
00065
00066 foreach( $tableArray as $tableNameArray )
00067 {
00068 $table_name = current( $tableNameArray );
00069 $schema_table['name'] = $table_name;
00070 $schema_table['fields'] = $this->fetchTableFields( $table_name, $params );
00071 $schema_table['indexes'] = $this->fetchTableIndexes( $table_name, $params );
00072
00073 $schema[$table_name] = $schema_table;
00074 }
00075 $this->transformSchema( $schema, $params['format'] == 'local' );
00076 ksort( $schema );
00077 $this->Schema = $schema;
00078 }
00079 else
00080 {
00081 $this->transformSchema( $this->Schema, $params['format'] == 'local' );
00082 $schema = $this->Schema;
00083 }
00084 return $schema;
00085 }
00086
00087
00088
00089
00090
00091
00092 function fetchTableFields( $table, $params )
00093 {
00094 $fields = array();
00095
00096 $resultArray = $this->DBInstance->arrayQuery( "DESCRIBE $table" );
00097
00098 foreach( $resultArray as $row )
00099 {
00100 $field = array();
00101 $field['type'] = $this->parseType ( $row['Type'], $field['length'] );
00102 if ( !$field['length'] )
00103 {
00104 unset( $field['length'] );
00105 }
00106 $field['not_null'] = 0;
00107 if ( $row['Null'] != 'YES' )
00108 {
00109 $field['not_null'] = '1';
00110 }
00111 $field['default'] = false;
00112 if ( !$field['not_null'] )
00113 {
00114 if ( $row['Default'] === null )
00115 $field['default'] = null;
00116 else
00117 $field['default'] = (string)$row['Default'];
00118 }
00119 else
00120 {
00121 $field['default'] = (string)$row['Default'];
00122 }
00123
00124 $numericTypes = array( 'float', 'int' );
00125 $blobTypes = array( 'tinytext', 'text', 'mediumtext', 'longtext' );
00126 $charTypes = array( 'varchar', 'char' );
00127 if ( in_array( $field['type'], $charTypes ) )
00128 {
00129 if ( !$field['not_null'] )
00130 {
00131 if ( $field['default'] === null )
00132 {
00133 $field['default'] = null;
00134 }
00135 else if ( $field['default'] === false )
00136 {
00137 $field['default'] = '';
00138 }
00139 }
00140 }
00141 else if ( in_array( $field['type'], $numericTypes ) )
00142 {
00143 if ( $field['default'] === false )
00144 {
00145 if ( $field['not_null'] )
00146 {
00147 $field['default'] = 0;
00148 }
00149 }
00150 else if ( $field['type'] == 'int' )
00151 {
00152 if ( $field['not_null'] or
00153 is_numeric( $field['default'] ) )
00154 $field['default'] = (int)$field['default'];
00155 }
00156 else if ( $field['type'] == 'float' or
00157 is_numeric( $field['default'] ) )
00158 {
00159 if ( $field['not_null'] or
00160 is_numeric( $field['default'] ) )
00161 $field['default'] = (float)$field['default'];
00162 }
00163 }
00164 else if ( in_array( $field['type'], $blobTypes ) )
00165 {
00166
00167 $field['default'] = false;
00168 }
00169
00170 if ( substr ( $row['Extra'], 'auto_increment' ) !== false )
00171 {
00172 unset( $field['length'] );
00173 $field['not_null'] = 0;
00174 $field['default'] = false;
00175 $field['type'] = 'auto_increment';
00176 }
00177
00178 if ( !$field['not_null'] )
00179 unset( $field['not_null'] );
00180
00181 $fields[$row['Field']] = $field;
00182 }
00183 ksort( $fields );
00184
00185 return $fields;
00186 }
00187
00188
00189
00190
00191 function fetchTableIndexes( $table, $params )
00192 {
00193 $metaData = false;
00194 if ( isset( $params['meta_data'] ) )
00195 {
00196 $metaData = $params['meta_data'];
00197 }
00198
00199 $indexes = array();
00200
00201 $resultArray = $this->DBInstance->arrayQuery( "SHOW INDEX FROM $table" );
00202
00203 foreach( $resultArray as $row )
00204 {
00205 $kn = $row['Key_name'];
00206
00207 if ( $kn == 'PRIMARY' )
00208 {
00209 $indexes[$kn]['type'] = 'primary';
00210 }
00211 else
00212 {
00213 $indexes[$kn]['type'] = $row['Non_unique'] ? 'non-unique' : 'unique';
00214 }
00215
00216 $indexFieldDef = array( 'name' => $row['Column_name'] );
00217
00218
00219 if ( $row['Sub_part'] )
00220 {
00221 $indexFieldDef['mysql:length'] = (int)$row['Sub_part'];
00222 }
00223
00224
00225 if ( count( array_diff( array_keys( $indexFieldDef ), array( 'name' ) ) ) == 0 )
00226 {
00227 $indexFieldDef = $indexFieldDef['name'];
00228 }
00229 $indexes[$kn]['fields'][$row['Seq_in_index'] - 1] = $indexFieldDef;
00230 }
00231 ksort( $indexes );
00232
00233 return $indexes;
00234 }
00235
00236 function parseType( $type_info, &$length_info )
00237 {
00238 preg_match ( "@([a-z ]*)(\(([0-9]*|[0-9]*,[0-9]*)\))?@", $type_info, $matches );
00239 if ( isset( $matches[3] ) )
00240 {
00241 $length_info = $matches[3];
00242 if ( is_numeric( $length_info ) )
00243 $length_info = (int)$length_info;
00244 }
00245 return $matches[1];
00246 }
00247
00248
00249
00250
00251 function generateAddIndexSql( $table_name, $index_name, $def, $params, $isEmbedded = false )
00252 {
00253 $diffFriendly = isset( $params['diff_friendly'] ) ? $params['diff_friendly'] : false;
00254
00255 $mysqlCompatible = isset( $params['compatible_sql'] ) ? $params['compatible_sql'] : false;
00256 $sql = '';
00257
00258
00259 if ( !$isEmbedded )
00260 {
00261 $sql .= "ALTER TABLE $table_name ADD";
00262 $sql .= " ";
00263 }
00264
00265 switch ( $def['type'] )
00266 {
00267 case 'primary':
00268 {
00269 $sql .= 'PRIMARY KEY';
00270 if ( $mysqlCompatible )
00271 $sql .= " ";
00272 } break;
00273
00274 case 'non-unique':
00275 {
00276 if ( $isEmbedded )
00277 {
00278 $sql .= "KEY $index_name";
00279 }
00280 else
00281 {
00282 $sql .= "INDEX $index_name";
00283 }
00284 } break;
00285
00286 case 'unique':
00287 {
00288 if ( $isEmbedded )
00289 {
00290 $sql .= "UNIQUE KEY $index_name";
00291 }
00292 else
00293 {
00294 $sql .= "UNIQUE $index_name";
00295 }
00296 } break;
00297 }
00298
00299 $sql .= ( $diffFriendly ? " (\n " : ( $mysqlCompatible ? " (" : " ( " ) );
00300 $fields = $def['fields'];
00301 $i = 0;
00302 foreach ( $fields as $fieldDef )
00303 {
00304 if ( $i > 0 )
00305 {
00306 $sql .= $diffFriendly ? ",\n " : ( $mysqlCompatible ? ',' : ', ' );
00307 }
00308 if ( is_array( $fieldDef ) )
00309 {
00310 $sql .= $fieldDef['name'];
00311 if ( isset( $fieldDef['mysql:length'] ) )
00312 {
00313 if ( $diffFriendly )
00314 {
00315 $sql .= "(\n";
00316 $sql .= " " . str_repeat( ' ', strlen( $fieldDef['name'] ) );
00317 }
00318 else
00319 {
00320 $sql .= $mysqlCompatible ? "(" : "( ";
00321 }
00322 $sql .= $fieldDef['mysql:length'];
00323 if ( $diffFriendly )
00324 {
00325 $sql .= ")";
00326 }
00327 else
00328 {
00329 $sql .= $mysqlCompatible ? ")" : " )";
00330 }
00331 }
00332 }
00333 else
00334 {
00335 $sql .= $fieldDef;
00336 }
00337 ++$i;
00338 }
00339 $sql .= ( $diffFriendly ? "\n)" : ( $mysqlCompatible ? ")" : " )" ) );
00340
00341 if ( !$isEmbedded )
00342 {
00343 return $sql . ";\n";
00344 }
00345 return $sql;
00346 }
00347
00348
00349
00350
00351 function generateDropIndexSql( $table_name, $index_name, $def, $params )
00352 {
00353 $sql = '';
00354 $sql .= "ALTER TABLE $table_name DROP ";
00355
00356 if ( $def['type'] == 'primary' )
00357 {
00358 $sql .= 'PRIMARY KEY';
00359 }
00360 else
00361 {
00362 $sql .= "INDEX $index_name";
00363 }
00364 return $sql . ";\n";
00365 }
00366
00367
00368
00369
00370 function generateFieldDef( $field_name, $def, &$skip_primary, $params = null )
00371 {
00372 $diffFriendly = isset( $params['diff_friendly'] ) ? $params['diff_friendly'] : false;
00373
00374 $mysqlCompatible = isset( $params['compatible_sql'] ) ? $params['compatible_sql'] : false;
00375
00376 $sql_def = $field_name . ' ';
00377 $defaultText = $mysqlCompatible ? "default" : "DEFAULT";
00378
00379 if ( $def['type'] != 'auto_increment' )
00380 {
00381 $defList = array();
00382 $type = $def['type'];
00383 if ( isset( $def['length'] ) )
00384 {
00385 $type .= "({$def['length']})";
00386 }
00387 $defList[] = $type;
00388 if ( isset( $def['not_null'] ) && ( $def['not_null'] ) )
00389 {
00390 $defList[] = 'NOT NULL';
00391 }
00392 if ( array_key_exists( 'default', $def ) )
00393 {
00394 if ( $def['default'] === null )
00395 {
00396 $defList[] = "$defaultText NULL";
00397 }
00398 else if ( $def['default'] !== false )
00399 {
00400 $defList[] = "$defaultText '{$def['default']}'";
00401 }
00402 }
00403 else if ( $def['type'] == 'varchar' )
00404 {
00405 $defList[] = "$defaultText ''";
00406 }
00407 $sql_def .= join( $diffFriendly ? "\n " : " ", $defList );
00408 $skip_primary = false;
00409 }
00410 else
00411 {
00412 $incrementText = $mysqlCompatible ? "auto_increment" : "AUTO_INCREMENT";
00413 if ( $diffFriendly )
00414 {
00415 $sql_def .= "int(11)\n NOT NULL\n $incrementText";
00416 }
00417 else
00418 {
00419 $sql_def .= "int(11) NOT NULL $incrementText";
00420 }
00421 $skip_primary = true;
00422 }
00423 return $sql_def;
00424 }
00425
00426
00427
00428
00429 function generateAddFieldSql( $table_name, $field_name, $def, $params )
00430 {
00431 $sql = "ALTER TABLE $table_name ADD COLUMN ";
00432 $sql .= eZMysqlSchema::generateFieldDef ( $field_name, $def, $dummy );
00433
00434 return $sql . ";\n";
00435 }
00436
00437
00438
00439
00440 function generateAlterFieldSql( $table_name, $field_name, $def = array() )
00441 {
00442 $sql = "ALTER TABLE $table_name CHANGE COLUMN $field_name ";
00443 $sql .= eZMysqlSchema::generateFieldDef ( $field_name, $def, $dummy );
00444
00445 return $sql . ";\n";
00446 }
00447
00448
00449
00450
00451
00452 function generateTableSchema( $tableName, $table, $params )
00453 {
00454 return $this->generateTableSQL( $tableName, $table, $params, false, false );
00455 }
00456
00457
00458
00459
00460
00461 function generateTableSQLList( $tableName, $table, $params, $separateTypes )
00462 {
00463 return $this->generateTableSQL( $tableName, $table, $params, true, $separateTypes );
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473 function generateTableSQL( $tableName, $tableDef, $params, $asArray, $separateTypes = false )
00474 {
00475 $diffFriendly = isset( $params['diff_friendly'] ) ? $params['diff_friendly'] : false;
00476 $mysqlCompatible = isset( $params['compatible_sql'] ) ? $params['compatible_sql'] : false;
00477
00478 if ( $asArray )
00479 {
00480 if ( $separateTypes )
00481 {
00482 $sqlList = array( 'tables' => array() );
00483 }
00484 else
00485 {
00486 $sqlList = array();
00487 }
00488 }
00489
00490 $sql = '';
00491 $skip_pk = false;
00492 $sql_fields = array();
00493 $sql .= "CREATE TABLE $tableName (\n";
00494
00495 $fields = $tableDef['fields'];
00496
00497 foreach ( $fields as $field_name => $field_def )
00498 {
00499 $sql_fields[] = ' ' . eZMysqlSchema::generateFieldDef( $field_name, $field_def, $skip_pk_flag, $params );
00500 if ( $skip_pk_flag )
00501 {
00502 $skip_pk = true;
00503 }
00504 }
00505
00506
00507 $indexes = $tableDef['indexes'];
00508
00509
00510 foreach ( $indexes as $index_name => $index_def )
00511 {
00512 $sql_fields[] = ( $diffFriendly ? '' : ' ' ) . eZMysqlSchema::generateAddIndexSql( $tableName, $index_name, $index_def, $params, true );
00513 }
00514 $sql .= join( ",\n", $sql_fields );
00515 $sql .= "\n)";
00516
00517
00518 $extraOptions = array();
00519 if ( isset( $params['table_type'] ) and $params['table_type'] )
00520 {
00521 $typeName = $this->tableStorageTypeName( $params['table_type'] );
00522 if ( $typeName )
00523 {
00524 $extraOptions[] = "TYPE=" . $typeName;
00525 }
00526 }
00527 if ( isset( $params['table_charset'] ) and $params['table_charset'] )
00528 {
00529 $charsetName = $this->tableCharsetName( $params['table_charset'] );
00530 if ( $charsetName )
00531 {
00532 $extraOptions[] = "DEFAULT CHARACTER SET " . $charsetName;
00533 }
00534 }
00535 if ( isset( $tableDef['options'] ) )
00536 {
00537 foreach( $tableDef['options'] as $optionType => $optionValue )
00538 {
00539 $optionText = $this->generateTableOption( $tableName, $tableDef, $optionType, $optionValue, $params );
00540 if ( $optionText )
00541 $extraOptions[] = $optionText;
00542 }
00543 }
00544
00545 if ( count( $extraOptions ) > 0 )
00546 {
00547 $sql .= " " . implode( $diffFriendly ? "\n" : " ", $extraOptions );
00548 }
00549
00550 if ( $asArray )
00551 {
00552 if ( $separateTypes )
00553 {
00554 $sqlList['tables'][] = $sql;
00555 }
00556 else
00557 {
00558 $sqlList[] = $sql;
00559 }
00560 }
00561 else
00562 {
00563 $sql .= ";\n";
00564
00565 if ( $mysqlCompatible )
00566 {
00567 $sql .= "\n\n\n";
00568 }
00569 }
00570
00571 return $asArray ? $sqlList : $sql;
00572 }
00573
00574
00575
00576
00577
00578
00579
00580 function generateTableOption( $tableName, $tableDef, $optionType, $optionValue, $params )
00581 {
00582 switch ( $optionType )
00583 {
00584 case 'mysql:delay_key_write':
00585 {
00586 if ( $optionValue )
00587 return 'DELAY_KEY_WRITE=1';
00588 } break;
00589 }
00590 return false;
00591 }
00592
00593
00594
00595
00596 function tableCharsetName( $charset )
00597 {
00598 include_once( 'lib/ezi18n/classes/ezcharsetinfo.php' );
00599 $charset = eZCharsetInfo::realCharsetCode( $charset );
00600
00601 $charsetMapping = array( 'iso-8859-1' => 'latin1',
00602 'iso-8859-2' => 'latin2',
00603 'iso-8859-8' => 'hebrew',
00604 'iso-8859-7' => 'greek',
00605 'iso-8859-9' => 'latin5',
00606 'iso-8859-13' => 'latin7',
00607 'windows-1250' => 'cp1250',
00608 'windows-1251' => 'cp1251',
00609 'windows-1256' => 'cp1256',
00610 'windows-1257' => 'cp1257',
00611 'utf-8' => 'utf8',
00612 'koi8-r' => 'koi8r',
00613 'koi8-u' => 'koi8u' );
00614 $charset = strtolower( $charset );
00615 if ( isset( $charsetMapping ) )
00616 return $charsetMapping[$charset];
00617 return $charset;
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627 function tableStorageTypeName( $type )
00628 {
00629 $type = strtolower( $type );
00630 switch ( $type )
00631 {
00632 case 'bdb':
00633 {
00634 return 'BDB';
00635 }
00636
00637 case 'myisam':
00638 {
00639 return 'MyISAM';
00640 }
00641
00642 case 'innodb':
00643 {
00644 return 'InnoDB';
00645 }
00646 }
00647 return false;
00648 }
00649
00650
00651
00652
00653 function generateDropTable( $table, $params )
00654 {
00655 return "DROP TABLE $table;\n";
00656 }
00657
00658
00659
00660
00661
00662
00663
00664 function isMultiInsertSupported()
00665 {
00666 if ( is_subclass_of( $this->DBInstance, 'ezdbinterface' ) )
00667 {
00668 $versionInfo = $this->DBInstance->databaseServerVersion();
00669
00670
00671
00672 return ( version_compare( $versionInfo['string'], '3.22.5' ) >= 0 );
00673 }
00674 return true;
00675 }
00676
00677
00678
00679
00680 function escapeSQLString( $value )
00681 {
00682
00683
00684 if ( function_exists( 'mysql_escape_string' ) )
00685 return mysql_escape_string( $value );
00686 else
00687 str_replace( array( "\\",
00688 "'",
00689 '"',
00690 "\x00",
00691 "\x1a",
00692 "\n",
00693 "\r" ),
00694 array( "\\\\",
00695 "\\'",
00696 "\\\"",
00697 "\\0",
00698 "\\Z",
00699 "\\n",
00700 "\\r" ),
00701 $value );
00702 }
00703
00704
00705
00706
00707 function schemaType()
00708 {
00709 return 'mysql';
00710 }
00711
00712
00713
00714
00715 function schemaName()
00716 {
00717 return 'MySQL';
00718 }
00719
00720 }
00721 ?>