use of com.blazebit.persistence.spi.JpqlFunction in project blaze-persistence by Blazebit.
the class SelectManager method addJpqlFunctionProcessor.
private void addJpqlFunctionProcessor(Expression expr, int index) {
if (expr instanceof FunctionExpression) {
String functionName = ((FunctionExpression) expr).getFunctionName().toLowerCase();
JpqlFunction jpqlFunction = mainQuery.cbf.getRegisteredFunctions().get(functionName);
if (jpqlFunction instanceof JpqlFunctionProcessor<?>) {
jpqlFunctionProcessors.put(index, (JpqlFunctionProcessor<?>) jpqlFunction);
if ("to_multiset".equals(functionName)) {
Subquery subquery = ((SubqueryExpression) ((FunctionExpression) expr).getExpressions().get(0)).getSubquery();
if (subquery instanceof SubqueryInternalBuilder<?>) {
SubqueryInternalBuilder<?> subqueryInternalBuilder = (SubqueryInternalBuilder<?>) subquery;
jpqlFunctionProcessors.put(index, new NestedToMultisetJpqlFunctionProcessor((JpqlFunctionProcessor<?>) jpqlFunction, subqueryInternalBuilder.getJpqlFunctionProcessors(), subqueryInternalBuilder.getSelectExpressions()));
}
}
}
} else if (expr instanceof SubqueryExpression) {
Subquery subquery = ((SubqueryExpression) expr).getSubquery();
if (subquery instanceof SubqueryInternalBuilder<?>) {
SubqueryInternalBuilder<?> subqueryInternalBuilder = (SubqueryInternalBuilder<?>) subquery;
if (!subqueryInternalBuilder.getJpqlFunctionProcessors().isEmpty()) {
jpqlFunctionProcessors.put(index, subqueryInternalBuilder.getJpqlFunctionProcessors().get(0));
}
}
}
}
use of com.blazebit.persistence.spi.JpqlFunction 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 com.blazebit.persistence.spi.JpqlFunction in project blaze-persistence by Blazebit.
the class AbstractHibernateEntityManagerFactoryIntegrator method registerFunctions.
@Override
public EntityManagerFactory registerFunctions(EntityManagerFactory entityManagerFactory, Map<String, JpqlFunctionGroup> dbmsFunctions) {
EntityManager em = null;
try {
em = entityManagerFactory.createEntityManager();
Session s = em.unwrap(Session.class);
Map<String, SQLFunction> originalFunctions = getFunctions(s);
Map<String, SQLFunction> functions = new TreeMap<String, SQLFunction>(String.CASE_INSENSITIVE_ORDER);
functions.putAll(originalFunctions);
Dialect dialect = getDialect(s);
String dbms = getDbmsName(entityManagerFactory, em, dialect);
for (Map.Entry<String, JpqlFunctionGroup> functionEntry : dbmsFunctions.entrySet()) {
String functionName = functionEntry.getKey();
JpqlFunctionGroup dbmsFunctionMap = functionEntry.getValue();
JpqlFunction function = dbmsFunctionMap.get(dbms);
if (function == null && !dbmsFunctionMap.contains(dbms)) {
function = dbmsFunctionMap.get(null);
}
if (function == null) {
if (functions.containsKey(functionName)) {
LOG.finest("Using ORM registered function '" + functionName + "' because there is neither an implementation for the dbms '" + dbms + "' nor a default implementation.");
} else {
LOG.warning("Could not register the function '" + functionName + "' because there is neither an implementation for the dbms '" + dbms + "' nor a default implementation!");
}
} else {
functions.put(functionName, new HibernateJpqlFunctionAdapter(function));
}
}
replaceFunctions(s, functions);
return entityManagerFactory;
} finally {
if (em != null) {
em.close();
}
}
}
use of com.blazebit.persistence.spi.JpqlFunction in project blaze-persistence by Blazebit.
the class ScalarTargetResolvingExpressionVisitor method visit.
@Override
public void visit(FunctionExpression expression) {
String name = expression.getFunctionName().toLowerCase();
switch(name) {
case "function":
String functionName = ((StringLiteral) expression.getExpressions().get(0)).getValue();
JpqlFunction jpqlFunction = functions.get(functionName.toLowerCase());
if (jpqlFunction == null) {
// Can't reliably resolve the type
currentPosition.setAttribute(null);
currentPosition.setCurrentType(null);
} else {
// Skip the function name
resolveFirst(expression.getExpressions().subList(1, expression.getExpressions().size()), true);
resolveToFunctionReturnType(functionName);
}
break;
case "size":
// According to our grammar, we can only get a path here
currentPosition.setAttribute(null);
currentPosition.setCurrentType(metamodel.type(Long.class));
break;
case "coalesce":
resolveAny(expression.getExpressions(), true);
resolveToFunctionReturnType(name);
break;
default:
resolveFirst(expression.getExpressions(), true);
resolveToFunctionReturnType(name);
break;
}
}
use of com.blazebit.persistence.spi.JpqlFunction in project blaze-persistence by Blazebit.
the class EclipseLinkEntityManagerIntegrator method getRegisteredFunctions.
@Override
public Map<String, JpqlFunction> getRegisteredFunctions(EntityManagerFactory entityManagerFactory) {
AbstractSession session = entityManagerFactory.unwrap(JpaEntityManagerFactory.class).getDatabaseSession();
DatabasePlatform platform = session.getPlatform();
@SuppressWarnings("unchecked") Map<Integer, ExpressionOperator> platformOperators = platform.getPlatformOperators();
Map<String, JpqlFunction> functions = new HashMap<>(platformOperators.size());
for (ExpressionOperator op : platformOperators.values()) {
String name = (String) ExpressionOperator.getPlatformOperatorNames().get(op.getSelector());
if (name != null) {
if (op instanceof JpqlFunctionExpressionOperator) {
functions.put(name.toLowerCase(), ((JpqlFunctionExpressionOperator) op).unwrap());
} else {
int selector = op.getSelector();
// No support for these expressions
if (selector != ExpressionOperator.Union && selector != ExpressionOperator.UnionAll && selector != ExpressionOperator.Intersect && selector != ExpressionOperator.IntersectAll && selector != ExpressionOperator.Except && selector != ExpressionOperator.ExceptAll) {
functions.put(name.toLowerCase(), new ExpressionOperatorJpqlFunction(op));
}
}
}
}
// Eclipselink doesn't report all functions..
functions.put("count", new ExpressionOperatorJpqlFunction(ExpressionOperator.count()));
functions.put("sum", new ExpressionOperatorJpqlFunction(ExpressionOperator.sum()));
functions.put("avg", new ExpressionOperatorJpqlFunction(ExpressionOperator.average()));
functions.put("max", new ExpressionOperatorJpqlFunction(ExpressionOperator.maximum()));
functions.put("min", new ExpressionOperatorJpqlFunction(ExpressionOperator.minimum()));
functions.put("stddev", new ExpressionOperatorJpqlFunction(ExpressionOperator.standardDeviation()));
functions.put("var", new ExpressionOperatorJpqlFunction(ExpressionOperator.variance()));
return functions;
}
Aggregations