Search in sources :

Example 56 with JavaTypeMapping

use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.

the class SQLStatementHelper method applyParametersToStatement.

/**
 * Convenience method to apply parameter values to the provided statement.
 * @param ps The prepared statement
 * @param ec ExecutionContext
 * @param parameters The parameters
 * @param paramNameByPosition Optional map of parameter names keyed by the position
 * @param paramValuesByName Value of parameter keyed by name (or position)
 */
public static void applyParametersToStatement(PreparedStatement ps, ExecutionContext ec, List<SQLStatementParameter> parameters, Map<Integer, String> paramNameByPosition, Map paramValuesByName) {
    if (parameters != null) {
        int num = 1;
        Map<String, Integer> paramNumberByName = null;
        int nextParamNumber = 0;
        Iterator<SQLStatementParameter> i = parameters.iterator();
        while (i.hasNext()) {
            SQLStatementParameter param = i.next();
            JavaTypeMapping mapping = param.getMapping();
            RDBMSStoreManager storeMgr = mapping.getStoreManager();
            // Find the overall parameter value for this parameter
            Object value = null;
            if (paramNumberByName != null) {
                // Parameters are numbered but the query has named, so use lookup
                Integer position = paramNumberByName.get("" + param.getName());
                if (position == null) {
                    value = paramValuesByName.get(Integer.valueOf(nextParamNumber));
                    paramNumberByName.put(param.getName(), nextParamNumber);
                    nextParamNumber++;
                } else {
                    value = paramValuesByName.get(position);
                }
            } else {
                if (paramValuesByName.containsKey(param.getName())) {
                    // Named parameter has value in the input map
                    value = paramValuesByName.get(param.getName());
                } else {
                    // Named parameter doesn't have value, so maybe using numbered input params
                    if (paramNameByPosition != null) {
                        int paramPosition = -1;
                        Set<String> paramNamesEncountered = new HashSet<>();
                        for (Map.Entry<Integer, String> entry : paramNameByPosition.entrySet()) {
                            String paramName = entry.getValue();
                            if (!paramNamesEncountered.contains(paramName)) {
                                paramPosition++;
                                paramNamesEncountered.add(paramName);
                            }
                            if (paramName.equals(param.getName())) {
                                value = paramValuesByName.get(paramPosition);
                                break;
                            }
                        }
                        paramNamesEncountered.clear();
                        paramNamesEncountered = null;
                    } else {
                        try {
                            value = paramValuesByName.get(Integer.valueOf(param.getName()));
                        } catch (NumberFormatException nfe) {
                            value = paramValuesByName.get(Integer.valueOf(nextParamNumber));
                            paramNumberByName = new HashMap<>();
                            paramNumberByName.put(param.getName(), Integer.valueOf(nextParamNumber));
                            nextParamNumber++;
                        }
                    }
                }
            }
            AbstractClassMetaData cmd = ec.getMetaDataManager().getMetaDataForClass(mapping.getType(), ec.getClassLoaderResolver());
            if (param.getColumnNumber() >= 0 && cmd != null) {
                // Apply the value for this column of the mapping
                Object colValue = null;
                if (value != null) {
                    if (cmd.getIdentityType() == IdentityType.DATASTORE) {
                        colValue = mapping.getValueForDatastoreMapping(ec.getNucleusContext(), param.getColumnNumber(), value);
                    } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
                        colValue = getValueForPrimaryKeyIndexOfObjectUsingReflection(value, param.getColumnNumber(), cmd, storeMgr, ec.getClassLoaderResolver());
                    }
                }
                mapping.getDatastoreMapping(param.getColumnNumber()).setObject(ps, num, colValue);
            } else {
                // Apply the value as a whole
                if (ec.getApiAdapter().isPersistable(value)) {
                    if (!ec.getApiAdapter().isPersistent(value) && !ec.getApiAdapter().isDetached(value)) {
                        // Transient persistable object passed in as query parameter! We cannot simply use mapping.setObject since it will PERSIST the object
                        // See also JDO TCK Assertion ID: A14.6.2-44 "Comparisons between persistent and non-persistent instances return not equal"
                        boolean supported = false;
                        if (!supported) {
                            // Transient persistable object, so don't use (use null instead) since would cause its persistence
                            NucleusLogger.QUERY.warn("Attempt to use transient object as parameter in query. Not supported, so using NULL for parameter value");
                            mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, mapping), null);
                        }
                    } else if (ec.getApiAdapter().isDetached(value)) {
                        // Detached, so avoid re-attaching
                        Object id = ec.getApiAdapter().getIdForObject(value);
                        PersistableIdMapping idMapping = new PersistableIdMapping((PersistableMapping) mapping);
                        idMapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, idMapping), id);
                    } else {
                        mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, mapping), value);
                    }
                } else {
                    if (mapping.getNumberOfDatastoreMappings() == 1) {
                        // Set whole object and only 1 column
                        mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num, mapping), value);
                    } else if (mapping.getNumberOfDatastoreMappings() > 1 && param.getColumnNumber() == (mapping.getNumberOfDatastoreMappings() - 1)) {
                        // Set whole object and this is the last parameter entry for it, so set now
                        mapping.setObject(ec, ps, MappingHelper.getMappingIndices(num - mapping.getNumberOfDatastoreMappings() + 1, mapping), value);
                    }
                }
            }
            num++;
        }
    }
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) HashMap(java.util.HashMap) PersistableIdMapping(org.datanucleus.store.rdbms.mapping.java.PersistableIdMapping) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) Map(java.util.Map) HashMap(java.util.HashMap) HashSet(java.util.HashSet)

