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

数据库系统

开发平台:

Unix_Linux

  1. package postgresql.jdbc2;
  2. // IMPORTANT NOTE: This file implements the JDBC 2 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 1 class in the
  5. // postgresql.jdbc1 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.  * ** DEPRECIATED IN JDBC 2 **
  358.  *
  359.  * <P><B>Note:</B> This stream object can either be a standard Java
  360.  * stream object or your own subclass that implements the standard
  361.  * interface.
  362.  *
  363.  * @param parameterIndex the first parameter is 1...
  364.  * @param x the parameter value
  365.  * @exception SQLException if a database access error occurs
  366.  * @deprecated
  367.  */
  368. public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
  369. {
  370. setBinaryStream(parameterIndex, x, length);
  371. }
  372. /**
  373.  * When a very large binary value is input to a LONGVARBINARY parameter,
  374.  * it may be more practical to send it via a java.io.InputStream.
  375.  * JDBC will read the data from the stream as needed, until it reaches
  376.  * end-of-file.  
  377.  *
  378.  * <P><B>Note:</B> This stream object can either be a standard Java
  379.  * stream object or your own subclass that implements the standard
  380.  * interface.
  381.  *
  382.  * @param parameterIndex the first parameter is 1...
  383.  * @param x the parameter value
  384.  * @exception SQLException if a database access error occurs
  385.  */
  386. public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
  387. {
  388. throw new PSQLException("postgresql.prep.is");
  389. }
  390. /**
  391.  * In general, parameter values remain in force for repeated used of a
  392.  * Statement.  Setting a parameter value automatically clears its
  393.  * previous value.  However, in coms cases, it is useful to immediately
  394.  * release the resources used by the current parameter values; this
  395.  * can be done by calling clearParameters
  396.  *
  397.  * @exception SQLException if a database access error occurs
  398.  */
  399. public void clearParameters() throws SQLException
  400. {
  401. int i;
  402. for (i = 0 ; i < inStrings.length ; i++)
  403. inStrings[i] = null;
  404. }
  405. /**
  406.  * Set the value of a parameter using an object; use the java.lang
  407.  * equivalent objects for integral values.
  408.  *
  409.  * <P>The given Java object will be converted to the targetSqlType before
  410.  * being sent to the database.
  411.  *
  412.  * <P>note that this method may be used to pass database-specific
  413.  * abstract data types.  This is done by using a Driver-specific
  414.  * Java type and using a targetSqlType of java.sql.Types.OTHER
  415.  *
  416.  * @param parameterIndex the first parameter is 1...
  417.  * @param x the object containing the input parameter value
  418.  * @param targetSqlType The SQL type to be send to the database
  419.  * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
  420.  * types this is the number of digits after the decimal.  For 
  421.  * all other types this value will be ignored.
  422.  * @exception SQLException if a database access error occurs
  423.  */
  424. public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
  425. {
  426. switch (targetSqlType)
  427. {
  428. case Types.TINYINT:
  429. case Types.SMALLINT:
  430. case Types.INTEGER:
  431. case Types.BIGINT:
  432. case Types.REAL:
  433. case Types.FLOAT:
  434. case Types.DOUBLE:
  435. case Types.DECIMAL:
  436. case Types.NUMERIC:
  437. if (x instanceof Boolean)
  438. set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
  439. else
  440. set(parameterIndex, x.toString());
  441. break;
  442. case Types.CHAR:
  443. case Types.VARCHAR:
  444. case Types.LONGVARCHAR:
  445. setString(parameterIndex, x.toString());
  446. break;
  447. case Types.DATE:
  448. setDate(parameterIndex, (java.sql.Date)x);
  449. break;
  450. case Types.TIME:
  451. setTime(parameterIndex, (Time)x);
  452. break;
  453. case Types.TIMESTAMP:
  454. setTimestamp(parameterIndex, (Timestamp)x);
  455. break;
  456. case Types.OTHER:
  457. setString(parameterIndex, ((PGobject)x).getValue());
  458. break;
  459. default:
  460. throw new PSQLException("postgresql.prep.type");
  461. }
  462. }
  463. public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
  464. {
  465. setObject(parameterIndex, x, targetSqlType, 0);
  466. }
  467.   /**
  468.    * This stores an Object into a parameter.
  469.    * <p>New for 6.4, if the object is not recognised, but it is
  470.    * Serializable, then the object is serialised using the
  471.    * postgresql.util.Serialize class.
  472.    */
  473. public void setObject(int parameterIndex, Object x) throws SQLException
  474. {
  475. if (x instanceof String)
  476. setString(parameterIndex, (String)x);
  477. else if (x instanceof BigDecimal)
  478. setBigDecimal(parameterIndex, (BigDecimal)x);
  479. else if (x instanceof Short)
  480. setShort(parameterIndex, ((Short)x).shortValue());
  481. else if (x instanceof Integer)
  482. setInt(parameterIndex, ((Integer)x).intValue());
  483. else if (x instanceof Long)
  484. setLong(parameterIndex, ((Long)x).longValue());
  485. else if (x instanceof Float)
  486. setFloat(parameterIndex, ((Float)x).floatValue());
  487. else if (x instanceof Double)
  488. setDouble(parameterIndex, ((Double)x).doubleValue());
  489. else if (x instanceof byte[])
  490. setBytes(parameterIndex, (byte[])x);
  491. else if (x instanceof java.sql.Date)
  492. setDate(parameterIndex, (java.sql.Date)x);
  493. else if (x instanceof Time)
  494. setTime(parameterIndex, (Time)x);
  495. else if (x instanceof Timestamp)
  496. setTimestamp(parameterIndex, (Timestamp)x);
  497. else if (x instanceof Boolean)
  498. setBoolean(parameterIndex, ((Boolean)x).booleanValue());
  499. else if (x instanceof PGobject)
  500. setString(parameterIndex, ((PGobject)x).getValue());
  501. else
  502. setLong(parameterIndex, connection.putObject(x));
  503. }
  504. /**
  505.  * Some prepared statements return multiple results; the execute method
  506.  * handles these complex statements as well as the simpler form of 
  507.  * statements handled by executeQuery and executeUpdate
  508.  *
  509.  * @return true if the next result is a ResultSet; false if it is an
  510.  * update count or there are no more results
  511.  * @exception SQLException if a database access error occurs
  512.  */
  513. public boolean execute() throws SQLException
  514. {
  515. StringBuffer s = new StringBuffer();
  516. int i;
  517. for (i = 0 ; i < inStrings.length ; ++i)
  518. {
  519. if (inStrings[i] == null)
  520. throw new PSQLException("postgresql.prep.param",new Integer(i + 1));
  521. s.append (templateStrings[i]);
  522. s.append (inStrings[i]);
  523. }
  524. s.append(templateStrings[inStrings.length]);
  525. return super.execute(s.toString());  // in Statement class
  526. }
  527. /**
  528.  * Returns the SQL statement with the current template values
  529.  * substituted.
  530.  */
  531. public String toString() {
  532. StringBuffer s = new StringBuffer();
  533. int i;
  534. for (i = 0 ; i < inStrings.length ; ++i)
  535. {
  536. if (inStrings[i] == null)
  537. s.append( '?' );
  538. else
  539. s.append (templateStrings[i]);
  540. s.append (inStrings[i]);
  541. }
  542. s.append(templateStrings[inStrings.length]);
  543. return s.toString();
  544. }
  545. // **************************************************************
  546. // END OF PUBLIC INTERFACE
  547. // **************************************************************
  548. /**
  549.  * There are a lot of setXXX classes which all basically do
  550.  * the same thing.  We need a method which actually does the
  551.  * set for us.
  552.  *
  553.  * @param paramIndex the index into the inString
  554.  * @param s a string to be stored
  555.  * @exception SQLException if something goes wrong
  556.  */
  557. private void set(int paramIndex, String s) throws SQLException
  558. {
  559. if (paramIndex < 1 || paramIndex > inStrings.length)
  560. throw new PSQLException("postgresql.prep.range");
  561. inStrings[paramIndex - 1] = s;
  562. }
  563.     
  564.     // ** JDBC 2 Extensions **
  565.     
  566.     public void addBatch() throws SQLException
  567.     {
  568. throw postgresql.Driver.notImplemented();
  569.     }
  570.     
  571.     public java.sql.ResultSetMetaData getMetaData() throws SQLException
  572.     {
  573. throw postgresql.Driver.notImplemented();
  574.     }
  575.     
  576.     public void setArray(int i,Array x) throws SQLException
  577.     {
  578. throw postgresql.Driver.notImplemented();
  579.     }
  580.     
  581.     public void setBlob(int i,Blob x) throws SQLException
  582.     {
  583. throw postgresql.Driver.notImplemented();
  584.     }
  585.     
  586.     public void setCharacterStream(int i,java.io.Reader x,int length) throws SQLException
  587.     {
  588. throw postgresql.Driver.notImplemented();
  589.     }
  590.     
  591.     public void setClob(int i,Clob x) throws SQLException
  592.     {
  593. throw postgresql.Driver.notImplemented();
  594.     }
  595.     
  596.     public void setNull(int i,int t,String s) throws SQLException
  597.     {
  598. throw postgresql.Driver.notImplemented();
  599.     }
  600.     
  601.     public void setRef(int i,Ref x) throws SQLException
  602.     {
  603. throw postgresql.Driver.notImplemented();
  604.     }
  605.     
  606.     public void setDate(int i,java.sql.Date d,java.util.Calendar cal) throws SQLException
  607.     {
  608. throw postgresql.Driver.notImplemented();
  609.     }
  610.     
  611.     public void setTime(int i,Time t,java.util.Calendar cal) throws SQLException
  612.     {
  613. throw postgresql.Driver.notImplemented();
  614.     }
  615.     
  616.     public void setTimestamp(int i,Timestamp t,java.util.Calendar cal) throws SQLException
  617.     {
  618. throw postgresql.Driver.notImplemented();
  619.     }
  620.     
  621. }