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.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