1 //
2 // Copyright 1998 CDS Networks, Inc., Medford Oregon
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // 1. Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // 3. All advertising materials mentioning features or use of this software
14 // must display the following acknowledgement:
15 // This product includes software developed by CDS Networks, Inc.
16 // 4. The name of CDS Networks, Inc. may not be used to endorse or promote
17 // products derived from this software without specific prior
18 // written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY CDS NETWORKS, INC. ``AS IS'' AND
21 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 // ARE DISCLAIMED. IN NO EVENT SHALL CDS NETWORKS, INC. BE LIABLE
24 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 // SUCH DAMAGE.
31 //
32
33
34
35 /***
36 * A Statement object is used for executing a static SQL statement and
37 * obtaining the results produced by it.
38 *
39 * <p>Only one ResultSet per Statement can be open at any point in time.
40 * Therefore, if the reading of one ResultSet is interleaved with the
41 * reading of another, each must have been generated by different
42 * Statements. All statement execute methods implicitly close a
43 * statement's current ResultSet if an open one exists.
44 *
45 * @see java.sql.Statement
46 * @see ResultSet
47 * @version $Id: Statement.java,v 1.6 2007/01/15 11:03:43 alex Exp $
48 */
49 package com.internetcds.jdbc.tds;
50
51 import java.sql.*;
52
53
54 public class Statement implements java.sql.Statement
55 {
56 public static final String cvsVersion = "$Id: Statement.java,v 1.6 2007/01/15 11:03:43 alex Exp $";
57
58
59 private java.sql.Connection connection; // The connection who created us
60 // ResultSet currentResults = null; // The current results
61 protected SQLWarningChain warningChain; // The warnings chain.
62 protected int timeout = 0; // The timeout for a query
63
64 protected Tds tds = null;
65
66 protected java.sql.ResultSet results = null;
67 private java.sql.ResultSetMetaData metaResults = null;
68
69 private boolean escapeProcessing = true;
70
71 protected int updateCount = -1;
72
73 private int maxFieldSize = (1<<31)-1;
74 private int maxRows = 0;
75 private boolean isClosed = false;
76
77
78 /***
79 * Constructor for a Statement. It simply sets the connection
80 * that created us.
81 *
82 * @param connection_ the Connection instantation that creates us
83 * @param tds_ a TDS instance to use for communication with server.
84 */
85 public Statement(
86 Object connection_,
87 Tds tds_)
88 throws SQLException
89 {
90 tds = tds_;
91 connection = (java.sql.Connection)connection_;
92 warningChain = new SQLWarningChain();
93 }
94
95
96 private void NotImplemented() throws java.sql.SQLException
97 {
98 throw new SQLException("Not Implemented");
99 }
100
101 protected void finalize()
102 throws Throwable
103 {
104 super.finalize();
105
106 if (tds != null)
107 {
108 close();
109 }
110 }
111
112
113
114 /***
115 * Execute a SQL statement that retruns a single ResultSet
116 *
117 * @param Sql typically a static SQL SELECT statement
118 * @return a ResulSet that contains the data produced by the query
119 * @exception SQLException if a database access error occurs
120 */
121 public java.sql.ResultSet executeQuery(String sql) throws SQLException
122 {
123
124
125 if (execute(sql))
126 {
127 startResultSet();
128 }
129
130 return results;
131 }
132
133
134
135 /***
136 * Execute a SQL INSERT, UPDATE or DELETE statement. In addition
137 * SQL statements that return nothing such as SQL DDL statements
138 * can be executed
139 *
140 * Any IDs generated for AUTO_INCREMENT fields can be retrieved
141 * by looking through the SQLWarning chain of this statement
142 * for warnings of the form "LAST_INSERTED_ID = 'some number',
143 * COMMAND = 'your sql'".
144 *
145 * @param Sql a SQL statement
146 * @return either a row count, or 0 for SQL commands
147 * @exception SQLException if a database access error occurs
148 */
149
150 public int executeUpdate(String sql) throws SQLException
151 {
152 if (execute(sql))
153 {
154 startResultSet();
155 closeResults();
156 throw new SQLException("executeUpdate can't return a result set");
157 }
158 else
159 {
160 return getUpdateCount();
161 }
162 }
163
164 protected void closeResults()
165 throws java.sql.SQLException
166 {
167
168 if (results != null)
169 {
170 results.close();
171 results = null;
172 }
173 }
174
175 private void skipToEnd()
176 throws java.sql.SQLException, java.io.IOException,
177 com.internetcds.jdbc.tds.TdsUnknownPacketSubType,
178 com.internetcds.jdbc.tds.TdsException
179 {
180 boolean done;
181 PacketResult tmp;
182
183 do
184 {
185 tmp = tds.processSubPacket();
186 done = (tmp instanceof PacketEndTokenResult)
187 && (! ((PacketEndTokenResult)tmp).moreResults());
188 } while (! done);
189 }
190
191
192 public void commit()
193 throws java.sql.SQLException, java.io.IOException, com.internetcds.jdbc.tds.TdsUnknownPacketSubType, com.internetcds.jdbc.tds.TdsException
194 {
195 String sql = "IF @@TRANCOUNT > 0 COMMIT TRAN ";
196
197 if (tds == null)
198 {
199 throw new SQLException("Statement is closed");
200 }
201
202 executeQuery(sql);
203 skipToEnd();
204 }
205
206 public void rollback()
207 throws java.sql.SQLException, java.io.IOException, com.internetcds.jdbc.tds.TdsUnknownPacketSubType, com.internetcds.jdbc.tds.TdsException
208 {
209 String sql = "IF @@TRANCOUNT > 0 ROLLBACK TRAN ";
210
211 if (tds == null)
212 {
213 throw new SQLException("Statement is closed");
214 }
215
216 executeQuery(sql);
217 skipToEnd();
218 }
219
220 /***
221 * In many cases, it is desirable to immediately release a
222 * Statement's database and JDBC resources instead of waiting
223 * for this to happen when it is automatically closed. The
224 * close method provides this immediate release.
225 *
226 * <p><B>Note:</B> A Statement is automatically closed when it is
227 * garbage collected. When a Statement is closed, its current
228 * ResultSet, if one exists, is also closed.
229 *
230 * @exception SQLException if a database access error occurs (why?)
231 */
232 public void close() throws SQLException
233 {
234 closeResults();
235
236 // Rollback any pending transactions
237 /* try
238 {
239 rollback();
240 }
241 catch (com.internetcds.jdbc.tds.TdsUnknownPacketSubType e)
242 {
243 throw new SQLException("Unknown packet. \n" + e.getMessage());
244 }
245 catch (com.internetcds.jdbc.tds.TdsException e)
246 {
247 // XXX
248 // ignore this for now
249 }
250 catch (java.io.IOException e)
251 {
252 // XXX
253 // ignore this for now
254 }
255
256 */
257 // now we need to relinquish the connection
258 if (tds != null)
259 {
260 Tds tmpTds = tds;
261 tds = null;
262 try
263 {
264 ((ConnectionHelper)connection).relinquish(tmpTds);
265 }
266 catch(TdsException e)
267 {
268 throw new SQLException("Internal Error: " + e.getMessage());
269 }
270 }
271 try
272 {
273 ((ConnectionHelper)connection).markAsClosed(this);
274 }
275 catch(TdsException e)
276 {
277 throw new SQLException(e.getMessage());
278 }
279 this.isClosed = true;
280
281 }
282
283 /***
284 * The maxFieldSize limit (in bytes) is the maximum amount of
285 * data returned for any column value; it only applies to
286 * BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR
287 * columns. If the limit is exceeded, the excess data is silently
288 * discarded.
289 *
290 * @return the current max column size limit; zero means unlimited
291 * @exception SQLException if a database access error occurs
292 */
293
294 public int getMaxFieldSize() throws SQLException
295 {
296 return maxFieldSize;
297 }
298
299 /***
300 * Sets the maxFieldSize
301 *
302 * @param max the new max column size limit; zero means unlimited
303 * @exception SQLException if size exceeds buffer size
304 */
305
306 public void setMaxFieldSize(int max) throws SQLException
307 {
308 maxFieldSize = max;
309 }
310
311 /***
312 * The maxRows limit is set to limit the number of rows that
313 * any ResultSet can contain. If the limit is exceeded, the
314 * excess rows are silently dropped.
315 *
316 * @return the current maximum row limit; zero means unlimited
317 * @exception SQLException if a database access error occurs
318 */
319
320 public int getMaxRows() throws SQLException
321 {
322 return maxRows;
323 }
324
325 /***
326 * Set the maximum number of rows
327 *
328 * @param max the new max rows limit; zero means unlimited
329 * @exception SQLException if a database access error occurs
330 * @see getMaxRows
331 */
332
333 public void setMaxRows(int max) throws SQLException
334 {
335 if (maxRows < 0)
336 {
337 throw new SQLException("Negative row count");
338 }
339 maxRows = max;
340
341 this.executeUpdate("set rowcount " + maxRows);
342 }
343
344 /***
345 * If escape scanning is on (the default), the driver will do escape
346 * substitution before sending the SQL to the database.
347 *
348 * @param enable true to enable; false to disable
349 * @exception SQLException if a database access error occurs
350 */
351
352 public void setEscapeProcessing(boolean enable) throws SQLException
353 {
354 escapeProcessing = enable;
355 }
356
357 /***
358 * The queryTimeout limit is the number of seconds the driver
359 * will wait for a Statement to execute. If the limit is
360 * exceeded, a SQLException is thrown.
361 *
362 * @return the current query timeout limit in seconds; 0 = unlimited
363 * @exception SQLException if a database access error occurs
364 */
365
366 public int getQueryTimeout() throws SQLException
367 {
368 return timeout;
369 }
370
371 /***
372 * Sets the queryTimeout limit
373 *
374 * @param seconds - the new query timeout limit in seconds
375 * @exception SQLException if a database access error occurs
376 */
377
378 public void setQueryTimeout(int seconds) throws SQLException
379 {
380 timeout = seconds;
381 }
382
383 /***
384 *
385 * @exception SQLException
386 */
387 public void cancel() throws SQLException
388 {
389 if (tds == null)
390 {
391 throw new SQLException("Statement is closed");
392 }
393
394 try
395 {
396 tds.cancel();
397 }
398 catch(com.internetcds.jdbc.tds.TdsException e)
399 {
400 throw new SQLException(e.getMessage());
401 }
402 catch(java.io.IOException e)
403 {
404 throw new SQLException(e.getMessage());
405 }
406 }
407
408
409 /***
410 * The first warning reported by calls on this Statement is
411 * returned. A Statement's execute methods clear its SQLWarning
412 * chain. Subsequent Statement warnings will be chained to this
413 * SQLWarning.
414 *
415 * <p>The Warning chain is automatically cleared each time a statement
416 * is (re)executed.
417 *
418 * <p><B>Note:</B> If you are processing a ResultSet then any warnings
419 * associated with ResultSet reads will be chained on the ResultSet
420 * object.
421 *
422 * @return the first SQLWarning on null
423 * @exception SQLException if a database access error occurs
424 */
425 public SQLWarning getWarnings() throws SQLException
426 {
427 return warningChain.getWarnings();
428 }
429
430
431 /***
432 * After this call, getWarnings returns null until a new warning
433 * is reported for this Statement.
434 *
435 * @exception SQLException if a database access error occurs (why?)
436 */
437 public void clearWarnings() throws SQLException
438 {
439 warningChain.clearWarnings();
440 }
441
442 /***
443 * setCursorName defines the SQL cursor name that will be used by
444 * subsequent execute methods. This name can then be used in SQL
445 * positioned update/delete statements to identify the current row
446 * in the ResultSet generated by this statement. If a database
447 * doesn't support positioned update/delete, this method is a
448 * no-op.
449 *
450 *
451 * @param name the new cursor name
452 * @exception SQLException if a database access error occurs
453 */
454 public void setCursorName(String name) throws SQLException
455 {
456 NotImplemented();
457 }
458
459 /***
460 * @param sql any SQL statement
461 * @return true if the next result is a ResulSet, false if it is
462 * an update count or there are no more results
463 * @exception SQLException if a database access error occurs
464 */
465 public boolean execute(String sql) throws SQLException
466 {
467
468 SQLException exception = null;
469
470 if (tds == null)
471 {
472 throw new SQLException("Statement is closed");
473 }
474
475
476 closeResults();
477 clearWarnings();
478 updateCount = -1;
479 try
480 {
481 if (escapeProcessing)
482 {
483 sql = Tds.toNativeSql(sql, tds.getServerType());
484 }
485 tds.executeQuery(sql, this, timeout);
486 }
487 catch(java.io.IOException e)
488 {
489 throw new SQLException("Network error- " + e.getMessage());
490 }
491 catch(com.internetcds.jdbc.tds.TdsException e)
492 {
493 throw new SQLException("TDS error- " + e.getMessage());
494 }
495 return getMoreResults();
496 } // execute()
497
498
499 /***
500 * getResultSet returns the current result as a ResultSet. It
501 * should only be called once per result.
502 *
503 * @return the current result set; null if there are no more
504 * @exception SQLException if a database access error occurs
505 */
506 public java.sql.ResultSet getResultSet() throws SQLException
507 {
508 try
509 {
510 if (tds == null)
511 {
512 throw new SQLException("Statement is closed");
513 }
514 closeResults();
515
516 if (tds.peek()==TdsDefinitions.TDS_DONEINPROC)
517 {
518 PacketResult tmp = tds.processSubPacket();
519 }
520
521 if (tds.isResultSet()) // JJ 1999-01-09 used be: ;getMoreResults())
522 {
523 startResultSet();
524 }
525 else if (updateCount!=-1)
526 {
527 if (! tds.isEndOfResults())
528 {
529 // XXX
530 throw new SQLException("Internal error. "+
531 " expected EndOfResults, found 0x"
532 + Integer.toHexString(tds.peek()&0xff));
533 }
534 PacketEndTokenResult end =
535 (PacketEndTokenResult) tds.processSubPacket();
536 updateCount = end.getRowCount();
537 results = null;
538 }
539 else
540 {
541 // We didn't have more data and we didn't have an update count,
542 // now what?
543 throw new SQLException("Internal error. Confused");
544 }
545 }
546 catch(java.io.IOException e)
547 {
548 throw new SQLException(e.getMessage());
549 }
550 catch(TdsException e)
551 {
552 throw new SQLException(e.getMessage());
553 }
554
555 return results;
556 }
557
558 /***
559 * getUpdateCount returns the current result as an update count,
560 * if the result is a ResultSet or there are no more results, -1
561 * is returned. It should only be called once per result.
562 *
563 * @return the current result as an update count.
564 * @exception SQLException if a database access error occurs
565 */
566 public int getUpdateCount() throws SQLException
567 {
568 // if (updateCount == -1)
569 // {
570 // throw new SQLException("Don't have a count yet.");
571 // }
572 // XXX This isn't correct. We need to check to see if
573 // the result was a result set or if there are no more results.
574 // If either of those are true we are supposed to return -1
575 return updateCount;
576 }
577
578 /***
579 * getMoreResults moves to a Statement's next result. If it returns
580 * true, this result is a ResulSet.
581 *
582 * @return true if the next ResultSet is valid
583 * @exception SQLException if a database access error occurs
584 */
585 public boolean getMoreResults() throws SQLException
586 {
587 SQLException exception = null;
588 if (tds == null)
589 {
590 throw new SQLException("Statement is closed");
591 }
592
593 updateCount = -1; // Do we need this global variable?
594
595 if (!tds.moreResults())
596 {
597 return false;
598 }
599
600 closeResults(); // Reset all internal variables (why is this done here?)
601
602 try
603 {
604 tds.isResultSet();
605
606 // Keep eating garbage and warnings until we reach the next result
607 while (!tds.isResultSet() && !tds.isEndOfResults())
608 {
609 if (tds.isProcId())
610 {
611 tds.processSubPacket();
612 }
613 else if (tds.isDoneInProc())
614 {
615 PacketDoneInProcResult tmp =
616 (PacketDoneInProcResult)tds.processSubPacket();
617 }
618 else if (tds.isTextUpdate())
619 {
620 PacketResult tmp1 =
621 (PacketResult)tds.processSubPacket();
622 }
623 else if (tds.isMessagePacket() || tds.isErrorPacket())
624 {
625 PacketMsgResult tmp = (PacketMsgResult)tds.processSubPacket();
626 exception = warningChain.addOrReturn(tmp);
627 }
628 else if (tds.isReturnStatus())
629 {
630 tds.processSubPacket();
631 // skipToEnd();
632 }
633 else
634 {
635 throw new SQLException("Protocol confusion. "
636 + "Got a 0x"
637 + Integer.toHexString((tds.peek() & 0xff))
638 + " packet");
639 }
640 } // end while
641
642 if (exception != null)
643 {
644 try
645 {
646 tds.discardResultSet(null);
647 }
648 catch(java.io.IOException e)
649 {
650 throw new SQLException("Error discarding result set while processing sql error- " +
651 exception.getMessage() +
652 "\nIOException was " +
653 e.getMessage());
654 }
655 catch(com.internetcds.jdbc.tds.TdsException e)
656 {
657 throw new SQLException("Error discarding result set while processing sql error- " +
658 exception.getMessage() +
659 "\nIOException was " +
660 e.getMessage());
661 }
662 throw exception;
663 }
664
665 if (tds.isEndOfResults())
666 {
667 PacketEndTokenResult end =
668 (PacketEndTokenResult)tds.processSubPacket();
669 updateCount = end.getRowCount();
670 return false;
671
672 }
673 else if (tds.isResultSet())
674 {
675 return true;
676 }
677 else
678 {
679 throw new SQLException("Protocol confusion. "
680 + "Got a 0x"
681 + Integer.toHexString((tds.peek() & 0xff))
682 + " packet");
683 }
684 }
685
686 catch(java.io.IOException e)
687 {
688 throw new SQLException("Network error- " + e.getMessage());
689 }
690 catch(com.internetcds.jdbc.tds.TdsException e)
691 {
692 throw new SQLException("TDS error- " + e.getMessage());
693 }
694 }
695
696
697
698 protected void startResultSet()
699 throws SQLException
700 {
701
702 Columns names = null;
703 Columns info = null;
704 SQLException exception = null;
705
706
707 try
708 {
709 while (!tds.isResultRow() && !tds.isEndOfResults())
710 {
711 PacketResult tmp = tds.processSubPacket();
712
713 if (tmp.getPacketType() == TdsDefinitions.TDS_DONEINPROC)
714 {
715 // XXX We should do something with the possible ret_stat
716 }
717 else if (tmp instanceof PacketColumnNamesResult)
718 {
719 names = ((PacketColumnNamesResult)tmp).getColumnNames();
720 }
721 else if (tmp instanceof PacketColumnInfoResult)
722 {
723 info = ((PacketColumnInfoResult)tmp).getColumnInfo();
724 }
725 else if (tmp instanceof PacketColumnOrderResult)
726 {
727 // nop
728 // XXX do we want to do anything with this
729 }
730 else if (tmp instanceof PacketTabNameResult)
731 {
732 // nop
733 // XXX What should be done with this information?
734 }
735 else if (tmp instanceof PacketControlResult)
736 {
737 // nop
738 // XXX do we want to do anything with this
739 }
740 else if (tmp instanceof PacketMsgResult)
741 {
742 exception = warningChain.addOrReturn((PacketMsgResult)tmp);
743 }
744 else if (tmp instanceof PacketUnknown)
745 {
746 // XXX Need to add to the warning chain
747 }
748 else
749 {
750 throw new SQLException("Trying to get a result set. Found a "
751 + tmp.getClass().getName());
752 }
753 }
754
755 if (exception != null)
756 {
757 throw exception;
758 }
759 else if (!tds.isResultRow() && !tds.isEndOfResults())
760 {
761 // XXX
762 throw new SQLException("Confused. Was expecting a result row. "
763 + "Got a 0x" + Integer.toHexString(tds.peek() & 0xff));
764 }
765
766 // TDS 7.0 includes everything in one subpacket.
767 if (info != null)
768 names.merge(info);
769 results = Constructors.newResultSet(tds, this, names);
770 }
771 catch(com.internetcds.jdbc.tds.TdsException e)
772 {
773 e.printStackTrace();
774 throw new SQLException(e.getMessage());
775 }
776 catch( java.io.IOException e)
777 {
778 e.printStackTrace();
779 throw new SQLException(e.getMessage());
780 }
781 }
782
783
784
785
786 //--------------------------JDBC 2.0-----------------------------
787
788
789 /***
790 * JDBC 2.0
791 *
792 * Gives the driver a hint as to the direction in which
793 * the rows in a result set
794 * will be processed. The hint applies only to result sets created
795 * using this Statement object. The default value is
796 * ResultSet.FETCH_FORWARD.
797 * <p>Note that this method sets the default fetch direction for
798 * result sets generated by this <code>Statement</code> object.
799 * Each result set has its own methods for getting and setting
800 * its own fetch direction.
801 * @param direction the initial direction for processing rows
802 * @exception SQLException if a database access error occurs
803 * or the given direction
804 * is not one of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or
805 * ResultSet.FETCH_UNKNOWN
806 */
807 public void setFetchDirection(int direction) throws SQLException
808 {
809 NotImplemented();
810 }
811
812
813 /***
814 * JDBC 2.0
815 *
816 * Retrieves the direction for fetching rows from
817 * database tables that is the default for result sets
818 * generated from this <code>Statement</code> object.
819 * If this <code>Statement</code> object has not set
820 * a fetch direction by calling the method <code>setFetchDirection</code>,
821 * the return value is implementation-specific.
822 *
823 * @return the default fetch direction for result sets generated
824 * from this <code>Statement</code> object
825 * @exception SQLException if a database access error occurs
826 */
827 public int getFetchDirection() throws SQLException
828 {
829 NotImplemented();
830 return 0;
831 }
832
833
834 /***
835 * JDBC 2.0
836 *
837 * Gives the JDBC driver a hint as to the number of rows that should
838 * be fetched from the database when more rows are needed. The number
839 * of rows specified affects only result sets created using this
840 * statement. If the value specified is zero, then the hint is ignored.
841 * The default value is zero.
842 *
843 * @param rows the number of rows to fetch
844 * @exception SQLException if a database access error occurs, or the
845 * condition 0 <= rows <= this.getMaxRows() is not satisfied.
846 */
847 public void setFetchSize(int rows) throws SQLException
848 {
849 NotImplemented();
850 }
851
852
853 /***
854 * JDBC 2.0
855 *
856 * Retrieves the number of result set rows that is the default
857 * fetch size for result sets
858 * generated from this <code>Statement</code> object.
859 * If this <code>Statement</code> object has not set
860 * a fetch size by calling the method <code>setFetchSize</code>,
861 * the return value is implementation-specific.
862 * @return the default fetch size for result sets generated
863 * from this <code>Statement</code> object
864 * @exception SQLException if a database access error occurs
865 */
866 public int getFetchSize() throws SQLException
867 {
868 NotImplemented();
869 return 0;
870 }
871
872
873 /***
874 * JDBC 2.0
875 *
876 * Retrieves the result set concurrency.
877 */
878 public int getResultSetConcurrency() throws SQLException
879 {
880 NotImplemented();
881 return 0;
882 }
883
884
885 /***
886 * JDBC 2.0
887 *
888 * Determine the result set type.
889 */
890 public int getResultSetType() throws SQLException
891 {
892 NotImplemented();
893 return 0;
894 }
895
896
897 /***
898 * JDBC 2.0
899 *
900 * Adds a SQL command to the current batch of commmands for the statement.
901 * This method is optional.
902 *
903 * @param sql typically this is a static SQL INSERT or UPDATE statement
904 * @exception SQLException if a database access error occurs, or the
905 * driver does not support batch statements
906 */
907 public void addBatch( String sql ) throws SQLException
908 {
909 NotImplemented();
910 }
911
912 /***
913 * JDBC 2.0
914 *
915 * Makes the set of commands in the current batch empty.
916 * This method is optional.
917 *
918 * @exception SQLException if a database access error occurs or the
919 * driver does not support batch statements
920 */
921 public void clearBatch() throws SQLException
922 {
923 NotImplemented();
924 }
925
926
927 /***
928 * JDBC 2.0
929 *
930 * Submits a batch of commands to the database for execution.
931 * This method is optional.
932 *
933 * @return an array of update counts containing one element for each
934 * command in the batch. The array is ordered according
935 * to the order in which commands were inserted into the batch.
936 * @exception SQLException if a database access error occurs or the
937 * driver does not support batch statements
938 */
939 public int[] executeBatch() throws SQLException
940 {
941 NotImplemented();
942 return null;
943 }
944
945
946 /***
947 * JDBC 2.0
948 *
949 * Returns the <code>Connection</code> object
950 * that produced this <code>Statement</code> object.
951 * @return the connection that produced this statement
952 * @exception SQLException if a database access error occurs
953 */
954 public java.sql.Connection getConnection() throws SQLException
955 {
956 return connection;
957 }
958
959
960
961 //---------------------------------------------------------------------
962 // JDBC 3.0
963 //---------------------------------------------------------------------
964
965 public boolean getMoreResults(int current) throws SQLException {
966 throw new UnsupportedOperationException("Statement.getMoreResults(int) unsupported");
967 }
968
969 public ResultSet getGeneratedKeys() throws SQLException {
970 throw new UnsupportedOperationException("Statement.getGeneratedKeys() unsupported");
971 }
972
973 public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
974 throw new UnsupportedOperationException("Statement.executeUpdate(String,int) unsupported");
975 }
976
977 public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
978 throw new UnsupportedOperationException("Statement.executeUpdate(String,int[]) unsupported");
979 }
980
981 public int executeUpdate(String sql, String[] columnNames) throws SQLException {
982 throw new UnsupportedOperationException("Statement.executeUpdate(String,String[]) unsupported");
983 }
984
985 public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
986 throw new UnsupportedOperationException("Statement.execute(String,int) unsupported");
987 }
988
989 public boolean execute(String sql, int[] columnIndexes) throws SQLException {
990 throw new UnsupportedOperationException("Statement.execute(String,int[]) unsupported");
991 }
992
993 public boolean execute(String sql, String[] columnNames) throws SQLException {
994 throw new UnsupportedOperationException("Statement.execute(String,String[]) unsupported");
995 }
996
997 public int getResultSetHoldability() throws SQLException {
998 throw new UnsupportedOperationException("Statement.getResultSetHoldability() unsupported");
999 }
1000
1001
1002
1003
1004 static public void main(String args[])
1005 throws java.lang.ClassNotFoundException,
1006 java.lang.IllegalAccessException,
1007 java.lang.InstantiationException,
1008 SQLException
1009 {
1010
1011 String query = null;
1012
1013 String url = url = ""
1014 + "jdbc:freetds:"
1015 + "//"
1016 + "kap"
1017 + "/"
1018 + "pubs";
1019
1020 Class.forName("com.internetcds.jdbc.tds.Driver").newInstance();
1021 java.sql.Connection connection;
1022 connection = DriverManager.getConnection(url,
1023 "testuser",
1024 "password");
1025 java.sql.Statement stmt = connection.createStatement();
1026
1027 query = ""
1028 + "update titles "
1029 + " set price=price+1.00 "
1030 + " where title_id='MC3021' or title_id = 'BU1032' ";
1031 int count = stmt.executeUpdate(query);
1032 System.out.println("Updated " + count + " rows.");
1033
1034 query =
1035 ""
1036 +"select price, title_id, title, price*ytd_sales gross from titles"
1037 +" where title like 'The%'";
1038 java.sql.ResultSet rs = stmt.executeQuery(query);
1039
1040 while(rs.next())
1041 {
1042 float price = rs.getFloat("price");
1043 if (rs.wasNull())
1044 {
1045 System.out.println("price: null");
1046 }
1047 else
1048 {
1049 System.out.println("price: " + price);
1050 }
1051
1052 String title_id = rs.getString("title_id");
1053 String title = rs.getString("title");
1054 float gross = rs.getFloat("gross");
1055
1056
1057 System.out.println("id: " + title_id);
1058 System.out.println("name: " + title);
1059 System.out.println("gross: " + gross);
1060 System.out.println("");
1061 }
1062 }
1063
1064 public boolean isClosed() {
1065 return isClosed;
1066 }
1067
1068 }
1069
1070
This page was automatically generated by Maven