PreparedStatement.java
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:19k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. package postgresql.jdbc1;
  2. // IMPORTANT NOTE: This file implements the JDBC 1 version of the driver.
  3. // If you make any modifications to this file, you must make sure that the
  4. // changes are also made (if relevent) to the related JDBC 2 class in the
  5. // postgresql.jdbc2 package.
  6. import java.io.*;
  7. import java.math.*;
  8. import java.sql.*;
  9. import java.text.*;
  10. import java.util.*;
  11. import postgresql.largeobject.*;
  12. import postgresql.util.*;
  13. /**
  14.  * A SQL Statement is pre-compiled and stored in a PreparedStatement object.
  15.  * This object can then be used to efficiently execute this statement multiple
  16.  * times.
  17.  *
  18.  * <p><B>Note:</B> The setXXX methods for setting IN parameter values must
  19.  * specify types that are compatible with the defined SQL type of the input
  20.  * parameter.  For instance, if the IN parameter has SQL type Integer, then
  21.  * setInt should be used.
  22.  *
  23.  * <p>If arbitrary parameter type conversions are required, then the setObject 
  24.  * method should be used with a target SQL type.
  25.  *
  26.  * @see ResultSet
  27.  * @see java.sql.PreparedStatement
  28.  */
  29. public class PreparedStatement extends Statement implements java.sql.PreparedStatement 
  30. {
  31. String sql;
  32. String[] templateStrings;
  33. String[] inStrings;
  34. Connection connection;
  35. /**
  36.  * Constructor for the PreparedStatement class.
  37.  * Split the SQL statement into segments - separated by the arguments.
  38.  * When we rebuild the thing with the arguments, we can substitute the
  39.  * args and join the whole thing together.
  40.  *
  41.  * @param conn the instanatiating connection
  42.  * @param sql the SQL statement with ? for IN markers
  43.  * @exception SQLException if something bad occurs
  44.  */
  45. public PreparedStatement(Connection connection, String sql) throws SQLException
  46. {
  47. super(connection);
  48. Vector v = new Vector();
  49. boolean inQuotes = false;
  50. int lastParmEnd = 0, i;
  51. this.sql = sql;
  52. this.connection = connection;
  53. for (i = 0; i < sql.length(); ++i)
  54. {
  55. int c = sql.charAt(i);
  56. if (c == ''')
  57. inQuotes = !inQuotes;
  58. if (c == '?' && !inQuotes)
  59. {
  60. v.addElement(sql.substring (lastParmEnd, i));
  61. lastParmEnd = i + 1;
  62. }
  63. }
  64. v.addElement(sql.substring (lastParmEnd, sql.length()));
  65. templateStrings = new String[v.size()];
  66. inStrings = new String[v.size() - 1];
  67. clearParameters();
  68. for (i = 0 ; i < templateStrings.length; ++i)
  69. templateStrings[i] = (String)v.elementAt(i);
  70. }
  71. /**
  72.  * A Prepared SQL query is executed and its ResultSet is returned
  73.  *
  74.  * @return a ResultSet that contains the data produced by the
  75.  * query - never null
  76.  * @exception SQLException if a database access error occurs
  77.  */
  78. public java.sql.ResultSet executeQuery() throws SQLException
  79. {
  80. StringBuffer s = new StringBuffer();
  81. int i;
  82. for (i = 0 ; i < inStrings.length ; ++i)
  83. {
  84. if (inStrings[i] == null)
  85. throw new PSQLException("postgresql.prep.param",new Integer(i + 1));
  86. s.append (templateStrings[i]);
  87. s.append (inStrings[i]);
  88. }
  89. s.append(templateStrings[inStrings.length]);
  90. return super.executeQuery(s.toString());  // in Statement class
  91. }
  92. /**
  93.  * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition,
  94.  * SQL statements that return nothing such as SQL DDL statements can
  95.  * be executed.
  96.  *
  97.  * @return either the row count for INSERT, UPDATE or DELETE; or
  98.  *  0 for SQL statements that return nothing.
  99.  * @exception SQLException if a database access error occurs
  100.  */
  101. public int executeUpdate() throws SQLException
  102. {
  103. StringBuffer s = new StringBuffer();
  104. int i;
  105. for (i = 0 ; i < inStrings.length ; ++i)
  106. {
  107. if (inStrings[i] == null)
  108. throw new PSQLException("postgresql.prep.param",new Integer(i + 1));
  109. s.append (templateStrings[i]);
  110. s.append (inStrings[i]);
  111. }
  112. s.append(templateStrings[inStrings.length]);
  113. return super.executeUpdate(s.toString());  // in Statement class
  114. }
  115. /**
  116.  * Set a parameter to SQL NULL
  117.  *
  118.  * <p><B>Note:</B> You must specify the parameters SQL type (although
  119.  * PostgreSQL ignores it)
  120.  *
  121.  * @param parameterIndex the first parameter is 1, etc...
  122.  * @param sqlType the SQL type code defined in java.sql.Types
  123.  * @exception SQLException if a database access error occurs
  124.  */
  125. public void setNull(int parameterIndex, int sqlType) throws SQLException
  126. {
  127. set(parameterIndex, "null");
  128. }
  129. /**
  130.  * Set a parameter to a Java boolean value.  The driver converts this
  131.  * to a SQL BIT value when it sends it to the database.
  132.  *
  133.  * @param parameterIndex the first parameter is 1...
  134.  * @param x the parameter value
  135.  * @exception SQLException if a database access error occurs
  136.  */
  137. public void setBoolean(int parameterIndex, boolean x) throws SQLException
  138. {
  139. set(parameterIndex, x ? "'t'" : "'f'");
  140. }
  141. /**
  142.  * Set a parameter to a Java byte value.  The driver converts this to
  143.  * a SQL TINYINT value when it sends it to the database.
  144.  *
  145.  * @param parameterIndex the first parameter is 1...
  146.  * @param x the parameter value
  147.  * @exception SQLException if a database access error occurs
  148.  */
  149. public void setByte(int parameterIndex, byte x) throws SQLException
  150. {
  151. set(parameterIndex, (new Integer(x)).toString());
  152. }
  153. /**
  154.  * Set a parameter to a Java short value.  The driver converts this
  155.  * to a SQL SMALLINT value when it sends it to the database.
  156.  *
  157.  * @param parameterIndex the first parameter is 1...
  158.  * @param x the parameter value
  159.  * @exception SQLException if a database access error occurs
  160.  */
  161. public void setShort(int parameterIndex, short x) throws SQLException
  162. {
  163. set(parameterIndex, (new Integer(x)).toString());
  164. }
  165. /**
  166.  * Set a parameter to a Java int value.  The driver converts this to
  167.  * a SQL INTEGER value when it sends it to the database.
  168.  *
  169.  * @param parameterIndex the first parameter is 1...
  170.  * @param x the parameter value
  171.  * @exception SQLException if a database access error occurs
  172.  */
  173. public void setInt(int parameterIndex, int x) throws SQLException
  174. {
  175. set(parameterIndex, (new Integer(x)).toString());
  176. }
  177. /**
  178.  * Set a parameter to a Java long value.  The driver converts this to
  179.  * a SQL BIGINT value when it sends it to the database.
  180.  *
  181.  * @param parameterIndex the first parameter is 1...
  182.  * @param x the parameter value
  183.  * @exception SQLException if a database access error occurs
  184.  */
  185. public void setLong(int parameterIndex, long x) throws SQLException
  186. {
  187. set(parameterIndex, (new Long(x)).toString());
  188. }
  189. /**
  190.  * Set a parameter to a Java float value.  The driver converts this
  191.  * to a SQL FLOAT value when it sends it to the database.
  192.  *
  193.  * @param parameterIndex the first parameter is 1...
  194.  * @param x the parameter value
  195.  * @exception SQLException if a database access error occurs
  196.  */
  197. public void setFloat(int parameterIndex, float x) throws SQLException
  198. {
  199. set(parameterIndex, (new Float(x)).toString());
  200. }
  201. /**
  202.  * Set a parameter to a Java double value.  The driver converts this
  203.  * to a SQL DOUBLE value when it sends it to the database
  204.  *
  205.  * @param parameterIndex the first parameter is 1...
  206.  * @param x the parameter value
  207.  * @exception SQLException if a database access error occurs
  208.  */
  209. public void setDouble(int parameterIndex, double x) throws SQLException
  210. {
  211. set(parameterIndex, (new Double(x)).toString());
  212. }
  213. /**
  214.  * Set a parameter to a java.lang.BigDecimal value.  The driver
  215.  * converts this to a SQL NUMERIC value when it sends it to the
  216.  * database.
  217.  *
  218.  * @param parameterIndex the first parameter is 1...
  219.  * @param x the parameter value
  220.  * @exception SQLException if a database access error occurs
  221.  */
  222. public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
  223. {
  224. set(parameterIndex, x.toString());
  225. }
  226. /**
  227.  * Set a parameter to a Java String value.  The driver converts this
  228.  * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
  229.  * size relative to the driver's limits on VARCHARs) when it sends it
  230.  * to the database.
  231.  *
  232.  * @param parameterIndex the first parameter is 1...
  233.  * @param x the parameter value
  234.  * @exception SQLException if a database access error occurs
  235.  */
  236. public void setString(int parameterIndex, String x) throws SQLException
  237. {
  238.   // if the passed string is null, then set this column to null
  239.   if(x==null)
  240.     set(parameterIndex,"null");
  241.   else {
  242.     StringBuffer b = new StringBuffer();
  243.     int i;
  244.     
  245.     b.append(''');
  246.     for (i = 0 ; i < x.length() ; ++i)
  247.       {
  248. char c = x.charAt(i);
  249. if (c == '\' || c == ''')
  250.   b.append((char)'\');
  251. b.append(c);
  252.       }
  253.     b.append(''');
  254.     set(parameterIndex, b.toString());
  255.   }
  256. }
  257.   /**
  258.    * Set a parameter to a Java array of bytes.  The driver converts this
  259.    * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
  260.    * size relative to the driver's limits on VARBINARYs) when it sends
  261.    * it to the database.
  262.    *
  263.    * <p>Implementation note:
  264.    * <br>With postgresql, this creates a large object, and stores the
  265.    * objects oid in this column.
  266.    *
  267.    * @param parameterIndex the first parameter is 1...
  268.    * @param x the parameter value
  269.    * @exception SQLException if a database access error occurs
  270.    */
  271.   public void setBytes(int parameterIndex, byte x[]) throws SQLException
  272.   {
  273.     LargeObjectManager lom = connection.getLargeObjectAPI();
  274.     int oid = lom.create();
  275.     LargeObject lob = lom.open(oid);
  276.     lob.write(x);
  277.     lob.close();
  278.     setInt(parameterIndex,oid);
  279.   }
  280. /**
  281.  * Set a parameter to a java.sql.Date value.  The driver converts this
  282.  * to a SQL DATE value when it sends it to the database.
  283.  *
  284.  * @param parameterIndex the first parameter is 1...
  285.  * @param x the parameter value
  286.  * @exception SQLException if a database access error occurs
  287.  */
  288. public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
  289. {
  290.   SimpleDateFormat df = new SimpleDateFormat("''yyyy-MM-dd''");
  291.   
  292.   set(parameterIndex, df.format(x));
  293.   
  294.   // The above is how the date should be handled.
  295.   //
  296.   // However, in JDK's prior to 1.1.6 (confirmed with the
  297.   // Linux jdk1.1.3 and the Win95 JRE1.1.5), SimpleDateFormat seems
  298.   // to format a date to the previous day. So the fix is to add a day
  299.   // before formatting.
  300.   //
  301.   // PS: 86400000 is one day
  302.   //
  303.   //set(parameterIndex, df.format(new java.util.Date(x.getTime()+86400000)));
  304. }
  305.   
  306. /**
  307.  * Set a parameter to a java.sql.Time value.  The driver converts
  308.  * this to a SQL TIME value when it sends it to the database.
  309.  *
  310.  * @param parameterIndex the first parameter is 1...));
  311.  * @param x the parameter value
  312.  * @exception SQLException if a database access error occurs
  313.  */
  314. public void setTime(int parameterIndex, Time x) throws SQLException
  315. {
  316. set(parameterIndex, "'" + x.toString() + "'");
  317. }
  318. /**
  319.  * Set a parameter to a java.sql.Timestamp value.  The driver converts
  320.  * this to a SQL TIMESTAMP value when it sends it to the database.
  321.  *
  322.  * @param parameterIndex the first parameter is 1...
  323.  * @param x the parameter value
  324.  * @exception SQLException if a database access error occurs
  325.  */
  326. public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
  327. {
  328. set(parameterIndex, "'" + x.toString() + "'");
  329. }
  330. /**
  331.  * When a very large ASCII value is input to a LONGVARCHAR parameter,
  332.  * it may be more practical to send it via a java.io.InputStream.
  333.  * JDBC will read the data from the stream as needed, until it reaches
  334.  * end-of-file.  The JDBC driver will do any necessary conversion from
  335.  * ASCII to the database char format.
  336.  *
  337.  * <P><B>Note:</B> This stream object can either be a standard Java
  338.  * stream object or your own subclass that implements the standard
  339.  * interface.
  340.  *
  341.  * @param parameterIndex the first parameter is 1...
  342.  * @param x the parameter value
  343.  * @param length the number of bytes in the stream
  344.  * @exception SQLException if a database access error occurs
  345.  */
  346. public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
  347. {
  348. setBinaryStream(parameterIndex, x, length);
  349. }
  350. /**
  351.  * When a very large Unicode value is input to a LONGVARCHAR parameter,
  352.  * it may be more practical to send it via a java.io.InputStream.
  353.  * JDBC will read the data from the stream as needed, until it reaches
  354.  * end-of-file.  The JDBC driver will do any necessary conversion from
  355.  * UNICODE to the database char format.
  356.  *
  357.  * <P><B>Note:</B> This stream object can either be a standard Java
  358.  * stream object or your own subclass that implements the standard
  359.  * interface.
  360.  *
  361.  * @param parameterIndex the first parameter is 1...
  362.  * @param x the parameter value
  363.  * @exception SQLException if a database access error occurs
  364.  */
  365. public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
  366. {
  367. setBinaryStream(parameterIndex, x, length);
  368. }
  369. /**
  370.  * When a very large binary value is input to a LONGVARBINARY parameter,
  371.  * it may be more practical to send it via a java.io.InputStream.
  372.  * JDBC will read the data from the stream as needed, until it reaches
  373.  * end-of-file.  
  374.  *
  375.  * <P><B>Note:</B> This stream object can either be a standard Java
  376.  * stream object or your own subclass that implements the standard
  377.  * interface.
  378.  *
  379.  * @param parameterIndex the first parameter is 1...
  380.  * @param x the parameter value
  381.  * @exception SQLException if a database access error occurs
  382.  */
  383. public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
  384. {
  385.     throw postgresql.Driver.notImplemented();
  386. }
  387. /**
  388.  * In general, parameter values remain in force for repeated used of a
  389.  * Statement.  Setting a parameter value automatically clears its
  390.  * previous value.  However, in coms cases, it is useful to immediately
  391.  * release the resources used by the current parameter values; this
  392.  * can be done by calling clearParameters
  393.  *
  394.  * @exception SQLException if a database access error occurs
  395.  */
  396. public void clearParameters() throws SQLException
  397. {
  398. int i;
  399. for (i = 0 ; i < inStrings.length ; i++)
  400. inStrings[i] = null;
  401. }
  402. /**
  403.  * Set the value of a parameter using an object; use the java.lang
  404.  * equivalent objects for integral values.
  405.  *
  406.  * <P>The given Java object will be converted to the targetSqlType before
  407.  * being sent to the database.
  408.  *
  409.  * <P>note that this method may be used to pass database-specific
  410.  * abstract data types.  This is done by using a Driver-specific
  411.  * Java type and using a targetSqlType of java.sql.Types.OTHER
  412.  *
  413.  * @param parameterIndex the first parameter is 1...
  414.  * @param x the object containing the input parameter value
  415.  * @param targetSqlType The SQL type to be send to the database
  416.  * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
  417.  * types this is the number of digits after the decimal.  For 
  418.  * all other types this value will be ignored.
  419.  * @exception SQLException if a database access error occurs
  420.  */
  421. public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
  422. {
  423. switch (targetSqlType)
  424. {
  425. case Types.TINYINT:
  426. case Types.SMALLINT:
  427. case Types.INTEGER:
  428. case Types.BIGINT:
  429. case Types.REAL:
  430. case Types.FLOAT:
  431. case Types.DOUBLE:
  432. case Types.DECIMAL:
  433. case Types.NUMERIC:
  434. if (x instanceof Boolean)
  435. set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
  436. else
  437. set(parameterIndex, x.toString());
  438. break;
  439. case Types.CHAR:
  440. case Types.VARCHAR:
  441. case Types.LONGVARCHAR:
  442. setString(parameterIndex, x.toString());
  443. break;
  444. case Types.DATE:
  445. setDate(parameterIndex, (java.sql.Date)x);
  446. break;
  447. case Types.TIME:
  448. setTime(parameterIndex, (Time)x);
  449. break;
  450. case Types.TIMESTAMP:
  451. setTimestamp(parameterIndex, (Timestamp)x);
  452. break;
  453. case Types.OTHER:
  454. setString(parameterIndex, ((PGobject)x).getValue());
  455. break;
  456. default:
  457. throw new PSQLException("postgresql.prep.type");
  458. }
  459. }
  460. public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
  461. {
  462. setObject(parameterIndex, x, targetSqlType, 0);
  463. }
  464.   /**
  465.    * This stores an Object into a parameter.
  466.    * <p>New for 6.4, if the object is not recognised, but it is
  467.    * Serializable, then the object is serialised using the
  468.    * postgresql.util.Serialize class.
  469.    */
  470. public void setObject(int parameterIndex, Object x) throws SQLException
  471. {
  472. if (x instanceof String)
  473. setString(parameterIndex, (String)x);
  474. else if (x instanceof BigDecimal)
  475. setBigDecimal(parameterIndex, (BigDecimal)x);
  476. else if (x instanceof Short)
  477. setShort(parameterIndex, ((Short)x).shortValue());
  478. else if (x instanceof Integer)
  479. setInt(parameterIndex, ((Integer)x).intValue());
  480. else if (x instanceof Long)
  481. setLong(parameterIndex, ((Long)x).longValue());
  482. else if (x instanceof Float)
  483. setFloat(parameterIndex, ((Float)x).floatValue());
  484. else if (x instanceof Double)
  485. setDouble(parameterIndex, ((Double)x).doubleValue());
  486. else if (x instanceof byte[])
  487. setBytes(parameterIndex, (byte[])x);
  488. else if (x instanceof java.sql.Date)
  489. setDate(parameterIndex, (java.sql.Date)x);
  490. else if (x instanceof Time)
  491. setTime(parameterIndex, (Time)x);
  492. else if (x instanceof Timestamp)
  493. setTimestamp(parameterIndex, (Timestamp)x);
  494. else if (x instanceof Boolean)
  495. setBoolean(parameterIndex, ((Boolean)x).booleanValue());
  496. else if (x instanceof PGobject)
  497. setString(parameterIndex, ((PGobject)x).getValue());
  498. else
  499. setLong(parameterIndex, connection.putObject(x));
  500. }
  501. /**
  502.  * Some prepared statements return multiple results; the execute method
  503.  * handles these complex statements as well as the simpler form of 
  504.  * statements handled by executeQuery and executeUpdate
  505.  *
  506.  * @return true if the next result is a ResultSet; false if it is an
  507.  * update count or there are no more results
  508.  * @exception SQLException if a database access error occurs
  509.  */
  510. public boolean execute() throws SQLException
  511. {
  512. StringBuffer s = new StringBuffer();
  513. int i;
  514. for (i = 0 ; i < inStrings.length ; ++i)
  515. {
  516. if (inStrings[i] == null)
  517. throw new PSQLException("postgresql.prep.param",new Integer(i + 1));
  518. s.append (templateStrings[i]);
  519. s.append (inStrings[i]);
  520. }
  521. s.append(templateStrings[inStrings.length]);
  522. return super.execute(s.toString());  // in Statement class
  523. }
  524. /**
  525.  * Returns the SQL statement with the current template values
  526.  * substituted.
  527.  */
  528. public String toString() {
  529. StringBuffer s = new StringBuffer();
  530. int i;
  531. for (i = 0 ; i < inStrings.length ; ++i)
  532. {
  533. if (inStrings[i] == null)
  534. s.append( '?' );
  535. else
  536. s.append (templateStrings[i]);
  537. s.append (inStrings[i]);
  538. }
  539. s.append(templateStrings[inStrings.length]);
  540. return s.toString();
  541. }
  542. // **************************************************************
  543. // END OF PUBLIC INTERFACE
  544. // **************************************************************
  545. /**
  546.  * There are a lot of setXXX classes which all basically do
  547.  * the same thing.  We need a method which actually does the
  548.  * set for us.
  549.  *
  550.  * @param paramIndex the index into the inString
  551.  * @param s a string to be stored
  552.  * @exception SQLException if something goes wrong
  553.  */
  554. private void set(int paramIndex, String s) throws SQLException
  555. {
  556. if (paramIndex < 1 || paramIndex > inStrings.length)
  557. throw new PSQLException("postgresql.prep.range");
  558. inStrings[paramIndex - 1] = s;
  559. }
  560. }