com.torodb.torod.db.postgresql.meta.routines.QueryRoutine.java Source code

Java tutorial

Introduction

Here is the source code for com.torodb.torod.db.postgresql.meta.routines.QueryRoutine.java

Source

/*
 *     This file is part of ToroDB.
 *
 *     ToroDB 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.
 *
 *     ToroDB 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 ToroDB. If not, see <http://www.gnu.org/licenses/>.
 *
 *     Copyright (c) 2014, 8Kdata Technology
 *     
 */

package com.torodb.torod.db.postgresql.meta.routines;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Lists;
import com.google.common.collect.Table;
import com.torodb.torod.core.language.projection.Projection;
import com.torodb.torod.core.subdocument.SplitDocument;
import com.torodb.torod.db.postgresql.converters.SplitDocumentConverter;
import com.torodb.torod.db.postgresql.meta.CollectionSchema;
import com.torodb.torod.db.postgresql.meta.tables.SubDocTable;
import java.sql.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
import org.jooq.Configuration;

public class QueryRoutine {

    public static final String DOC_ID = "did";
    public static final String TYPE_ID = "typeid";
    public static final String INDEX = "index";
    public static final String _JSON = "_json";

    private static final String QUERY = "SELECT " + DOC_ID + "," + TYPE_ID + "," + INDEX + "," + _JSON
            + " FROM find_docs(?, ?, ?) ORDER BY " + DOC_ID;

    private QueryRoutine() {
    }

    public static List<SplitDocument> execute(Configuration configuration, CollectionSchema colSchema,
            Integer[] requestedDocs, Projection projection) {

        if (requestedDocs.length == 0) {
            return Collections.emptyList();
        }

        Connection c;
        PreparedStatement ps = null;

        try {
            c = configuration.connectionProvider().acquire();
            ps = c.prepareStatement(QUERY);

            ps.setString(1, colSchema.getCollection());

            ps.setArray(2, c.createArrayOf("integer", requestedDocs));

            Integer[] requiredTables = requiredTables(colSchema, projection);
            ps.setArray(3, c.createArrayOf("integer", requiredTables));

            configuration.connectionProvider().release(c);

            return translateDocuments(colSchema, requestedDocs.length, ps.executeQuery());
        } catch (SQLException ex) {
            //TODO: Study exceptions
            throw new RuntimeException(ex);
        } finally {
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException ex1) {
                    //TODO: Study exceptions
                    throw new RuntimeException(ex1);
                }
            }
        }
    }

    private static Integer[] requiredTables(CollectionSchema colSchema, Projection projection) {
        Collection<SubDocTable> subDocTables = colSchema.getSubDocTables();

        Integer[] result = new Integer[subDocTables.size()];
        int i = 0;
        for (SubDocTable subDocTable : subDocTables) {
            result[i] = subDocTable.getTypeId();
            i++;
        }
        return result;
    }

    @Nonnull
    private static List<SplitDocument> translateDocuments(CollectionSchema colSchema, int expectedDocs,
            ResultSet rs) {
        try {
            List<SplitDocument> result = Lists.newArrayListWithCapacity(expectedDocs);

            Table<Integer, Integer, String> docInfo = HashBasedTable.create();

            Integer lastDocId = null;
            Integer structureId = null;
            while (rs.next()) {
                int docId = rs.getInt(DOC_ID);
                if (lastDocId == null || lastDocId != docId) {
                    if (lastDocId != null) { //if this is not the first iteration
                        SplitDocument doc = processDocument(colSchema, lastDocId, structureId, docInfo);
                        result.add(doc);
                    }
                    lastDocId = docId;
                    structureId = null;
                    assert docInfo.isEmpty();
                }

                Object typeId = rs.getObject(TYPE_ID);
                Object index = rs.getObject(INDEX);
                String json = rs.getString(_JSON);

                if (typeId != null) { //subdocument
                    assert typeId instanceof Integer;
                    assert index == null || index instanceof Integer;
                    assert json != null;

                    if (index == null) {
                        index = 0;
                    }

                    docInfo.put((Integer) typeId, (Integer) index, json);
                } else { //metainfo
                    assert index != null;
                    assert json == null;

                    structureId = (Integer) index;
                }
            }
            if (lastDocId != null) {
                SplitDocument doc = processDocument(colSchema, lastDocId, structureId, docInfo);
                result.add(doc);
            }

            return result;
        } catch (SQLException ex) {
            //TODO: Change exception
            throw new RuntimeException(ex);
        }
    }

    private static SplitDocument processDocument(CollectionSchema colSchema, int lastDocId, Integer structureId,
            Table<Integer, Integer, String> docInfo) {

        if (structureId == null) {
            //TODO: Change exception
            throw new RuntimeException("Structure id was expected");
        }

        SplitDocumentConverter converter = SplitDocumentConverter.INSTANCE;

        return converter.convert(colSchema, lastDocId, structureId, docInfo);
    }
}