001: /*
002: * TableIdentifier.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.db;
013:
014: import java.sql.SQLException;
015: import java.util.ArrayList;
016: import java.util.List;
017: import workbench.resource.ResourceMgr;
018: import workbench.util.SqlUtil;
019: import workbench.util.StringUtil;
020: import workbench.util.WbStringTokenizer;
021:
022: /**
023: *
024: * @author support@sql-workbench.net
025: */
026: public class TableIdentifier implements DbObject,
027: Comparable<TableIdentifier> {
028: private String tablename;
029: private String schema;
030: private String catalog;
031: private String expression;
032: private boolean isNewTable;
033: private boolean tableWasQuoted;
034: private boolean catalogWasQuoted;
035: private boolean schemaWasQuoted;
036: private String pkName;
037: private String type;
038: private boolean neverAdjustCase;
039: private boolean preserveQuotes;
040: private boolean showOnlyTableName;
041:
042: public TableIdentifier(String aName) {
043: this .expression = null;
044: this .isNewTable = false;
045: this .setTable(aName);
046: }
047:
048: public TableIdentifier(String aName, WbConnection conn) {
049: this .expression = null;
050: this .isNewTable = false;
051: this .setTable(aName);
052: this .adjustCase(conn);
053: }
054:
055: /**
056: * Initialize a TableIdentifier for a new (to be defined) table
057: * This is mainly used by the {@link workbench.db.datacopy.DataCopier}
058: * to flag the target table to be created on the fly
059: */
060: public TableIdentifier() {
061: this .expression = null;
062: this .schema = null;
063: this .catalog = null;
064: this .tablename = null;
065: this .isNewTable = true;
066: }
067:
068: public TableIdentifier(String aSchema, String aTable) {
069: this .setCatalog(null);
070: this .setTable(aTable);
071: this .setSchema(aSchema);
072: }
073:
074: public TableIdentifier(String aCatalog, String aSchema,
075: String aTable) {
076: this .setTable(aTable);
077: this .setCatalog(aCatalog);
078: this .setSchema(aSchema);
079: }
080:
081: public String getObjectName(WbConnection conn) {
082: return conn.getMetadata().quoteObjectname(this .tablename);
083: }
084:
085: public String getObjectExpression(WbConnection conn) {
086: return getTableExpression(conn);
087: }
088:
089: public String getObjectType() {
090: if (type == null)
091: return "TABLE";
092: return type.toUpperCase();
093: }
094:
095: public String getObjectName() {
096: return getTableName();
097: }
098:
099: public void setPreserveQuotes(boolean flag) {
100: this .preserveQuotes = flag;
101: }
102:
103: public boolean getNeverAdjustCase() {
104: return this .neverAdjustCase;
105: }
106:
107: public void setNeverAdjustCase(boolean flag) {
108: this .neverAdjustCase = flag;
109: }
110:
111: public void checkQuotesNeeded(WbConnection con) {
112: if (con == null)
113: return;
114: DbMetadata meta = con.getMetadata();
115: this .schemaWasQuoted = !meta.isDefaultCase(this .schema);
116: this .catalogWasQuoted = !meta.isDefaultCase(this .catalog);
117: this .tableWasQuoted = !meta.isDefaultCase(this .tablename);
118: this .preserveQuotes = (this .schemaWasQuoted
119: || this .catalogWasQuoted || this .tableWasQuoted);
120: if (!preserveQuotes) {
121: this .setNeverAdjustCase(false);
122: }
123: }
124:
125: public TableIdentifier createCopy() {
126: TableIdentifier copy = new TableIdentifier();
127: copy.isNewTable = this .isNewTable;
128: copy.pkName = this .pkName;
129: copy.schema = this .schema;
130: copy.tablename = this .tablename;
131: copy.catalog = this .catalog;
132: copy.expression = null;
133: copy.neverAdjustCase = this .neverAdjustCase;
134: copy.tableWasQuoted = this .tableWasQuoted;
135: copy.catalogWasQuoted = this .catalogWasQuoted;
136: copy.schemaWasQuoted = this .schemaWasQuoted;
137: copy.showOnlyTableName = this .showOnlyTableName;
138: copy.preserveQuotes = this .preserveQuotes;
139: copy.type = this .type;
140: return copy;
141: }
142:
143: public String getTableExpression() {
144: if (this .expression == null)
145: this .initExpression();
146: return this .expression;
147: }
148:
149: public int hashCode() {
150: return getTableExpression().hashCode();
151: }
152:
153: public String getTableExpression(WbConnection conn) {
154: return this .buildTableExpression(conn);
155: }
156:
157: private void initExpression() {
158: this .expression = this .buildTableExpression(null);
159: }
160:
161: private String buildTableExpression(WbConnection conn) {
162: if (this .isNewTable) {
163: if (this .tablename == null) {
164: return ResourceMgr.getString("TxtNewTableIdentifier");
165: } else {
166: return this .tablename;
167: }
168: }
169:
170: StringBuilder result = new StringBuilder(30);
171: if (conn == null) {
172: if (this .catalog != null) {
173: result.append(SqlUtil.quoteObjectname(this .catalog,
174: preserveQuotes && catalogWasQuoted));
175: result.append('.');
176: }
177: if (this .schema != null) {
178: result.append(SqlUtil.quoteObjectname(this .schema,
179: preserveQuotes && schemaWasQuoted));
180: result.append('.');
181: }
182: result.append(SqlUtil.quoteObjectname(this .tablename,
183: preserveQuotes && tableWasQuoted));
184: } else {
185: DbMetadata meta = conn.getMetadata();
186: this .adjustCase(conn);
187: if (meta.needCatalogInDML(this )) {
188: String catalogToUse = this .catalog;
189: if (catalogToUse == null) {
190: catalogToUse = meta.getCurrentCatalog();
191: }
192:
193: if (catalogToUse != null
194: && !meta.ignoreCatalog(catalogToUse)) {
195: result.append(meta.quoteObjectname(catalogToUse,
196: preserveQuotes && catalogWasQuoted));
197: result.append('.');
198: }
199: }
200:
201: if (meta.needSchemaInDML(this )) {
202: String schemaToUse = this .schema;
203: if (schemaToUse == null) {
204: schemaToUse = meta.getSchemaToUse();
205: }
206:
207: if (schemaToUse != null
208: && !meta.ignoreSchema(schemaToUse)) {
209: result.append(meta.quoteObjectname(schemaToUse,
210: preserveQuotes && schemaWasQuoted));
211: result.append('.');
212: }
213: }
214:
215: result.append(meta.quoteObjectname(this .tablename,
216: preserveQuotes && tableWasQuoted));
217: }
218: return result.toString();
219: }
220:
221: public void adjustCase(WbConnection conn) {
222: if (this .neverAdjustCase)
223: return;
224: if (conn == null)
225: return;
226: DbMetadata meta = conn.getMetadata();
227:
228: if (this .tablename != null && !tableWasQuoted)
229: this .tablename = meta.adjustObjectnameCase(this .tablename);
230: if (this .schema != null && !schemaWasQuoted)
231: this .schema = meta.adjustSchemaNameCase(this .schema);
232: if (this .catalog != null && !catalogWasQuoted)
233: this .catalog = meta.adjustObjectnameCase(this .catalog);
234: this .expression = null;
235: }
236:
237: /**
238: * Return the fully qualified name of the table
239: * (including catalog and schema) but not quoted
240: * even if it needed quotes
241: */
242: public String getQualifiedName() {
243: StringBuilder result = new StringBuilder(32);
244: if (catalog != null) {
245: result.append(catalog);
246: result.append('.');
247: }
248: if (schema != null) {
249: result.append(schema);
250: result.append('.');
251: }
252: result.append(this .tablename);
253: return result.toString();
254: }
255:
256: String getRawCatalog() {
257: return this .catalog;
258: }
259:
260: String getRawTableName() {
261: return this .tablename;
262: }
263:
264: String getRawSchema() {
265: return this .schema;
266: }
267:
268: public String getTableName() {
269: if (tablename == null)
270: return null;
271: if (!tableWasQuoted || !preserveQuotes)
272: return this .tablename;
273:
274: StringBuilder result = new StringBuilder(tablename.length() + 2);
275: result.append('\"');
276: result.append(tablename);
277: result.append('\"');
278: return result.toString();
279: }
280:
281: public void setTable(String aTable) {
282: if (!this .isNewTable
283: && (aTable == null || aTable.trim().length() == 0))
284: throw new IllegalArgumentException(
285: "Table name may not be null");
286:
287: if (aTable == null) {
288: this .tablename = null;
289: this .schema = null;
290: this .expression = null;
291: return;
292: }
293:
294: List<String> elements = new ArrayList<String>(4);
295: WbStringTokenizer tok = new WbStringTokenizer('.', "\"", true);
296: tok.setSourceString(aTable);
297: while (tok.hasMoreTokens()) {
298: elements.add(tok.nextToken());
299: }
300:
301: if (elements.size() == 1) {
302: setTablename(aTable);
303: } else if (elements.size() == 2) {
304: setSchema(elements.get(0));
305: setTablename(elements.get(1));
306: } else if (elements.size() == 3) {
307: setCatalog(elements.get(0));
308: setSchema(elements.get(1));
309: setTablename(elements.get(2));
310: }
311:
312: this .expression = null;
313: }
314:
315: private void setTablename(String name) {
316: if (name == null)
317: return;
318: tableWasQuoted = name.trim().startsWith("\"");
319: this .tablename = StringUtil.trimQuotes(name).trim();
320: }
321:
322: public String getSchema() {
323: if (schema == null)
324: return null;
325: if (!schemaWasQuoted || !preserveQuotes)
326: return schema;
327:
328: StringBuilder result = new StringBuilder(schema.length() + 2);
329: result.append('\"');
330: result.append(schema);
331: result.append('\"');
332: return result.toString();
333: }
334:
335: public void setSchema(String aSchema) {
336: if (this .isNewTable)
337: return;
338:
339: if (aSchema == null || aSchema.trim().length() == 0) {
340: this .schema = null;
341: } else {
342: schemaWasQuoted = aSchema.trim().startsWith("\"");
343: this .schema = StringUtil.trimQuotes(aSchema).trim();
344: }
345: this .expression = null;
346: }
347:
348: public String getCatalog() {
349: if (catalog == null)
350: return null;
351: if (!catalogWasQuoted || !preserveQuotes)
352: return this .catalog;
353:
354: StringBuilder result = new StringBuilder(catalog.length() + 2);
355: result.append('\"');
356: result.append(catalog);
357: result.append('\"');
358: return result.toString();
359: }
360:
361: public void setCatalog(String aCatalog) {
362: if (this .isNewTable)
363: return;
364:
365: if (aCatalog == null || aCatalog.trim().length() == 0) {
366: this .catalog = null;
367: } else {
368: catalogWasQuoted = aCatalog.trim().startsWith("\"");
369: this .catalog = StringUtil.trimQuotes(aCatalog).trim();
370: }
371: this .expression = null;
372: }
373:
374: public String toString() {
375: if (this .isNewTable) {
376: if (this .tablename == null) {
377: return this .getTableExpression();
378: } else {
379: return "(+) " + this .tablename;
380: }
381: } else if (this .showOnlyTableName) {
382: return this .getTableName();
383: } else {
384: return this .getTableExpression();
385: }
386: }
387:
388: public boolean isNewTable() {
389: return this .isNewTable;
390: }
391:
392: public void setNewTable(boolean flag) {
393: this .expression = null;
394: this .isNewTable = flag;
395: }
396:
397: public void setShowTablenameOnly(boolean flag) {
398: this .showOnlyTableName = flag;
399: }
400:
401: public int compareTo(TableIdentifier other) {
402: return this .getTableExpression().compareTo(
403: other.getTableExpression());
404: }
405:
406: public boolean equals(Object other) {
407: if (other instanceof TableIdentifier) {
408: boolean result = false;
409: TableIdentifier t = (TableIdentifier) other;
410: if (this .isNewTable && t.isNewTable) {
411: result = true;
412: } else if (this .isNewTable || t.isNewTable) {
413: result = false;
414: } else {
415: result = this .getTableExpression().equals(
416: t.getTableExpression());
417: }
418: return result;
419: }
420: return false;
421: }
422:
423: /**
424: * Compare this TableIdentifier to another. The schema and catalog fields
425: * are only compared if bothe identifiers have them. This is different
426: * to the equals() method, which returns false if one TableIdentifier has
427: * a schema and/or catalog and the other doesn't
428: */
429: public boolean compareNames(TableIdentifier other) {
430: boolean result = false;
431: if (this .isNewTable && other.isNewTable) {
432: result = true;
433: } else if (this .isNewTable || other.isNewTable) {
434: result = false;
435: } else {
436: result = this .getTableName().equals(other.getTableName());
437: if (result && this .schema != null && other.schema != null) {
438: result = this .schema.equals(other.schema);
439: }
440: if (result && this .catalog != null && other.catalog != null) {
441: result = this .catalog.equals(other.catalog);
442: }
443: }
444: return result;
445: }
446:
447: public String getPrimaryKeyName() {
448: return this .pkName;
449: }
450:
451: public void setPrimaryKeyName(String name) {
452: this .pkName = name;
453: }
454:
455: public String getType() {
456: return type;
457: }
458:
459: public void setType(String type) {
460: this .type = type;
461: }
462:
463: public CharSequence getSource(WbConnection con) throws SQLException {
464: CharSequence source = null;
465: DbMetadata meta = con.getMetadata();
466: if (DbMetadata.MVIEW_NAME.equalsIgnoreCase(type)) {
467: source = meta.getExtendedViewSource(this , false);
468: } else if ("SYNONYM".equalsIgnoreCase(type)) {
469: source = meta.getSynonymSource(this );
470: } else if ("VIEW".equalsIgnoreCase(type)) {
471: source = meta.getExtendedViewSource(this , false);
472: } else if ("SEQUENCE".equalsIgnoreCase(type)) {
473: source = meta.getSequenceSource(getTableExpression(con));
474: } else {
475: source = meta.getTableSource(this , false, false);
476: }
477: return source;
478: }
479:
480: }
|