1 2 12 package com.versant.core.jdbc.metadata; 13 14 import com.versant.core.metadata.ClassMetaData; 15 import com.versant.core.metadata.FieldMetaData; 16 import com.versant.core.jdbc.JdbcKeyGenerator; 17 import com.versant.core.jdbc.sql.exp.*; 18 import com.versant.core.jdbc.sql.SqlDriver; 19 import com.versant.core.common.Debug; 20 import com.versant.core.util.CharBuf; 21 22 import java.io.Serializable ; 23 import java.io.PrintStream ; 24 import java.util.*; 25 26 31 public final class JdbcClass implements Serializable { 32 33 36 public static final int OPTIMISTIC_LOCKING_NONE = 1; 37 40 public static final int OPTIMISTIC_LOCKING_VERSION = 2; 41 44 public static final int OPTIMISTIC_LOCKING_TIMESTAMP = 3; 45 49 public static final int OPTIMISTIC_LOCKING_CHANGED = 4; 50 51 54 public static final int INHERITANCE_FLAT = 1; 55 58 public static final int INHERITANCE_VERTICAL = 2; 59 62 public static final int INHERITANCE_HORIZONTAL = 3; 63 64 67 public ClassMetaData cmd; 68 71 public final SqlDriver sqlDriver; 72 79 public int inheritance; 80 84 public JdbcTable table; 85 88 public String tableName; 89 94 public JdbcTable[] allTables; 95 99 public JdbcField[] fields; 100 105 public JdbcField[] stateFields; 106 109 private transient Map colNamesToJdbcField; 110 114 public JdbcKeyGenerator jdbcKeyGenerator; 115 121 public int useJoin; 122 131 public Object jdbcClassId; 132 138 public JdbcColumn classIdCol; 139 144 public ClassMetaData readAsClass; 145 149 public int optimisticLocking; 150 155 public JdbcSimpleField optimisticLockingField; 156 160 public boolean doNotCreateTable; 161 164 public String deleteRowSql; 165 168 public String lockRowSql; 169 172 public boolean noBatching; 173 174 private String lockRowColumnName; 176 public JdbcClass(SqlDriver sqlDriver) { 177 this.sqlDriver = sqlDriver; 178 } 179 180 public String toString() { 181 return cmd.qname + " (" + table.name + ")"; 182 } 183 184 187 public void getTables(HashSet tables) { 188 if (table != null) { 189 tables.add(table); 190 } 191 int n = 0; 192 if (fields != null) { 193 n = fields.length; 194 } 195 for (int i = 0; i < n; i++) { 196 JdbcField f = fields[i]; 197 if (f != null) f.getTables(tables); 198 } 199 } 200 201 204 public void buildStateFields() { 205 if (cmd.pcSuperMetaData == null) buildStateFieldsImp(); 206 } 207 208 private void buildStateFieldsImp() { 209 if (cmd.pcSuperMetaData != null) { 210 JdbcField[] superStateFields = ((JdbcClass)cmd.pcSuperMetaData.storeClass).stateFields; 211 if (superStateFields != null) { 212 int n = superStateFields.length; 213 stateFields = new JdbcField[n + fields.length]; 214 System.arraycopy(superStateFields, 0, stateFields, 0, n); 215 System.arraycopy(fields, 0, stateFields, n, fields.length); 216 } 217 } else { 218 stateFields = fields; 219 } 220 if (cmd.pcSubclasses != null) { 221 for (int i = cmd.pcSubclasses.length - 1; i >= 0; i--) { 222 ((JdbcClass)cmd.pcSubclasses[i].storeClass).buildStateFieldsImp(); 223 } 224 } 225 } 226 227 230 public void setJdbcKeyGenerator(JdbcKeyGenerator jdbcKeyGenerator) { 231 this.jdbcKeyGenerator = jdbcKeyGenerator; 232 cmd.useKeyGen = true; 233 cmd.postInsertKeyGenerator = jdbcKeyGenerator.isPostInsertGenerator(); 234 ClassMetaData[] pcSubclasses = cmd.pcSubclasses; 235 if (pcSubclasses == null) return; 236 for (int i = 0; i < pcSubclasses.length; i++) { 237 ((JdbcClass)pcSubclasses[i].storeClass).setJdbcKeyGenerator(jdbcKeyGenerator); 238 } 239 } 240 241 244 public void copyOptimisticLockingToSubs() { 245 ClassMetaData[] pcSubclasses = cmd.pcSubclasses; 246 if (pcSubclasses == null) return; 247 for (int i = 0; i < pcSubclasses.length; i++) { 248 JdbcClass sc = (JdbcClass)pcSubclasses[i].storeClass; 249 sc.optimisticLocking = optimisticLocking; 250 sc.cmd.changedOptimisticLocking = 251 optimisticLocking == JdbcClass.OPTIMISTIC_LOCKING_CHANGED; 252 sc.optimisticLockingField = optimisticLockingField; 253 if (optimisticLockingField != null) { 254 sc.cmd.optimisticLockingField = optimisticLockingField.fmd; 255 } 256 sc.copyOptimisticLockingToSubs(); 257 } 258 } 259 260 263 public void setClassIdCol(JdbcColumn classIdCol) { 264 this.classIdCol = classIdCol; 265 ClassMetaData[] pcSubclasses = cmd.pcSubclasses; 266 if (pcSubclasses == null) return; 267 for (int i = 0; i < pcSubclasses.length; i++) { 268 ((JdbcClass)pcSubclasses[i].storeClass).setClassIdCol(classIdCol); 269 } 270 } 271 272 276 public ClassMetaData findClass(Object jdbcClassId) { 277 if (this.jdbcClassId.equals(jdbcClassId)) return cmd; 278 ClassMetaData[] subs = cmd.pcSubclasses; 279 if (subs != null) { 280 for (int i = subs.length - 1; i >= 0; i--) { 281 ClassMetaData ans = ((JdbcClass)subs[i].storeClass).findClass(jdbcClassId); 282 if (ans != null) return ans; 283 } 284 } 285 return null; 286 } 287 288 292 public boolean isMultiTableHeirachy() { 293 return table != ((JdbcClass)cmd.pcHeirachy[0].storeClass).table; 294 } 295 296 public void dump() { 297 dump(Debug.OUT, ""); 298 } 299 300 public void dump(PrintStream out, String indent) { 301 out.println(indent + this); 302 String is = indent + " "; 303 out.println(is + "cmd = " + cmd); 304 out.println(is + "jdbcKeyGenerator = " + jdbcKeyGenerator); 305 out.println(is + "useJoin = " + JdbcRefField.toUseJoinString(useJoin)); 306 out.println(is + "classId = " + jdbcClassId); 307 out.println(is + "classIdCol = " + classIdCol); 308 out.println(is + "optimisticLocking = " + 309 toOptimisticLockingString(optimisticLocking)); 310 out.println( 311 is + "optLockFieldStateFieldNo = " + optimisticLockingField); 312 out.println(is + "fields = " + 313 (fields == null ? "null" : Integer.toString(fields.length))); 314 out.println(is + "stateFields = " + 315 (stateFields == null ? "null" : Integer.toString( 316 stateFields.length))); 317 } 318 319 public static String toOptimisticLockingString(int o) { 320 switch (o) { 321 case OPTIMISTIC_LOCKING_NONE: 322 return "none"; 323 case OPTIMISTIC_LOCKING_CHANGED: 324 return "changed"; 325 case OPTIMISTIC_LOCKING_VERSION: 326 return "version"; 327 case OPTIMISTIC_LOCKING_TIMESTAMP: 328 return "timestamp"; 329 } 330 return "unknown(" + o + ")"; 331 } 332 333 337 public JdbcSimpleField findPkField(String fname) { 338 FieldMetaData f = cmd.findPkField(fname); 339 if (f == null) return null; 340 return (JdbcSimpleField)f.storeField; 341 } 342 343 346 public int findPkFieldIndex(JdbcSimpleField f) { 347 for (int i = cmd.pkFields.length - 1; i >= 0; i--) { 348 if (cmd.pkFields[i].storeField == f) return i; 349 } 350 return -1; 351 } 352 353 359 public int getMaxOIDsForIN(SqlDriver sqlDriver) { 360 if (table.pkSimpleColumnCount > 1) return 0; 361 return sqlDriver.getMaxInOperands(); 362 } 363 364 368 public void findFieldsForColumn(ClassMetaData cmd, String columnName, 369 List list) { 370 for (int i = 0; i < fields.length; i++) { 371 JdbcField f = fields[i]; 372 if (f != null && f.findMainTableColumn(columnName) != null) { 373 ClassMetaData fcmd = f.fmd.classMetaData; 374 if ((cmd.isAncestorOrSelf(fcmd) || fcmd.isAncestorOrSelf(cmd))) { 375 list.add(f); 376 } 377 } 378 } 379 } 380 381 385 public void markSubclassColumnsShared(String columnName) { 386 if (cmd.pcSubclasses == null) return; 387 for (int i = cmd.pcSubclasses.length - 1; i >= 0; i--) { 388 JdbcClass jc = (JdbcClass)cmd.pcSubclasses[i].storeClass; 389 jc.markColumnsShared(columnName, table); 390 jc.markSubclassColumnsShared(columnName); 391 } 392 } 393 394 398 public void markColumnsShared(String columnName, JdbcTable cTable) { 399 for (int i = 0; i < fields.length; i++) { 400 JdbcField f = fields[i]; 401 if (f == null || f.fmd.primaryKey) continue; 402 if (f.mainTable != cTable) continue; 403 JdbcColumn c = f.findMainTableColumn(columnName); 404 if (c != null) c.setShared(true); 405 } 406 } 407 408 411 public String getLockRowColumnName() { 412 if (lockRowColumnName == null) { 413 lockRowColumnName = table.getLockRowColumn().name; 414 } 415 return lockRowColumnName; 416 } 417 418 423 public void setTable(JdbcTable table) { 424 this.table = table; 425 tableName = table.name; 426 ArrayList a = new ArrayList(); 427 JdbcTable prev = null; 428 for (int i = 0; i < cmd.pcHeirachy.length; i++) { 429 JdbcTable t = ((JdbcClass)cmd.pcHeirachy[i].storeClass).table; 430 if (t != prev) a.add(t); 431 prev = t; 432 } 433 allTables = new JdbcTable[a.size()]; 434 a.toArray(allTables); 435 } 436 437 441 public LiteralExp getClassIdExp(boolean subclasses) { 442 LiteralExp root = classIdCol.createClassIdLiteralExp(jdbcClassId); 443 444 if (subclasses && cmd.pcSubclasses != null) { 445 ClassMetaData[] a = cmd.pcSubclasses; 446 SqlExp pos = root; 447 for (int i = a.length - 1; i >= 0; i--) { 448 pos = pos.next = ((JdbcClass)a[i].storeClass).getClassIdExp(true); 449 for (; pos.next != null; pos = pos.next) ; 450 } 451 } 452 return root; 453 } 454 455 461 public SqlExp getCheckClassIdExp(SelectExp se) { 462 if (classIdCol == null) return null; 463 SqlExp colExp = classIdCol.toSqlExp(se); 464 LiteralExp idExp = getClassIdExp(true); 465 if (idExp.next == null) { 466 return new BinaryOpExp(colExp, BinaryOpExp.EQUAL, idExp); 467 } else { 468 colExp.next = idExp; 469 return new InExp(colExp); 470 } 471 } 472 473 478 public boolean isIntJdbcClassIdHeirachy() { 479 if (jdbcClassId == null) return false; 480 if (jdbcClassId instanceof Integer ) return true; 481 try { 482 Integer.parseInt((String )jdbcClassId); 483 } catch (NumberFormatException e) { 484 return false; 485 } 486 if (cmd.pcSubclasses == null) return true; 487 for (int i = cmd.pcSubclasses.length - 1; i >= 0; i--) { 488 if (!((JdbcClass)cmd.pcSubclasses[i].storeClass).isIntJdbcClassIdHeirachy()) { 489 return false; 490 } 491 } 492 return true; 493 } 494 495 499 public void convertJdbcClassIdToInteger() { 500 if (jdbcClassId instanceof String ) { 501 jdbcClassId = new Integer ((String )jdbcClassId); 502 } 503 if (cmd.pcSubclasses != null) { 504 for (int i = cmd.pcSubclasses.length - 1; i >= 0; i--) { 505 ((JdbcClass)cmd.pcSubclasses[i].storeClass).convertJdbcClassIdToInteger(); 506 } 507 } 508 } 509 510 public Map getColNamesToJdbcField() { 511 if (colNamesToJdbcField == null) { 512 colNamesToJdbcField = new HashMap(stateFields.length); 513 JdbcField[] fs = stateFields; 514 for (int i = 0; i < fs.length; i++) { 515 JdbcField f = fs[i]; 516 if (f.mainTableCols != null) { 517 JdbcColumn[] cols = f.mainTableCols; 518 for (int j = 0; j < cols.length; j++) { 519 JdbcColumn col = cols[j]; 520 colNamesToJdbcField.put(col.name.toUpperCase(), f); 521 } 522 } 523 } 524 } 525 return colNamesToJdbcField; 526 } 527 528 531 public String getLockRowSql() { 532 if (lockRowSql == null) { 533 CharBuf s = new CharBuf(); 534 s.append("UPDATE "); 535 s.append(table.name); 536 s.append(" SET "); 537 String c = getLockRowColumnName(); 538 s.append(c); 539 s.append('='); 540 s.append(c); 541 s.append(" WHERE "); 542 table.appendWherePK(s); 543 lockRowSql = s.toString(); 544 } 545 return lockRowSql; 546 } 547 548 } 549 550 | Popular Tags |