Source Code Cross Referenced for DataTable.java in  » Database-DBMS » mckoi » com » mckoi » database » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » mckoi » com.mckoi.database 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * com.mckoi.database.DataTable  08 Mar 1998
003:         *
004:         * Mckoi SQL Database ( http://www.mckoi.com/database )
005:         * Copyright (C) 2000, 2001, 2002  Diehl and Associates, Inc.
006:         *
007:         * This program is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU General Public License
009:         * Version 2 as published by the Free Software Foundation.
010:         *
011:         * This program is distributed in the hope that it will be useful,
012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014:         * GNU General Public License Version 2 for more details.
015:         *
016:         * You should have received a copy of the GNU General Public License
017:         * Version 2 along with this program; if not, write to the Free Software
018:         * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
019:         *
020:         * Change Log:
021:         * 
022:         * 
023:         */package com.mckoi.database;
024:
025:        import com.mckoi.database.global.SQLTypes;
026:        import com.mckoi.util.IntegerVector;
027:        import com.mckoi.debug.*;
028:        import java.math.BigDecimal;
029:        import java.util.Vector;
030:        import java.util.ArrayList;
031:        import java.io.IOException;
032:        import java.io.OutputStream;
033:        import java.io.InputStream;
034:        import java.io.File;
035:
036:        /**
037:         * DataTable is a wrapper for a MutableTableDataSource that fits into the
038:         * query hierarchy level.  A DataTable represents a table within a
039:         * transaction.  Adding, removing rows to a DataTable will change the
040:         * contents only with the context of the transaction the table was created in.
041:         * <p>
042:         * @author Tobias Downer
043:         */
044:
045:        public final class DataTable extends DefaultDataTable {
046:
047:            /**
048:             * The DatabaseConnection object that is the parent of this DataTable.
049:             */
050:            private DatabaseConnection connection;
051:
052:            /**
053:             * A low level access to the underlying transactional data source.
054:             */
055:            private MutableTableDataSource data_source;
056:
057:            /**
058:             * ------
059:             * NOTE: Following values are only kept for lock debugging reasons.  These
060:             *   is no technical reason why they shouldn't be removed.  They allow us
061:             *   to check that a data table is locked correctly when accesses are
062:             *   performed on it.
063:             * ------
064:             */
065:
066:            final static boolean LOCK_DEBUG = true;
067:
068:            /**
069:             * The number of read locks we have on this table.
070:             */
071:            private int debug_read_lock_count = 0;
072:
073:            /**
074:             * The number of write locks we have on this table (this should only ever be
075:             * 0 or 1).
076:             */
077:            private int debug_write_lock_count = 0;
078:
079:            /**
080:             * Cosntructs the data table.
081:             */
082:            DataTable(DatabaseConnection connection,
083:                    MutableTableDataSource data_source)
084:                    throws DatabaseException {
085:                super (connection.getDatabase());
086:                this .connection = connection;
087:                this .data_source = data_source;
088:            }
089:
090:            /**
091:             * Convenience - used to log debug messages.
092:             */
093:            public final DebugLogger Debug() {
094:                return connection.getSystem().Debug();
095:            }
096:
097:            /**
098:             * Overwritten from DefaultDataTable to do nothing.  All selectable
099:             * schemes are handled within the DataTableManager now.
100:             */
101:            protected void blankSelectableSchemes(int type) {
102:            }
103:
104:            /**
105:             * Returns the SelectableScheme for the given column.
106:             * (Overridden from DefaultDataTable).  If the schemes are not in memory then
107:             * they are loaded now.  This will synchronize over the 'table_manager'
108:             * which will effectively block this table at the lowest layer until the
109:             * indices are loaded into memory.
110:             */
111:            protected SelectableScheme getRootColumnScheme(int column) {
112:                checkReadLock(); // Read op
113:
114:                return data_source.getColumnScheme(column);
115:            }
116:
117:            /**
118:             * We can declare a DataTable as a new type.  This means, instead of
119:             * referencing a column as 'Customer.CustomerID' we can change the 'Customer'
120:             * part to anything we wish such as 'C1'.
121:             */
122:            public ReferenceTable declareAs(TableName new_name) {
123:                return new ReferenceTable(this , new_name);
124:            }
125:
126:            /**
127:             * Generates an empty RowData object for 'addRow'ing into the Table.
128:             * We must first call this method to retrieve a blank RowData object,
129:             * fill it in with the required information, and then call 'addRow'
130:             */
131:            public final RowData createRowDataObject(QueryContext context) {
132:                checkSafeOperation(); // safe op
133:                return new RowData(this );
134:            }
135:
136:            /**
137:             * Returns the current row count.  This queries the DataTableManager for
138:             * the real value.
139:             */
140:            public int getRowCount() {
141:                checkReadLock(); // read op
142:
143:                return data_source.getRowCount();
144:            }
145:
146:            /**
147:             * Adds a given 'RowData' object to the table.  This should be used for
148:             * any rows added to the table.  The order that rows are added into a table
149:             * is not important.
150:             * <p>
151:             * This method performs some checking of the cells in the table.  It first
152:             * checks that all columns declared as 'not null' have a value that is not
153:             * null.  It then checks that a the added row will not cause any duplicates
154:             * in a column declared as unique.
155:             * <p>
156:             * It then uses the low level io manager to store the data.
157:             * <p>
158:             * SYNCHRONIZATION ISSUE: We are assuming this is running in a synchronized
159:             *   environment that is unable to add or alter rows in this object within
160:             *   the lifetime of this method.
161:             */
162:            public final void add(RowData row_data) throws DatabaseException {
163:                checkReadWriteLock(); // write op
164:
165:                if (!row_data.isSameTable(this )) {
166:                    throw new DatabaseException(
167:                            "Internal Error: Using RowData from different table");
168:                }
169:
170:                // Checks passed, so add to table.
171:                addRow(row_data);
172:
173:                // Perform a referential integrity check on any changes to the table.
174:                data_source.constraintIntegrityCheck();
175:            }
176:
177:            /**
178:             * Adds an array of 'RowData' objects to the table.  This should be used for
179:             * adding a group of rows to the table.  The order that rows are added into
180:             * a table is not important.
181:             * <p>
182:             * This method performs some checking of the cells in the table.  It first
183:             * checks that all columns declared as 'not null' have a value that is not
184:             * null.  It then checks that a the added row will not cause any duplicates
185:             * in a column declared as unique.
186:             * <p>
187:             * It then uses the low level io manager to store the data.
188:             * <p>
189:             * SYNCHRONIZATION ISSUE: We are assuming this is running in a synchronized
190:             *   environment that is unable to add or alter rows in this object within
191:             *   the lifetime of this method.
192:             */
193:            public final void add(RowData[] row_data_arr)
194:                    throws DatabaseException {
195:                checkReadWriteLock(); // write op
196:
197:                for (int i = 0; i < row_data_arr.length; ++i) {
198:                    RowData row_data = row_data_arr[i];
199:                    if (!row_data.isSameTable(this )) {
200:                        throw new DatabaseException(
201:                                "Internal Error: Using RowData from different table");
202:                    }
203:                    addRow(row_data);
204:                }
205:
206:                // Perform a referential integrity check on any changes to the table.
207:                data_source.constraintIntegrityCheck();
208:            }
209:
210:            /**
211:             * Adds a new row of data to the table.  First of all, this tells the
212:             * underlying database mechanism to add the data to this table.  It then
213:             * add the row information to each SelectableScheme.
214:             */
215:            private void addRow(RowData row) throws DatabaseException {
216:
217:                // This table name (for event notification)
218:                TableName table_name = getTableName();
219:
220:                // Fire the 'before' trigger for an insert on this table
221:                connection.fireTableEvent(new TableModificationEvent(
222:                        connection, table_name, row, true));
223:
224:                // Add the row to the underlying file system
225:                int row_number = data_source.addRow(row);
226:
227:                // Fire the 'after' trigger for an insert on this table
228:                connection.fireTableEvent(new TableModificationEvent(
229:                        connection, table_name, row, false));
230:
231:                // NOTE: currently nothing being done with 'row_number' after it's added.
232:                //   The underlying table data source manages the row index.
233:
234:            }
235:
236:            /**
237:             * Removes the given row from the table.  This is called just before the
238:             * row is actually deleted.  The method is provided to allow for some
239:             * maintenance of any search structures such as B-Trees.  This is called
240:             * from the 'delete' method in Table.
241:             */
242:            private void removeRow(int row_number) throws DatabaseException {
243:
244:                // This table name (for event notification)
245:                TableName table_name = getTableName();
246:
247:                // Fire the 'before' trigger for the delete on this table
248:                connection.fireTableEvent(new TableModificationEvent(
249:                        connection, table_name, row_number, true));
250:
251:                // Delete the row from the underlying database
252:                data_source.removeRow(row_number);
253:
254:                // Fire the 'after' trigger for the delete on this table
255:                connection.fireTableEvent(new TableModificationEvent(
256:                        connection, table_name, row_number, false));
257:
258:            }
259:
260:            /**
261:             * Updates the given row with the given data in this table.  This method
262:             * will likely add the modified data to a new row and delete the old
263:             * version of the row.
264:             */
265:            private void updateRow(int row_number, RowData row)
266:                    throws DatabaseException {
267:
268:                // This table name (for event notification)
269:                TableName table_name = getTableName();
270:
271:                // Fire the 'before' trigger for the update on this table
272:                connection.fireTableEvent(new TableModificationEvent(
273:                        connection, table_name, row_number, row, true));
274:
275:                // Update the row in the underlying database
276:                data_source.updateRow(row_number, row);
277:
278:                // Fire the 'after' trigger for the update on this table
279:                connection.fireTableEvent(new TableModificationEvent(
280:                        connection, table_name, row_number, row, false));
281:
282:            }
283:
284:            /**
285:             * This is the public method for removing a given result set from this
286:             * table.  Given a Table object, this will remove from this table any row
287:             * that are in the given table.  The given Table must have this object as
288:             * its distant ancestor.  If it does not then it will throw an exception.
289:             * Examples: table.delete(table)           -- delete the entire table.
290:             *           table.delete(table.select( < some condition > ));
291:             * It returns the number of rows that were deleted.
292:             * <p>
293:             * <strong>INTERNAL NOTE:</strong> The 'table' parameter may be the result
294:             *   of joins.  This may cause the same row in this table to be referenced
295:             *   more than once.  We must make sure that we delete any given row only
296:             *   once by using the 'distinct' function.
297:             * <p>
298:             * 'limit' dictates how many rows will be deleted.  If 'limit' is less than
299:             * 0 then this indicates there is no limit.  Keep in mind that rows are
300:             * picked out from top to bottom in the 'table' object.  Normally the
301:             * input table will be the result of an un-ordered 'where' clause so using
302:             * a limit does not permit deletes in a deterministic manner.
303:             * <p>
304:             * ASSUMPTION: There are no duplicate rows in the input set.
305:             */
306:            public int delete(Table table, int limit) throws DatabaseException {
307:                checkReadWriteLock(); // write op
308:
309:                IntegerVector row_set = new IntegerVector(table.getRowCount());
310:                RowEnumeration e = table.rowEnumeration();
311:                while (e.hasMoreRows()) {
312:                    row_set.addInt(e.nextRowIndex());
313:                }
314:                e = null;
315:
316:                // HACKY: Find the first column of this table in the search table.  This
317:                //   will allow us to generate a row set of only the rows in the search
318:                //   table.
319:                int first_column = table.findFieldName(getResolvedVariable(0));
320:
321:                if (first_column == -1) {
322:                    throw new DatabaseException(
323:                            "Search table does not contain any "
324:                                    + "reference to table being deleted from");
325:                }
326:
327:                // Generate a row set that is in this tables domain.
328:                table.setToRowTableDomain(first_column, row_set, this );
329:
330:                // row_set may contain duplicate row indices, therefore we must sort so
331:                // any duplicates are grouped and therefore easier to find.
332:                row_set.quickSort();
333:
334:                // If limit less than zero then limit is whole set.
335:                if (limit < 0) {
336:                    limit = Integer.MAX_VALUE;
337:                }
338:
339:                // Remove each row in row set in turn.  Make sure we don't remove the
340:                // same row index twice.
341:                int len = Math.min(row_set.size(), limit);
342:                int last_removed = -1;
343:                int remove_count = 0;
344:                for (int i = 0; i < len; ++i) {
345:                    int to_remove = row_set.intAt(i);
346:                    if (to_remove < last_removed) {
347:                        throw new DatabaseException(
348:                                "Internal error: row sorting error or row_set not in the range > 0");
349:                    }
350:
351:                    if (to_remove != last_removed) {
352:                        removeRow(to_remove);
353:                        last_removed = to_remove;
354:                        ++remove_count;
355:                    }
356:
357:                }
358:
359:                if (remove_count > 0) {
360:                    // Perform a referential integrity check on any changes to the table.
361:                    data_source.constraintIntegrityCheck();
362:                }
363:
364:                return remove_count;
365:            }
366:
367:            // Unlimited delete
368:            public int delete(Table table) throws DatabaseException {
369:                return delete(table, -1);
370:            }
371:
372:            /**
373:             * Updates the table by applying the assignment operations over each row
374:             * that is found in the input 'table' set.  The input table must be a direct
375:             * child of this DataTable.
376:             * <p>
377:             * This operation assumes that there is a WRITE lock on this table.  A
378:             * WRITE lock means no other thread may access this table while the
379:             * operation is being performed.  (However, a result set may still be
380:             * downloading from this table).
381:             * <p>
382:             * 'limit' dictates how many rows will be updated.  If 'limit' is less than
383:             * 0 then this indicates there is no limit.  Keep in mind that rows are
384:             * picked out from top to bottom in the 'table' object.  Normally the
385:             * input table will be the result of an un-ordered 'where' clause so using
386:             * a limit does not permit updates in a deterministic manner.
387:             * <p>
388:             * Returns the number of rows updated in this table.
389:             * <p>
390:             * NOTE: We assume there are no duplicate rows to the root set from the
391:             *   given 'table'.
392:             */
393:            public final int update(QueryContext context, Table table,
394:                    Assignment[] assign_list, int limit)
395:                    throws DatabaseException {
396:                checkReadWriteLock(); // write op
397:
398:                // Get the rows from the input table.
399:                IntegerVector row_set = new IntegerVector();
400:                RowEnumeration e = table.rowEnumeration();
401:                while (e.hasMoreRows()) {
402:                    row_set.addInt(e.nextRowIndex());
403:                }
404:                e = null;
405:
406:                // HACKY: Find the first column of this table in the search table.  This
407:                //   will allow us to generate a row set of only the rows in the search
408:                //   table.
409:                int first_column = table.findFieldName(getResolvedVariable(0));
410:                if (first_column == -1) {
411:                    throw new DatabaseException(
412:                            "Search table does not contain any "
413:                                    + "reference to table being updated from");
414:                }
415:
416:                // Convert the row_set to this table's domain.
417:                table.setToRowTableDomain(first_column, row_set, this );
418:
419:                // NOTE: Assume there's no duplicate rows.
420:
421:                RowData original_data = createRowDataObject(context);
422:                RowData row_data = createRowDataObject(context);
423:
424:                // If limit less than zero then limit is whole set.
425:                if (limit < 0) {
426:                    limit = Integer.MAX_VALUE;
427:                }
428:
429:                // Update each row in row set in turn up to the limit.
430:                int len = Math.min(row_set.size(), limit);
431:                int update_count = 0;
432:                for (int i = 0; i < len; ++i) {
433:                    int to_update = row_set.intAt(i);
434:
435:                    // Make a RowData object from this row (plus keep the original intact
436:                    // incase we need to roll back to it).
437:                    original_data.setFromRow(to_update);
438:                    row_data.setFromRow(to_update);
439:
440:                    // Run each assignment on the RowData.
441:                    for (int n = 0; n < assign_list.length; ++n) {
442:                        Assignment assignment = assign_list[n];
443:                        row_data.evaluate(assignment, context);
444:                    }
445:
446:                    // Update the row
447:                    updateRow(to_update, row_data);
448:
449:                    ++update_count;
450:                }
451:
452:                if (update_count > 0) {
453:                    // Perform a referential integrity check on any changes to the table.
454:                    data_source.constraintIntegrityCheck();
455:                }
456:
457:                return update_count;
458:
459:            }
460:
461:            /**
462:             * Returns the DataTableDef object for this table.  This object describes
463:             * how the table is made up.
464:             * <p>
465:             * <strong>NOTE:</strong> Do not keep references to this object.  The
466:             *   DataTableDef is invalidated when a table is closed.
467:             */
468:            public DataTableDef getDataTableDef() {
469:                checkSafeOperation(); // safe op
470:
471:                return data_source.getDataTableDef();
472:            }
473:
474:            /**
475:             * Returns the schema that this table is within.
476:             */
477:            public String getSchema() {
478:                checkSafeOperation(); // safe op
479:
480:                return getDataTableDef().getSchema();
481:            }
482:
483:            /**
484:             * Adds a DataTableListener to the DataTable objects at the root of this
485:             * table tree hierarchy.  If this table represents the join of a number of
486:             * tables then the DataTableListener is added to all the DataTable objects
487:             * at the root.
488:             * <p>
489:             * A DataTableListener is notified of all modifications to the raw entries
490:             * of the table.  This listener can be used for detecting changes in VIEWs,
491:             * for triggers or for caching of common queries.
492:             */
493:            public void addDataTableListener(DataTableListener listener) {
494:                // Currently we do nothing with this info.
495:            }
496:
497:            /**
498:             * Removes a DataTableListener from the DataTable objects at the root of
499:             * this table tree hierarchy.  If this table represents the join of a
500:             * number of tables, then the DataTableListener is removed from all the
501:             * DataTable objects at the root.
502:             */
503:            public void removeDataTableListener(DataTableListener listener) {
504:                // Currently we do nothing with this info.
505:            }
506:
507:            // -------- Methods implemented for DefaultDataTable --------
508:
509:            /**
510:             * Given a set, this trickles down through the Table hierarchy resolving
511:             * the given row_set to a form that the given ancestor understands.
512:             * Say you give the set { 0, 1, 2, 3, 4, 5, 6 }, this function may check
513:             * down three levels and return a new 7 element set with the rows fully
514:             * resolved to the given ancestors domain.
515:             */
516:            void setToRowTableDomain(int column, IntegerVector row_set,
517:                    TableDataSource ancestor) {
518:                checkReadLock(); // read op
519:
520:                if (ancestor != this  && ancestor != data_source) {
521:                    throw new RuntimeException(
522:                            "Method routed to incorrect table ancestor.");
523:                }
524:            }
525:
526:            /**
527:             * Returns an object that represents the information in the given cell
528:             * in the table.  This can be used to obtain information about the given
529:             * table cells.
530:             */
531:            public TObject getCellContents(int column, int row) {
532:                checkSafeOperation(); // safe op
533:
534:                return data_source.getCellContents(column, row);
535:            }
536:
537:            /**
538:             * Returns an Enumeration of the rows in this table.
539:             * Each call to 'nextRowIndex' returns the next valid row index in the table.
540:             */
541:            public RowEnumeration rowEnumeration() {
542:                checkReadLock(); // read op
543:
544:                return data_source.rowEnumeration();
545:            }
546:
547:            /**
548:             * Locks the root table(s) of this table so that it is impossible to
549:             * overwrite the underlying rows that may appear in this table.
550:             * This is used when cells in the table need to be accessed 'outside' the
551:             * lock.  So we may have late access to cells in the table.
552:             * 'lock_key' is a given key that will also unlock the root table(s).
553:             * <p>
554:             * NOTE: This is nothing to do with the 'LockingMechanism' object.
555:             */
556:            public void lockRoot(int lock_key) {
557:                checkSafeOperation(); // safe op
558:
559:                data_source.addRootLock();
560:            }
561:
562:            /**
563:             * Unlocks the root tables so that the underlying rows may
564:             * once again be used if they are not locked and have been removed.  This
565:             * should be called some time after the rows have been locked.
566:             */
567:            public void unlockRoot(int lock_key) {
568:                checkSafeOperation(); // safe op
569:
570:                data_source.removeRootLock();
571:            }
572:
573:            /**
574:             * Returns true if the table has its row roots locked (via the lockRoot(int)
575:             * method.
576:             */
577:            public boolean hasRootsLocked() {
578:                // There is no reason why we would need to know this information at
579:                // this level.
580:                // We need to deprecate this properly.
581:                throw new Error("hasRootsLocked is deprecated.");
582:            }
583:
584:            // ------------ Lock debugging methods ----------
585:
586:            /**
587:             * This is called by the 'Lock' class to notify this DataTable that a read/
588:             * write lock has been applied to this table.  This is for lock debugging
589:             * purposes only.
590:             */
591:            final void notifyAddRWLock(int lock_type) {
592:                if (LOCK_DEBUG) {
593:                    if (lock_type == Lock.READ) {
594:                        ++debug_read_lock_count;
595:                    } else if (lock_type == Lock.WRITE) {
596:                        ++debug_write_lock_count;
597:                        if (debug_write_lock_count > 1) {
598:                            throw new Error(">1 write lock on table "
599:                                    + getTableName());
600:                        }
601:                    } else {
602:                        throw new Error("Unknown lock type: " + lock_type);
603:                    }
604:                }
605:            }
606:
607:            /**
608:             * This is called by the 'Lock' class to notify this DataTable that a read/
609:             * write lock has been released from this table.  This is for lock debugging
610:             * purposes only.
611:             */
612:            final void notifyReleaseRWLock(int lock_type) {
613:                if (LOCK_DEBUG) {
614:                    if (lock_type == Lock.READ) {
615:                        --debug_read_lock_count;
616:                    } else if (lock_type == Lock.WRITE) {
617:                        --debug_write_lock_count;
618:                    } else {
619:                        Debug().writeException(
620:                                new RuntimeException("Unknown lock type: "
621:                                        + lock_type));
622:                    }
623:                }
624:            }
625:
626:            /**
627:             * Returns true if the database is in exclusive mode.
628:             */
629:            private boolean isInExclusiveMode() {
630:                // Check the connection locking mechanism is in exclusive mode
631:                return connection.getLockingMechanism().isInExclusiveMode();
632:            }
633:
634:            /**
635:             * Checks the database is in exclusive mode.
636:             */
637:            private void checkInExclusiveMode() {
638:                if (!isInExclusiveMode()) {
639:                    Debug()
640:                            .writeException(
641:                                    new RuntimeException(
642:                                            "Performed exclusive operation on table and not in exclusive mode!"));
643:                }
644:            }
645:
646:            /**
647:             * Check that we can safely read from this table.
648:             */
649:            private void checkReadLock() {
650:                if (LOCK_DEBUG) {
651:                    // All 'sUSR' tables are given read access because they may only be
652:                    // written under exclusive mode anyway.
653:
654:                    boolean is_internal_table = getTableName().getSchema()
655:                            .equals(Database.SYSTEM_SCHEMA);
656:
657:                    if (!(is_internal_table || debug_read_lock_count > 0
658:                            || debug_write_lock_count > 0 || isInExclusiveMode())) {
659:
660:                        System.err.println();
661:                        System.err.print(" is_internal_table = "
662:                                + is_internal_table);
663:                        System.err.print(" debug_read_lock_count = "
664:                                + debug_read_lock_count);
665:                        System.err.print(" debug_write_lock_count = "
666:                                + debug_write_lock_count);
667:                        System.err.println(" isInExclusiveMode = "
668:                                + isInExclusiveMode());
669:
670:                        Debug().writeException(
671:                                new Error("Invalid read access on table '"
672:                                        + getTableName() + "'"));
673:                    }
674:                }
675:            }
676:
677:            /**
678:             * Check that we can safely read/write from this table.  This should catch
679:             * any synchronization concurrent issues.
680:             */
681:            private void checkReadWriteLock() {
682:                if (LOCK_DEBUG) {
683:                    // We have to own exactly one write lock, or be in exclusive mode.
684:                    if (!(debug_write_lock_count == 1 || isInExclusiveMode())) {
685:                        Debug().writeException(
686:                                new Error(
687:                                        "Invalid read/write access on table '"
688:                                                + getTableName() + "'"));
689:                    }
690:                }
691:            }
692:
693:            /**
694:             * Check that we can run a safe operation.
695:             */
696:            private void checkSafeOperation() {
697:                // no operation - nothing to check for...
698:            }
699:
700:            // ---------- Overwritten to output debug info ----------
701:            // NOTE: These can all safely be commented out.
702:
703:            public int getColumnCount() {
704:                checkSafeOperation(); // safe op
705:
706:                return super .getColumnCount();
707:            }
708:
709:            public Variable getResolvedVariable(int column) {
710:                checkSafeOperation(); // safe op
711:
712:                return super .getResolvedVariable(column);
713:            }
714:
715:            public int findFieldName(Variable v) {
716:                checkSafeOperation(); // safe op
717:
718:                return super .findFieldName(v);
719:            }
720:
721:            SelectableScheme getSelectableSchemeFor(int column,
722:                    int original_column, Table table) {
723:                checkReadLock(); // read op
724:
725:                return super .getSelectableSchemeFor(column, original_column,
726:                        table);
727:            }
728:
729:            RawTableInformation resolveToRawTable(RawTableInformation info) {
730:                checkReadLock(); // read op
731:
732:                return super.resolveToRawTable(info);
733:            }
734:
735:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.