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.List;
027
028import org.nuxeo.ecm.core.storage.sql.Model;
029import org.nuxeo.ecm.core.storage.sql.RowMapper.RowUpdate;
030import org.nuxeo.ecm.core.storage.sql.jdbc.db.Column;
031
032/**
033 * Collection IO for arrays of scalar values.
034 */
035public class ScalarCollectionIO implements CollectionIO {
036
037    /** Whether we always insert all the rows in the row update or just the values starting from pos. */
038    protected final boolean insertAll;
039
040    public ScalarCollectionIO(boolean insertAll) {
041        this.insertAll = insertAll;
042    }
043
044    @Override
045    public Serializable getCurrentFromResultSet(ResultSet rs, List<Column> columns, Model model,
046            Serializable[] returnId, int[] returnPos) throws SQLException {
047        Serializable id = null;
048        Serializable value = null;
049        int i = 0;
050        for (Column column : columns) {
051            i++;
052            String key = column.getKey();
053            Serializable v = column.getFromResultSet(rs, i);
054            if (key.equals(model.MAIN_KEY)) {
055                id = v;
056            } else if (key.equals(model.COLL_TABLE_POS_KEY)) {
057                // (the pos column is ignored, results are already ordered by id
058                // then pos)
059            } else if (key.equals(model.COLL_TABLE_VALUE_KEY)) {
060                value = v;
061            } else {
062                throw new RuntimeException(key);
063            }
064        }
065        Serializable prevId = returnId[0];
066        returnId[0] = id;
067        int pos = (id != null && !id.equals(prevId)) ? 0 : returnPos[0] + 1;
068        returnPos[0] = pos;
069        return value;
070    }
071
072    @Override
073    public void executeInserts(PreparedStatement ps, List<RowUpdate> rowus, List<Column> columns,
074            boolean supportsBatchUpdates, String sql, JDBCConnection connection) throws SQLException {
075        List<Serializable> debugValues = connection.logger.isLogEnabled() ? new ArrayList<Serializable>() : null;
076        String loggedSql = supportsBatchUpdates && rowus.size() > 1 ? sql + " -- BATCHED" : sql;
077        int batch = 0;
078        for (RowUpdate rowu : rowus) {
079            batch++;
080            int start;
081            if (rowu.pos == -1 || insertAll) {
082                start = 0;
083            } else {
084                start = rowu.pos;
085            }
086            Serializable id = rowu.row.id;
087            Serializable[] array = rowu.row.values;
088            for (int i = start; i < array.length; i++) {
089                int n = 0;
090                for (Column column : columns) {
091                    n++;
092                    String key = column.getKey();
093                    Serializable v;
094                    if (key.equals(Model.MAIN_KEY)) {
095                        v = id;
096                    } else if (key.equals(Model.COLL_TABLE_POS_KEY)) {
097                        v = Long.valueOf((long) i);
098                    } else if (key.equals(Model.COLL_TABLE_VALUE_KEY)) {
099                        v = array[i];
100                    } else {
101                        throw new RuntimeException(key);
102                    }
103                    column.setToPreparedStatement(ps, n, v);
104                    if (debugValues != null) {
105                        debugValues.add(v);
106                    }
107                }
108                if (debugValues != null) {
109                    connection.logger.logSQL(loggedSql, debugValues);
110                    debugValues.clear();
111                }
112                if (supportsBatchUpdates) {
113                    ps.addBatch();
114                    if (batch % JDBCRowMapper.UPDATE_BATCH_SIZE == 0) {
115                        ps.executeBatch();
116                        connection.countExecute();
117                    }
118                } else {
119                    ps.execute();
120                    connection.countExecute();
121                }
122            }
123        }
124        if (supportsBatchUpdates) {
125            ps.executeBatch();
126            connection.countExecute();
127        }
128    }
129
130}