Example 57 with JavaTypeMapping

use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.

the class LocateRequest method execute.

/**
 * Method performing the retrieval of the record from the datastore.
 * Takes the constructed retrieval query and populates with the specific record information.
 * @param op ObjectProvider for the record to be retrieved
 */
public void execute(ObjectProvider op) {
    if (statementLocked != null) {
        ExecutionContext ec = op.getExecutionContext();
        RDBMSStoreManager storeMgr = table.getStoreManager();
        boolean locked = ec.getSerializeReadForClass(op.getClassMetaData().getFullClassName());
        LockMode lockType = ec.getLockManager().getLockMode(op.getInternalObjectId());
        if (lockType != LockMode.LOCK_NONE) {
            if (lockType == LockMode.LOCK_PESSIMISTIC_READ || lockType == LockMode.LOCK_PESSIMISTIC_WRITE) {
                // Override with pessimistic lock
                locked = true;
            }
        }
        String statement = (locked ? statementLocked : statementUnlocked);
        try {
            ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
            SQLController sqlControl = storeMgr.getSQLController();
            try {
                PreparedStatement ps = sqlControl.getStatementForQuery(mconn, statement);
                AbstractClassMetaData cmd = op.getClassMetaData();
                try {
                    // Provide the primary key field(s)
                    if (cmd.getIdentityType() == IdentityType.DATASTORE) {
                        StatementMappingIndex datastoreIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
                        for (int i = 0; i < datastoreIdx.getNumberOfParameterOccurrences(); i++) {
                            table.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false).setObject(ec, ps, datastoreIdx.getParameterPositionsForOccurrence(i), op.getInternalObjectId());
                        }
                    } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
                        op.provideFields(cmd.getPKMemberPositions(), new ParameterSetter(op, ps, mappingDefinition));
                    }
                    JavaTypeMapping multitenancyMapping = table.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
                    if (multitenancyMapping != null) {
                        // Set MultiTenancy parameter in statement
                        StatementMappingIndex multitenancyIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.MULTITENANCY.getFieldNumber());
                        String tenantId = ec.getNucleusContext().getMultiTenancyId(ec, cmd);
                        for (int i = 0; i < multitenancyIdx.getNumberOfParameterOccurrences(); i++) {
                            multitenancyMapping.setObject(ec, ps, multitenancyIdx.getParameterPositionsForOccurrence(i), tenantId);
                        }
                    }
                    JavaTypeMapping softDeleteMapping = table.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
                    if (softDeleteMapping != null) {
                        // Set SoftDelete parameter in statement
                        StatementMappingIndex softDeleteIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.SOFTDELETE.getFieldNumber());
                        for (int i = 0; i < softDeleteIdx.getNumberOfParameterOccurrences(); i++) {
                            softDeleteMapping.setObject(ec, ps, softDeleteIdx.getParameterPositionsForOccurrence(i), Boolean.FALSE);
                        }
                    }
                    // Execute the statement
                    ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, statement, ps);
                    try {
                        if (!rs.next()) {
                            NucleusLogger.DATASTORE_RETRIEVE.info(Localiser.msg("050018", op.getInternalObjectId()));
                            throw new NucleusObjectNotFoundException("No such database row", op.getInternalObjectId());
                        }
                    } finally {
                        rs.close();
                    }
                } finally {
                    sqlControl.closeStatement(mconn, ps);
                }
            } finally {
                mconn.release();
            }
        } catch (SQLException sqle) {
            String msg = Localiser.msg("052220", op.getObjectAsPrintable(), statement, sqle.getMessage());
            NucleusLogger.DATASTORE_RETRIEVE.warn(msg);
            List exceptions = new ArrayList();
            exceptions.add(sqle);
            while ((sqle = sqle.getNextException()) != null) {
                exceptions.add(sqle);
            }
            throw new NucleusDataStoreException(msg, (Throwable[]) exceptions.toArray(new Throwable[exceptions.size()]));
        }
    }
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) PreparedStatement(java.sql.PreparedStatement) LockMode(org.datanucleus.state.LockMode) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) ParameterSetter(org.datanucleus.store.rdbms.fieldmanager.ParameterSetter) NucleusObjectNotFoundException(org.datanucleus.exceptions.NucleusObjectNotFoundException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) SQLController(org.datanucleus.store.rdbms.SQLController) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ExecutionContext(org.datanucleus.ExecutionContext) ResultSet(java.sql.ResultSet) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) ArrayList(java.util.ArrayList) List(java.util.List)

