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;
}
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;
}
Aggregations