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