Example 58 with JavaTypeMapping

use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.

the class CollectionLiteral method invoke.

public SQLExpression invoke(String methodName, List args) {
    if (methodName.equals("get") && args.size() == 1 && value instanceof List) {
        // List.get
        SQLExpression argExpr = (SQLExpression) args.get(0);
        if (argExpr instanceof SQLLiteral) {
            // List.get(SQLLiteral)
            Object val = ((List) value).get((Integer) ((SQLLiteral) argExpr).getValue());
            if (val == null) {
                return new NullLiteral(stmt, null, null, null);
            }
            JavaTypeMapping m = stmt.getRDBMSManager().getSQLExpressionFactory().getMappingForType(val.getClass(), false);
            return new ObjectLiteral(stmt, m, val, null);
        }
        // Don't support List.get(SQLExpression)
        throw new IllegalExpressionOperationException(this, "get", argExpr);
    }
    return super.invoke(methodName, args);
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) List(java.util.List) ArrayList(java.util.ArrayList)

Example 59 with JavaTypeMapping

use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.

the class CollectionLiteral method setStatement.

protected void setStatement() {
    if (value != null && value.size() > 0) {
        RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
        elementExpressions = new ArrayList();
        st.append("(");
        boolean hadPrev = false;
        for (Iterator it = value.iterator(); it.hasNext(); ) {
            Object element = it.next();
            if (element != null) {
                JavaTypeMapping elemMapping = storeMgr.getSQLExpressionFactory().getMappingForType(element.getClass(), false);
                SQLExpression elemExpr = storeMgr.getSQLExpressionFactory().newLiteral(stmt, elemMapping, element);
                // Append the SQLExpression (should be a literal) for the current element
                st.append(hadPrev ? "," : "");
                st.append(elemExpr);
                elementExpressions.add(elemExpr);
                hadPrev = true;
            }
        }
        st.append(")");
    }
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ArrayList(java.util.ArrayList) Iterator(java.util.Iterator) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager)

Example 60 with JavaTypeMapping

use of org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping in project datanucleus-rdbms by datanucleus.

the class MapContainsKeyMethod method getExpression.

/* (non-Javadoc)
     * @see org.datanucleus.store.rdbms.sql.method.SQLMethod#getExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression, java.util.List)
     */
