Search in sources :

Example 26 with NucleusException

use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.

the class RDBMSStoreManager method validateSchemaForClasses.

public void validateSchemaForClasses(Set<String> classNames, Properties props) {
    if (classNames != null && !classNames.isEmpty()) {
        // Validate the tables/constraints
        // Validates since we have the flags set
        manageClasses(nucleusContext.getClassLoaderResolver(null), classNames.toArray(new String[classNames.size()]));
    } else {
        String msg = Localiser.msg("014039");
        NucleusLogger.DATASTORE_SCHEMA.error(msg);
        System.out.println(msg);
        throw new NucleusException(msg);
    }
}
Also used : MacroString(org.datanucleus.util.MacroString) NucleusException(org.datanucleus.exceptions.NucleusException)

Example 27 with NucleusException

use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.

the class BaseDatastoreAdapter method loadColumnMappings.

/**
 * Load all column mappings defined in the associated plugins via the plugin mechanism.
 * All individual DatastoreAdapters should load up their own built-in support.
 * @param pluginMgr the PluginManager
 * @param clr the ClassLoaderResolver
 */
protected void loadColumnMappings(PluginManager pluginMgr, ClassLoaderResolver clr) {
    // Load from plugin mechanism
    ConfigurationElement[] elems = pluginMgr.getConfigurationElementsForExtension("org.datanucleus.store.rdbms.column_mapping", null, null);
    if (elems != null) {
        for (ConfigurationElement elem : elems) {
            String javaName = elem.getAttribute("java-type").trim();
            String columnMappingClassName = elem.getAttribute("column-mapping-class");
            String jdbcType = elem.getAttribute("jdbc-type");
            String sqlType = elem.getAttribute("sql-type");
            String defaultJava = elem.getAttribute("default");
            boolean defaultForJavaType = false;
            if (defaultJava != null) {
                if (defaultJava.equalsIgnoreCase("true")) {
                    defaultForJavaType = Boolean.TRUE.booleanValue();
                }
            }
            Class mappingType = null;
            if (!StringUtils.isWhitespace(columnMappingClassName)) {
                try {
                    mappingType = pluginMgr.loadClass(elem.getExtension().getPlugin().getSymbolicName(), columnMappingClassName);
                } catch (NucleusException ne) {
                    NucleusLogger.DATASTORE.error(Localiser.msg("041013", columnMappingClassName));
                }
                Set includes = new HashSet();
                Set excludes = new HashSet();
                for (ConfigurationElement childElem : elem.getChildren()) {
                    if (childElem.getName().equals("includes")) {
                        includes.add(childElem.getAttribute("vendor-id"));
                    } else if (childElem.getName().equals("excludes")) {
                        excludes.add(childElem.getAttribute("vendor-id"));
                    }
                }
                if (!excludes.contains(getVendorID())) {
                    if (includes.isEmpty() || includes.contains(getVendorID())) {
                        registerColumnMapping(javaName, mappingType, jdbcType, sqlType, defaultForJavaType);
                    }
                }
            }
        }
    }
}
Also used : ConfigurationElement(org.datanucleus.plugin.ConfigurationElement) ResultSet(java.sql.ResultSet) Set(java.util.Set) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) NucleusException(org.datanucleus.exceptions.NucleusException) HashSet(java.util.HashSet)

Example 28 with NucleusException

use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.

the class ConnectionFactoryImpl method generateDataSource.

/**
 * Method to generate the datasource used by this connection factory.
 * Searches initially for a provided DataSource then, if not found, for JNDI DataSource, and finally for the DataSource at a connection URL.
 * @param storeMgr Store Manager
 * @param connDS Factory data source object
 * @param connJNDI DataSource JNDI name(s)
 * @param resourceName Resource name
 * @param requiredPoolingType Type of connection pool
 * @param connURL URL for connections
 * @return The DataSource
 */
