View Javadoc
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