public SQLExpression getExpression(SQLStatement stmt, SQLExpression expr, List<SQLExpression> args) {
    if (args == null || args.size() == 0 || args.size() > 1) {
        throw new NucleusException(Localiser.msg("060016", "containsKey", "MapExpression", 1));
    }
    MapExpression mapExpr = (MapExpression) expr;
    SQLExpression keyExpr = args.get(0);
    if (keyExpr.isParameter()) {
        // Key is a parameter so make sure its type is set
        AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData();
        if (mmd != null && mmd.getMap() != null) {
            Class keyCls = stmt.getQueryGenerator().getClassLoaderResolver().classForName(mmd.getMap().getKeyType());
            stmt.getQueryGenerator().bindParameter(keyExpr.getParameterName(), keyCls);
        }
    }
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    if (expr instanceof MapLiteral) {
        // Literal Map
        MapLiteral lit = (MapLiteral) expr;
        Map map = (Map) lit.getValue();
        JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
        if (map == null || map.size() == 0) {
            return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
        }
        boolean useInExpression = false;
        List<SQLExpression> mapKeyExprs = lit.getKeyLiteral().getKeyExpressions();
        if (mapKeyExprs != null && !mapKeyExprs.isEmpty()) {
            // Make sure the the map key(s) are compatible with the keyExpr
            boolean incompatible = true;
            Class elemtype = clr.classForName(keyExpr.getJavaTypeMapping().getType());
            Iterator<SQLExpression> mapKeyExprIter = mapKeyExprs.iterator();
            while (mapKeyExprIter.hasNext()) {
                SQLExpression mapKeyExpr = mapKeyExprIter.next();
                Class mapKeyType = clr.classForName(mapKeyExpr.getJavaTypeMapping().getType());
                if (keyTypeCompatible(elemtype, mapKeyType)) {
                    incompatible = false;
                    break;
                }
            }
            if (incompatible) {
                // The provided element type isn't assignable to any of the input collection elements!
                return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
            }
            // Check if we should compare using an "IN (...)" expression
            SQLExpression mapKeyExpr = mapKeyExprs.get(0);
            if (mapKeyExpr instanceof StringExpression || mapKeyExpr instanceof NumericExpression || mapKeyExpr instanceof TemporalExpression || mapKeyExpr instanceof CharacterExpression || mapKeyExpr instanceof EnumExpression) {
                useInExpression = true;
            }
        }
        if (useInExpression) {
            // Return "key IN (val1, val2, ...)"
            SQLExpression[] exprs = (mapKeyExprs != null ? mapKeyExprs.toArray(new SQLExpression[mapKeyExprs.size()]) : null);
            return new InExpression(keyExpr, exprs);
        }
        // TODO If keyExpr is a parameter and mapExpr is derived from a parameter ?
        MapKeyLiteral mapKeyLiteral = lit.getKeyLiteral();
        BooleanExpression bExpr = null;
        List<SQLExpression> elementExprs = mapKeyLiteral.getKeyExpressions();
        for (int i = 0; i < elementExprs.size(); i++) {
            if (bExpr == null) {
                bExpr = (elementExprs.get(i)).eq(keyExpr);
            } else {
                bExpr = bExpr.ior((elementExprs.get(i)).eq(keyExpr));
            }
        }
        if (bExpr != null) {
            bExpr.encloseInParentheses();
        }
        return bExpr;
    }
    if (stmt.getQueryGenerator().getCompilationComponent() == CompilationComponent.FILTER) {
        boolean useSubquery = getNeedsSubquery(stmt);
        JoinType joinType = JoinType.INNER_JOIN;
        if (keyExpr instanceof UnboundExpression) {
            // See if the user has defined what should be used
            String varName = ((UnboundExpression) keyExpr).getVariableName();
            String extensionName = "datanucleus.query.jdoql." + varName + ".join";
            String extensionValue = (String) stmt.getQueryGenerator().getValueForExtension(extensionName);
            if (extensionValue != null) {
                if (extensionValue.equalsIgnoreCase("SUBQUERY")) {
                    useSubquery = true;
                } else if (extensionValue.equalsIgnoreCase("INNERJOIN")) {
                    useSubquery = false;
                } else if (extensionValue.equalsIgnoreCase("LEFTOUTERJOIN")) {
                    joinType = JoinType.LEFT_OUTER_JOIN;
                }
            }
        }
        // TODO Check if *this* "containsKey" is negated, not any of them (and remove above check)
        if (useSubquery) {
            return containsAsSubquery(stmt, mapExpr, keyExpr);
        }
        return containsAsJoin(stmt, mapExpr, keyExpr, joinType);
    }
    return containsAsSubquery(stmt, mapExpr, keyExpr);
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) InExpression(org.datanucleus.store.rdbms.sql.expression.InExpression) UnboundExpression(org.datanucleus.store.rdbms.sql.expression.UnboundExpression) BooleanExpression(org.datanucleus.store.rdbms.sql.expression.BooleanExpression) MapExpression(org.datanucleus.store.rdbms.sql.expression.MapExpression) TemporalExpression(org.datanucleus.store.rdbms.sql.expression.TemporalExpression) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) NumericExpression(org.datanucleus.store.rdbms.sql.expression.NumericExpression) JoinType(org.datanucleus.store.rdbms.sql.SQLJoin.JoinType) EnumExpression(org.datanucleus.store.rdbms.sql.expression.EnumExpression) CharacterExpression(org.datanucleus.store.rdbms.sql.expression.CharacterExpression) MapLiteral(org.datanucleus.store.rdbms.sql.expression.MapLiteral) StringExpression(org.datanucleus.store.rdbms.sql.expression.StringExpression) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) Map(java.util.Map) MapKeyLiteral(org.datanucleus.store.rdbms.sql.expression.MapLiteral.MapKeyLiteral)

Aggregations

JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)230 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)96 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)82 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)82 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)81 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)76 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)69 ArrayList (java.util.ArrayList)66 NucleusException (org.datanucleus.exceptions.NucleusException)57 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)50 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)47 NumericExpression (org.datanucleus.store.rdbms.sql.expression.NumericExpression)43 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)37 PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)30 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)30 StringExpression (org.datanucleus.store.rdbms.sql.expression.StringExpression)27 List (java.util.List)25 ReferenceMapping (org.datanucleus.store.rdbms.mapping.java.ReferenceMapping)22 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)21 StringLiteral (org.datanucleus.store.rdbms.sql.expression.StringLiteral)21