private DataSource generateDataSource(StoreManager storeMgr, Object connDS, String connJNDI, String resourceName, String requiredPoolingType, String connURL) {
    DataSource dataSource = null;
    if (connDS != null) {
        if (!(connDS instanceof DataSource) && !(connDS instanceof XADataSource)) {
            throw new UnsupportedConnectionFactoryException(connDS);
        }
        dataSource = (DataSource) connDS;
    } else if (connJNDI != null) {
        String connectionFactoryName = connJNDI.trim();
        try {
            Object obj = new InitialContext().lookup(connectionFactoryName);
            if (!(obj instanceof DataSource) && !(obj instanceof XADataSource)) {
                throw new UnsupportedConnectionFactoryException(obj);
            }
            dataSource = (DataSource) obj;
        } catch (NamingException e) {
            throw new ConnectionFactoryNotFoundException(connectionFactoryName, e);
        }
    } else if (connURL != null) {
        String poolingType = requiredPoolingType;
        if (StringUtils.isWhitespace(requiredPoolingType)) {
            // Default to dbcp2-builtin when nothing specified
            poolingType = "dbcp2-builtin";
        }
        // User has requested internal database connection pooling so check the registered plugins
        try {
            // Create the ConnectionPool to be used
            ConnectionPoolFactory connPoolFactory = null;
            // Try built-in pools first
            if (poolingType.equalsIgnoreCase("dbcp2-builtin")) {
                connPoolFactory = new DBCP2BuiltinConnectionPoolFactory();
            } else if (poolingType.equalsIgnoreCase("HikariCP")) {
                connPoolFactory = new HikariCPConnectionPoolFactory();
            } else if (poolingType.equalsIgnoreCase("BoneCP")) {
                connPoolFactory = new BoneCPConnectionPoolFactory();
            } else if (poolingType.equalsIgnoreCase("C3P0")) {
                connPoolFactory = new C3P0ConnectionPoolFactory();
            } else if (poolingType.equalsIgnoreCase("Tomcat")) {
                connPoolFactory = new TomcatConnectionPoolFactory();
            } else if (poolingType.equalsIgnoreCase("DBCP2")) {
                connPoolFactory = new DBCP2ConnectionPoolFactory();
            } else if (poolingType.equalsIgnoreCase("None")) {
                connPoolFactory = new DefaultConnectionPoolFactory();
            } else {
                // Fallback to the plugin mechanism
                connPoolFactory = (ConnectionPoolFactory) storeMgr.getNucleusContext().getPluginManager().createExecutableExtension("org.datanucleus.store.rdbms.connectionpool", "name", poolingType, "class-name", null, null);
                if (connPoolFactory == null) {
                    // User has specified a pool plugin that has not registered
                    throw new NucleusUserException(Localiser.msg("047003", poolingType)).setFatal();
                }
            }
            // Create the ConnectionPool and get the DataSource
            pool = connPoolFactory.createConnectionPool(storeMgr);
            dataSource = pool.getDataSource();
            if (NucleusLogger.CONNECTION.isDebugEnabled()) {
                NucleusLogger.CONNECTION.debug(Localiser.msg("047008", resourceName, poolingType));
            }
        } catch (ClassNotFoundException cnfe) {
            throw new NucleusUserException(Localiser.msg("047003", poolingType), cnfe).setFatal();
        } catch (Exception e) {
            if (e instanceof InvocationTargetException) {
                InvocationTargetException ite = (InvocationTargetException) e;
                throw new NucleusException(Localiser.msg("047004", poolingType, ite.getTargetException().getMessage()), ite.getTargetException()).setFatal();
            }
            throw new NucleusException(Localiser.msg("047004", poolingType, e.getMessage()), e).setFatal();
        }
    }
    return dataSource;
}
Also used : DefaultConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.DefaultConnectionPoolFactory) XADataSource(javax.sql.XADataSource) UnsupportedConnectionFactoryException(org.datanucleus.exceptions.UnsupportedConnectionFactoryException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ConnectionFactoryNotFoundException(org.datanucleus.exceptions.ConnectionFactoryNotFoundException) DBCP2ConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.DBCP2ConnectionPoolFactory) BoneCPConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.BoneCPConnectionPoolFactory) InitialContext(javax.naming.InitialContext) NamingException(javax.naming.NamingException) SQLException(java.sql.SQLException) ConnectionFactoryNotFoundException(org.datanucleus.exceptions.ConnectionFactoryNotFoundException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) UnsupportedConnectionFactoryException(org.datanucleus.exceptions.UnsupportedConnectionFactoryException) NucleusException(org.datanucleus.exceptions.NucleusException) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) InvocationTargetException(java.lang.reflect.InvocationTargetException) XAException(javax.transaction.xa.XAException) InvocationTargetException(java.lang.reflect.InvocationTargetException) XADataSource(javax.sql.XADataSource) DataSource(javax.sql.DataSource) DBCP2BuiltinConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.DBCP2BuiltinConnectionPoolFactory) C3P0ConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.C3P0ConnectionPoolFactory) NamingException(javax.naming.NamingException) NucleusException(org.datanucleus.exceptions.NucleusException) HikariCPConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.HikariCPConnectionPoolFactory) TomcatConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.TomcatConnectionPoolFactory) DBCP2BuiltinConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.DBCP2BuiltinConnectionPoolFactory) TomcatConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.TomcatConnectionPoolFactory) HikariCPConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.HikariCPConnectionPoolFactory) DefaultConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.DefaultConnectionPoolFactory) BoneCPConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.BoneCPConnectionPoolFactory) C3P0ConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.C3P0ConnectionPoolFactory) ConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.ConnectionPoolFactory) DBCP2ConnectionPoolFactory(org.datanucleus.store.rdbms.connectionpool.DBCP2ConnectionPoolFactory)

