KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > platform > database > SybasePlatform


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.platform.database;
23
24 import java.io.*;
25 import java.sql.*;
26 import java.util.*;
27 import oracle.toplink.essentials.exceptions.*;
28 import oracle.toplink.essentials.expressions.*;
29 import oracle.toplink.essentials.internal.databaseaccess.*;
30 import oracle.toplink.essentials.internal.expressions.*;
31 import oracle.toplink.essentials.internal.helper.*;
32 import oracle.toplink.essentials.queryframework.*;
33 import oracle.toplink.essentials.sessions.SessionProfiler;
34 import oracle.toplink.essentials.internal.sessions.AbstractRecord;
35 import oracle.toplink.essentials.internal.sessions.AbstractSession;
36
37 /**
38  * <p><b>Purpose</b>: Provides Sybase specific behaviour.
39  * <p><b>Responsibilities</b>:<ul>
40  * <li> Native SQL for byte[], Date, Time, & Timestamp.
41  * <li> Native sequencing using @@IDENTITY.
42  * </ul>
43  *
44  * @since TOPLink/Java 1.0
45  */

46 public class SybasePlatform extends oracle.toplink.essentials.platform.database.DatabasePlatform {
47     // An array could be used here with the type being the index, but upon looking at the source some types are
48
// assigned negative values, making them unusable as indexes without guessing at modifying them.
49
// this attribute is used for registering output params in stored procedure calls. JConnect 5.5 requires
50
// that the API that accepts a string is called so we have a collection of strings to use.
51
protected Hashtable typeStrings;
52
53     protected Hashtable getTypeStrings() {
54         if (typeStrings == null) {
55             initializeTypeStrings();
56         }
57         return typeStrings;
58     }
59
60     protected synchronized void initializeTypeStrings() {
61         if (typeStrings == null) {
62             typeStrings = new Hashtable(30);
63             typeStrings.put(new Integer JavaDoc(Types.ARRAY), "ARRAY");
64             typeStrings.put(new Integer JavaDoc(Types.BIGINT), "BIGINT");
65             typeStrings.put(new Integer JavaDoc(Types.BINARY), "BINARY");
66             typeStrings.put(new Integer JavaDoc(Types.BIT), "BIT");
67             typeStrings.put(new Integer JavaDoc(Types.BLOB), "BLOB");
68             typeStrings.put(new Integer JavaDoc(Types.CHAR), "CHAR");
69             typeStrings.put(new Integer JavaDoc(Types.CLOB), "CLOB");
70             typeStrings.put(new Integer JavaDoc(Types.DATE), "DATE");
71             typeStrings.put(new Integer JavaDoc(Types.DECIMAL), "DECIMAL");
72             typeStrings.put(new Integer JavaDoc(Types.DOUBLE), "DOUBLE");
73             typeStrings.put(new Integer JavaDoc(Types.FLOAT), "FLOAT");
74             typeStrings.put(new Integer JavaDoc(Types.INTEGER), "INTEGER");
75             typeStrings.put(new Integer JavaDoc(Types.JAVA_OBJECT), "JAVA_OBJECT");
76             typeStrings.put(new Integer JavaDoc(Types.LONGVARBINARY), "LONGVARBINARY");
77             typeStrings.put(new Integer JavaDoc(Types.LONGVARCHAR), "LONGVARCHAR");
78             typeStrings.put(new Integer JavaDoc(Types.NULL), "NULL");
79             typeStrings.put(new Integer JavaDoc(Types.NUMERIC), "NUMERIC");
80             typeStrings.put(new Integer JavaDoc(Types.OTHER), "OTHER");
81             typeStrings.put(new Integer JavaDoc(Types.REAL), "REAL");
82             typeStrings.put(new Integer JavaDoc(Types.REF), "REF");
83             typeStrings.put(new Integer JavaDoc(Types.SMALLINT), "SMALLINT");
84             typeStrings.put(new Integer JavaDoc(Types.STRUCT), "STRUCT");
85             typeStrings.put(new Integer JavaDoc(Types.TIME), "TIME");
86             typeStrings.put(new Integer JavaDoc(Types.TIMESTAMP), "TIMESTAMP");
87             typeStrings.put(new Integer JavaDoc(Types.TINYINT), "TINYINT");
88             typeStrings.put(new Integer JavaDoc(Types.VARBINARY), "VARBINARY");
89             typeStrings.put(new Integer JavaDoc(Types.VARCHAR), "VARCHAR");
90         }
91     }
92
93     /**
94      * INTERNAL:
95      * If using native SQL then print a byte[] as '0xFF...'
96      */

97     protected void appendByteArray(byte[] bytes, Writer writer) throws IOException {
98         if (usesNativeSQL() && (!usesByteArrayBinding())) {
99             writer.write("0x");
100             Helper.writeHexString(bytes, writer);
101         } else {
102             super.appendByteArray(bytes, writer);
103         }
104     }
105
106     /**
107      * INTERNAL:
108      * Answer a platform correct string representation of a Date, suitable for SQL generation.
109      * Native format: 'yyyy-mm-dd
110      */

111     protected void appendDate(java.sql.Date JavaDoc date, Writer writer) throws IOException {
112         if (usesNativeSQL()) {
113             writer.write("'");
114             writer.write(Helper.printDate(date));
115             writer.write("'");
116         } else {
117             super.appendDate(date, writer);
118         }
119     }
120
121     /**
122      * INTERNAL:
123      * Write a timestamp in Sybase specific format (yyyy-mm-dd-hh.mm.ss.fff).
124      */

125     protected void appendSybaseTimestamp(java.sql.Timestamp JavaDoc timestamp, Writer writer) throws IOException {
126         writer.write("'");
127         writer.write(Helper.printTimestampWithoutNanos(timestamp));
128         writer.write(':');
129
130         // Must truncate the nanos to three decimal places,
131
// it is actually a complex algorithm...
132
String JavaDoc nanoString = Integer.toString(timestamp.getNanos());
133         int numberOfZeros = 0;
134         for (int num = Math.min(9 - nanoString.length(), 3); num > 0; num--) {
135             writer.write('0');
136             numberOfZeros++;
137         }
138         if ((nanoString.length() + numberOfZeros) > 3) {
139             nanoString = nanoString.substring(0, (3 - numberOfZeros));
140         }
141         writer.write(nanoString);
142         writer.write("'");
143     }
144
145     /**
146      * INTERNAL:
147      * Answer a platform correct string representation of a Time, suitable for SQL generation.
148      * The time is printed in the ODBC platform independent format {t'hh:mm:ss'}.
149      */

150     protected void appendTime(java.sql.Time JavaDoc time, Writer writer) throws IOException {
151         if (usesNativeSQL()) {
152             writer.write("'");
153             writer.write(Helper.printTime(time));
154             writer.write("'");
155         } else {
156             super.appendTime(time, writer);
157         }
158     }
159
160     /**
161      * INTERNAL:
162      * Answer a platform correct string representation of a Timestamp, suitable for SQL generation.
163      * The date is printed in the ODBC platform independent format {d'YYYY-MM-DD'}.
164      */

165     protected void appendTimestamp(java.sql.Timestamp JavaDoc timestamp, Writer writer) throws IOException {
166         if (usesNativeSQL()) {
167             appendSybaseTimestamp(timestamp, writer);
168         } else {
169             super.appendTimestamp(timestamp, writer);
170         }
171     }
172
173     /**
174      * INTERNAL:
175      * Answer a platform correct string representation of a Calendar, suitable for SQL generation.
176      * The date is printed in the ODBC platform independent format {d'YYYY-MM-DD'}.
177      */

178     protected void appendCalendar(Calendar calendar, Writer writer) throws IOException {
179         if (usesNativeSQL()) {
180             appendSybaseCalendar(calendar, writer);
181         } else {
182             super.appendCalendar(calendar, writer);
183         }
184     }
185
186     /**
187      * INTERNAL:
188      * Write a timestamp in Sybase specific format ( yyyy-mm-dd-hh.mm.ss.fff)
189      */

190     protected void appendSybaseCalendar(Calendar calendar, Writer writer) throws IOException {
191         writer.write("'");
192         writer.write(Helper.printCalendar(calendar));
193         writer.write("'");
194     }
195
196     /**
197      * INTERNAL:
198      * Build operator.
199      */

200     public ExpressionOperator atan2Operator() {
201         return ExpressionOperator.simpleTwoArgumentFunction(ExpressionOperator.Atan2, "ATN2");
202     }
203
204     protected Hashtable buildFieldTypes() {
205         Hashtable fieldTypeMapping;
206
207         fieldTypeMapping = new Hashtable();
208         fieldTypeMapping.put(Boolean JavaDoc.class, new FieldTypeDefinition("BIT default 0", false, false));
209
210         fieldTypeMapping.put(Integer JavaDoc.class, new FieldTypeDefinition("INTEGER", false));
211         fieldTypeMapping.put(Long JavaDoc.class, new FieldTypeDefinition("NUMERIC", 19));
212         fieldTypeMapping.put(Float JavaDoc.class, new FieldTypeDefinition("FLOAT(16)", false));
213         fieldTypeMapping.put(Double JavaDoc.class, new FieldTypeDefinition("FLOAT(32)", false));
214         fieldTypeMapping.put(Short JavaDoc.class, new FieldTypeDefinition("SMALLINT", false));
215         fieldTypeMapping.put(Byte JavaDoc.class, new FieldTypeDefinition("SMALLINT", false));
216         fieldTypeMapping.put(java.math.BigInteger JavaDoc.class, new FieldTypeDefinition("NUMERIC", 38));
217         fieldTypeMapping.put(java.math.BigDecimal JavaDoc.class, new FieldTypeDefinition("NUMERIC", 38).setLimits(38, -19, 19));
218         fieldTypeMapping.put(Number JavaDoc.class, new FieldTypeDefinition("NUMERIC", 38).setLimits(38, -19, 19));
219
220         fieldTypeMapping.put(String JavaDoc.class, new FieldTypeDefinition("VARCHAR", 255));
221         fieldTypeMapping.put(Character JavaDoc.class, new FieldTypeDefinition("CHAR", 1));
222         
223         fieldTypeMapping.put(Byte JavaDoc[].class, new FieldTypeDefinition("IMAGE", false));
224         fieldTypeMapping.put(Character JavaDoc[].class, new FieldTypeDefinition("TEXT", false));
225         fieldTypeMapping.put(byte[].class, new FieldTypeDefinition("IMAGE", false));
226         fieldTypeMapping.put(char[].class, new FieldTypeDefinition("TEXT", false));
227         fieldTypeMapping.put(java.sql.Blob JavaDoc.class, new FieldTypeDefinition("IMAGE", false));
228         fieldTypeMapping.put(java.sql.Clob JavaDoc.class, new FieldTypeDefinition("TEXT", false));
229         
230         fieldTypeMapping.put(java.sql.Date JavaDoc.class, new FieldTypeDefinition("DATETIME", false));
231         fieldTypeMapping.put(java.sql.Time JavaDoc.class, new FieldTypeDefinition("DATETIME", false));
232         fieldTypeMapping.put(java.sql.Timestamp JavaDoc.class, new FieldTypeDefinition("DATETIME", false));
233
234         return fieldTypeMapping;
235     }
236
237     /**
238      * INTERNAL:
239      * Build the identity query for native sequencing.
240      */

241     public ValueReadQuery buildSelectQueryForNativeSequence() {
242         ValueReadQuery selectQuery = new ValueReadQuery();
243         StringWriter writer = new StringWriter();
244         writer.write("SELECT @@IDENTITY");
245         selectQuery.setSQLString(writer.toString());
246         return selectQuery;
247     }
248
249     /**
250      * INTERNAL:
251      * Because each platform has different requirements for accessing stored procedures and
252      * the way that we can combine resultsets and output params the stored procedure call
253      * is being executed on the platform. This entire process needs some serious refactoring to eliminate
254      * the chance of bugs.
255      */

256     public Object JavaDoc executeStoredProcedure(DatabaseCall dbCall, PreparedStatement statement, DatabaseAccessor accessor, AbstractSession session) throws SQLException {
257         Object JavaDoc result = null;
258         ResultSet resultSet = null;
259         if (!dbCall.getReturnsResultSet()) {
260             accessor.executeDirectNoSelect(statement, dbCall, session);
261             result = accessor.buildOutputRow((CallableStatement)statement, dbCall, session);
262
263             //ReadAllQuery may be returning just output params, or they may be executing a DataReadQuery, which also
264
//assumes a vector
265
if (dbCall.areManyRowsReturned()) {
266                 Vector tempResult = new Vector();
267                 ((Vector)tempResult).add(result);
268                 result = tempResult;
269             }
270         } else {
271             // start the process of procesing the result set and the output params. this is specific to Sybase JConnect 5.5
272
// as we must process the result set before the output params.
273
session.startOperationProfile(SessionProfiler.STATEMENT_EXECUTE);
274             try {
275                 resultSet = statement.executeQuery();
276             } finally {
277                 session.endOperationProfile(SessionProfiler.STATEMENT_EXECUTE);
278             }
279             dbCall.matchFieldOrder(resultSet, accessor, session);
280
281             // cursored result set and output params not supported because of database limitation
282
if (dbCall.isCursorReturned()) {
283                 dbCall.setStatement(statement);
284                 dbCall.setResult(resultSet);
285                 return dbCall;
286             }
287             result = processResultSet(resultSet, dbCall, statement, accessor, session);
288
289             if (dbCall.shouldBuildOutputRow()) {
290                 AbstractRecord outputRow = accessor.buildOutputRow((CallableStatement)statement, dbCall, session);
291                 dbCall.getQuery().setProperty("output", outputRow);
292                 session.getEventManager().outputParametersDetected(outputRow, dbCall);
293             }
294             return result;
295             // end special sybase behaviour.
296
}
297         return result;
298     }
299
300     /**
301      * INTERNAL:
302      * Used for batch writing and sp defs.
303      */

304     public String JavaDoc getBatchDelimiterString() {
305         return "";
306     }
307
308     /**
309      * INTERNAL:
310      * This method is used to print the required output parameter token for the
311      * specific platform. Used when stored procedures are created.
312      */

313     public String JavaDoc getCreationInOutputProcedureToken() {
314         return getInOutputProcedureToken();
315     }
316
317     /**
318      * INTERNAL:
319      * This method was added because SQLServer requires the output paramater token
320      * to be set on creation but not on execution.
321      */

322     public String JavaDoc getCreationOutputProcedureToken() {
323         return getOutputProcedureToken();
324     }
325
326     /**
327      * INTERNAL:
328      * This method is used to print the output parameter token when stored
329      * procedures are called
330      */

331     public String JavaDoc getInOutputProcedureToken() {
332         return "OUT";
333     }
334
335     /**
336      * INTERNAL:
337      * Returns the type name corresponding to the jdbc type
338      */

339     public String JavaDoc getJdbcTypeName(int jdbcType) {
340         return (String JavaDoc)getTypeStrings().get(new Integer JavaDoc(jdbcType));
341     }
342
343     /**
344      * INTERNAL:
345      * returns the maximum number of characters that can be used in a field
346      * name on this platform.
347      */

348     public int getMaxFieldNameSize() {
349         return 22;
350     }
351
352     /**
353      * INTERNAL:
354      * Return the catalog information through using the native SQL catalog selects.
355      * This is required because many JDBC driver do not support meta-data.
356      * Willcards can be passed as arguments.
357      */

358     public Vector getNativeTableInfo(String JavaDoc table, String JavaDoc creator, AbstractSession session) {
359         // need to filter only tables / views
360
String JavaDoc query = "SELECT * FROM sysobjects WHERE table_type <> 'SYSTEM_TABLE'";
361         if (table != null) {
362             if (table.indexOf('%') != -1) {
363                 query = query + " AND table_name LIKE " + table;
364             } else {
365                 query = query + " AND table_name = " + table;
366             }
367         }
368         if (creator != null) {
369             if (creator.indexOf('%') != -1) {
370                 query = query + " AND table_owner LIKE " + creator;
371             } else {
372                 query = query + " AND table_owner = " + creator;
373             }
374         }
375         return session.executeSelectingCall(new oracle.toplink.essentials.queryframework.SQLCall(query));
376     }
377
378     /**
379      * INTERNAL:
380      * This method is used to print the output parameter token when stored
381      * procedures are called
382      */

383     public String JavaDoc getOutputProcedureToken() {
384         return "OUTPUT";
385     }
386
387     /**
388      * INTERNAL:
389      * Used for sp defs.
390      */

391     public String JavaDoc getProcedureArgumentString() {
392         return "@";
393     }
394
395     /**
396      * INTERNAL:
397      * Used for sp calls.
398      */

399     public String JavaDoc getProcedureCallHeader() {
400         return "EXECUTE ";
401     }
402
403     /**
404      * INTERNAL:
405      */

406     public String JavaDoc getStoredProcedureParameterPrefix() {
407         return "@";
408     }
409
410     /**
411      * INTERNAL:
412      * This method returns the delimiter between stored procedures in multiple stored procedure
413      * calls.
414      */

415     public String JavaDoc getStoredProcedureTerminationToken() {
416         return " go";
417     }
418
419     /**
420      * INTERNAL:
421      * This method returns the query to select the timestamp
422      * from the server for Sybase.
423      */

424     public ValueReadQuery getTimestampQuery() {
425         if (timestampQuery == null) {
426             timestampQuery = new ValueReadQuery();
427             timestampQuery.setSQLString("SELECT GETDATE()");
428         }
429         return timestampQuery;
430     }
431
432     /**
433      * INTERNAL:
434      * Initialize any platform-specific operators
435      */

436     protected void initializePlatformOperators() {
437         super.initializePlatformOperators();
438         addOperator(operatorOuterJoin());
439         addOperator(ExpressionOperator.simpleFunction(ExpressionOperator.Today, "GETDATE"));
440         // GETDATE retuens both date and time. It is not the perfect match for ExpressionOperator.currentDate
441
// However, there is no known function on sybase that returns just the date
442
addOperator(ExpressionOperator.simpleFunction(ExpressionOperator.currentDate, "GETDATE"));
443         addOperator(ExpressionOperator.simpleFunction(ExpressionOperator.Length, "CHAR_LENGTH"));
444         addOperator(ExpressionOperator.sybaseLocateOperator());
445         addOperator(ExpressionOperator.simpleThreeArgumentFunction(ExpressionOperator.Substring, "SUBSTRING"));
446         addOperator(ExpressionOperator.addDate());
447         addOperator(ExpressionOperator.dateName());
448         addOperator(ExpressionOperator.datePart());
449         addOperator(ExpressionOperator.dateDifference());
450         addOperator(ExpressionOperator.difference());
451         addOperator(ExpressionOperator.charIndex());
452         addOperator(ExpressionOperator.charLength());
453         addOperator(ExpressionOperator.reverse());
454         addOperator(ExpressionOperator.replicate());
455         addOperator(ExpressionOperator.right());
456         addOperator(ExpressionOperator.cot());
457         addOperator(ExpressionOperator.sybaseAtan2Operator());
458         addOperator(ExpressionOperator.sybaseAddMonthsOperator());
459         addOperator(ExpressionOperator.sybaseInStringOperator());
460         // bug 3061144
461
addOperator(ExpressionOperator.simpleTwoArgumentFunction(ExpressionOperator.Nvl, "ISNULL"));
462         // CR### TO_NUMBER, TO_CHAR, TO_DATE is CONVERT(type, ?)
463
addOperator(ExpressionOperator.sybaseToNumberOperator());
464         addOperator(ExpressionOperator.sybaseToDateToStringOperator());
465         addOperator(ExpressionOperator.sybaseToDateOperator());
466         addOperator(ExpressionOperator.sybaseToCharOperator());
467         addOperator(ExpressionOperator.simpleFunction(ExpressionOperator.Ceil, "CEILING"));
468         addOperator(modOperator());
469     }
470
471     public boolean isSybase() {
472         return true;
473     }
474
475     /**
476      * INTERNAL:
477      * Builds a table of maximum numeric values keyed on java class. This is used for type testing but
478      * might also be useful to end users attempting to sanitize values.
479      * <p><b>NOTE</b>: BigInteger & BigDecimal maximums are dependent upon their precision & Scale
480      */

481     public Hashtable maximumNumericValues() {
482         Hashtable values = new Hashtable();
483
484         values.put(Integer JavaDoc.class, new Integer JavaDoc(Integer.MAX_VALUE));
485         values.put(Long JavaDoc.class, new Long JavaDoc(Long.MAX_VALUE));
486         values.put(Double JavaDoc.class, new Double JavaDoc((double)Float.MAX_VALUE));
487         values.put(Short JavaDoc.class, new Short JavaDoc(Short.MAX_VALUE));
488         values.put(Byte JavaDoc.class, new Byte JavaDoc(Byte.MAX_VALUE));
489         values.put(Float JavaDoc.class, new Float JavaDoc(Float.MAX_VALUE));
490         values.put(java.math.BigInteger JavaDoc.class, new java.math.BigInteger JavaDoc("99999999999999999999999999999999999999"));
491         values.put(java.math.BigDecimal JavaDoc.class, new java.math.BigDecimal JavaDoc("9999999999999999999.9999999999999999999"));
492         return values;
493     }
494
495     /**
496      * INTERNAL:
497      * Builds a table of minimum numeric values keyed on java class. This is used for type testing but
498      * might also be useful to end users attempting to sanitize values.
499      * <p><b>NOTE</b>: BigInteger & BigDecimal minimums are dependent upon their precision & Scale
500      */

501     public Hashtable minimumNumericValues() {
502         Hashtable values = new Hashtable();
503
504         values.put(Integer JavaDoc.class, new Integer JavaDoc(Integer.MIN_VALUE));
505         values.put(Long JavaDoc.class, new Long JavaDoc(Long.MIN_VALUE));
506         values.put(Double JavaDoc.class, new Double JavaDoc((double)1.4012984643247149E-44));// The double values are weird. They lose precision at E-45
507
values.put(Short JavaDoc.class, new Short JavaDoc(Short.MIN_VALUE));
508         values.put(Byte JavaDoc.class, new Byte JavaDoc(Byte.MIN_VALUE));
509         values.put(Float JavaDoc.class, new Float JavaDoc(Float.MIN_VALUE));
510         values.put(java.math.BigInteger JavaDoc.class, new java.math.BigInteger JavaDoc("-99999999999999999999999999999999999999"));
511         values.put(java.math.BigDecimal JavaDoc.class, new java.math.BigDecimal JavaDoc("-9999999999999999999.9999999999999999999"));
512         return values;
513     }
514
515     /**
516      * INTERNAL:
517      * Override the default MOD operator.
518      */

519     public ExpressionOperator modOperator() {
520         ExpressionOperator result = new ExpressionOperator();
521         result.setSelector(ExpressionOperator.Mod);
522         Vector v = new Vector();
523         v.addElement(" % ");
524         result.printsAs(v);
525         result.bePostfix();
526         result.setNodeClass(oracle.toplink.essentials.internal.expressions.FunctionExpression.class);
527         return result;
528     }
529
530     /**
531      * INTERNAL:
532      * Create the outer join operator for this platform
533      */

534     protected ExpressionOperator operatorOuterJoin() {
535         ExpressionOperator result = new ExpressionOperator();
536         result.setSelector(ExpressionOperator.EqualOuterJoin);
537         Vector v = new Vector();
538         v.addElement(" =* ");
539         result.printsAs(v);
540         result.bePostfix();
541         result.setNodeClass(RelationExpression.class);
542         return result;
543     }
544
545     /**
546      * INTERNAL:
547      * Append the receiver's field 'identity' constraint clause to a writer.
548      */

549     public void printFieldIdentityClause(Writer writer) throws ValidationException {
550         try {
551             writer.write(" IDENTITY");
552         } catch (IOException ioException) {
553             throw ValidationException.fileError(ioException);
554         }
555     }
556
557     /**
558      * INTERNAL:
559      * Append the receiver's field 'NULL' constraint clause to a writer.
560      */

561     public void printFieldNullClause(Writer writer) throws ValidationException {
562         try {
563             writer.write(" NULL");
564         } catch (IOException ioException) {
565             throw ValidationException.fileError(ioException);
566         }
567     }
568
569     /**
570      * INTERNAL:
571      * This method is used to register output parameter on Callable Statements for Stored Procedures
572      * as each database seems to have a different method.
573      */

574     public void registerOutputParameter(CallableStatement statement, int index, int jdbcType) throws SQLException {
575         statement.registerOutParameter(index, jdbcType, (String JavaDoc)getTypeStrings().get(new Integer JavaDoc(jdbcType)));
576     }
577
578     /**
579      * INTERNAL:
580      * USed for sp calls.
581      */

582     public boolean requiresProcedureCallBrackets() {
583         return false;
584     }
585
586     /**
587      * INTERNAL:
588      * Used for sp calls. Sybase must print output after output params.
589      */

590     public boolean requiresProcedureCallOuputToken() {
591         return true;
592     }
593
594     /**
595      * INTERNAL:
596      * Indicates whether the version of CallableStatement.registerOutputParameter method
597      * that takes type name should be used.
598      */

599     public boolean requiresTypeNameToRegisterOutputParameter() {
600         return true;
601     }
602
603     /**
604      * INTERNAL:
605      * This is required in the construction of the stored procedures with
606      * output parameters
607      */

608     public boolean shouldPrintInOutputTokenBeforeType() {
609         return false;
610     }
611
612     /**
613      * INTERNAL:
614      * Some database require outer joins to be given in the where clause, others require it in the from clause.
615      */

616     public boolean shouldPrintOuterJoinInWhereClause() {
617         return false;
618     }
619
620     /**
621      * INTERNAL:
622      * This is required in the construction of the stored procedures with
623      * output parameters
624      */

625     public boolean shouldPrintOutputTokenBeforeType() {
626         return false;
627     }
628
629     /**
630      * INTERNAL:
631      * If native sequencing is being used on Sybase then the values must be
632      * retrieved after the insert.
633      * This method is to be used *ONLY* by sequencing classes
634      */

635     public boolean shouldNativeSequenceAcquireValueAfterInsert() {
636         return true;
637     }
638
639     /**
640      * INTERNAL:
641      * JDBC defines and outer join syntax, many drivers do not support this. So we normally avoid it.
642      */

643     public boolean shouldUseJDBCOuterJoinSyntax() {
644         return false;
645     }
646
647     /**
648      * INTERNAL:
649      * Return true if the receiver uses host sequence numbers, generated on the database.
650      * Sybase does through IDENTITY field types.
651      */

652     public boolean supportsNativeSequenceNumbers() {
653         return true;
654     }
655
656     /**
657      * INTERNAL:
658      */

659     public boolean supportsLocalTempTables() {
660         return true;
661     }
662      
663     /**
664      * INTERNAL:
665      */

666     protected String JavaDoc getCreateTempTableSqlPrefix() {
667         return "CREATE TABLE ";
668     }
669
670     /**
671      * INTERNAL:
672      */

673     public DatabaseTable getTempTableForTable(DatabaseTable table) {
674         return new DatabaseTable("#" + table.getName(), table.getTableQualifier());
675     }
676
677     /**
678      * INTERNAL:
679      */

680     public void writeUpdateOriginalFromTempTableSql(Writer writer, DatabaseTable table,
681                                                     Collection pkFields,
682                                                     Collection assignedFields) throws IOException
683     {
684         writer.write("UPDATE ");
685         String JavaDoc tableName = table.getQualifiedName();
686         writer.write(tableName);
687         String JavaDoc tempTableName = getTempTableForTable(table).getQualifiedName();
688         writeAutoAssignmentSetClause(writer, null, tempTableName, assignedFields);
689         writer.write(" FROM ");
690         writer.write(tableName);
691         writer.write(", ");
692         writer.write(tempTableName);
693         writeAutoJoinWhereClause(writer, tableName, tempTableName, pkFields);
694     }
695 }
696
Popular Tags