001/* 002 * Copyright 2018 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.contentio.export.sql; 017 018import java.io.IOException; 019import java.sql.Connection; 020import java.sql.PreparedStatement; 021import java.sql.SQLException; 022import java.util.ArrayList; 023import java.util.HashMap; 024import java.util.LinkedHashMap; 025import java.util.List; 026import java.util.Map; 027import java.util.Map.Entry; 028import java.util.regex.Matcher; 029import java.util.regex.Pattern; 030 031import org.apache.avalon.framework.component.Component; 032import org.apache.avalon.framework.service.ServiceException; 033import org.apache.avalon.framework.service.ServiceManager; 034import org.apache.avalon.framework.service.Serviceable; 035import org.apache.commons.lang.StringUtils; 036 037import org.ametys.cms.contenttype.ContentType; 038import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 039import org.ametys.cms.data.type.ModelItemTypeConstants; 040import org.ametys.cms.languages.LanguagesManager; 041import org.ametys.core.datasource.ConnectionHelper; 042import org.ametys.core.util.I18nUtils; 043import org.ametys.plugins.repository.model.CompositeDefinition; 044import org.ametys.plugins.repository.model.RepeaterDefinition; 045import org.ametys.runtime.config.Config; 046import org.ametys.runtime.i18n.I18nizableText; 047import org.ametys.runtime.model.ElementDefinition; 048import org.ametys.runtime.model.ModelItem; 049import org.ametys.runtime.model.ModelItemContainer; 050import org.ametys.runtime.plugin.component.AbstractLogEnabled; 051 052/** 053 * Create SQl Table Component 054 */ 055public class CreateSqlTableComponent extends AbstractLogEnabled implements Component, Serviceable 056{ 057 /** The component role */ 058 public static final String ROLE = CreateSqlTableComponent.class.getName(); 059 060 /** Code of default language for comments */ 061 public static final String DEFAULT_LANGUAGE_CODE_FOR_COMMENTS = "en"; 062 063 /** The engine */ 064 public static final String MYSQL_CONTENT_EXPORT_ENGINE = "MyISAM"; 065 066 /** The encoding */ 067 public static final String MYSQL_CONTENT_EXPORT_CHARSET = "UTF8MB4"; 068 069 /** Prefix for parent table column */ 070 public static final String COLUMN_PARENT_TABLE_PREFIX = "PID_"; 071 072 private static final Pattern _MYSQL_VERSION_NUMBER_EXTRACT = Pattern.compile("^([0-9]+).*$"); 073 074 /** Content type extension point. */ 075 protected ContentTypeExtensionPoint _contentTypeExtensionPoint; 076 077 /** The i18n translator. */ 078 protected I18nUtils _i18nTranslator; 079 080 /** The normalise name component. */ 081 protected NormalizeNameComponent _normalizeNameComponent; 082 083 /** The language manager */ 084 protected LanguagesManager _languageManager; 085 086 private Connection _connection; 087 private String _databaseType; 088 089 private LinkedHashMap<String, ExportTableInfo> _tablesInfos; 090 private int _commentTableMaxLength; 091 private int _commentColumnMaxLength; 092 private String _sqlTablePrefix; 093 private String _sqlPrefixConf; 094 private Map<String, Map<String, String>> _mapping; 095 private Map<String, Map<String, String>> _reservedWords; 096 private String _mappingPolicy; 097 private ArrayList<String> _mappingTablesQueries; 098 private boolean _exportNoMultiValuedTable; 099 100 private int _fkIndice; 101 private int _pkIndice; 102 103 @Override 104 public void service(ServiceManager manager) throws ServiceException 105 { 106 _i18nTranslator = (I18nUtils) manager.lookup(I18nUtils.ROLE); 107 _contentTypeExtensionPoint = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE); 108 _normalizeNameComponent = (NormalizeNameComponent) manager.lookup(NormalizeNameComponent.ROLE); 109 _languageManager = (LanguagesManager) manager.lookup(LanguagesManager.ROLE); 110 } 111 112 /** 113 * Create sql tables for contents 114 * @param exportConfiguration the content export configuration 115 * @return tablesInfos 116 * @throws SQLException if a sql error occurred 117 * @throws IOException if an IO error occurred 118 */ 119 public synchronized Map<String, ExportTableInfo> createTables(ExportConfiguration exportConfiguration) throws SQLException, IOException 120 { 121 // Get from configuration 122 _sqlPrefixConf = exportConfiguration.getTablePrefix(); 123 _sqlTablePrefix = exportConfiguration.getTablePrefix(); 124 _mapping = exportConfiguration.getMappingSql(); 125 _mappingPolicy = exportConfiguration.getMappingPolicy(); 126 _reservedWords = exportConfiguration.getReservedWords(); 127 _exportNoMultiValuedTable = exportConfiguration.exportNoMultiValuedTable(); 128 129 // Initialization 130 _fkIndice = 1; 131 _pkIndice = 1; 132 _tablesInfos = new LinkedHashMap<>(); 133 _mappingTablesQueries = new ArrayList<>(); 134 135 try 136 { 137 String datasourceId = Config.getInstance().getValue("org.ametys.plugins.contentio.content.export.datasource"); 138 _connection = ConnectionHelper.getConnection(datasourceId); 139 _databaseType = ConnectionHelper.getDatabaseType(_connection); 140 141 String productVersion = _connection.getMetaData().getDatabaseProductVersion(); 142 initialize(productVersion); 143 144 boolean isInfoEnabled = getLogger().isInfoEnabled(); 145 if (isInfoEnabled) 146 { 147 getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_ANALYZE_TABLE_CREATE_BEGIN"))); 148 } 149 150 createTablesInfos(exportConfiguration.getContentTypesToExport()); 151 152 if (isInfoEnabled) 153 { 154 getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_ANALYZE_TABLE_CREATE_END"))); 155 getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_ANALYZE_TABLE_CREATE_MAPPING_BEGIN"))); 156 } 157 158 createMappingTables(); 159 160 if (isInfoEnabled) 161 { 162 getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_ANALYZE_TABLE_CREATE_MAPPING_END"))); 163 } 164 165 createRichTextDataTable(); 166 createContentTable(); 167 168 executeQueries(); 169 } 170 finally 171 { 172 ConnectionHelper.cleanup(_connection); 173 } 174 175 return _tablesInfos; 176 } 177 178 /** 179 * Initialization 180 * @param productVersion The database product version 181 */ 182 protected void initialize(String productVersion) 183 { 184 // Get the maximun number of authorized characters for table and column comments 185 if (_databaseType.equals(ConnectionHelper.DATABASE_MYSQL)) 186 { 187 String[] parts = productVersion.split("\\."); 188 189 int majorVersion = Integer.parseInt(parts[0]); 190 int minorVersion = 0; 191 int patchVersion = 0; 192 if (parts.length > 1) 193 { 194 Matcher matcher = _MYSQL_VERSION_NUMBER_EXTRACT.matcher(parts[1]); 195 if (matcher.matches()) 196 { 197 minorVersion = Integer.parseInt(matcher.group(1)); 198 } 199 } 200 201 if (parts.length > 2) 202 { 203 Matcher matcher = _MYSQL_VERSION_NUMBER_EXTRACT.matcher(parts[2]); 204 if (matcher.matches()) 205 { 206 patchVersion = Integer.parseInt(matcher.group(1)); 207 } 208 } 209 210 if (majorVersion > 5 || majorVersion >= 5 && minorVersion > 5 || majorVersion >= 5 && minorVersion >= 5 && patchVersion >= 3) 211 { 212 // Version 5.5.3 or later 213 _commentTableMaxLength = 2048; 214 _commentColumnMaxLength = 1024; 215 } 216 else 217 { 218 // Version before 5.5.3 219 _commentTableMaxLength = 60; 220 _commentColumnMaxLength = 255; 221 } 222 } 223 else 224 { 225 // No max 226 _commentTableMaxLength = 2048; 227 _commentColumnMaxLength = 1024; 228 } 229 } 230 231 /** 232 * Created all tables informations 233 * @param contents to export 234 * @throws SQLException if a sql error occurred 235 */ 236 protected void createTablesInfos(Map<String, String> contents) throws SQLException 237 { 238 for (Entry<String, String> entry : contents.entrySet()) 239 { 240 String contentTypeId = entry.getKey(); 241 242 ContentType contentType = _contentTypeExtensionPoint.getExtension(contentTypeId); 243 if (!contentType.isAbstract()) 244 { 245 String tableName = entry.getValue(); 246 String comment = _i18nTranslator.translate(contentType.getLabel(), DEFAULT_LANGUAGE_CODE_FOR_COMMENTS) + ": " + _i18nTranslator.translate(contentType.getDescription(), DEFAULT_LANGUAGE_CODE_FOR_COMMENTS); 247 createQueriesForTableCreation(contentType, tableName, null, comment, false); 248 } 249 250 _sqlTablePrefix = _sqlPrefixConf; 251 } 252 } 253 254 /** 255 * Create SQL queries to create necessary SQL tables for content type export 256 * @param modelItemContainer the current {@link ModelItemContainer} 257 * @param tableName the table name The SQL table name 258 * @param tableParentName The SQL parent table name 259 * @param comment the comment 260 * @param isSortTable true if table's rows have to be ordered 261 */ 262 protected void createQueriesForTableCreation(ModelItemContainer modelItemContainer, String tableName, String tableParentName, String comment, boolean isSortTable) 263 { 264 ExportTableInfo tableInfo = new ExportTableInfo(tableName); 265 tableInfo.incrementNbColumns(); 266 267 String tableNameNormalized = _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, tableName, _connection); 268 _tablesInfos.put(tableName, tableInfo); 269 270 StringBuilder currentCreateTableSQLQuery = new StringBuilder(); 271 272 currentCreateTableSQLQuery.append("CREATE TABLE "); 273 currentCreateTableSQLQuery.append(tableNameNormalized); 274 currentCreateTableSQLQuery.append(" ("); 275 currentCreateTableSQLQuery.append(_normalizeNameComponent.normalizedColumnName(_mappingPolicy, "id_" + tableName, tableName, _reservedWords, _connection)); 276 currentCreateTableSQLQuery.append(" VARCHAR(250)"); 277 currentCreateTableSQLQuery.append(createPrimaryKeyQuery()); 278 currentCreateTableSQLQuery.append(createCommentQuery(tableName, "id_" + tableName, "Ametys ID")); 279 280 if (StringUtils.isNotEmpty(tableParentName)) 281 { 282 currentCreateTableSQLQuery.append(", "); 283 addColumnParentId(currentCreateTableSQLQuery, tableParentName, tableName); 284 } 285 286 if (isSortTable) 287 { 288 currentCreateTableSQLQuery.append(", "); 289 addSortColumn(currentCreateTableSQLQuery, tableName); 290 } 291 292 addColumnForContainer(modelItemContainer, currentCreateTableSQLQuery, tableName, ""); 293 294 if (modelItemContainer instanceof ContentType) 295 { 296 addAdditionalData((ContentType) modelItemContainer, currentCreateTableSQLQuery, tableName); 297 } 298 299 currentCreateTableSQLQuery.append(") "); 300 currentCreateTableSQLQuery.append(createEngineQuery()); 301 currentCreateTableSQLQuery.append(createCommentQuery(tableName, null, comment)); 302 303 tableInfo.addCreateQuery(currentCreateTableSQLQuery.toString()); 304 } 305 306 /** 307 * Create table for images in rich text 308 */ 309 protected void createRichTextDataTable() 310 { 311 String dataTableName = _sqlTablePrefix + ExportManager.RICH_TEXT_DATA_TABLE_NAME; 312 ExportTableInfo tableInfo = new ExportTableInfo(dataTableName); 313 tableInfo.incrementNbColumns(8); 314 315 String dateTableNameNormalized = _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, "FULL", dataTableName, _connection); 316 _tablesInfos.put(dataTableName, tableInfo); 317 318 StringBuilder currentCreateTableSQLQuery = new StringBuilder(); 319 320 currentCreateTableSQLQuery.append("CREATE TABLE "); 321 currentCreateTableSQLQuery.append(dateTableNameNormalized); 322 currentCreateTableSQLQuery.append(" (id_data VARCHAR(250)"); 323 currentCreateTableSQLQuery.append(createPrimaryKeyQuery()); 324 currentCreateTableSQLQuery.append(createCommentQuery(dataTableName, "id_data", "Data ID")); 325 currentCreateTableSQLQuery.append(", id_content VARCHAR(255)"); 326 currentCreateTableSQLQuery.append(createCommentQuery(dataTableName, "id_content", "Parent ID")); 327 328 currentCreateTableSQLQuery.append(", attribute_name "); 329 currentCreateTableSQLQuery.append(convertTypeToSql("string")); 330 currentCreateTableSQLQuery.append(createCommentQuery(dataTableName, "attribute_name", "Richtext attribute name")); 331 currentCreateTableSQLQuery.append(", data_name "); 332 currentCreateTableSQLQuery.append(convertTypeToSql("string")); 333 currentCreateTableSQLQuery.append(createCommentQuery(dataTableName, "data_name", "Name")); 334 335 currentCreateTableSQLQuery.append(", data "); 336 currentCreateTableSQLQuery.append(convertTypeToSql("file")); 337 currentCreateTableSQLQuery.append(createCommentQuery(dataTableName, "data", "Data")); 338 currentCreateTableSQLQuery.append(", data_mimetype VARCHAR(255)"); 339 currentCreateTableSQLQuery.append(createCommentQuery(dataTableName, "data_mimetype", "Mime type")); 340 currentCreateTableSQLQuery.append(", data_size INT"); 341 currentCreateTableSQLQuery.append(createCommentQuery(dataTableName, "data_size", "Size")); 342 currentCreateTableSQLQuery.append(", data_lastmodified "); 343 currentCreateTableSQLQuery.append(convertTypeToSql("datetime")); 344 currentCreateTableSQLQuery.append(createCommentQuery(dataTableName, "data_lastmodified", "Last modification date")); 345 currentCreateTableSQLQuery.append(", "); 346 347 addSortColumn(currentCreateTableSQLQuery, dataTableName); 348 349 currentCreateTableSQLQuery.append(") "); 350 currentCreateTableSQLQuery.append(createEngineQuery()); 351 352 String comment = "Data table of all rich text"; 353 currentCreateTableSQLQuery.append(createCommentQuery(dataTableName, null, comment)); 354 355 tableInfo.addCreateQuery(currentCreateTableSQLQuery.toString()); 356 } 357 358 /** 359 * Create table for content 360 */ 361 protected void createContentTable() 362 { 363 String dataTableName = _sqlPrefixConf + ExportManager.CONTENT_TABLE_NAME; 364 ExportTableInfo tableInfo = new ExportTableInfo(dataTableName); 365 tableInfo.incrementNbColumns(2); 366 367 String dataTableNameNormalized = _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, "FULL", dataTableName, _connection); 368 _tablesInfos.put(dataTableName, tableInfo); 369 370 StringBuilder currentCreateTableSQLQuery = new StringBuilder(); 371 372 currentCreateTableSQLQuery.append("CREATE TABLE "); 373 currentCreateTableSQLQuery.append(dataTableNameNormalized); 374 currentCreateTableSQLQuery.append(" (id_content VARCHAR(80)"); 375 currentCreateTableSQLQuery.append(createCommentQuery(dataTableName, "id_content", "Content ID")); 376 currentCreateTableSQLQuery.append(", table_name VARCHAR(170)"); 377 currentCreateTableSQLQuery.append(createCommentQuery(dataTableName, "table_name", "Table name")); 378 currentCreateTableSQLQuery.append(", CONSTRAINT pk_content PRIMARY KEY (id_content, table_name) "); 379 currentCreateTableSQLQuery.append(") "); 380 currentCreateTableSQLQuery.append(createEngineQuery()); 381 382 String comment = "Link table of content with it's own table"; 383 currentCreateTableSQLQuery.append(createCommentQuery(dataTableName, null, comment)); 384 385 tableInfo.addCreateQuery(currentCreateTableSQLQuery.toString()); 386 } 387 388 /** 389 * Create the table for the enumerator (key, value) 390 * @param definition the attribute definition 391 * @param tableParentName the table parent name 392 * @param tableName the table name 393 * @param columnName the column name 394 * @param currentCreateTableSQLQuery the current SQL create table query 395 */ 396 protected void createTableForEnumerator(ElementDefinition definition, String tableParentName, String tableName, String columnName, StringBuilder currentCreateTableSQLQuery) 397 { 398 ExportTableInfo tableInfo = new ExportTableInfo(tableName); 399 tableInfo.incrementNbColumns(); 400 401 String tableNameNormalized = _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, tableName, _connection); 402 _tablesInfos.put(tableName, tableInfo); 403 404 StringBuilder sql = new StringBuilder(); 405 406 sql.append("CREATE TABLE "); 407 sql.append(tableNameNormalized); 408 sql.append(" (key_enum "); 409 sql.append(definition.getType().getId().equals(org.ametys.runtime.model.type.ModelItemTypeConstants.LONG_TYPE_ID) ? "INT" : "VARCHAR(250)"); 410 sql.append(createPrimaryKeyQuery()); 411 sql.append(createCommentQuery(tableName, "key_enum_" + definition.getName(), "Enumerator key")); 412 413 addColumn(sql, "value_enum_" + definition.getName(), tableName, null, "string"); 414 415 sql.append(") "); 416 sql.append(createEngineQuery()); 417 sql.append(createCommentQuery(tableName, null, "Enumerator table " + definition.getName() + " linked to the table " + tableParentName)); 418 419 tableInfo.addCreateQuery(sql.toString()); 420 421// String fkName = _normaliseNameComponent.normalizedColumnName(_mappingPolicy, columnName, tableParentName, _connection); 422// String fkTableName = _normaliseNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, tableName, _connection); 423// String fkColumnName = "key_enum"; 424// currentCreateTableSQLQuery.append(createForeignKeyQuery(fkName, fkTableName, fkColumnName)); 425 //TODO foreign key ?? 426 427 fillTableForEnumerator(definition, tableName); 428 } 429 430 /** 431 * Fill values for the enumerator table 432 * @param definition the attribute definition 433 * @param tableName the table name 434 */ 435 protected void fillTableForEnumerator(ElementDefinition definition, String tableName) 436 { 437 try 438 { 439 for (Entry<Object, I18nizableText> entry : ((Map<Object, I18nizableText>) definition.getEnumerator().getTypedEntries()).entrySet()) 440 { 441 String enumValue = _i18nTranslator.translate(entry.getValue(), DEFAULT_LANGUAGE_CODE_FOR_COMMENTS); 442 String enumKey = entry.getKey().toString(); 443 444 StringBuilder sql = new StringBuilder(); 445 sql.append("INSERT INTO "); 446 sql.append(_normalizeNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, tableName, _connection)); 447 sql.append(" VALUES ('"); 448 sql.append(_normalizeNameComponent.escapeValue(enumKey, _connection)); 449 sql.append("', '"); 450 sql.append(_normalizeNameComponent.escapeValue(enumValue, _connection)); 451 sql.append("')"); 452 453 _tablesInfos.get(tableName).addInsertQuery(sql.toString()); 454 } 455 } 456 catch (Exception e) 457 { 458 getLogger().warn(e.getMessage(), e); 459 } 460 } 461 462 /** 463 * Create the two table mapping (for table name and column name) 464 */ 465 protected void createMappingTables() 466 { 467 PreparedStatement stmt = null; 468 String mappingTableName = _sqlTablePrefix + ExportManager.MAPPING_TABLE_NAME; 469 String mappingColumnName = _sqlTablePrefix + ExportManager.MAPPING_COLUMN_NAME; 470 471 ExportTableInfo mappingTableInfo = new ExportTableInfo(mappingTableName); 472 mappingTableInfo.incrementNbColumns(3); 473 474 ExportTableInfo mappingColumnInfo = new ExportTableInfo(mappingColumnName); 475 mappingColumnInfo.incrementNbColumns(3); 476 477 String mappingTableNameNormalized = _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, "FULL", mappingTableName, _connection); 478 String mappingColumnNameNormalized = _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, "FULL", mappingColumnName, _connection); 479 480 _tablesInfos.put(mappingTableName, mappingTableInfo); 481 _tablesInfos.put(mappingColumnName, mappingColumnInfo); 482 483 StringBuilder createMappingTableSQLQuery = new StringBuilder(); 484 485 createMappingTableSQLQuery.append("CREATE TABLE "); 486 createMappingTableSQLQuery.append(mappingTableNameNormalized); 487 createMappingTableSQLQuery.append(" (id_table INT"); 488 createMappingTableSQLQuery.append(createPrimaryKeyQuery()); 489 createMappingTableSQLQuery.append(createCommentQuery(mappingTableName, "id_table", "Table name ID")); 490 createMappingTableSQLQuery.append(", real_name VARCHAR(512)"); 491 createMappingTableSQLQuery.append(createCommentQuery(mappingTableName, "real_name", "Real name")); 492 createMappingTableSQLQuery.append(", modified_name VARCHAR(512)"); 493 createMappingTableSQLQuery.append(createCommentQuery(mappingTableName, "modified_name", "Normalized name")); 494 495 createMappingTableSQLQuery.append(") "); 496 createMappingTableSQLQuery.append(createEngineQuery()); 497 498 String comment = "Mapping table between real name and normalized name."; 499 createMappingTableSQLQuery.append(createCommentQuery(mappingTableName, null, comment)); 500 501 try 502 { 503 _mappingTablesQueries.add(createMappingTableSQLQuery.toString()); 504 stmt = _connection.prepareStatement(createMappingTableSQLQuery.toString()); 505 stmt.execute(); 506 } 507 catch (SQLException e) 508 { 509 getLogger().error(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_ANALYZE_TABLE_CREATE_MAPPING_TABLE_ERROR")), e); 510 } 511 finally 512 { 513 ConnectionHelper.cleanup(stmt); 514 } 515 516 StringBuilder createMappingColumnSQLQuery = new StringBuilder(); 517 518 createMappingColumnSQLQuery.append("CREATE TABLE "); 519 createMappingColumnSQLQuery.append(mappingColumnNameNormalized); 520 createMappingColumnSQLQuery.append(" (id_table INT"); 521 createMappingColumnSQLQuery.append(createCommentQuery(mappingColumnName, "id_table", "Table name id")); 522 createMappingColumnSQLQuery.append(createForeignKeyQuery("id_table", _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, mappingTableName, _connection), "id_table")); 523 createMappingColumnSQLQuery.append(", real_name VARCHAR(512)"); 524 createMappingColumnSQLQuery.append(createCommentQuery(mappingColumnName, "real_name", "Real column name")); 525 createMappingColumnSQLQuery.append(", modified_name VARCHAR(512)"); 526 createMappingColumnSQLQuery.append(createCommentQuery(mappingColumnName, "modified_name", "Normalized column name")); 527 528 createMappingColumnSQLQuery.append(") "); 529 createMappingColumnSQLQuery.append(createEngineQuery()); 530 531 String commentColum = "Mapping table between real column name and normalized column name."; 532 createMappingColumnSQLQuery.append(createCommentQuery(mappingColumnName, null, commentColum)); 533 534 try 535 { 536 _mappingTablesQueries.add(createMappingColumnSQLQuery.toString()); 537 stmt = _connection.prepareStatement(createMappingColumnSQLQuery.toString()); 538 stmt.execute(); 539 } 540 catch (SQLException e) 541 { 542 getLogger().error(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_ANALYZE_TABLE_CREATE_MAPPING_COLUMN_ERROR")), e); 543 } 544 finally 545 { 546 ConnectionHelper.cleanup(stmt); 547 } 548 549 fillMappingTables(mappingTableName, mappingColumnName); 550 } 551 552 /** 553 * Fill the two mapping table (for table name and column name) 554 * @param mappingTableName the table mapping table name 555 * @param mappingColumnName the column mapping table name 556 */ 557 protected void fillMappingTables(String mappingTableName, String mappingColumnName) 558 { 559 HashMap<String, String> mappingTable = (HashMap<String, String>) _normalizeNameComponent.getMappingTableNameFromCache(); 560 HashMap<String, HashMap<String, String>> mappingColumn = (HashMap<String, HashMap<String, String>>) _normalizeNameComponent.getMappingTableColumnNameFromCache(); 561 562 PreparedStatement stmtTableName = null; 563 PreparedStatement stmtColumnName = null; 564 try 565 { 566 stmtTableName = getInsertPreparedStatementFromTableName(mappingTableName); 567 stmtColumnName = getInsertPreparedStatementFromTableName(mappingColumnName); 568 int i = 0; 569 for (Entry<String, String> entry : mappingTable.entrySet()) 570 { 571 String realName = entry.getKey(); 572 String modifiedName = entry.getValue(); 573 574 if (getLogger().isDebugEnabled()) 575 { 576 String tableName = _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, mappingTableName, _connection); 577 getLogger().debug("INSERT INTO {} VALUES ('{}', '{}', '{}')", tableName, i, realName, modifiedName); 578 } 579 580 stmtTableName.setInt(1, i); 581 stmtTableName.setString(2, realName); 582 stmtTableName.setString(3, modifiedName); 583 584 stmtTableName.addBatch(); 585 586 if (mappingColumn.containsKey(realName)) 587 { 588 for (Entry<String, String> entryCol : mappingColumn.get(realName).entrySet()) 589 { 590 String realNameCol = entryCol.getKey(); 591 String modifiedNameCol = entryCol.getValue(); 592 593 if (getLogger().isDebugEnabled()) 594 { 595 String tableName = _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, mappingTableName, _connection); 596 getLogger().debug("INSERT INTO {} VALUES ('{}', '{}', '{}')", tableName, i, realNameCol, modifiedNameCol); 597 } 598 599 stmtColumnName.setInt(1, i); 600 stmtColumnName.setString(2, realNameCol); 601 stmtColumnName.setString(3, modifiedNameCol); 602 603 stmtColumnName.addBatch(); 604 605 } 606 } 607 i++; 608 } 609 610 stmtTableName.executeBatch(); 611 stmtColumnName.executeBatch(); 612 } 613 catch (SQLException e) 614 { 615 getLogger().error(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_ANALYZE_TABLE_FILL_MAPPING_ERROR")), e); 616 } 617 finally 618 { 619 ConnectionHelper.cleanup(stmtTableName); 620 ConnectionHelper.cleanup(stmtColumnName); 621 } 622 } 623 624 /** 625 * Add all the column for each attribute in the {@link ModelItemContainer}. 626 * @param modelItemContainer the attribute definitions 627 * @param currentCreateTableSQLQuery the current SQL create table query 628 * @param tableName the table name 629 * @param columnNamePrefix the column namePrefix 630 */ 631 protected void addColumnForContainer(ModelItemContainer modelItemContainer, StringBuilder currentCreateTableSQLQuery, String tableName, String columnNamePrefix) 632 { 633 for (ModelItem modelItem : modelItemContainer.getModelItems()) 634 { 635 String name = modelItem.getName(); 636 String columnName = columnNamePrefix + name; 637 if (modelItem instanceof ElementDefinition) 638 { 639 // simple element 640 ElementDefinition definition = (ElementDefinition) modelItem; 641 if (definition.isMultiple()) 642 { 643 if (_exportNoMultiValuedTable) 644 { 645 String comment = _i18nTranslator.translate(definition.getLabel(), DEFAULT_LANGUAGE_CODE_FOR_COMMENTS) + ": " + _i18nTranslator.translate(definition.getDescription(), DEFAULT_LANGUAGE_CODE_FOR_COMMENTS); 646 addColumn(currentCreateTableSQLQuery, columnName, tableName, comment, "string"); 647 } 648 else 649 { 650 createQueryForMultipleAttribute(definition, tableName, tableName + "_" + columnName); 651 } 652 } 653 else 654 { 655 addColumnForSingleAttribute(definition, currentCreateTableSQLQuery, tableName, columnName); 656 657 if (definition.getEnumerator() != null) 658 { 659 createTableForEnumerator(definition, tableName, tableName + "_" + name, columnName, currentCreateTableSQLQuery); 660 } 661 } 662 } 663 else if (modelItem instanceof CompositeDefinition) 664 { 665 // composite 666 addColumnForContainer((CompositeDefinition) modelItem, currentCreateTableSQLQuery, tableName, columnName + "_"); 667 } 668 else if (modelItem instanceof RepeaterDefinition) 669 { 670 // repeater 671 String commentTable = "Repeater " + _normalizeNameComponent.normalizedColumnName(_mappingPolicy, columnName, tableName, _reservedWords, _connection) + " linked to the table " + _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, tableName, _connection); 672 createQueriesForTableCreation((RepeaterDefinition) modelItem, tableName + "_" + columnName, tableName, commentTable, true); 673 } 674 } 675 } 676 677 /** 678 * Add column for single attribute 679 * @param definition the attribute definition 680 * @param currentCreateTableSQLQuery the current SQL create table query 681 * @param tableName the table name 682 * @param columnName the column name 683 */ 684 protected void addColumnForSingleAttribute(ElementDefinition definition, StringBuilder currentCreateTableSQLQuery, String tableName, String columnName) 685 { 686 String comment = _i18nTranslator.translate(definition.getLabel(), DEFAULT_LANGUAGE_CODE_FOR_COMMENTS) + ": " + _i18nTranslator.translate(definition.getDescription(), DEFAULT_LANGUAGE_CODE_FOR_COMMENTS); 687 688 String type = definition.getType().getId(); 689 if (type.equals(ModelItemTypeConstants.USER_ELEMENT_TYPE_ID)) 690 { 691 addColumn(currentCreateTableSQLQuery, columnName + "_login", tableName, "User login", "string"); 692 addColumn(currentCreateTableSQLQuery, columnName + "_population", tableName, "User population", "string"); 693 } 694 else if (type.equals(ModelItemTypeConstants.GEOCODE_ELEMENT_TYPE_ID)) 695 { 696 addColumn(currentCreateTableSQLQuery, columnName + "_longitude", tableName, "Longitude of " + columnName, "double"); 697 addColumn(currentCreateTableSQLQuery, columnName + "_latitude", tableName, "Latitude type of " + columnName, "double"); 698 } 699 else if (type.equals(ModelItemTypeConstants.BINARY_ELEMENT_TYPE_ID) || type.equals(ModelItemTypeConstants.FILE_ELEMENT_TYPE_ID)) 700 { 701 String actualColumnName = addColumn(currentCreateTableSQLQuery, columnName, tableName, comment, "string"); 702 addColumn(currentCreateTableSQLQuery, actualColumnName + "_data", tableName, "Data of " + columnName, "binary"); 703 addColumn(currentCreateTableSQLQuery, actualColumnName + "_mimetype", tableName, "Mime type of " + columnName, "short-string"); 704 addColumn(currentCreateTableSQLQuery, actualColumnName + "_size", tableName, "Size of " + columnName, "long"); 705 addColumn(currentCreateTableSQLQuery, actualColumnName + "_lastmodified", tableName, "Last modification date of " + columnName, "datetime"); 706 } 707 else if (type.equals(ModelItemTypeConstants.MULTILINGUAL_STRING_ELEMENT_TYPE_ID)) 708 { 709 for (String lang : _languageManager.getAvailableLanguages().keySet()) 710 { 711 addColumn(currentCreateTableSQLQuery, columnName + "_" + lang, tableName, "Value of " + columnName + " for lang " + lang, "string"); 712 } 713 } 714 else 715 { 716 addColumn(currentCreateTableSQLQuery, columnName, tableName, comment, type); 717 } 718 } 719 720 /** 721 * Add a column 722 * @param currentCreateTableSQLQuery the current SQL create table query 723 * @param tableName the table name 724 * @param columnName the desired column name 725 * @param comment the column comment 726 * @param type the column type 727 * @return the actual column name, after normalization of the desired one 728 */ 729 protected String addColumn(StringBuilder currentCreateTableSQLQuery, String columnName, String tableName, String comment, String type) 730 { 731 String actualColumnName = _normalizeNameComponent.normalizedColumnName(_mappingPolicy, columnName, tableName, _reservedWords, _connection); 732 733 currentCreateTableSQLQuery.append(", ").append(actualColumnName); 734 currentCreateTableSQLQuery.append(" ").append(convertTypeToSql(type)); 735 736 if (comment != null) 737 { 738 currentCreateTableSQLQuery.append(createCommentQuery(tableName, columnName, comment)); 739 } 740 741 ExportTableInfo tableInfo = _tablesInfos.get(tableName); 742 tableInfo.incrementNbColumns(); 743 744 return actualColumnName; 745 } 746 747 /** 748 * Create table for multiple attribute 749 * @param definition the attribute definition 750 * @param tableParentName the name of the table for the attribute's container 751 * @param tableName the table name 752 */ 753 protected void createQueryForMultipleAttribute(ElementDefinition definition, String tableParentName, String tableName) 754 { 755 ExportTableInfo tableInfo = new ExportTableInfo(tableName); 756 tableInfo.incrementNbColumns(); 757 758 String normalizeTableName = _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, tableName, _connection); 759 _tablesInfos.put(tableName, tableInfo); 760 761 String normalizedColumnName = _normalizeNameComponent.normalizedColumnName(_mappingPolicy, COLUMN_PARENT_TABLE_PREFIX + tableParentName, tableName, _reservedWords, _connection); 762 763 StringBuilder currentCreateTableSQLQuery = new StringBuilder(); 764 currentCreateTableSQLQuery.append("CREATE TABLE "); 765 currentCreateTableSQLQuery.append(normalizeTableName); 766 currentCreateTableSQLQuery.append(" ("); 767 currentCreateTableSQLQuery.append(normalizedColumnName); 768 currentCreateTableSQLQuery.append(" VARCHAR(245)"); 769 currentCreateTableSQLQuery.append(createCommentQuery(tableName, COLUMN_PARENT_TABLE_PREFIX + tableParentName, "Parent ID of the multiple attribute")); 770 771 String fkName = normalizedColumnName; 772 String fkTableName = _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, tableParentName, _connection); 773 String fkColumnName = _normalizeNameComponent.normalizedColumnName(_mappingPolicy, "id_" + tableParentName, tableParentName, _reservedWords, _connection); 774 currentCreateTableSQLQuery.append(createForeignKeyQuery(fkName, fkTableName, fkColumnName)); 775 776 addColumnForSingleAttribute(definition, currentCreateTableSQLQuery, tableName, definition.getName()); 777 778 currentCreateTableSQLQuery.append(", "); 779 addSortColumn(currentCreateTableSQLQuery, tableName); 780 781 String primaryKey = "pk_" + _pkIndice; 782 _pkIndice++; 783 784 currentCreateTableSQLQuery.append(", CONSTRAINT "); 785 currentCreateTableSQLQuery.append(primaryKey); 786 currentCreateTableSQLQuery.append(" PRIMARY KEY ("); 787 currentCreateTableSQLQuery.append(normalizedColumnName); 788 currentCreateTableSQLQuery.append(", position)"); 789 currentCreateTableSQLQuery.append(") "); 790 currentCreateTableSQLQuery.append(createEngineQuery()); 791 792 String comment = "Multiple attribute " + definition.getName() + " linked to the table" + _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, tableParentName, _connection); 793 currentCreateTableSQLQuery.append(createCommentQuery(tableName, null, comment)); 794 795 tableInfo.addCreateQuery(currentCreateTableSQLQuery.toString()); 796 } 797 798 /** 799 * Add additionnal data for content (title, type, language, creator, creationDate, ....) 800 * @param contentType the model 801 * @param currentCreateTableSQLQuery the current SQL create table query 802 * @param tableName the table name 803 */ 804 protected void addAdditionalData(ContentType contentType, StringBuilder currentCreateTableSQLQuery, String tableName) 805 { 806 addColumn(currentCreateTableSQLQuery, "content_title", tableName, "Content title", "string"); 807 addColumn(currentCreateTableSQLQuery, "content_type", tableName, "Content type", "string"); 808 addColumn(currentCreateTableSQLQuery, "content_language", tableName, "Content lang", "string"); 809 addColumn(currentCreateTableSQLQuery, "content_creator", tableName, "Content author", "string"); 810 addColumn(currentCreateTableSQLQuery, "content_creationDate", tableName, "Content creation date", "datetime"); 811 addColumn(currentCreateTableSQLQuery, "content_lastContributor", tableName, "Content last contributor", "string"); 812 addColumn(currentCreateTableSQLQuery, "content_lastModificationDate", tableName, "Content last modification date", "datetime"); 813 addColumn(currentCreateTableSQLQuery, "content_lastValidationDate", tableName, "Content last validation date", "datetime"); 814 addColumn(currentCreateTableSQLQuery, "content_lastMajorValidationDate", tableName, "Content last major validation date", "datetime"); 815 } 816 817 /** 818 * Add a column to sort 819 * @param currentCreateTableSQLQuery the current SQL create table query 820 * @param tableName the table name 821 */ 822 protected void addSortColumn(StringBuilder currentCreateTableSQLQuery, String tableName) 823 { 824 currentCreateTableSQLQuery.append("position INT"); 825 currentCreateTableSQLQuery.append(createCommentQuery(tableName, "position", "Order of the row")); 826 827 ExportTableInfo tableInfo = _tablesInfos.get(tableName); 828 tableInfo.incrementNbColumns(); 829 } 830 831 /** 832 * Add an id column which refer to another table 833 * @param currentCreateTableSQLQuery the current SQL create table query 834 * @param tableParentName the table parent name 835 * @param tableName the table name 836 */ 837 protected void addColumnParentId(StringBuilder currentCreateTableSQLQuery, String tableParentName, String tableName) 838 { 839 currentCreateTableSQLQuery.append(_normalizeNameComponent.normalizedColumnName(_mappingPolicy, COLUMN_PARENT_TABLE_PREFIX + tableParentName, tableName, _reservedWords, _connection)); 840 currentCreateTableSQLQuery.append(" VARCHAR(250)"); //TODO NOT NULL 841 currentCreateTableSQLQuery.append(createCommentQuery(tableName, COLUMN_PARENT_TABLE_PREFIX + tableParentName, "Parent table ID " + tableParentName)); 842 843 String fkName = _normalizeNameComponent.normalizedColumnName(_mappingPolicy, COLUMN_PARENT_TABLE_PREFIX + tableParentName, tableName, _reservedWords, _connection); 844 String fkTableName = _normalizeNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, tableParentName, _connection); 845 String fkColumnName = _normalizeNameComponent.normalizedColumnName(_mappingPolicy, "id_" + tableParentName, tableParentName, _reservedWords, _connection); 846 currentCreateTableSQLQuery.append(createForeignKeyQuery(fkName, fkTableName, fkColumnName)); 847 848 ExportTableInfo tableInfo = _tablesInfos.get(tableName); 849 tableInfo.incrementNbColumns(); 850 } 851 852 /** 853 * Create the query to add comment to a table or a column 854 * @param table the table name 855 * @param column the column name 856 * @param comments the comments 857 * @return the query to add comment to a table or a column 858 */ 859 protected String createCommentQuery(String table, String column, String comments) 860 { 861 String normalizedComment = _normalizeNameComponent.normalizedComment(comments, StringUtils.isEmpty(column) ? _commentTableMaxLength : _commentColumnMaxLength, _connection); 862 863 String commentSql = ""; 864 if (_databaseType.equals(ConnectionHelper.DATABASE_MYSQL)) 865 { 866 commentSql = " COMMENT '" + normalizedComment + "'"; 867 } 868 else if (_databaseType.equals(ConnectionHelper.DATABASE_ORACLE)) //TODO 869 { 870 /*if (StringUtils.isNotEmpty(table)) 871 { 872 if (StringUtils.isEmpty(column)) 873 { 874// _tablesInfos.get(table).addCommentQuery("COMMENT ON TABLE " + _normaliseNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, table, _connection) + " IS '" + normalizedComment + "'"); 875 } 876 else 877 { 878// _tablesInfos.get(table).addCommentQuery("COMMENT ON COLUMN " + _normaliseNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, table, _connection) + "." + _normaliseNameComponent.normalizedColumnName(_mappingPolicy, column, table, _connection) + " IS '" + normalizedComment + "'"); 879 } 880 }*/ 881 } 882 883 return commentSql; 884 } 885 886 /** 887 * Create the query to add foreign key 888 * @param fkName the foreign key name 889 * @param tableName the table name 890 * @param columnName the column name 891 * @return the query to add comment to a table or a column 892 */ 893 protected String createForeignKeyQuery(String fkName, String tableName, String columnName) 894 { 895 StringBuilder foreignKeySQLQuery = new StringBuilder(); 896 foreignKeySQLQuery.append(", CONSTRAINT fk_"); 897 foreignKeySQLQuery.append(_fkIndice); 898 _fkIndice++; 899 900 foreignKeySQLQuery.append(" FOREIGN KEY ("); 901 foreignKeySQLQuery.append(fkName); 902 foreignKeySQLQuery.append(")"); 903 foreignKeySQLQuery.append(" REFERENCES "); 904 foreignKeySQLQuery.append(tableName); 905 foreignKeySQLQuery.append(" ("); 906 foreignKeySQLQuery.append(columnName); 907 foreignKeySQLQuery.append(")"); 908 909 return foreignKeySQLQuery.toString(); 910 } 911 912 /** 913 * Create the query to add engine 914 * @return the query to add engine 915 */ 916 protected String createEngineQuery() 917 { 918 if (_databaseType.equals(ConnectionHelper.DATABASE_MYSQL)) 919 { 920 return "ENGINE=" + MYSQL_CONTENT_EXPORT_ENGINE + " ROW_FORMAT=COMPRESSED DEFAULT CHARACTER SET " + MYSQL_CONTENT_EXPORT_CHARSET + " "; 921 } 922 else if (_databaseType.equals(ConnectionHelper.DATABASE_ORACLE)) 923 { 924 return "STORAGE (INITIAL 8K NEXT 8K)"; 925 } 926 927 return ""; 928 } 929 930 /** 931 * Create the query to add primary key 932 * @return the query to add primary key 933 */ 934 protected String createPrimaryKeyQuery() 935 { 936 return " PRIMARY KEY NOT NULL"; 937 } 938 939 /** 940 * Return the sql type corresponding to the attribute and the database type 941 * @param type the attribute's type 942 * @return the sql type 943 */ 944 protected String convertTypeToSql(String type) 945 { 946 String sqlType = ""; 947 948 if (_databaseType.equals(ConnectionHelper.DATABASE_MYSQL)) 949 { 950 sqlType = _mapping.get("mysql").get(type); 951 } 952 else if (_databaseType.equals(ConnectionHelper.DATABASE_ORACLE)) 953 { 954 sqlType = _mapping.get("oracle").get(type); 955 } 956 957 return sqlType; 958 } 959 960 /** 961 * Execute SQL queries 962 * @throws SQLException if a sql error occurred 963 * @throws IOException if an IO error occurred 964 */ 965 protected void executeQueries() throws SQLException, IOException 966 { 967 int nbTotalTable = _getNbTable(); 968 969 boolean isInfoEnabled = getLogger().isInfoEnabled(); 970 if (isInfoEnabled) 971 { 972 List<String> i18nParams = new ArrayList<>(); 973 i18nParams.add(String.valueOf(nbTotalTable)); 974 getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_ANALYZE_TABLE_CREATE_BEGINNING", i18nParams))); 975 } 976 977 int nbTableCreated = 0; 978 int limitPourcentReport = 10; 979 try 980 { 981 for (Entry<String, ExportTableInfo> entry : _tablesInfos.entrySet()) 982 { 983 ExportTableInfo tableInfo = entry.getValue(); 984 985 List<String> queries = tableInfo.getCreateQueries(); 986 _executeQueries(queries); 987 nbTableCreated += queries.size(); 988 989 int pourcent = nbTableCreated * 100 / nbTotalTable; 990 if (pourcent >= limitPourcentReport) 991 { 992 if (isInfoEnabled) 993 { 994 List<String> i18nParams = new ArrayList<>(); 995 i18nParams.add(String.valueOf(limitPourcentReport)); 996 getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_ANALYZE_TABLE_CREATE_ADVANCE", i18nParams))); 997 } 998 limitPourcentReport += 10; 999 } 1000 1001 _executeQueries(tableInfo.getCommentQueries()); 1002 _executeQueries(tableInfo.getInsertQueries()); 1003 } 1004 } 1005 catch (IOException e) 1006 { 1007 getLogger().error(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_ANALYZE_TABLE_GET_FILE_ERROR")), e); 1008 } 1009 finally 1010 { 1011 if (isInfoEnabled) 1012 { 1013 List<String> i18nParams = new ArrayList<>(); 1014 i18nParams.add(String.valueOf(nbTableCreated)); 1015 getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_ANALYZE_TABLE_CREATE_FINISH", i18nParams))); 1016 } 1017 } 1018 } 1019 1020 private int _getNbTable() 1021 { 1022 int nbTable = 0; 1023 for (Entry<String, ExportTableInfo> entry : _tablesInfos.entrySet()) 1024 { 1025 ExportTableInfo tableInfo = entry.getValue(); 1026 1027 List<String> listQuery = tableInfo.getCreateQueries(); 1028 nbTable += listQuery.size(); 1029 } 1030 1031 return nbTable; 1032 } 1033 1034 /** 1035 * Execute query list 1036 * @param listQuery the list of query to execute 1037 * @throws SQLException if a sql error occurred 1038 * @throws IOException if an IO error occurred 1039 */ 1040 protected void _executeQueries(List<String> listQuery) throws SQLException, IOException 1041 { 1042 for (String query : listQuery) 1043 { 1044 getLogger().debug(query); 1045 1046 PreparedStatement stmt = null; 1047 try 1048 { 1049 stmt = _connection.prepareStatement(query); 1050 stmt.execute(); 1051 } 1052 catch (SQLException e) 1053 { 1054 throw new SQLException("The SQL query failed : " + query, e); 1055 } 1056 finally 1057 { 1058 // Close the connection resources 1059 ConnectionHelper.cleanup(stmt); 1060 } 1061 } 1062 } 1063 1064 /** 1065 * Prepare INSERT statement 1066 * @param tableName the table name 1067 * @return the INSERT preparedStatement 1068 * @throws SQLException if a sql error occurred 1069 */ 1070 protected PreparedStatement getInsertPreparedStatementFromTableName(String tableName) throws SQLException 1071 { 1072 StringBuilder sql = new StringBuilder(); 1073 sql.append("INSERT INTO "); 1074 sql.append(_normalizeNameComponent.normalizedTableName(_sqlTablePrefix, _mappingPolicy, tableName, _connection)); 1075 sql.append(" VALUES ( ?"); 1076 1077 ExportTableInfo tableInfo = _tablesInfos.get(tableName); 1078 1079 for (int i = 1; i < tableInfo.getNbColumns(); i++) 1080 { 1081 sql.append(", ?"); 1082 } 1083 sql.append(")"); 1084 1085 PreparedStatement stmt = _connection.prepareStatement(sql.toString()); 1086 return stmt; 1087 } 1088}