Example 29 with NucleusException

use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.

the class RDBMSPersistenceHandler method insertObject.

/**
 * Inserts a persistent object into the database.
 * The insert can take place in several steps, one insert per table that it is stored in.
 * e.g When persisting an object that uses "new-table" inheritance for each level of the inheritance tree then will get an INSERT into each table.
 * When persisting an object that uses "complete-table" inheritance then will get a single INSERT into its table.
 * @param sm StateManager for the object to be inserted.
 * @throws NucleusDataStoreException when an error occurs in the datastore communication
 */
@Override
public void insertObject(DNStateManager sm) {
    // Check if read-only so update not permitted
    assertReadOnlyForUpdateOfObject(sm);
    // Check if we need to do any updates to the schema before inserting this object
    checkForSchemaUpdatesForFieldsOfObject(sm, sm.getLoadedFieldNumbers());
    ExecutionContext ec = sm.getExecutionContext();
    ClassLoaderResolver clr = sm.getExecutionContext().getClassLoaderResolver();
    String className = sm.getClassMetaData().getFullClassName();
    DatastoreClass dc = getDatastoreClass(className, clr);
    if (dc == null) {
        if (sm.getClassMetaData().getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUBCLASS_TABLE) {
            throw new NucleusUserException(Localiser.msg("032013", className));
        }
        throw new NucleusException(Localiser.msg("032014", className, sm.getClassMetaData().getInheritanceMetaData().getStrategy())).setFatal();
    }
    if (ec.getStatistics() != null) {
        ec.getStatistics().incrementInsertCount();
    }
    insertObjectInTable(dc, sm, clr);
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) SecondaryDatastoreClass(org.datanucleus.store.rdbms.table.SecondaryDatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException)

Example 30 with NucleusException

use of org.datanucleus.exceptions.NucleusException in project datanucleus-rdbms by datanucleus.

the class ObjectExpression method is.

/**
 * An "is" (instanceOf) expression, providing a BooleanExpression whether this expression is an instanceof the provided type.
 * @param expr The expression representing the type
 * @param not Whether the operator is "!instanceof"
 * @return Whether this expression is an instance of the provided type
 */
