001: /**
002: * com.mckoi.database.sql.FromTableDirectSource 20 Jul 2001
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.interpret;
024:
025: import com.mckoi.database.*;
026: import java.util.List;
027: import java.util.Collections;
028:
029: /**
030: * An implementation of FromTableInterface that wraps around an
031: * TableName/AbstractDataTable object. The handles case insensitive
032: * resolution.
033: *
034: * @author Tobias Downer
035: */
036:
037: public class FromTableDirectSource implements FromTableInterface {
038:
039: /**
040: * The TableQueryDef object that links to the underlying table.
041: */
042: private TableQueryDef table_query;
043:
044: /**
045: * The DataTableDef object that describes the table.
046: */
047: private DataTableDef data_table_def;
048:
049: /**
050: * The unique name given to this source.
051: */
052: private String unique_name;
053:
054: /**
055: * The given TableName of this table.
056: */
057: private TableName table_name;
058:
059: /**
060: * The root name of the table. For example, if this table is 'Part P' the
061: * root name is 'Part' and 'P' is the aliased name.
062: */
063: private TableName root_name;
064:
065: /**
066: * Set to true if this should do case insensitive resolutions.
067: */
068: private boolean case_insensitive = false;
069:
070: /**
071: * Constructs the source.
072: */
073: public FromTableDirectSource(DatabaseConnection connection,
074: TableQueryDef table_query, String unique_name,
075: TableName given_name, TableName root_name) {
076: this .unique_name = unique_name;
077: this .data_table_def = table_query.getDataTableDef();
078: this .root_name = root_name;
079: if (given_name != null) {
080: this .table_name = given_name;
081: } else {
082: this .table_name = root_name;
083: }
084: // Is the database case insensitive?
085: this .case_insensitive = connection.isInCaseInsensitiveMode();
086: this .table_query = table_query;
087: }
088:
089: /**
090: * Returns the given name of the table. For example, if the Part table is
091: * aliased as P this returns P. If there is no given name, returns the
092: * root table name.
093: */
094: public TableName getGivenTableName() {
095: return table_name;
096: }
097:
098: /**
099: * Returns the root name of the table. This TableName can always be used as
100: * a direct reference to a table in the database.
101: */
102: public TableName getRootTableName() {
103: return root_name;
104: }
105:
106: /**
107: * Creates a QueryPlanNode to be added into a query tree that fetches the
108: * table source.
109: */
110: public QueryPlanNode createFetchQueryPlanNode() {
111: return table_query.getQueryPlanNode();
112: }
113:
114: /**
115: * Toggle the case sensitivity flag.
116: */
117: public void setCaseInsensitive(boolean status) {
118: case_insensitive = status;
119: }
120:
121: private boolean stringCompare(String str1, String str2) {
122: if (!case_insensitive) {
123: return str1.equals(str2);
124: }
125: return str1.equalsIgnoreCase(str2);
126: }
127:
128: // ---------- Implemented from FromTableInterface ----------
129:
130: public String getUniqueName() {
131: return unique_name;
132: }
133:
134: public boolean matchesReference(String catalog, String schema,
135: String table) {
136: // System.out.println("Matches reference: " + schema + " " + table);
137: // System.out.println(table_name.getName());
138:
139: // Does this table name represent the correct schema?
140: if (schema != null
141: && !stringCompare(schema, table_name.getSchema())) {
142: // If schema is present and we can't resolve to this schema then false
143: return false;
144: }
145: if (table != null
146: && !stringCompare(table, table_name.getName())) {
147: // If table name is present and we can't resolve to this table name
148: // then return false
149: return false;
150: }
151: // System.out.println("MATCHED!");
152: // Match was successful,
153: return true;
154: }
155:
156: public int resolveColumnCount(String catalog, String schema,
157: String table, String column) {
158: // NOTE: With this type, we can only ever return either 1 or 0 because
159: // it's impossible to have an ambiguous reference
160:
161: // NOTE: Currently 'catalog' is ignored.
162:
163: // Does this table name represent the correct schema?
164: if (schema != null
165: && !stringCompare(schema, table_name.getSchema())) {
166: // If schema is present and we can't resolve to this schema then return 0
167: return 0;
168: }
169: if (table != null
170: && !stringCompare(table, table_name.getName())) {
171: // If table name is present and we can't resolve to this table name then
172: // return 0
173: return 0;
174: }
175:
176: if (column != null) {
177: if (!case_insensitive) {
178: // Can we resolve the column in this table?
179: int i = data_table_def.fastFindColumnName(column);
180: // If i doesn't equal -1 then we've found our column
181: return i == -1 ? 0 : 1;
182: } else {
183: // Case insensitive search (this is slower than case sensitive).
184: int resolve_count = 0;
185: int col_count = data_table_def.columnCount();
186: for (int i = 0; i < col_count; ++i) {
187: if (data_table_def.columnAt(i).getName()
188: .equalsIgnoreCase(column)) {
189: ++resolve_count;
190: }
191: }
192: return resolve_count;
193: }
194: } else { // if (column == null)
195: // Return the column count
196: return data_table_def.columnCount();
197: }
198: }
199:
200: public Variable resolveColumn(String catalog, String schema,
201: String table, String column) {
202:
203: // Does this table name represent the correct schema?
204: if (schema != null
205: && !stringCompare(schema, table_name.getSchema())) {
206: // If schema is present and we can't resolve to this schema
207: throw new Error("Incorrect schema.");
208: }
209: if (table != null
210: && !stringCompare(table, table_name.getName())) {
211: // If table name is present and we can't resolve to this table name
212: throw new Error("Incorrect table.");
213: }
214:
215: if (column != null) {
216: if (!case_insensitive) {
217: // Can we resolve the column in this table?
218: int i = data_table_def.fastFindColumnName(column);
219: if (i == -1) {
220: throw new Error("Could not resolve '" + column
221: + "'");
222: }
223: return new Variable(table_name, column);
224: } else {
225: // Case insensitive search (this is slower than case sensitive).
226: int col_count = data_table_def.columnCount();
227: for (int i = 0; i < col_count; ++i) {
228: String col_name = data_table_def.columnAt(i)
229: .getName();
230: if (col_name.equalsIgnoreCase(column)) {
231: return new Variable(table_name, col_name);
232: }
233: }
234: throw new Error("Could not resolve '" + column + "'");
235: }
236: } else { // if (column == null)
237: // Return the first column in the table
238: return new Variable(table_name, data_table_def.columnAt(0)
239: .getName());
240: }
241:
242: }
243:
244: public Variable[] allColumns() {
245: int col_count = data_table_def.columnCount();
246: Variable[] vars = new Variable[col_count];
247: for (int i = 0; i < col_count; ++i) {
248: vars[i] = new Variable(table_name, data_table_def.columnAt(
249: i).getName());
250: }
251: return vars;
252: }
253:
254: }
|