Search in sources :

Example 1 with QueryGenerator

use of org.datanucleus.store.rdbms.query.QueryGenerator in project blaze-persistence by Blazebit.

the class DataNucleusEntityManagerFactoryIntegrator method getRegisteredFunctions.

@Override
public Map<String, JpqlFunction> getRegisteredFunctions(EntityManagerFactory entityManagerFactory) {
    NucleusContext context = entityManagerFactory.unwrap(NucleusContext.class);
    RDBMSStoreManager storeMgr = (RDBMSStoreManager) entityManagerFactory.unwrap(StoreManager.class);
    String storeName = storeMgr.getDatastoreAdapter().getVendorID();
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    Set<Object> methodKeys = fieldGet("methodNamesSupported", exprFactory, VERSION);
    if (methodKeys.isEmpty()) {
        return new HashMap<>();
    }
    Map<String, JpqlFunction> functions = new HashMap<>();
    // We need to construct a statement object and how this is done changed between 4 and 5 so we have to do a little reflection hack
    // We need this because the function methods retrieve the expression factory through it
    Class<?>[] parameterTypes = { RDBMSStoreManager.class, Table.class, DatastoreIdentifier.class, String.class };
    SQLStatement stmt;
    try {
        Constructor c = Class.forName("org.datanucleus.store.rdbms.sql.SelectStatement").getConstructor(parameterTypes);
        stmt = (SQLStatement) c.newInstance(storeMgr, null, null, null);
    } catch (Exception e) {
        try {
            Constructor c = Class.forName("org.datanucleus.store.rdbms.sql.SQLStatement").getConstructor(parameterTypes);
            stmt = (SQLStatement) c.newInstance(storeMgr, null, null, null);
        } catch (Exception e2) {
            throw new RuntimeException("Could not access the required methods to dynamically retrieve registered functions. Please report this version of datanucleus(" + VERSION + ") so we can provide support for it!", e2);
        }
    }
    // Well apparently expressions get their class loader resolver by asking the statement they are part of
    // which in turn asks the query generator that is responsible for it
    // So this is the most non-hackish way to get this to work...
    QueryGenerator noopGenerator = (QueryGenerator) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { QueryGenerator.class }, new QueryGeneratorInvocationHandler(context));
    stmt.setQueryGenerator(noopGenerator);
    for (Object methodKey : methodKeys) {
        String className = fieldGet("clsName", methodKey, VERSION);
        String datastoreName = fieldGet("datastoreName", methodKey, VERSION);
        String name = fieldGet("methodName", methodKey, VERSION);
        if (className.isEmpty() && name.indexOf('.') == -1 && ("ALL".equals(datastoreName) || storeName.equals(datastoreName))) {
            // Only consider normal functions
            SQLMethod method = exprFactory.getMethod(null, name, Collections.emptyList());
            if (method instanceof DataNucleusJpqlFunctionAdapter) {
                functions.put(name, ((DataNucleusJpqlFunctionAdapter) method).unwrap());
            } else {
                functions.put(name, new JpqlFunctionSQLMethod(stmt, method));
            }
        }
    }
    // The length function is the single exception to all functions that is based on a class
    SQLMethod method = exprFactory.getMethod("java.lang.String", "length", Collections.emptyList());
    functions.put("length", new JpqlFunctionInstanceSQLMethod(stmt, method));
    return functions;
}
Also used : JpqlFunction(com.blazebit.persistence.spi.JpqlFunction) SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) HashMap(java.util.HashMap) Constructor(java.lang.reflect.Constructor) NucleusContext(org.datanucleus.NucleusContext) SQLStatement(org.datanucleus.store.rdbms.sql.SQLStatement) IOException(java.io.IOException) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) StoreManager(org.datanucleus.store.StoreManager) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) QueryGenerator(org.datanucleus.store.rdbms.query.QueryGenerator) SQLMethod(org.datanucleus.store.rdbms.sql.method.SQLMethod)

Example 2 with QueryGenerator

use of org.datanucleus.store.rdbms.query.QueryGenerator in project blaze-persistence by Blazebit.

the class DataNucleus51EntityManagerFactoryIntegrator method getRegisteredFunctions.

