/* * The contents of this file are subject to the Mozilla 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 . * * 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 Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ package com.silverwrist.venice.db; import java.sql.*; import java.util.*; import com.silverwrist.util.AnyCharMatcher; import com.silverwrist.util.StringUtil; /** * Utility functions commonly used for passing string values to SQL commands, and interpreting the results. * * @author Eric J. Bowersox <erbo@silcom.com> * @version X * @see com.silverwrist.util.StringUtil */ public class SQLUtil { /*-------------------------------------------------------------------------------- * Static data members *-------------------------------------------------------------------------------- */ private static final String SQL_WILDCARD_CHARS = "%_'"; // used to convert dates and times to UTC for sending to SQL private static SimpleTimeZone utc = new SimpleTimeZone(0,"UTC"); /*-------------------------------------------------------------------------------- * Internal functions *-------------------------------------------------------------------------------- */ /** * Converts a date-and-time string (an SQL DATETIME value) to a standard Java date. * * @param dstr The date-and-time string to convert, presumed to be in UTC. * @return The converted date and time. * @exception java.sql.SQLException The date and time string was in an invalid format. */ private static java.util.Date convertDateTimeString(String dstr) throws SQLException { if (dstr==null) return null; // null values are the same try { // do almost the reverse process of formatting it into a string GregorianCalendar cal = new GregorianCalendar(utc); cal.set(Calendar.YEAR,Integer.parseInt(dstr.substring(0,4))); cal.set(Calendar.MONTH,Integer.parseInt(dstr.substring(5,7)) - 1 + Calendar.JANUARY); cal.set(Calendar.DAY_OF_MONTH,Integer.parseInt(dstr.substring(8,10))); cal.set(Calendar.HOUR_OF_DAY,Integer.parseInt(dstr.substring(11,13))); cal.set(Calendar.MINUTE,Integer.parseInt(dstr.substring(14,16))); cal.set(Calendar.SECOND,Integer.parseInt(dstr.substring(17,19))); return cal.getTime(); } // end try catch (NumberFormatException e) { // the NumberFormatException becomes an SQLException throw new SQLException("invalid DATETIME field format"); } // end catch } // end convertDateString /*-------------------------------------------------------------------------------- * External static operations *-------------------------------------------------------------------------------- */ /** * Performs SQL encoding of an arbitrary string. When a string is SQL-encoded, all single-quote * characters are doubled, and all other characters are left untouched. * * @param str The string to be SQL-encoded. May be null. * @return The SQL-encoded equivalent of str. If str is * null, returns null. * @see com.silverwrist.util.StringUtil#encodeStringSQL(java.lang.String) */ public static String encodeString(String str) { return StringUtil.encodeStringSQL(str); } // end encodeString /** * Performs SQL encoding of an arbitrary string, enclosing it in quotes, so that it may be passed as an * argument in an SQL statement. When a string is SQL-encoded, all single-quote characters are doubled, * and all other characters are left untouched. * * @param str The string to be SQL-encoded. May be null. * @return The SQL-encoded equivalent of str, in quotes. If str is * null, returns "NULL". * @see com.silverwrist.util.StringUtil#encodeStringSQL(java.lang.String) */ public static String encodeStringArg(String str) { if (str==null) return "NULL"; StringBuffer b = new StringBuffer("'"); b.append(StringUtil.encodeStringSQL(str)).append('\''); return b.toString(); } // end encodeStringArg /** * Performs SQL-encoding of a string which may contain the SQL wildcard characters, '%' and '_'. The * wildcard characters are escaped with '\', and the single-quote characters are doubled, but all other * characters are left untouched. * * @param str The string to be SQL-encoded. May be null. * @return The SQL-encoded equivalent of str. If str is * null, returns null. */ public static String encodeStringWildcards(String str) { if (str==null) return null; // safety feature AnyCharMatcher nhc = new AnyCharMatcher(SQL_WILDCARD_CHARS); int ndx = nhc.get(str); if (ndx<0) return str; // trivial short-circuit case StringBuffer buf = new StringBuffer(); while (ndx>=0) { // append the matched "head" and then the encoded character if (ndx>0) buf.append(str.substring(0,ndx)); switch (str.charAt(ndx++)) { case '%': buf.append("\\%"); break; case '_': buf.append("\\_"); break; case '\'': buf.append("\'\'"); break; } // end switch if (ndx==str.length()) return buf.toString(); // munched the entire string - all done! str = str.substring(ndx); ndx = nhc.get(str); } // end while buf.append(str); // append the unmatched tail return buf.toString(); } // end encodeStringWildcards /** * Encodes a date as an SQL date/time string, expressed in UTC. * * @param d The date to be encoded. * @return The string equivalent of that date. */ public static String encodeDate(java.util.Date d) { // Break down the date as a UTC value. GregorianCalendar cal = new GregorianCalendar(utc); cal.setTime(d); // Create the two string buffers converting the date. StringBuffer rc = new StringBuffer(); StringBuffer conv = new StringBuffer(); String c; // Encode the year first. conv.append("0000").append(cal.get(Calendar.YEAR)); c = conv.toString(); rc.append(c.substring(c.length()-4)).append('-'); // Now the month... conv.setLength(0); conv.append("00").append(cal.get(Calendar.MONTH) - Calendar.JANUARY + 1); c = conv.toString(); rc.append(c.substring(c.length()-2)).append('-'); // And the day... conv.setLength(0); conv.append("00").append(cal.get(Calendar.DAY_OF_MONTH)); c = conv.toString(); rc.append(c.substring(c.length()-2)).append(' '); // And the hour... conv.setLength(0); conv.append("00").append(cal.get(Calendar.HOUR_OF_DAY)); c = conv.toString(); rc.append(c.substring(c.length()-2)).append(':'); // And the minute... conv.setLength(0); conv.append("00").append(cal.get(Calendar.MINUTE)); c = conv.toString(); rc.append(c.substring(c.length()-2)).append(':'); // And the second... conv.setLength(0); conv.append("00").append(cal.get(Calendar.SECOND)); c = conv.toString(); rc.append(c.substring(c.length()-2)); // This is the resulting date/time value. return rc.toString(); } // end encodeDate /** * Returns the value of a DATETIME column in the current row of an SQL result set, formatted as a date. * * @param rs The result set to look in. * @param column The name of the column to be returned. * @return The value of the specified column, expressed as a date. * @exception java.sql.SQLException If the column could not be retrieved or converted. */ public static java.util.Date getFullDateTime(ResultSet rs, String column) throws SQLException { return convertDateTimeString(rs.getString(column)); } // end getFullDateTime /** * Returns the value of a DATETIME column in the current row of an SQL result set, formatted as a date. * * @param rs The result set to look in. * @param column The 1-based index of the column to be returned. * @return The value of the specified column, expressed as a date. * @exception java.sql.SQLException If the column could not be retrieved or converted. */ public static java.util.Date getFullDateTime(ResultSet rs, int column) throws SQLException { return convertDateTimeString(rs.getString(column)); } // end getFullDateTime } // end class SQLUtil