001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.jdbc.sql;
012:
013: import com.versant.core.jdbc.metadata.*;
014: import com.versant.core.jdbc.sql.conv.*;
015: import com.versant.core.jdbc.sql.exp.SqlExp;
016: import com.versant.core.jdbc.sql.exp.UnaryFunctionExp;
017: import com.versant.core.util.CharBuf;
018:
019: import java.util.Date;
020: import java.util.HashMap;
021: import java.sql.*;
022:
023: import com.versant.core.common.BindingSupportImpl;
024:
025: /**
026: * A driver for Daffodil pure Java database.
027: */
028: public class DaffodilSqlDriver extends SqlDriver {
029:
030: /**
031: * Get the name of this driver.
032: */
033: public String getName() {
034: return "daffodil";
035: }
036:
037: /**
038: * Get the default type mapping for the supplied JDBC type code from
039: * java.sql.Types or null if the type is not supported. There is no
040: * need to set the database or jdbcType on the mapping as this is done
041: * after this call returns. Subclasses should override this and to
042: * customize type mappings.
043: */
044: protected JdbcTypeMapping getTypeMapping(int jdbcType) {
045: switch (jdbcType) {
046: case Types.BIT:
047: return new JdbcTypeMapping("BOOLEAN", 0, 0,
048: JdbcTypeMapping.TRUE, JdbcTypeMapping.TRUE, null);
049: case Types.TINYINT:
050: return new JdbcTypeMapping("TINYINT", 0, 0,
051: JdbcTypeMapping.TRUE, JdbcTypeMapping.TRUE, null);
052: case Types.BIGINT:
053: return new JdbcTypeMapping("BIGINT", 0, 0,
054: JdbcTypeMapping.TRUE, JdbcTypeMapping.FALSE, null);
055: case Types.DOUBLE:
056: return new JdbcTypeMapping("DOUBLE PRECISION", 0, 0,
057: JdbcTypeMapping.TRUE, JdbcTypeMapping.FALSE, null);
058: case Types.LONGVARCHAR:
059: return new JdbcTypeMapping("LONG VARCHAR", 0, 0,
060: JdbcTypeMapping.TRUE, JdbcTypeMapping.FALSE, null);
061: case Types.CLOB:
062: return new JdbcTypeMapping("CLOB", 1024, 0,
063: JdbcTypeMapping.TRUE, JdbcTypeMapping.FALSE, null);
064: case Types.VARBINARY:
065: case Types.BLOB:
066: case Types.LONGVARBINARY:
067: return new JdbcTypeMapping("BLOB", 1024, 0,
068: JdbcTypeMapping.TRUE, JdbcTypeMapping.FALSE,
069: bytesConverterFactory);
070: }
071: return super .getTypeMapping(jdbcType);
072: }
073:
074: /**
075: * Should PreparedStatement batching be used for this database and
076: * JDBC driver?
077: */
078: public boolean isPreparedStatementPoolingOK() {
079: return false;
080: }
081:
082: /**
083: * Get the default field mappings for this driver. These map java classes
084: * to column properties. Subclasses should override this, call super() and
085: * replace mappings as needed.
086: */
087: public HashMap getJavaTypeMappings() {
088: HashMap ans = super .getJavaTypeMappings();
089:
090: // BooleanConverter.Factory bcf = new BooleanConverter.Factory();
091: // ((JdbcJavaTypeMapping)ans.get(Boolean.TYPE)).setConverterFactory(bcf);
092: // ((JdbcJavaTypeMapping)ans.get(Boolean.class)).setConverterFactory(bcf);
093:
094: DateTimestampConverter.Factory dtcf = new DateTimestampConverter.Factory();
095: ((JdbcJavaTypeMapping) ans.get(Date.class))
096: .setConverterFactory(dtcf);
097:
098: return ans;
099: }
100:
101: /**
102: * Does the JDBC driver support statement batching?
103: */
104: public boolean isInsertBatchingSupported() {
105: return true;
106: }
107:
108: /**
109: * Does the JDBC driver support statement batching for updates?
110: */
111: public boolean isUpdateBatchingSupported() {
112: return true;
113: }
114:
115: /**
116: * Does the JDBC driver support scrollable result sets?
117: */
118: public boolean isScrollableResultSetSupported() {
119: return true;
120: }
121:
122: /**
123: * Does this driver use the ANSI join syntax (i.e. the join clauses appear
124: * in the from list e.g. postgres)?
125: */
126: public boolean isAnsiJoinSyntax() {
127: return true;
128: }
129:
130: /**
131: * Is null a valid value for a column with a foreign key constraint?
132: */
133: public boolean isNullForeignKeyOk() {
134: return true;
135: }
136:
137: /**
138: * Create a default name generator instance for JdbcStore's using this
139: * driver.
140: */
141: public JdbcNameGenerator createJdbcNameGenerator() {
142: DefaultJdbcNameGenerator n = createDefaultJdbcNameGenerator();
143: n.setMaxColumnNameLength(128);
144: n.setMaxTableNameLength(128);
145: n.setMaxConstraintNameLength(128);
146: n.setMaxIndexNameLength(128);
147: return n;
148: }
149:
150: /**
151: * Drop the table and all its constraints etc. This must remove
152: * constraints to this table from other tables so it can be dropped.
153: */
154: public void dropTable(Connection con, String table, Statement stat)
155: throws SQLException {
156: stat.execute("drop table " + table + " cascade");
157: }
158:
159: /**
160: * Add the primary key constraint part of a create table statement to s.
161: */
162: protected void appendPrimaryKeyConstraint(JdbcTable t, CharBuf s) {
163: s.append("constraint ");
164: s.append(t.pkConstraintName);
165: s.append(" primary key (");
166: appendColumnNameList(t.pk, s);
167: s.append(')');
168: }
169:
170: /**
171: * Append an 'add constraint' statement for c.
172: */
173: protected void appendRefConstraint(final CharBuf s,
174: final JdbcConstraint c) {
175: s.append("alter table ");
176: s.append(c.src.name);
177: s.append(" add constraint ");
178: s.append(c.name);
179: s.append(" foreign key (");
180: appendColumnNameList(c.srcCols, s);
181: s.append(") references ");
182: s.append(c.dest.name);
183: s.append('(');
184: appendColumnNameList(c.dest.pk, s);
185: s.append(")");
186: }
187:
188: /**
189: * Append the from list entry for a table.
190: */
191: public void appendSqlFrom(JdbcTable table, String alias, CharBuf s) {
192: s.append(table.name);
193: if (alias != null) {
194: s.append(" AS ");
195: s.append(alias);
196: }
197: }
198:
199: /**
200: * Get the name of a function that accepts one argument.
201: * @see com.versant.core.jdbc.sql.exp.UnaryFunctionExp
202: */
203: public String getSqlUnaryFunctionName(int func) {
204: switch (func) {
205: case UnaryFunctionExp.FUNC_TO_LOWER_CASE:
206: return "lcase";
207: }
208: throw BindingSupportImpl.getInstance().internal(
209: "Unknown func: " + func);
210: }
211:
212: /**
213: * Append the from list entry for a table that is the right hand table
214: * in a join i.e. it is being joined to.
215: * @param exp This is the expression that joins the tables
216: * @param outer If true then this is an outer join
217: */
218: public void appendSqlFromJoin(JdbcTable table, String alias,
219: SqlExp exp, boolean outer, CharBuf s) {
220: if (outer)
221: s.append(" LEFT JOIN ");
222: else
223: s.append(" JOIN ");
224: s.append(table.name);
225: if (alias != null) {
226: s.append(" AS ");
227: s.append(alias);
228: }
229: if (exp != null) {
230: s.append(" ON (");
231: exp.appendSQL(this , s, null);
232: s.append(')');
233: }
234: }
235:
236: /**
237: * Get default SQL to test a connection or null if none available. This
238: * must be a query that returns at least one row.
239: */
240: public String getConnectionValidateSQL() {
241: return null;
242: }
243:
244: /**
245: * Get default SQL used to init a connection or null if none required.
246: */
247: public String getConnectionInitSQL() {
248: return null;
249: }
250:
251: /**
252: * Does this database support comments embedded in SQL?
253: */
254: public boolean isCommentSupported() {
255: return false;
256: }
257:
258: /**
259: * Should indexes be used for columns in the order by list that are
260: * also in the select list? This is used for databases that will not
261: * order by a column that is duplicated in the select list (e.g. Oracle).
262: */
263: public boolean isUseIndexesForOrderCols() {
264: return true;
265: }
266:
267: /**
268: * Get whatever needs to be appended to a SELECT statement to lock the
269: * rows if this makes sense for the database. This must have a leading
270: * space if not empty.
271: */
272: public char[] getSelectForUpdate() {
273: return null;
274: }
275:
276: }
|