1 10 package org.mmbase.storage.implementation.database; 11 12 import java.sql.SQLException ; 13 import java.sql.Statement ; 14 import java.util.*; 15 16 import org.mmbase.bridge.Field; 17 import org.mmbase.bridge.NodeManager; 18 import org.mmbase.core.CoreField; 19 import org.mmbase.module.core.MMObjectBuilder; 20 import org.mmbase.module.core.MMObjectNode; 21 import org.mmbase.storage.StorageError; 22 import org.mmbase.storage.StorageException; 23 import org.mmbase.storage.util.Index; 24 import org.mmbase.storage.util.Scheme; 25 import org.mmbase.util.logging.Logger; 26 import org.mmbase.util.logging.Logging; 27 28 34 public class ViewDatabaseStorageManager extends DatabaseStorageManager { 35 36 private static final Logger log = Logging.getLoggerInstance(ViewDatabaseStorageManager.class); 37 38 44 public boolean exists() throws StorageException { 45 return viewExists(factory.getMMBase().getRootBuilder()); 46 } 47 48 54 public boolean exists(MMObjectBuilder builder) throws StorageException { 55 return viewExists(builder); 56 } 57 58 62 public void create() throws StorageException { 63 if(!viewExists(factory.getMMBase().getRootBuilder())) { 64 viewCreate(factory.getMMBase().getRootBuilder()); 65 createSequence(); 66 } 67 } 68 69 74 public void create(MMObjectBuilder builder) throws StorageException { 75 if(!viewExists(builder)){ 76 viewCreate(builder); 77 } 78 } 79 80 public void create(final MMObjectNode node, final MMObjectBuilder builder) throws StorageException { 81 boolean localTransaction = !inTransaction; 82 if (localTransaction) { 83 beginTransaction(); 84 } 85 try { 86 if (factory.hasOption("database-supports-insert-triggers")) { 87 super.create(node, builder); 89 } else { 90 java.util.Iterator i = builder.getAncestors().iterator(); 92 while(i.hasNext()) { 93 MMObjectBuilder b = (MMObjectBuilder) i.next(); 94 createObject(node, b); 95 } 96 createObject(node, builder); 97 } 98 if (localTransaction) { 99 commit(); 100 } 101 } catch (StorageException se) { 102 if (localTransaction && inTransaction) rollback(); 103 throw se; 104 } 105 } 106 107 116 protected void createObject(MMObjectNode node, MMObjectBuilder builder) throws StorageException { 117 List createFields = new ArrayList(); 118 List builderFields = builder.getFields(NodeManager.ORDER_CREATE); 119 for (Iterator f = builderFields.iterator(); f.hasNext();) { 120 CoreField field = (CoreField)f.next(); 121 if (field.inStorage() && (!this.isInheritedField(field) || field.getName().equals(this.getNumberField().getName()))) { 122 createFields.add(field); 123 } 124 } 125 String tablename = getTableName(builder); 126 create(node, createFields, tablename); 127 } 128 129 135 public void change(MMObjectNode node, MMObjectBuilder builder) throws StorageException { 136 boolean localTransaction = !inTransaction; 137 if (localTransaction) { 138 beginTransaction(); 139 } 140 try { 141 if (factory.hasOption("database-supports-update-triggers")) { 142 super.change(node, builder); 143 } else { 144 do { 145 changeObject(node,builder); 146 builder = builder.getParentBuilder(); 147 } while (builder!=null); 148 } 149 if (localTransaction) { 150 commit(); 151 } 152 } catch (StorageException se) { 153 if (localTransaction && inTransaction) rollback(); 154 throw se; 155 } 156 } 157 158 private void changeObject(MMObjectNode node, MMObjectBuilder builder) { 159 List changeFields = new ArrayList(); 160 Collection fieldNames = node.getChanged(); 162 for (Iterator f = fieldNames.iterator(); f.hasNext();) { 163 String key = (String )f.next(); 164 CoreField field = builder.getField(key); 165 if ((field != null) && field.inStorage() && !isInheritedField(field)) { 166 changeFields.add(field); 167 } 168 } 169 change(node, builder, getTableName(builder), changeFields); 170 } 171 172 178 public void delete(MMObjectNode node, MMObjectBuilder builder) throws StorageException { 179 boolean localTransaction = !inTransaction; 180 if (localTransaction) { 181 beginTransaction(); 182 } 183 184 try { 185 if (factory.hasOption("database-supports-delete-triggers")) { 186 super.delete(node, builder); 187 } else { 188 do { 189 deleteObject(node, builder); 190 builder = builder.getParentBuilder(); 191 } while (builder!=null); 192 } 193 if (localTransaction) { 194 commit(); 195 } 196 } catch (StorageException se) { 197 if (localTransaction && inTransaction) rollback(); 198 throw se; 199 } 200 } 201 202 private void deleteObject(MMObjectNode node, MMObjectBuilder builder) { 203 List blobFileField = new ArrayList(); 204 List builderFields = builder.getFields(NodeManager.ORDER_CREATE); 205 for (Iterator f = builderFields.iterator(); f.hasNext();) { 206 CoreField field = (CoreField)f.next(); 207 if (field.inStorage() && !isInheritedField(field)) { 208 if (factory.hasOption(Attributes.STORES_BINARY_AS_FILE) && (field.getType() == Field.TYPE_BINARY)) { 209 blobFileField.add(field); 210 } 211 } 212 } 213 String tablename = getTableName(builder); 214 super.delete(node, builder, blobFileField, tablename); 215 } 216 217 public String getFieldName(CoreField field) { 218 return (String )factory.getStorageIdentifier(field); 219 } 220 221 public boolean isInheritedField(CoreField field) { 222 MMObjectBuilder inheritedBuilder = field.getParent().getParentBuilder(); 223 if(inheritedBuilder == null) { 224 return false; 226 } 227 return (inheritedBuilder.getField(field.getName()) != null); 228 } 229 230 public CoreField getNumberField() { 231 return factory.getMMBase().getRootBuilder().getField("number"); 232 } 233 234 public String getTableName(MMObjectBuilder builder) { 235 if (builder.getParentBuilder() == null) { 236 return (String ) factory.getStorageIdentifier(builder); 237 } else { 238 return getTableName((String ) factory.getStorageIdentifier(builder)); 239 } 240 } 241 242 public String getTableName(String viewname) { 243 String id = (String )factory.getStorageIdentifier(viewname + "_table"); 244 String toCase = (String )factory.getAttribute(org.mmbase.storage.Attributes.STORAGE_IDENTIFIER_CASE); 245 if ("lower".equals(toCase)) { 246 return id.toLowerCase(); 247 } else if ("upper".equals(toCase)) { 248 return id.toUpperCase(); 249 } else { 250 return id; 251 } 252 } 253 254 public String getViewName(MMObjectBuilder builder) { 255 return getViewName((String )factory.getStorageIdentifier(builder)); 256 } 257 public String getViewName(String viewname) { 258 return viewname; 259 } 260 261 265 protected void create(Index index) throws StorageException { 266 for (int i=0; i<index.size(); i++) { 267 CoreField f = (CoreField)index.get(i); 268 if (!isPartOfBuilderDefinition(f)) { 269 return; 270 } 271 } 272 273 super.createIndex(index, getTableName(index.getParent())); 274 } 275 276 protected boolean exists(Index index) throws StorageException { 277 return super.exists(index, getTableName(index.getParent())); 278 } 279 280 public boolean viewExists(MMObjectBuilder builder) { 281 return exists(getViewName(builder)); 282 } 283 284 public boolean viewCreate(MMObjectBuilder builder) { 285 MMObjectBuilder inheritedBuilder = builder.getParentBuilder(); 286 if(inheritedBuilder != null) { 288 if(!viewExists(inheritedBuilder)) { 289 if(!viewCreate(inheritedBuilder)) { 291 return false; 293 } 294 } 295 } 296 String tablename = getTableName(builder); 297 List fields = builder.getFields(NodeManager.ORDER_CREATE); 298 299 if (!super.exists(getTableName(builder))) { 300 List tableFields = new ArrayList(); 301 for (Iterator f = fields.iterator(); f.hasNext();) { 302 CoreField field = (CoreField)f.next(); 303 if (isPartOfBuilderDefinition(field) || field.getName().equals(getNumberField().getName())) { 305 tableFields.add(field); 306 } 307 } 308 createTable(builder, tableFields, tablename); 310 311 } 314 315 if (builder.getParentBuilder() != null) { 316 createView(builder, inheritedBuilder, fields, tablename); 317 } 318 return true; 319 } 320 321 private void createView(MMObjectBuilder builder, MMObjectBuilder inheritedBuilder, List fields, String tablename) throws StorageError { 322 log.debug("Creating a view for " + builder); 323 Scheme viewScheme = factory.getScheme(Schemes.CREATE_VIEW, Schemes.CREATE_VIEW_DEFAULT); 324 Scheme createInsertTriggerScheme = null; 325 Scheme createDeleteTriggerScheme = null; 326 Scheme createUpdateTriggerScheme = null; 327 if (factory.hasOption("database-supports-insert-triggers")) { 328 createInsertTriggerScheme = factory.getScheme(Schemes.CREATE_INSERT_TRIGGER, Schemes.CREATE_INSERT_TRIGGER_DEFAULT); 329 if (createInsertTriggerScheme == null) { 330 log.warn("Database supports insert-triggers, but no trigger scheme defined! Ignoring insert-trigger!!"); 331 } 332 } 333 if (factory.hasOption("database-supports-delete-triggers")) { 334 createDeleteTriggerScheme = factory.getScheme(Schemes.CREATE_DELETE_TRIGGER, Schemes.CREATE_DELETE_TRIGGER_DEFAULT); 335 if (createDeleteTriggerScheme == null) { 336 log.warn("Database supports delete-triggers, but no trigger scheme defined! Ignoring delete-trigger!!"); 337 } 338 } 339 if (factory.hasOption("database-supports-update-triggers")) { 340 createUpdateTriggerScheme = factory.getScheme(Schemes.CREATE_UPDATE_TRIGGER, Schemes.CREATE_UPDATE_TRIGGER_DEFAULT); 341 if (createUpdateTriggerScheme == null) { 342 log.warn("Database supports update-triggers, but no trigger scheme defined! Ignoring update-trigger!!"); 343 } 344 } 345 346 String viewname = getViewName(builder); 347 348 StringBuffer createViewFields = new StringBuffer (); 349 for (Iterator f = fields.iterator(); f.hasNext();) { 350 CoreField field = (CoreField)f.next(); 351 if (field.inStorage() && (field.getType() != Field.TYPE_BINARY || !factory.hasOption(Attributes.STORES_BINARY_AS_FILE))) { 352 if (createViewFields.length() > 0) { 353 createViewFields.append(", "); 354 } 355 createViewFields.append(getFieldName(field)); 356 } 357 } 358 359 StringBuffer createTableFields = new StringBuffer (); 360 Vector myFieldNames = new Vector(); 361 Vector parentFieldNames = new Vector(); 362 363 for (Iterator f = fields.iterator(); f.hasNext();) { 364 CoreField field = (CoreField)f.next(); 365 if (field.inStorage() && (field.getType() != Field.TYPE_BINARY || !factory.hasOption(Attributes.STORES_BINARY_AS_FILE))) { 366 367 if (createTableFields.length() > 0) { 368 createTableFields.append(", "); 369 } 370 if(isInheritedField(field)) { 371 if(inheritedBuilder == null) 372 throw new StorageError("Cannot have a inherited field while we dont extend inherit from a builder!"); 373 createTableFields.append(getViewName(inheritedBuilder) + "." + getFieldName(field)); 374 parentFieldNames.add(getFieldName(field)); 375 } else { 376 createTableFields.append(tablename + "." + getFieldName(field)); 377 myFieldNames.add(getFieldName(field)); 378 } 379 380 if (isInheritedField(field) && field.getName().equals(getNumberField().getName())) { 381 myFieldNames.add(getFieldName(field)); 382 } 383 } 384 } 385 386 String query = ""; 387 try { 388 getActiveConnection(); 389 query = viewScheme.format(new Object [] { this, viewname, tablename, createViewFields.toString(), createTableFields.toString(), getFieldName(getNumberField()), inheritedBuilder, factory.getDatabaseName() }); 391 if (factory.hasOption(Attributes.REMOVE_EMPTY_DEFINITIONS)) { 394 query = query.replaceAll("\\(\\s*\\)", ""); 395 } 396 397 Statement s = activeConnection.createStatement(); 398 long startTime = getLogStartTime(); 399 s.executeUpdate(query); 400 s.close(); 401 logQuery(query, startTime); 402 403 if (createInsertTriggerScheme != null) { 404 StringBuffer myFields = new StringBuffer (); 407 StringBuffer myValues = new StringBuffer (); 408 StringBuffer parentFields = new StringBuffer (); 409 StringBuffer parentValues = new StringBuffer (); 410 for (int i=0; i<myFieldNames.size(); i++) { 411 if (i > 0) { 412 myFields.append(", "); 413 myValues.append(", "); 414 } 415 myFields.append(myFieldNames.get(i)); 416 myValues.append(":NEW." + myFieldNames.get(i)); 417 } 418 for (int i=0; i<parentFieldNames.size(); i++) { 419 if (i > 0) { 420 parentFields.append(", "); 421 parentValues.append(", "); 422 } 423 parentFields.append(parentFieldNames.get(i)); 424 parentValues.append(":NEW." + parentFieldNames.get(i)); 425 } 426 Object triggerName = factory.getStorageIdentifier(viewname + "_INSERT"); 427 query = createInsertTriggerScheme.format(new Object []{this, viewname, tablename, inheritedBuilder, myFields.toString(), myValues.toString(), parentFields.toString(), parentValues.toString(), triggerName}); 428 429 if (factory.hasOption(Attributes.REMOVE_EMPTY_DEFINITIONS)) { 430 query = query.replaceAll("\\(\\s*\\)", ""); 431 } 432 433 s = activeConnection.createStatement(); 434 long startTime2 = getLogStartTime(); 435 s.executeUpdate(query); 436 s.close(); 437 logQuery(query, startTime2); 438 } 439 440 if (createDeleteTriggerScheme != null) { 441 Object triggerName = factory.getStorageIdentifier(viewname + "_DELETE"); 442 query = createDeleteTriggerScheme.format(new Object []{this, viewname, tablename, inheritedBuilder, getFieldName(getNumberField()), triggerName}); 443 if (factory.hasOption(Attributes.REMOVE_EMPTY_DEFINITIONS)) { 444 query = query.replaceAll("\\(\\s*\\)", ""); 445 } 446 447 s = activeConnection.createStatement(); 448 long startTime2 = getLogStartTime(); 449 s.executeUpdate(query); 450 s.close(); 451 logQuery(query, startTime2); 452 } 453 454 if (createUpdateTriggerScheme != null) { 455 StringBuffer myAssignments = new StringBuffer (); 456 StringBuffer parentAssignments = new StringBuffer (); 457 for (int i=0; i<myFieldNames.size(); i++) { 458 if (i > 0) { 459 myAssignments.append(", "); 460 } 461 myAssignments.append(myFieldNames.get(i)); 462 myAssignments.append(" = :NEW."); 463 myAssignments.append(myFieldNames.get(i)); 464 } 465 for (int i=0; i<parentFieldNames.size(); i++) { 466 if (i > 0) { 467 parentAssignments.append(", "); 468 } 469 parentAssignments.append(parentFieldNames.get(i)); 470 parentAssignments.append(" = :NEW."); 471 parentAssignments.append(parentFieldNames.get(i)); 472 } 473 Object triggerName = factory.getStorageIdentifier(viewname + "_UPDATE"); 474 query = createUpdateTriggerScheme.format(new Object []{this, viewname, tablename, inheritedBuilder, myAssignments.toString(), parentAssignments.toString(), getFieldName(getNumberField()), triggerName}); 475 476 if (factory.hasOption(Attributes.REMOVE_EMPTY_DEFINITIONS)) { 477 query = query.replaceAll("\\(\\s*\\)", ""); 478 } 479 480 s = activeConnection.createStatement(); 481 long startTime2 = getLogStartTime(); 482 s.executeUpdate(query); 483 s.close(); 484 logQuery(query, startTime2); 485 } 486 487 tableNameCache.add(viewname.toUpperCase()); 488 } catch (SQLException se) { 489 throw new StorageException(se.getMessage() + " in query:" + query, se); 490 } finally { 491 releaseActiveConnection(); 492 } 493 } 494 } 495 | Popular Tags |