Search in sources :

Example 1 with InsertStatement

use of org.datanucleus.store.rdbms.sql.InsertStatement in project datanucleus-rdbms by datanucleus.

the class JPQLQuery method compileQueryInsert.

/**
 * Method to compile the query for RDBMS for a bulk INSERT.
 * @param parameterValues The parameter values (if any)
 * @param candidateCmd Meta-data for the candidate class
 */
protected void compileQueryInsert(Map parameterValues, AbstractClassMetaData candidateCmd) {
    if (StringUtils.isWhitespace(insertFields) || StringUtils.isWhitespace(insertSelectQuery)) {
        // Nothing to INSERT
        return;
    }
    List<String> fieldNames = new ArrayList<>();
    StringTokenizer fieldTokenizer = new StringTokenizer(insertFields, ",");
    while (fieldTokenizer.hasMoreTokens()) {
        String token = fieldTokenizer.nextToken().trim();
        fieldNames.add(token);
    }
    // Generate statement for candidate and related classes in this inheritance tree
    RDBMSStoreManager storeMgr = (RDBMSStoreManager) getStoreManager();
    DatastoreClass candidateTbl = storeMgr.getDatastoreClass(candidateCmd.getFullClassName(), clr);
    if (candidateTbl == null) {
        // TODO Using subclass-table, so find the table(s) it can be persisted into
        throw new NucleusDataStoreException("Bulk INSERT of " + candidateCmd.getFullClassName() + " not supported since candidate has no table of its own");
    }
    // Find table(s) that need populating with this information
    List<BulkTable> tables = new ArrayList<>();
    tables.add(new BulkTable(candidateTbl, true));
    if (candidateTbl.getSuperDatastoreClass() != null) {
        DatastoreClass tbl = candidateTbl;
        while (tbl.getSuperDatastoreClass() != null) {
            tbl = tbl.getSuperDatastoreClass();
            tables.add(0, new BulkTable(tbl, false));
        }
    }
    if (tables.size() > 1) {
        throw new NucleusUserException("BULK INSERT only currently allows a single table, but this query implies INSERT into " + tables.size() + " tables!");
    }
    List<SQLStatement> stmts = new ArrayList<>();
    List<Boolean> stmtCountFlags = new ArrayList<>();
    for (BulkTable bulkTable : tables) {
        // Generate statement for candidate
        InsertStatement stmt = new InsertStatement(storeMgr, bulkTable.table, null, null, null);
        stmt.setClassLoaderResolver(clr);
        stmt.setCandidateClassName(candidateCmd.getFullClassName());
        // Set columns for this table
        for (String fieldName : fieldNames) {
            AbstractMemberMetaData fieldMmd = candidateCmd.getMetaDataForMember(fieldName);
            if (fieldMmd == null) {
            // No such field
            } else {
                JavaTypeMapping fieldMapping = bulkTable.table.getMemberMapping(fieldMmd);
                if (fieldMapping != null) {
                    SQLExpression fieldExpr = stmt.getSQLExpressionFactory().newExpression(stmt, stmt.getPrimaryTable(), fieldMapping);
                    for (int i = 0; i < fieldExpr.getNumberOfSubExpressions(); i++) {
                        ColumnExpression fieldColExpr = fieldExpr.getSubExpression(i);
                        fieldColExpr.setOmitTableFromString(true);
                    }
                    stmt.addColumn(fieldExpr);
                } else {
                // Not in this table
                }
            }
        }
        // Generate the select query and add it to the InsertStatement
        JPQLQuery selectQuery = new JPQLQuery(storeMgr, ec, insertSelectQuery);
        selectQuery.compile();
        stmt.setSelectStatement((SelectStatement) selectQuery.getDatastoreCompilation().getStatementCompilations().get(0).getStatement());
        selectQuery.closeAll();
        // TODO if we have multiple tables then this will mean only using some of the columns in the selectSQL
        stmts.add(stmt);
        stmtCountFlags.add(bulkTable.useInCount);
        datastoreCompilation.setStatementParameters(stmt.getSQLText().getParametersForStatement());
    }
    datastoreCompilation.clearStatements();
    Iterator<SQLStatement> stmtIter = stmts.iterator();
    Iterator<Boolean> stmtCountFlagsIter = stmtCountFlags.iterator();
    while (stmtIter.hasNext()) {
        SQLStatement stmt = stmtIter.next();
        Boolean useInCount = stmtCountFlagsIter.next();
        if (stmts.size() == 1) {
            useInCount = true;
        }
        datastoreCompilation.addStatement(stmt, stmt.getSQLText().toSQL(), useInCount);
    }
}
Also used : SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ArrayList(java.util.ArrayList) SQLStatement(org.datanucleus.store.rdbms.sql.SQLStatement) InsertStatement(org.datanucleus.store.rdbms.sql.InsertStatement) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) StringTokenizer(java.util.StringTokenizer) ColumnExpression(org.datanucleus.store.rdbms.sql.expression.ColumnExpression) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractJPQLQuery(org.datanucleus.store.query.AbstractJPQLQuery) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

ArrayList (java.util.ArrayList)1 StringTokenizer (java.util.StringTokenizer)1 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)1 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)1 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)1 AbstractJPQLQuery (org.datanucleus.store.query.AbstractJPQLQuery)1 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)1 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)1 InsertStatement (org.datanucleus.store.rdbms.sql.InsertStatement)1 SQLStatement (org.datanucleus.store.rdbms.sql.SQLStatement)1 ColumnExpression (org.datanucleus.store.rdbms.sql.expression.ColumnExpression)1 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)1 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)1