@Override
public Map<String, JpqlFunction> getRegisteredFunctions(EntityManagerFactory entityManagerFactory) {
    NucleusContext context = entityManagerFactory.unwrap(NucleusContext.class);
    RDBMSStoreManager storeMgr = (RDBMSStoreManager) entityManagerFactory.unwrap(StoreManager.class);
    String storeName = storeMgr.getDatastoreAdapter().getVendorID();
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    Set<Object> methodKeys = fieldGet("pluginSqlMethodsKeysSupported", exprFactory);
    Map<String, JpqlFunction> functions = new HashMap<>();
    // We need to construct a statement object and how this is done changed between 4 and 5 so we have to do a little reflection hack
    // We need this because the function methods retrieve the expression factory through it
    Class<?>[] parameterTypes = { RDBMSStoreManager.class, Table.class, DatastoreIdentifier.class, String.class };
    SQLStatement stmt;
    try {
        Constructor c = Class.forName("org.datanucleus.store.rdbms.sql.SelectStatement").getConstructor(parameterTypes);
        stmt = (SQLStatement) c.newInstance(storeMgr, null, null, null);
    } catch (Exception e) {
        try {
            Constructor c = Class.forName("org.datanucleus.store.rdbms.sql.SQLStatement").getConstructor(parameterTypes);
            stmt = (SQLStatement) c.newInstance(storeMgr, null, null, null);
        } catch (Exception e2) {
            throw new RuntimeException("Could not access the required methods to dynamically retrieve registered functions. Please report this version of datanucleus(" + VERSION + ") so we can provide support for it!", e2);
        }
    }
    // Well apparently expressions get their class loader resolver by asking the statement they are part of
    // which in turn asks the query generator that is responsible for it
    // So this is the most non-hackish way to get this to work...
    QueryGenerator noopGenerator = (QueryGenerator) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { QueryGenerator.class }, new QueryGeneratorInvocationHandler(context));
    stmt.setQueryGenerator(noopGenerator);
    try {
        Method getMethod = SQLExpressionFactory.class.getDeclaredMethod("getMethod", String.class, String.class, List.class);
        getMethod.setAccessible(true);
        for (Object methodKey : methodKeys) {
            String className = fieldGet("clsName", methodKey);
            String datastoreName = fieldGet("datastoreName", methodKey);
            String name = fieldGet("methodName", methodKey);
            if (className.isEmpty() && name.indexOf('.') == -1 && ("ALL".equals(datastoreName) || storeName.equals(datastoreName))) {
                // Only consider normal functions
                SQLMethod method = (SQLMethod) getMethod.invoke(exprFactory, null, name, Collections.emptyList());
                if (method instanceof DataNucleusJpqlFunctionAdapter) {
                    functions.put(name, ((DataNucleusJpqlFunctionAdapter) method).unwrap());
                } else {
                    functions.put(name, new JpqlFunctionSQLMethod(stmt, method));
                }
            }
        }
        for (String name : BUILTIN_FUNCTIONS) {
            SQLMethod method = (SQLMethod) getMethod.invoke(exprFactory, null, name, Collections.emptyList());
            if (method instanceof DataNucleusJpqlFunctionAdapter) {
                functions.put(name, ((DataNucleusJpqlFunctionAdapter) method).unwrap());
            } else {
                functions.put(name, new JpqlFunctionSQLMethod(stmt, method));
            }
        }
        // The length function is the single exception to all functions that is based on a class
        SQLMethod method = (SQLMethod) getMethod.invoke(exprFactory, "java.lang.String", "length", Collections.emptyList());
        functions.put("length", new JpqlFunctionInstanceSQLMethod(stmt, method));
    } catch (Exception ex) {
        throw new RuntimeException("Could not access the required methods to dynamically retrieve registered functions. Please report this version of datanucleus(" + VERSION + ") so we can provide support for it!", ex);
    }
    return functions;
}
Also used : JpqlFunction(com.blazebit.persistence.spi.JpqlFunction) SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) HashMap(java.util.HashMap) Constructor(java.lang.reflect.Constructor) NucleusContext(org.datanucleus.NucleusContext) SQLMethod(org.datanucleus.store.rdbms.sql.method.SQLMethod) Method(java.lang.reflect.Method) SQLStatement(org.datanucleus.store.rdbms.sql.SQLStatement) IOException(java.io.IOException) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) StoreManager(org.datanucleus.store.StoreManager) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) QueryGenerator(org.datanucleus.store.rdbms.query.QueryGenerator) SQLMethod(org.datanucleus.store.rdbms.sql.method.SQLMethod)

Aggregations

JpqlFunction (com.blazebit.persistence.spi.JpqlFunction)2 IOException (java.io.IOException)2 Constructor (java.lang.reflect.Constructor)2 HashMap (java.util.HashMap)2 NucleusContext (org.datanucleus.NucleusContext)2 StoreManager (org.datanucleus.store.StoreManager)2 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)2 QueryGenerator (org.datanucleus.store.rdbms.query.QueryGenerator)2 SQLStatement (org.datanucleus.store.rdbms.sql.SQLStatement)2 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)2 SQLMethod (org.datanucleus.store.rdbms.sql.method.SQLMethod)2 Method (java.lang.reflect.Method)1