/* * Copyright 2001-2008 Geert Bevin (gbevin[remove] at uwyn dot com) * Licensed under the Apache License, Version 2.0 (the "License") * $Id: Insert.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.database.queries; import com.uwyn.rife.database.Datasource; import com.uwyn.rife.database.capabilities.Capabilities; import com.uwyn.rife.database.exceptions.DbQueryException; import com.uwyn.rife.database.exceptions.FieldsRequiredException; import com.uwyn.rife.database.exceptions.TableNameRequiredException; import com.uwyn.rife.database.exceptions.UnsupportedSqlFeatureException; import com.uwyn.rife.database.types.SqlNull; import com.uwyn.rife.site.Constrained; import com.uwyn.rife.site.ConstrainedUtils; import com.uwyn.rife.template.Template; import com.uwyn.rife.template.TemplateFactory; import com.uwyn.rife.tools.StringUtils; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * Object representation of a SQL "INSERT" query. * * <p>This object may be used to dynamically construct a SQL statement in a * database-independent fashion. After it is finished, it may be executed using * {@link com.uwyn.rife.database.DbQueryManager#executeUpdate(Query) * DbQueryManager.executeUpdate()}. * * @author Geert Bevin (gbevin[remove] at uwyn dot com) * @author Steven Grimm (koreth[remove] at midwinter dot com) * @version $Revision: 3918 $ * @since 1.0 */ public class Insert extends AbstractParametrizedQuery implements Cloneable { private String mHint = null; private String mInto = null; private Map<String, List<Object>> mFields = null; public Insert(Datasource datasource) { super(datasource); if (null == datasource) throw new IllegalArgumentException("datasource can't be null."); clear(); } public void clear() { super.clear(); mHint = null; mInto = null; mFields = new LinkedHashMap<String, List<Object>>(); assert 0 == mFields.size(); } public String getHint() { return mHint; } public String getInto() { return mInto; } public Map<String, List<Object>> getFields() { return mFields; } public Capabilities getCapabilities() { return null; } public String getSql() throws DbQueryException { if (null == mSql) { if (null == mInto) { throw new TableNameRequiredException("Insert"); } else if (0 == mFields.size()) { throw new FieldsRequiredException("Insert"); } else { Template template = TemplateFactory.SQL.get("sql."+StringUtils.encodeClassname(mDatasource.getAliasedDriver())+".insert"); if (mHint != null) { if (!template.hasValueId("HINT")) { throw new UnsupportedSqlFeatureException("HINT", mDatasource.getAliasedDriver()); } template.setValue("EXPRESSION", mHint); template.setBlock("HINT", "HINT"); } template.setValue("INTO", mInto); // obtain the maximum number of values that are present by counting those of each field int maximum_number_of_value_rows = 0; for (List<Object> values : mFields.values()) { if (values.size() > maximum_number_of_value_rows) { maximum_number_of_value_rows = values.size(); } } // create the different rows that will be inserted into the database ArrayList<String> value_rows = new ArrayList<String>(); ArrayList<String> value_row = null; Object[] column_names = mFields.keySet().toArray(); String column_name = null; for (int current_value_row = 0; current_value_row < maximum_number_of_value_rows; current_value_row++) { value_row = new ArrayList<String>(); for (int i = 0; i < column_names.length; i++) { column_name = (String)column_names[i]; if (current_value_row <= mFields.get(column_name).size()-1) { value_row.add(mFields.get(column_name).get(current_value_row).toString()); } else { value_row.add("NULL"); } } template.setValue("VALUES", StringUtils.join(value_row, template.getBlock("SEPERATOR"))); value_rows.add(template.getBlock("VALUE_ROW")); } // create the strings of the columns that values will be inserted into and which values they are template.setValue("COLUMNS", StringUtils.join(column_names, template.getBlock("SEPERATOR"))); if (1 == value_rows.size()) { template.setValue("DATA", value_rows.get(0)); } else { if (template.hasValueId("VALUE_ROWS")) { template.setValue("VALUE_ROWS", StringUtils.join(value_rows, template.getBlock("SEPERATOR"))); } String block = template.getBlock("VALUE_ROWS"); if (0 == block.length()) { throw new UnsupportedSqlFeatureException("MULTIPLE INSERT ROWS", mDatasource.getAliasedDriver()); } template.setValue("DATA", block); } mSql = template.getBlock("QUERY"); assert mSql != null; assert mSql.length() > 0; } } return mSql; } public Insert hint(String hint) { clearGenerated(); mHint = hint; return this; } public Insert into(String into) { if (null == into) throw new IllegalArgumentException("into can't be null."); if (0 == into.length()) throw new IllegalArgumentException("into can't be empty."); clearGenerated(); mInto = into; return this; } public Insert fieldSubselect(Select query) { _fieldSubselect(query); return this; } protected Insert _field(String field, Object value) { assert field != null; assert field.length() > 0; clearGenerated(); if (!mFields.containsKey(field)) { mFields.put(field, new ArrayList<Object>()); } if (null == value) { mFields.get(field).add(SqlNull.NULL); } else { mFields.get(field).add(value); } return this; } public Insert fieldParameter(String field) { return fieldParameter(field, field); } public Insert fieldParameter(String field, String alias) { if (null == field) throw new IllegalArgumentException("field can't be null."); if (0 == field.length()) throw new IllegalArgumentException("field can't be empty."); if (null == alias) throw new IllegalArgumentException("alias can't be null."); if (0 == alias.length()) throw new IllegalArgumentException("alias can't be empty."); clearGenerated(); addFieldParameter(alias); return _field(field, "?"); } public Insert field(String field, char value) { return field(field, new Character(value)); } public Insert field(String field, boolean value) { return field(field, Boolean.valueOf(value)); } public Insert field(String field, byte value) { return field(field, new Byte(value)); } public Insert field(String field, double value) { return field(field, new Double(value)); } public Insert field(String field, float value) { return field(field, new Float(value)); } public Insert field(String field, int value) { return field(field, new Integer(value)); } public Insert field(String field, long value) { return field(field, new Long(value)); } public Insert field(String field, short value) { return field(field, new Short(value)); } public Insert field(String field, Select query) { if (null == query) throw new IllegalArgumentException("query can't be null."); StringBuilder buffer = new StringBuilder(); buffer.append("("); buffer.append(query.toString()); buffer.append(")"); fieldCustom(field, buffer.toString()); _fieldSubselect(query); return this; } public Insert field(String field, Object value) { if (null == field) throw new IllegalArgumentException("field can't be null."); if (0 == field.length()) throw new IllegalArgumentException("field can't be empty."); if (null == value) { return _field(field, null); } else { return _field(field, mDatasource.getSqlConversion().getSqlValue(value)); } } public Insert fieldCustom(String field, String expression) { if (null == field) throw new IllegalArgumentException("field can't be null."); if (0 == field.length()) throw new IllegalArgumentException("field can't be empty."); if (null == expression) { return _field(field, null); } else { return _field(field, expression); } } public Insert fields(Object[] keyValues) { if (null == keyValues) throw new IllegalArgumentException("keyValues can't be null."); if (0 == keyValues.length) throw new IllegalArgumentException("keyValues can't be empty."); for (int i = 0; i < keyValues.length; i+=2) { if (null != keyValues[i]) { field(keyValues[i].toString(), keyValues[i+1]); } } return this; } public Insert fields(Object bean) throws DbQueryException { return fieldsFiltered(bean, null, null); } public Insert fieldsIncluded(Object bean, String[] includedFields) throws DbQueryException { return fieldsFiltered(bean, includedFields, null); } public Insert fieldsExcluded(Object bean, String[] excludedFields) throws DbQueryException { return fieldsFiltered(bean, null, excludedFields); } public Insert fieldsFiltered(Object bean, String[] includedFields, String[] excludedFields) throws DbQueryException { if (null == bean) throw new IllegalArgumentException("bean can't be null."); Constrained constrained = ConstrainedUtils.makeConstrainedInstance(bean); Map<String, String> property_values = QueryHelper.getBeanPropertyValues(bean, includedFields, excludedFields, getDatasource()); for (String property_name : property_values.keySet()) { if (!ConstrainedUtils.saveConstrainedProperty(constrained, property_name, null)) { continue; } _field(property_name, property_values.get(property_name)); } return this; } public Insert fieldsParameters(Class beanClass) throws DbQueryException { return fieldsParametersExcluded(beanClass, null); } public Insert fieldsParametersExcluded(Class beanClass, String[] excludedFields) throws DbQueryException { if (null == beanClass) throw new IllegalArgumentException("beanClass can't be null."); clearGenerated(); Constrained constrained = ConstrainedUtils.getConstrainedInstance(beanClass); Set<String> property_names = QueryHelper.getBeanPropertyNames(beanClass, excludedFields); for (String property_name : property_names) { if (!ConstrainedUtils.saveConstrainedProperty(constrained, property_name, null)) { continue; } addFieldParameter(property_name); _field(property_name, "?"); } return this; } public Insert clone() { Insert new_instance = (Insert)super.clone(); if (new_instance != null) { if (mFields != null) { new_instance.mFields = new LinkedHashMap<String, List<Object>>(); List<Object> values = null; for (String field : mFields.keySet()) { values = mFields.get(field); if (values != null) { values = new ArrayList<Object>(values); } new_instance.mFields.put(field, values); } } } return new_instance; } }