1 24 25 package com.mckoi.database; 26 27 import java.util.HashMap ; 28 import com.mckoi.database.global.BlobAccessor; 29 import com.mckoi.database.jdbc.SQLQuery; 30 import com.mckoi.util.IntegerVector; 31 32 38 39 public class ViewManager { 40 41 44 private DatabaseConnection connection; 45 46 49 private DatabaseQueryContext context; 50 51 55 private boolean view_table_changed; 56 57 62 private HashMap local_cache; 63 64 67 ViewManager(DatabaseConnection connection) { 68 this.connection = connection; 69 this.context = new DatabaseQueryContext(connection); 70 this.local_cache = new HashMap (); 71 this.view_table_changed = false; 72 73 connection.attachTableBackedCache(new TableBackedCache(Database.SYS_VIEW) { 76 public void purgeCacheOfInvalidatedEntries( 77 IntegerVector added_rows, IntegerVector removed_rows) { 78 if (view_table_changed) { 80 invalidateViewCache(); 81 view_table_changed = false; 82 } 83 else if ((added_rows != null && added_rows.size() > 0) || 86 (removed_rows != null && removed_rows.size() > 0)) { 87 invalidateViewCache(); 88 } 89 } 90 }); 91 92 } 93 94 99 private HashMap getViewCache() { 100 return local_cache; 101 } 102 103 106 private void invalidateViewCache() { 107 local_cache.clear(); 108 } 109 110 116 private Table findViewEntry(DataTable table, 117 TableName view_name) { 118 119 Operator EQUALS = Operator.get("="); 120 121 Variable schemav = table.getResolvedVariable(0); 122 Variable namev = table.getResolvedVariable(1); 123 124 Table t = table.simpleSelect(context, namev, EQUALS, 125 new Expression(TObject.stringVal(view_name.getName()))); 126 t = t.exhaustiveSelect(context, Expression.simple( 127 schemav, EQUALS, TObject.stringVal(view_name.getSchema()))); 128 129 if (t.getRowCount() > 1) { 131 throw new RuntimeException ( 132 "Assert failed: multiple view entries for " + view_name); 133 } 134 135 return t; 137 138 } 139 140 143 public boolean viewExists(TableName view_name) { 144 145 DataTable table = connection.getTable(Database.SYS_VIEW); 146 return findViewEntry(table, view_name).getRowCount() == 1; 147 148 } 149 150 159 public void defineView(ViewDef view, SQLQuery query, User user) 160 throws DatabaseException { 161 162 DataTableDef data_table_def = view.getDataTableDef(); 163 DataTable view_table = connection.getTable(Database.SYS_VIEW); 164 165 TableName view_name = data_table_def.getTableName(); 166 167 RowData rdat = new RowData(view_table); 169 rdat.setColumnDataFromObject(0, data_table_def.getSchema()); 170 rdat.setColumnDataFromObject(1, data_table_def.getName()); 171 rdat.setColumnDataFromObject(2, query.serializeToBlob()); 172 rdat.setColumnDataFromObject(3, view.serializeToBlob()); 173 rdat.setColumnDataFromObject(4, user.getUserName()); 174 175 Table t = findViewEntry(view_table, view_name); 177 178 if (t.getRowCount() == 1) { 180 view_table.delete(t); 181 } 182 183 view_table.add(rdat); 185 186 connection.databaseObjectCreated(view_name); 188 189 view_table_changed = true; 191 192 } 193 194 198 public boolean deleteView(TableName view_name) throws DatabaseException { 199 200 DataTable table = connection.getTable(Database.SYS_VIEW); 201 202 Table t = findViewEntry(table, view_name); 204 205 if (t.getRowCount() == 0) { 207 return false; 208 } 209 210 table.delete(t); 211 212 connection.databaseObjectDropped(view_name); 214 215 view_table_changed = true; 217 218 return true; 220 } 221 222 229 private static ViewDef getViewDef(HashMap cache, 230 TableDataSource view_table, TableName view_name) { 231 232 RowEnumeration e = view_table.rowEnumeration(); 233 while (e.hasMoreRows()) { 234 int row = e.nextRowIndex(); 235 236 String c_schema = 237 view_table.getCellContents(0, row).getObject().toString(); 238 String c_name = 239 view_table.getCellContents(1, row).getObject().toString(); 240 241 if (view_name.getSchema().equals(c_schema) && 242 view_name.getName().equals(c_name)) { 243 244 Object cache_key = new Long (row); 245 ViewDef view_def = (ViewDef) cache.get(cache_key); 246 247 if (view_def == null) { 248 BlobAccessor blob = 250 (BlobAccessor) view_table.getCellContents(3, row).getObject(); 251 view_def = ViewDef.deserializeFromBlob(blob); 253 cache.put(cache_key, view_def); 255 256 } 257 return view_def; 258 } 259 260 } 261 262 throw new StatementException("View '" + view_name + "' not found."); 263 264 } 265 266 273 private static ViewDef getViewDef(HashMap cache, 274 TableDataSource view_table, int index) { 275 276 RowEnumeration e = view_table.rowEnumeration(); 277 int i = 0; 278 while (e.hasMoreRows()) { 279 int row = e.nextRowIndex(); 280 281 if (i == index) { 282 Object cache_key = new Long (row); 283 ViewDef view_def = (ViewDef) cache.get(cache_key); 284 285 if (view_def == null) { 286 BlobAccessor blob = 288 (BlobAccessor) view_table.getCellContents(3, row).getObject(); 289 view_def = ViewDef.deserializeFromBlob(blob); 291 cache.put(cache_key, view_def); 293 294 } 295 return view_def; 296 } 297 298 ++i; 299 } 300 throw new Error ("Index out of range."); 301 } 302 303 307 public QueryPlanNode createViewQueryPlanNode(TableName view_name) { 308 DataTable table = connection.getTable(Database.SYS_VIEW); 309 return getViewDef(local_cache, table, view_name).getQueryPlanNode(); 310 } 311 312 321 static InternalTableInfo createInternalTableInfo(ViewManager manager, 322 Transaction transaction) { 323 return new ViewInternalTableInfo(manager, transaction); 324 } 325 326 328 332 private static class ViewInternalTableInfo 333 extends AbstractInternalTableInfo2 { 334 335 ViewManager view_manager; 336 HashMap view_cache; 337 338 ViewInternalTableInfo(ViewManager manager, Transaction transaction) { 339 super(transaction, Database.SYS_VIEW); 340 this.view_manager = manager; 341 if (view_manager == null) { 342 view_cache = new HashMap (); 343 } 344 else { 345 view_cache = view_manager.getViewCache(); 346 } 347 } 348 349 public String getTableType(int i) { 350 return "VIEW"; 351 } 352 353 public DataTableDef getDataTableDef(int i) { 354 return getViewDef(view_cache, 355 transaction.getTable(Database.SYS_VIEW), i).getDataTableDef(); 356 } 357 358 public MutableTableDataSource createInternalTable(int i) { 359 throw new RuntimeException ("Not supported for views."); 360 } 361 362 } 363 364 } 365 366 | Popular Tags |