public BooleanExpression is(SQLExpression expr, boolean not) {
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    ClassLoaderResolver clr = stmt.getClassLoaderResolver();
    // Extract instanceOf type
    String instanceofClassName = null;
    SQLExpression classExpr = expr;
    if (expr instanceof TypeConverterLiteral) {
        // For some reason the user has input "TYPE(field) = :param" and param is a type-converted value
        classExpr = ((TypeConverterLiteral) expr).getDelegate();
    }
    if (classExpr instanceof StringLiteral) {
        instanceofClassName = (String) ((StringLiteral) classExpr).getValue();
    } else if (classExpr instanceof CollectionLiteral) {
        // "a instanceof (b1,b2,b3)"
        CollectionLiteral typesLiteral = (CollectionLiteral) classExpr;
        Collection values = (Collection) typesLiteral.getValue();
        if (values.size() == 1) {
            Object value = values.iterator().next();
            String valueStr = null;
            if (value instanceof Class) {
                valueStr = ((Class) value).getCanonicalName();
            } else if (value instanceof String) {
                valueStr = (String) value;
            } else {
                throw new NucleusUserException("Do not support CollectionLiteral of element type " + value.getClass().getName());
            }
            return is(new StringLiteral(stmt, typesLiteral.getJavaTypeMapping(), valueStr, typesLiteral.getParameterName()), not);
        }
        List<BooleanExpression> listExp = new LinkedList<>();
        for (Object value : values) {
            String valueStr = null;
            if (value instanceof Class) {
                valueStr = ((Class) value).getCanonicalName();
            } else if (value instanceof String) {
                valueStr = (String) value;
            } else {
                throw new NucleusUserException("Do not support CollectionLiteral of element type " + value.getClass().getName());
            }
            listExp.add(is(new StringLiteral(stmt, typesLiteral.getJavaTypeMapping(), valueStr, typesLiteral.getParameterName()), false));
        }
        BooleanExpression result = null;
        for (BooleanExpression sqlExpression : listExp) {
            result = result == null ? sqlExpression : result.ior(sqlExpression);
        }
        if (result != null) {
            return not ? result.not() : result;
        }
    } else {
        throw new NucleusUserException("Do not currently support `instanceof` with class expression of type " + classExpr);
    }
    Class type = null;
    try {
        type = stmt.getQueryGenerator().resolveClass(instanceofClassName);
    } catch (ClassNotResolvedException cnre) {
        type = null;
    }
    if (type == null) {
        throw new NucleusUserException(Localiser.msg("037016", instanceofClassName));
    }
    // Extract type of member and check obvious conditions
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    Class memberType = clr.classForName(mapping.getType());
    if (!memberType.isAssignableFrom(type) && !type.isAssignableFrom(memberType)) {
        // Member type and instanceof type are totally incompatible, so just return false
        JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
        return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, not));
    } else if (memberType == type) {
        // instanceof type is the same as the member type therefore must comply (can't store supertypes)
        JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
        return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, !not));
    }
    if (mapping instanceof EmbeddedMapping) {
        // Don't support embedded instanceof expressions
        AbstractClassMetaData fieldCmd = storeMgr.getMetaDataManager().getMetaDataForClass(mapping.getType(), clr);
        if (fieldCmd.hasDiscriminatorStrategy()) {
            // Embedded field with inheritance so add discriminator restriction
            JavaTypeMapping discMapping = ((EmbeddedMapping) mapping).getDiscriminatorMapping();
            AbstractClassMetaData typeCmd = storeMgr.getMetaDataManager().getMetaDataForClass(type, clr);
            SQLExpression discExpr = stmt.getSQLExpressionFactory().newExpression(stmt, table, discMapping);
            SQLExpression discValExpr = stmt.getSQLExpressionFactory().newLiteral(stmt, discMapping, typeCmd.getDiscriminatorValue());
            BooleanExpression typeExpr = (not ? discExpr.ne(discValExpr) : discExpr.eq(discValExpr));
            Iterator<String> subclassIter = storeMgr.getSubClassesForClass(type.getName(), true, clr).iterator();
            while (subclassIter.hasNext()) {
                String subclassName = subclassIter.next();
                AbstractClassMetaData subtypeCmd = storeMgr.getMetaDataManager().getMetaDataForClass(subclassName, clr);
                Object subtypeDiscVal = subtypeCmd.getDiscriminatorValue();
                discValExpr = stmt.getSQLExpressionFactory().newLiteral(stmt, discMapping, subtypeDiscVal);
                BooleanExpression subtypeExpr = (not ? discExpr.ne(discValExpr) : discExpr.eq(discValExpr));
                if (not) {
                    typeExpr = typeExpr.and(subtypeExpr);
                } else {
                    typeExpr = typeExpr.ior(subtypeExpr);
                }
            }
            return typeExpr;
        }
        JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
        return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, not));
    } else if (mapping instanceof PersistableMapping || mapping instanceof ReferenceMapping) {
        // Field has its own table, so join to it
        AbstractClassMetaData memberCmd = storeMgr.getMetaDataManager().getMetaDataForClass(mapping.getType(), clr);
        DatastoreClass memberTable = null;
        if (memberCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUBCLASS_TABLE) {
            // Field is a PC class that uses "subclass-table" inheritance strategy (and so has multiple possible tables to join to)
            AbstractClassMetaData[] cmds = storeMgr.getClassesManagingTableForClass(memberCmd, clr);
            if (cmds != null) {
                // TODO Allow for all possible tables. Can we do an OR of the tables ? How ?
                if (cmds.length > 1) {
                    NucleusLogger.QUERY.warn(Localiser.msg("037006", mapping.getMemberMetaData().getFullFieldName(), cmds[0].getFullClassName()));
                }
                memberTable = storeMgr.getDatastoreClass(cmds[0].getFullClassName(), clr);
            } else {
                // No subclasses with tables to join to, so throw a user error
                throw new NucleusUserException(Localiser.msg("037005", mapping.getMemberMetaData().getFullFieldName()));
            }
        } else {
            // Class of the field will have its own table
            memberTable = storeMgr.getDatastoreClass(mapping.getType(), clr);
        }
        DiscriminatorMetaData dismd = memberTable.getDiscriminatorMetaData();
        DiscriminatorMapping discMapping = (DiscriminatorMapping) memberTable.getSurrogateMapping(SurrogateColumnType.DISCRIMINATOR, false);
        if (discMapping != null) {
            SQLTable targetSqlTbl = null;
            if (mapping.getTable() != memberTable) {
                // FK is on source table so inner join to target table (holding the discriminator)
                targetSqlTbl = stmt.getTable(memberTable, null);
                if (targetSqlTbl == null) {
                    targetSqlTbl = stmt.join(JoinType.INNER_JOIN, getSQLTable(), mapping, memberTable, null, memberTable.getIdMapping(), null, null);
                }
            } else {
                // FK is on target side and already joined
                targetSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(stmt, getSQLTable(), discMapping);
            }
            // Add restrict to discriminator for the instanceOf type and subclasses
            SQLTable discSqlTbl = targetSqlTbl;
            BooleanExpression discExpr = null;
            if (!Modifier.isAbstract(type.getModifiers())) {
                discExpr = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, type.getName(), dismd, discMapping, discSqlTbl, clr);
            }
            Iterator<String> subclassIter = storeMgr.getSubClassesForClass(type.getName(), true, clr).iterator();
            boolean multiplePossibles = false;
            while (subclassIter.hasNext()) {
                String subclassName = subclassIter.next();
                Class subclass = clr.classForName(subclassName);
                if (Modifier.isAbstract(subclass.getModifiers())) {
                    continue;
                }
                BooleanExpression discExprSub = SQLStatementHelper.getExpressionForDiscriminatorForClass(stmt, subclassName, dismd, discMapping, discSqlTbl, clr);
                if (discExpr != null) {
                    multiplePossibles = true;
                    discExpr = discExpr.ior(discExprSub);
                } else {
                    discExpr = discExprSub;
                }
            }
            if (multiplePossibles && discExpr != null) {
                discExpr.encloseInParentheses();
            }
            return ((not && discExpr != null) ? discExpr.not() : discExpr);
        }
        // No discriminator, so the following is likely incomplete.
        // Join to member table
        DatastoreClass table = null;
        if (memberCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUBCLASS_TABLE) {
            // Field is a PC class that uses "subclass-table" inheritance strategy (and so has multiple possible tables to join to)
            AbstractClassMetaData[] cmds = storeMgr.getClassesManagingTableForClass(memberCmd, clr);
            if (cmds != null) {
                // TODO Allow for all possible tables. Can we do an OR of the tables ? How ?
                if (cmds.length > 1) {
                    NucleusLogger.QUERY.warn(Localiser.msg("037006", mapping.getMemberMetaData().getFullFieldName(), cmds[0].getFullClassName()));
                }
                table = storeMgr.getDatastoreClass(cmds[0].getFullClassName(), clr);
            } else {
                // No subclasses with tables to join to, so throw a user error
                throw new NucleusUserException(Localiser.msg("037005", mapping.getMemberMetaData().getFullFieldName()));
            }
        } else {
            // Class of the field will have its own table
            table = storeMgr.getDatastoreClass(mapping.getType(), clr);
        }
        if (table.managesClass(type.getName())) {
            // This type is managed in this table so must be an instance TODO Is this correct, what if member is using discrim?
            JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
            return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, !not));
        }
        if (table == stmt.getPrimaryTable().getTable()) {
            // This is member table, so just need to restrict to the instanceof type now
            JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
            if (stmt instanceof SelectStatement) {
                SelectStatement selectStmt = (SelectStatement) stmt;
                if (selectStmt.getNumberOfUnions() == 0) {
                    // No UNIONs so just check the main statement and return according to whether it is allowed
                    Class mainCandidateCls = clr.classForName(stmt.getCandidateClassName());
                    if (type.isAssignableFrom(mainCandidateCls) == not) {
                        SQLExpression returnExpr = exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
                        return (BooleanExpression) returnExpr;
                    }
                    SQLExpression returnExpr = exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, true));
                    return (BooleanExpression) returnExpr;
                }
                NucleusLogger.QUERY.warn("TYPE/INSTANCEOF operator for class=" + memberCmd.getFullClassName() + " on table=" + memberTable + " for type=" + instanceofClassName + " but there is no discriminator and using UNIONs. Any subsequent handling is likely incorrect TODO");
                // a). we have unions for the member, so restrict to just the applicable unions
                // Note that this is only really valid is wanting "a instanceof SUB1".
                // It fails when we want to do "a instanceof SUB1 || a instanceof SUB2"
                // TODO What if this "OP_IS" is in the SELECT clause??? Need to update QueryToSQLMapper.compileResult
                Class mainCandidateCls = clr.classForName(stmt.getCandidateClassName());
                if (type.isAssignableFrom(mainCandidateCls) == not) {
                    SQLExpression unionClauseExpr = exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, false));
                    stmt.whereAnd((BooleanExpression) unionClauseExpr, false);
                }
                List<SelectStatement> unionStmts = selectStmt.getUnions();
                for (SelectStatement unionStmt : unionStmts) {
                    Class unionCandidateCls = clr.classForName(unionStmt.getCandidateClassName());
                    if (type.isAssignableFrom(unionCandidateCls) == not) {
                        SQLExpression unionClauseExpr = exprFactory.newLiteral(unionStmt, m, true).eq(exprFactory.newLiteral(unionStmt, m, false));
                        // TODO Avoid using whereAnd
                        unionStmt.whereAnd((BooleanExpression) unionClauseExpr, false);
                    }
                }
                // Just return true since we applied the condition direct to the unions
                SQLExpression returnExpr = exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, true));
                return (BooleanExpression) returnExpr;
            }
            // b). The member table doesn't manage the instanceof type, so do inner join to
            // the table of the instanceof to impose the instanceof condition
            DatastoreClass instanceofTable = storeMgr.getDatastoreClass(type.getName(), clr);
            stmt.join(JoinType.INNER_JOIN, this.table, this.table.getTable().getIdMapping(), instanceofTable, null, instanceofTable.getIdMapping(), null, this.table.getGroupName());
            return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, !not));
        }
        // Do inner join to this table to impose the instanceOf
        DatastoreClass instanceofTable = storeMgr.getDatastoreClass(type.getName(), clr);
        stmt.join(JoinType.INNER_JOIN, this.table, this.table.getTable().getIdMapping(), instanceofTable, null, instanceofTable.getIdMapping(), null, this.table.getGroupName());
        JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true);
        return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, !not));
    } else {
        // TODO Implement instanceof for other types
        throw new NucleusException("Dont currently support " + this + " instanceof " + type.getName());
    }
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) Iterator(java.util.Iterator) LinkedList(java.util.LinkedList) List(java.util.List) DiscriminatorMapping(org.datanucleus.store.rdbms.mapping.java.DiscriminatorMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) ClassNotResolvedException(org.datanucleus.exceptions.ClassNotResolvedException) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) DiscriminatorMetaData(org.datanucleus.metadata.DiscriminatorMetaData) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) EmbeddedMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedMapping) Collection(java.util.Collection) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException)

Aggregations

NucleusException (org.datanucleus.exceptions.NucleusException)326 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)71 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)67 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)62 ParameterExpression (org.datanucleus.query.expression.ParameterExpression)53 PrimaryExpression (org.datanucleus.query.expression.PrimaryExpression)52 ArrayList (java.util.ArrayList)48 Literal (org.datanucleus.query.expression.Literal)47 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)44 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)43 InvokeExpression (org.datanucleus.query.expression.InvokeExpression)40 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)37 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)36 StringExpression (org.datanucleus.store.rdbms.sql.expression.StringExpression)35 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)35 Expression (org.datanucleus.query.expression.Expression)32 HashMap (java.util.HashMap)31 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)31 VariableExpression (org.datanucleus.query.expression.VariableExpression)26 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)26