001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.ecm.core.storage.sql.jdbc; 020 021import java.io.Serializable; 022import java.sql.PreparedStatement; 023import java.sql.ResultSet; 024import java.sql.SQLException; 025import java.util.ArrayList; 026import java.util.Iterator; 027import java.util.List; 028 029import org.nuxeo.ecm.core.storage.sql.Model; 030import org.nuxeo.ecm.core.storage.sql.RowMapper.RowUpdate; 031import org.nuxeo.ecm.core.storage.sql.jdbc.db.Column; 032 033/** 034 * Collection IO for arrays of scalar values. 035 */ 036public class ScalarCollectionIO implements CollectionIO { 037 038 /** Whether we always insert all the rows in the row update or just the values starting from pos. */ 039 protected final boolean insertAll; 040 041 public ScalarCollectionIO(boolean insertAll) { 042 this.insertAll = insertAll; 043 } 044 045 @Override 046 public Serializable getCurrentFromResultSet(ResultSet rs, List<Column> columns, Model model, 047 Serializable[] returnId, int[] returnPos) throws SQLException { 048 Serializable id = null; 049 Serializable value = null; 050 int i = 0; 051 for (Column column : columns) { 052 i++; 053 String key = column.getKey(); 054 Serializable v = column.getFromResultSet(rs, i); 055 if (key.equals(model.MAIN_KEY)) { 056 id = v; 057 } else if (key.equals(model.COLL_TABLE_POS_KEY)) { 058 // (the pos column is ignored, results are already ordered by id 059 // then pos) 060 } else if (key.equals(model.COLL_TABLE_VALUE_KEY)) { 061 value = v; 062 } else { 063 throw new RuntimeException(key); 064 } 065 } 066 Serializable prevId = returnId[0]; 067 returnId[0] = id; 068 int pos = (id != null && !id.equals(prevId)) ? 0 : returnPos[0] + 1; 069 returnPos[0] = pos; 070 return value; 071 } 072 073 @Override 074 public void executeInserts(PreparedStatement ps, List<RowUpdate> rowus, List<Column> columns, 075 boolean supportsBatchUpdates, String sql, JDBCConnection connection) throws SQLException { 076 List<Serializable> debugValues = connection.logger.isLogEnabled() ? new ArrayList<Serializable>() : null; 077 boolean batched = supportsBatchUpdates && rowus.size() > 1; 078 String loggedSql = batched ? sql + " -- BATCHED" : sql; 079 int batch = 0; 080 for (Iterator<RowUpdate> rowIt = rowus.iterator(); rowIt.hasNext();) { 081 RowUpdate rowu = rowIt.next(); 082 int start; 083 if (rowu.pos == -1 || insertAll) { 084 start = 0; 085 } else { 086 start = rowu.pos; 087 } 088 Serializable id = rowu.row.id; 089 Serializable[] array = rowu.row.values; 090 for (int i = start; i < array.length; i++) { 091 int n = 0; 092 for (Column column : columns) { 093 n++; 094 String key = column.getKey(); 095 Serializable v; 096 if (key.equals(Model.MAIN_KEY)) { 097 v = id; 098 } else if (key.equals(Model.COLL_TABLE_POS_KEY)) { 099 v = Long.valueOf((long) i); 100 } else if (key.equals(Model.COLL_TABLE_VALUE_KEY)) { 101 v = array[i]; 102 } else { 103 throw new RuntimeException(key); 104 } 105 column.setToPreparedStatement(ps, n, v); 106 if (debugValues != null) { 107 debugValues.add(v); 108 } 109 } 110 if (debugValues != null) { 111 connection.logger.logSQL(loggedSql, debugValues); 112 debugValues.clear(); 113 } 114 if (batched) { 115 ps.addBatch(); 116 batch++; 117 if (batch % JDBCRowMapper.UPDATE_BATCH_SIZE == 0 || !rowIt.hasNext()) { 118 ps.executeBatch(); 119 connection.countExecute(); 120 } 121 } else { 122 ps.execute(); 123 connection.countExecute(); 124 } 125 } 126 } 127 } 128 129}