001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     Florent Guillaume
011 */
012package org.nuxeo.ecm.core.storage.sql.jdbc;
013
014import java.io.Serializable;
015import java.sql.PreparedStatement;
016import java.sql.ResultSet;
017import java.sql.SQLException;
018import java.util.ArrayList;
019import java.util.List;
020
021import org.nuxeo.ecm.core.storage.sql.Model;
022import org.nuxeo.ecm.core.storage.sql.Row;
023import org.nuxeo.ecm.core.storage.sql.jdbc.db.Column;
024
025/**
026 * Collection IO for arrays of scalar values.
027 */
028public class ScalarCollectionIO implements CollectionIO {
029
030    public static final CollectionIO INSTANCE = new ScalarCollectionIO();
031
032    @Override
033    public Serializable getCurrentFromResultSet(ResultSet rs, List<Column> columns, Model model,
034            Serializable[] returnId, int[] returnPos) throws SQLException {
035        Serializable id = null;
036        Serializable value = null;
037        int i = 0;
038        for (Column column : columns) {
039            i++;
040            String key = column.getKey();
041            Serializable v = column.getFromResultSet(rs, i);
042            if (key.equals(model.MAIN_KEY)) {
043                id = v;
044            } else if (key.equals(model.COLL_TABLE_POS_KEY)) {
045                // (the pos column is ignored, results are already ordered by id
046                // then pos)
047            } else if (key.equals(model.COLL_TABLE_VALUE_KEY)) {
048                value = v;
049            } else {
050                throw new RuntimeException(key);
051            }
052        }
053        Serializable prevId = returnId[0];
054        returnId[0] = id;
055        int pos = (id != null && !id.equals(prevId)) ? 0 : returnPos[0] + 1;
056        returnPos[0] = pos;
057        return value;
058    }
059
060    @Override
061    public void executeInserts(PreparedStatement ps, List<Row> rows, List<Column> columns,
062            boolean supportsBatchUpdates, String sql, JDBCConnection connection) throws SQLException {
063        List<Serializable> debugValues = connection.logger.isLogEnabled() ? new ArrayList<Serializable>() : null;
064        String loggedSql = supportsBatchUpdates && rows.size() > 1 ? sql + " -- BATCHED" : sql;
065        int batch = 0;
066        for (Row row : rows) {
067            batch++;
068            Serializable id = row.id;
069            Serializable[] array = row.values;
070            for (int i = 0; i < array.length; i++) {
071                int n = 0;
072                for (Column column : columns) {
073                    n++;
074                    String key = column.getKey();
075                    Serializable v;
076                    if (key.equals(Model.MAIN_KEY)) {
077                        v = id;
078                    } else if (key.equals(Model.COLL_TABLE_POS_KEY)) {
079                        v = Long.valueOf((long) i);
080                    } else if (key.equals(Model.COLL_TABLE_VALUE_KEY)) {
081                        v = array[i];
082                    } else {
083                        throw new RuntimeException(key);
084                    }
085                    column.setToPreparedStatement(ps, n, v);
086                    if (debugValues != null) {
087                        debugValues.add(v);
088                    }
089                }
090                if (debugValues != null) {
091                    connection.logger.logSQL(loggedSql, debugValues);
092                    debugValues.clear();
093                }
094                if (supportsBatchUpdates) {
095                    ps.addBatch();
096                    if (batch % JDBCRowMapper.UPDATE_BATCH_SIZE == 0) {
097                        ps.executeBatch();
098                        connection.countExecute();
099                    }
100                } else {
101                    ps.execute();
102                    connection.countExecute();
103                }
104            }
105        }
106        if (supportsBatchUpdates) {
107            ps.executeBatch();
108            connection.countExecute();
109        }
110    }
111
112}