📄 monetpreparedstatement.java
字号:
/* * The contents of this file are subject to the MonetDB Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://monetdb.cwi.nl/Legal/MonetDBLicense-1.1.html * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Original Code is the MonetDB Database System. * * The Initial Developer of the Original Code is CWI. * Portions created by CWI are Copyright (C) 1997-2007 CWI. * All Rights Reserved. */package nl.cwi.monetdb.jdbc;import java.sql.*;import java.util.*;import java.net.URL;import java.io.*;import java.math.*; // BigDecimal, etc.import java.text.SimpleDateFormat;/** * A PreparedStatement suitable for the MonetDB database. * <br /><br /> * This implementation of the PreparedStatement interface uses the * capabilities of the MonetDB/SQL backend to prepare and execute * queries. The backend takes care of finding the '?'s in the input and * returns the types it expects for them. * <br /><br /> * An example of a server response on a prepare query is: * <pre> * % prepare select name from tables where id > ? and id < ?; * &5 0 2 3 2 * # prepare, prepare, prepare # table_name * # type, digits, scale # name * # varchar, int, int # type * # 0, 0, 0 # length * [ "int", 9, 0 ] * [ "int", 9, 0 ] * </pre> * * @author Fabian Groffen <Fabian.Groffen@cwi.nl> * @version 0.2 */public class MonetPreparedStatement extends MonetStatement implements PreparedStatement{ private final String[] monetdbType; private final int[] javaType; private final int[] digits; private final int[] scale; private final int id; private final int size; private final String[] values; private final StringBuffer buf; /* only parse the date patterns once, use multiple times */ /** Format of a timestamp with RFC822 time zone */ final SimpleDateFormat mTimestampZ = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ"); /** Format of a time with RFC822 time zone */ final SimpleDateFormat mTimeZ = new SimpleDateFormat("HH:mm:ss.SSSZ"); /** Format of a date used by Mserver */ final SimpleDateFormat mDate = new SimpleDateFormat("yyyy-MM-dd"); /** * MonetPreparedStatement constructor which checks the arguments for * validity. A MonetPreparedStatement is backed by a * MonetStatement, which deals with most of the required stuff of * this class. * * @param connection the connection that created this Statement * @param resultSetType type of ResultSet to produce * @param resultSetConcurrency concurrency of ResultSet to produce * @param prepareQuery the query string to prepare * @throws SQLException if an error occurs during login * @throws IllegalArgumentException is one of the arguments is null or empty */ MonetPreparedStatement( MonetConnection connection, int resultSetType, int resultSetConcurrency, String prepareQuery) throws SQLException, IllegalArgumentException { super( connection, resultSetType, resultSetConcurrency ); if (!super.execute("PREPARE " + prepareQuery)) throw new SQLException("Unexpected server response"); // cheat a bit to get the ID and the number of columns id = ((MonetConnection.ResultSetResponse)header).id; size = ((MonetConnection.ResultSetResponse)header).tuplecount; // initialise blank finals monetdbType = new String[size]; javaType = new int[size]; digits = new int[size]; scale = new int[size]; values = new String[size]; buf = new StringBuffer(6 + 12 * size); // fill the arrays ResultSet rs = super.getResultSet(); for (int i = 0; rs.next(); i++) { monetdbType[i] = rs.getString("type"); javaType[i] = MonetDriver.getJavaType(monetdbType[i]); digits[i] = rs.getInt("digits"); scale[i] = rs.getInt("scale"); } rs.close(); } /** * Constructs an empty MonetPreparedStatement. This constructor is * in particular useful for extensions of this class. * * @param connection the connection that created this Statement * @param resultSetType type of ResultSet to produce * @param resultSetConcurrency concurrency of ResultSet to produce * @throws SQLException if an error occurs during login */ MonetPreparedStatement( MonetConnection connection, int resultSetType, int resultSetConcurrency) throws SQLException { super( connection, resultSetType, resultSetConcurrency ); // initialise blank finals monetdbType = null; javaType = null; digits = null; scale = null; values = null; buf = null; id = -1; size = -1; } //== methods interface PreparedStatement /** * Adds a set of parameters to this PreparedStatement object's batch * of commands. * * @throws SQLException if a database access error occurs */ public void addBatch() throws SQLException { super.addBatch(transform()); } /** override the addBatch from the Statement to throw an SQLException */ public void addBatch(String q) throws SQLException { throw new SQLException("This method is not available in a PreparedStatement!"); } /** * Clears the current parameter values immediately. * <br /><br /> * In general, parameter values remain in force for repeated use of a * statement. Setting a parameter value automatically clears its previous * value. However, in some cases it is useful to immediately release the * resources used by the current parameter values; this can be done by * calling the method clearParameters. */ public void clearParameters() { for (int i = 0; i < values.length; i++) { values[i] = null; } } /** * Executes the SQL statement in this PreparedStatement object, * which may be any kind of SQL statement. Some prepared statements * return multiple results; the execute method handles these complex * statements as well as the simpler form of statements handled by * the methods executeQuery and executeUpdate. * <br /><br /> * The execute method returns a boolean to indicate the form of the * first result. You must call either the method getResultSet or * getUpdateCount to retrieve the result; you must call * getMoreResults to move to any subsequent result(s). * * @return true if the first result is a ResultSet object; false if the * first result is an update count or there is no result * @throws SQLException if a database access error occurs or an argument * is supplied to this method */ public boolean execute() throws SQLException { return(super.execute(transform())); } /** override the execute from the Statement to throw an SQLException */ public boolean execute(String q) throws SQLException { throw new SQLException("This method is not available in a PreparedStatement!"); } /** * Executes the SQL query in this PreparedStatement object and returns the * ResultSet object generated by the query. * * @return a ResultSet object that contains the data produced by the query; * never null * @throws SQLException if a database access error occurs or the SQL * statement does not return a ResultSet object */ public ResultSet executeQuery() throws SQLException{ if (execute() != true) throw new SQLException("Query did not produce a result set"); return(getResultSet()); } /** override the executeQuery from the Statement to throw an SQLException*/ public ResultSet executeQuery(String q) throws SQLException { throw new SQLException("This method is not available in a PreparedStatement!"); } /** * Executes the SQL statement in this PreparedStatement object, which must * be an SQL INSERT, UPDATE or DELETE statement; or an SQL statement that * returns nothing, such as a DDL statement. * * @return either (1) the row count for INSERT, UPDATE, or DELETE * statements or (2) 0 for SQL statements that return nothing * @throws SQLException if a database access error occurs or the SQL * statement returns a ResultSet object */ public int executeUpdate() throws SQLException { if (execute() != false) throw new SQLException("Query produced a result set"); return(getUpdateCount()); } /** override the executeUpdate from the Statement to throw an SQLException*/ public int executeUpdate(String q) throws SQLException { throw new SQLException("This method is not available in a PreparedStatement!"); } /** * Retrieves a ResultSetMetaData object that contains information * about the columns of the ResultSet object that will be returned * when this PreparedStatement object is executed. * <br /><br /> * Because a PreparedStatement object is precompiled, it is possible * to know about the ResultSet object that it will return without * having to execute it. Consequently, it is possible to invoke the * method getMetaData on a PreparedStatement object rather than * waiting to execute it and then invoking the ResultSet.getMetaData * method on the ResultSet object that is returned. * <br /><br /> * NOTE: Using this method is expensive for this driver due to the * lack of underlying DBMS support. Currently not implemented * * @return the description of a ResultSet object's columns or null if the * driver cannot return a ResultSetMetaData object * @throws SQLException if a database access error occurs */ public ResultSetMetaData getMetaData() throws SQLException { throw new SQLException("Method currently not supported, sorry!"); } /** * Retrieves the number, types and properties of this * PreparedStatement object's parameters. * * @return a ParameterMetaData object that contains information * about the number, types and properties of this * PreparedStatement object's parameters * @throws SQLException if a database access error occurs */ public ParameterMetaData getParameterMetaData() throws SQLException { return(new ParameterMetaData() { /** * Retrieves the number of parameters in the * PreparedStatement object for which this ParameterMetaData * object contains information. * * @return the number of parameters * @throws SQLException if a database access error occurs */ public int getParameterCount() throws SQLException { return(size); } /** * Retrieves whether null values are allowed in the * designated parameter. * <br /><br /> * This is currently always unknown for MonetDB/SQL. * * @param param the first parameter is 1, the second is 2, ... * @return the nullability status of the given parameter; * one of ParameterMetaData.parameterNoNulls, * ParameterMetaData.parameterNullable, or * ParameterMetaData.parameterNullableUnknown * @throws SQLException if a database access error occurs */ public int isNullable(int param) throws SQLException { return(ParameterMetaData.parameterNullableUnknown); } /** * Retrieves whether values for the designated parameter can * be signed numbers. * * @param param the first parameter is 1, the second is 2, ... * @return true if so; false otherwise * @throws SQLException if a database access error occurs */ public boolean isSigned(int param) throws SQLException { if (param < 1 || param > size) throw new SQLException("No such parameter with index: " + param); // we can hardcode this, based on the colum type // (from ResultSetMetaData.isSigned) switch (javaType[param - 1]) { case Types.NUMERIC: case Types.DECIMAL:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -