/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.query; import java.util.Arrays; import com.servoy.base.query.BaseAbstractBaseQuery; import com.servoy.base.query.BaseQueryTable; import com.servoy.j2db.util.serialize.ReplacedObject; import com.servoy.j2db.util.visitor.IVisitor; /** * Query insert statement. * * @author rgansevles * */ public class QueryInsert extends AbstractBaseQuery implements ISQLUpdate { BaseQueryTable table; private QueryColumn[] columns = null; private Object values = null; // maybe SQLValue placeholder or subquery public QueryInsert(BaseQueryTable table) { this.table = table; } public QueryInsert(BaseQueryTable table, QueryColumn[] columns, Object values) { this.table = table; setColumnValues(columns, values); } public void setColumnValues(QueryColumn[] columns, Object values) { this.values = validateValues(columns, values); this.columns = columns; } public boolean removeColumn(QueryColumn column) { for (int i = 0; i < columns.length; i++) { if (columns[i].getName().equals(column.getName())) { if (values instanceof Placeholder && ((Placeholder)values).isSet() && ((Placeholder)values).getValue() instanceof Object[]) { ((Placeholder)values).setValue(removeItem((Object[])((Placeholder)values).getValue(), i)); } else if (values instanceof Object[]) { values = removeItem((Object[])values, i); } columns = (QueryColumn[])removeItem(columns, i); return true; } } return false; } /** * Remove the nth item from the object array. Return an array of the same type. */ private Object[] removeItem(Object[] array, int n) { Object[] res = (Object[])java.lang.reflect.Array.newInstance(array.getClass().getComponentType(), array.length - 1); if (n > 0) { System.arraycopy(array, 0, res, 0, n); } if (n < res.length) { System.arraycopy(array, n + 1, res, n, res.length - n); } return res; } private static Object validateValues(QueryColumn[] columns, Object values) { Object vals = values; if (columns == null || columns.length == 0) { throw new IllegalArgumentException("Empty column set in insert"); //$NON-NLS-1$ } if (vals instanceof Placeholder || vals instanceof ISQLSelect) { // placeholder or sub-query: ok return vals; } // convenience: array of objects as wide as columns, convert to array of value arrays if (vals instanceof Object[] && !(vals instanceof Object[][]) && ((Object[])vals).length == columns.length) { Object[][] converted = new Object[((Object[])vals).length][]; for (int i = 0; i < converted.length; i++) { converted[i] = new Object[] { ((Object[])vals)[i] }; } vals = converted; } if (vals == null || !(vals instanceof Object[][]) || ((Object[][])vals).length != columns.length) { throw new IllegalArgumentException("Value list does not match column list in insert"); //$NON-NLS-1$ } // ok return vals; } public BaseQueryTable getTable() { return table; } public QueryColumn[] getColumns() { return columns; } public Object getValues() { return values; } @Override public Object shallowClone() throws CloneNotSupportedException { return super.clone(); } public void acceptVisitor(IVisitor visitor) { table = AbstractBaseQuery.acceptVisitor(table, visitor); columns = AbstractBaseQuery.acceptVisitor(columns, visitor); values = AbstractBaseQuery.acceptVisitor(values, visitor); if (values instanceof Placeholder && visitor instanceof PlaceHolderSetter) { PlaceHolderSetter phs = (PlaceHolderSetter)visitor; Placeholder ph = (Placeholder)values; if (ph.getKey().equals(phs.getKey())) { ph.setValue(validateValues(columns, phs.getValue())); } } } @Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + BaseAbstractBaseQuery.hashCode(this.columns); result = PRIME * result + ((this.table == null) ? 0 : this.table.hashCode()); result = PRIME * result + ((this.values == null) ? 0 : BaseAbstractBaseQuery.arrayHashcode(this.values)); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final QueryInsert other = (QueryInsert)obj; if (!Arrays.equals(this.columns, other.columns)) return false; if (this.table == null) { if (other.table != null) return false; } else if (!this.table.equals(other.table)) return false; return BaseAbstractBaseQuery.arrayEquals(this.values, other.values); } @Override public String toString() { StringBuffer sb = new StringBuffer("INSERT INTO ").append(table.toString()); //$NON-NLS-1$ sb.append('('); for (int i = 0; i < columns.length; i++) { if (i > 0) { sb.append('|'); } sb.append(columns[i].toString()); } sb.append(") VALUES ("); //$NON-NLS-1$ if (values instanceof Object[][]) { Object[][] cols = (Object[][])values; for (int k = 0; k < cols.length; k++) { if (k > 0) { sb.append('|'); } sb.append(BaseAbstractBaseQuery.toString(cols[k])); } } else { sb.append(BaseAbstractBaseQuery.toString(values)); } sb.append(')'); return sb.toString(); } ///////// serialization //////////////// @Override public Object writeReplace() { // Note: when this serialized structure changes, make sure that old data (maybe saved as serialized xml) can still be deserialized! return new ReplacedObject(AbstractBaseQuery.QUERY_SERIALIZE_DOMAIN, getClass(), new Object[] { table, ReplacedObject.convertArray(columns, Object.class), values }); } public QueryInsert(ReplacedObject s) { Object[] members = (Object[])s.getObject(); int i = 0; this.table = (QueryTable)members[i++]; this.columns = (QueryColumn[])ReplacedObject.convertArray((Object[])members[i++], QueryColumn.class); this.values = members[i++]; } }