blob: c3786f805bd6698077c110946ccbce46f31ab3e9 [file] [log] [blame]
/*
* Copyright (c) 2005, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2015 SAP. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// SAP - initial API and implementation
package org.eclipse.persistence.testing.tests.wdf.jpa1.query;
import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import jakarta.persistence.TemporalType;
import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Car;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Cubicle;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.CubiclePrimaryKeyClass;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department.KrassDep;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Employee;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Employee.KrassEmp;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.MotorVehicle;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.TransmissionType;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Truck;
import org.eclipse.persistence.testing.models.wdf.jpa1.types.UserDefinedEnum;
import org.junit.Test;
public class TestArguments extends QueryTest {
private final Set<Department> ALL_DEPARTMENTS = new HashSet<Department>();
private final Department dep10 = new Department(10, "ten");
private final Department dep20 = new Department(20, "twenty");
private void init() throws SQLException {
clearAllTables();
ALL_DEPARTMENTS.add(dep10);
ALL_DEPARTMENTS.add(dep20);
JPAEnvironment env = getEnvironment();
EntityManager em = env.getEntityManager();
try {
env.beginTransaction(em);
Employee knut = new Employee(1, "Knut", "Maier", dep10);
Employee fred = new Employee(2, "Fred", "Schmidt", null);
Cubicle green = new Cubicle(1, 2, "green", knut);
knut.setCubicle(green);
em.persist(dep10);
em.persist(dep20);
em.persist(green);
em.persist(knut);
em.persist(fred);
env.commitTransactionAndClear(em);
} finally {
closeEntityManager(em);
}
}
@Test
// @TestProperties(unsupportedDatabaseVendors = { DatabaseVendor.OPEN_SQL})
public void testArgumentInArithmeticExpr() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
try {
getEnvironment().beginTransaction(em);
Query updateQuery = em
.createQuery("UPDATE Employee e SET e.salary = e.salary*(1+(:percent/100)) WHERE EXISTS (SELECT p FROM e.projects p WHERE p.name LIKE :projectName)");
updateQuery.setParameter("percent", 15);
updateQuery.setParameter("projectName", "testing project");
updateQuery.executeUpdate();
getEnvironment().commitTransaction(em);
} catch (Exception ex) {
getEnvironment().rollbackTransaction(em);
throw new RuntimeException(ex);
} finally {
closeEntityManager(em);
}
}
@Test
public void testLongVarBinaryParameters() {
EntityManager em = getEnvironment().getEntityManager();
try {
// the mapped query is not executable on DB hence it will only be created and the parameter is set to test type
// validation
Query q1 = em
.createQuery("SELECT bfa.primitiveByteArray2Blob FROM BasicTypesFieldAccess bfa WHERE bfa.wrapperByteArray2Longvarbinary IS NULL AND (?1) IS NULL AND (?2) IS NULL");
q1.setParameter(1, new Byte[10]);
q1.setParameter(2, new byte[10]);
} finally {
closeEntityManager(em);
}
}
@Test
public void testSinglePk() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
try {
Query query = em.createQuery("select e from Employee e where e.department = :dep");
query.setParameter("dep", dep10);
List<?> result = query.getResultList();
Iterator<?> iter = result.iterator();
verify(iter.hasNext(), "no results");
Object object = iter.next();
verify(object instanceof Employee, "wrong instance: " + object.getClass().getName());
Employee employee = (Employee) object;
verify(employee.getId() == 1, "wrong id: " + employee.getId());
verify(!iter.hasNext(), "too many rows");
} finally {
closeEntityManager(em);
}
}
@SuppressWarnings("boxing")
@Test
public void testCompoundPk() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
try {
Cubicle cubicle = em.find(Cubicle.class, new CubiclePrimaryKeyClass(1, 2));
Query query = em.createQuery("select e from Employee e where e.cubicle = :cub");
query.setParameter("cub", cubicle);
List<?> result = query.getResultList();
Iterator<?> iter = result.iterator();
verify(iter.hasNext(), "no results");
Object object = iter.next();
verify(object instanceof Employee, "wrong instance: " + object.getClass().getName());
Employee employee = (Employee) object;
verify(employee.getId() == 1, "wrong id: " + employee.getId());
verify(!iter.hasNext(), "too many rows");
} finally {
closeEntityManager(em);
}
}
@Test
public void testInvalidParameterHandling() {
assertInvalidQuery("SELECT e FROM Employee e WHERE e.id = ?");
}
@Test
public void testSubclassParameter() {
EntityManager em = getEnvironment().getEntityManager();
try {
Query q = em.createQuery("SELECT e FROM Employee e WHERE e.department=?1");
q.setParameter(1, new KrassDep("foo"));
q.getResultList();
} finally {
closeEntityManager(em);
}
}
@Test
public void testIllegalSubclassParameter() {
boolean errorCaught = false;
EntityManager em = getEnvironment().getEntityManager();
try {
Query q = em.createQuery("SELECT e FROM Employee e WHERE e.department=?1");
q.setParameter(1, new KrassEmp("foo"));
q.getResultList();
} catch (IllegalArgumentException iaex) {
errorCaught = true;
} finally {
closeEntityManager(em);
}
assertTrue("Unable to detect illegal typed input parameter.", errorCaught);
}
@SuppressWarnings("boxing")
@Test
public void testEnumParameters() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
try {
getEnvironment().beginTransaction(em);
MotorVehicle motorVehicle = new MotorVehicle();
motorVehicle.setTransmissionType(TransmissionType.AUTOMATIC);
Truck truck = new Truck();
truck.setTransmissionType(TransmissionType.STICK_SHIFT);
Car car = new Car();
em.persist(motorVehicle);
em.persist(truck);
em.persist(car);
getEnvironment().commitTransactionAndClear(em);
short mvId = motorVehicle.getId();
short truckId = truck.getId();
Query query = em.createQuery("select m from MotorVehicle m where m.transmissionType = :tr");
query.setParameter("tr", TransmissionType.AUTOMATIC);
List<?> result = query.getResultList();
Iterator<?> iter = result.iterator();
verify(iter.hasNext(), "no results");
Object object = iter.next();
verify(object instanceof MotorVehicle, "wrong instance: " + object.getClass().getName());
MotorVehicle vehicle = (MotorVehicle) object;
verify(vehicle.getId() == mvId, "wrong id: " + vehicle.getId());
verify(!iter.hasNext(), "too many rows");
query.setParameter("tr", TransmissionType.STICK_SHIFT);
result = query.getResultList();
iter = result.iterator();
verify(iter.hasNext(), "no results");
object = iter.next();
verify(object instanceof MotorVehicle, "wrong instance: " + object.getClass().getName());
vehicle = (MotorVehicle) object;
verify(vehicle.getId() == truckId, "wrong id: " + vehicle.getId());
verify(!iter.hasNext(), "too many rows");
} finally {
closeEntityManager(em);
}
}
protected void assertValidParameterForBasicTypesFieldAccess(final String fieldname, Object value) {
EntityManager em = getEnvironment().getEntityManager();
// queries
List<Query> orderedParamQueries = new ArrayList<Query>();
List<Query> namedParamQueries = new ArrayList<Query>();
orderedParamQueries
.add(em.createQuery("SELECT btfa FROM BasicTypesFieldAccess btfa WHERE btfa." + fieldname + " = ?1"));
orderedParamQueries.add(em.createQuery("UPDATE BasicTypesFieldAccess btfa SET btfa." + fieldname
+ " = ?1 WHERE btfa.id=1"));
namedParamQueries.add(em.createQuery("SELECT btfa FROM BasicTypesFieldAccess btfa WHERE btfa." + fieldname
+ " = :param1"));
namedParamQueries.add(em.createQuery("UPDATE BasicTypesFieldAccess btfa SET btfa." + fieldname
+ " = :param1 WHERE btfa.id=1"));
for (Query q : orderedParamQueries) {
if (Calendar.class.isAssignableFrom(value.getClass())) {
q.setParameter(1, (Calendar) value, TemporalType.TIMESTAMP);
} else if (value.getClass().isAssignableFrom(Date.class)) {
q.setParameter(1, (Date) value, TemporalType.TIMESTAMP);
} else {
q.setParameter(1, value);
}
}
for (Query q : namedParamQueries) {
if (Calendar.class.isAssignableFrom(value.getClass())) {
q.setParameter("param1", (Calendar) value, TemporalType.TIMESTAMP);
} else if (value.getClass().isAssignableFrom(Date.class)) {
q.setParameter("param1", (Date) value, TemporalType.TIMESTAMP);
} else {
q.setParameter("param1", value);
}
}
}
// primitive types
@Test
public void testPrimitiveBoolean() {
assertValidParameterForBasicTypesFieldAccess("primitiveBoolean", true);
}
@Test
public void testPrimitiveByte() {
assertValidParameterForBasicTypesFieldAccess("primititveByte", (byte) 2);
}
@Test
public void testPrimitiveChar() {
assertValidParameterForBasicTypesFieldAccess("primitiveChar", 'c');
}
@Test
public void testPrimitiveShort() {
assertValidParameterForBasicTypesFieldAccess("primitiveShort", (short) 2);
}
@Test
public void testPrimitiveInt() {
assertValidParameterForBasicTypesFieldAccess("primitiveInt", 1);
}
@Test
public void testPrimitiveLong() {
assertValidParameterForBasicTypesFieldAccess("primitiveLong", 1L);
}
@Test
public void testPrimitiveFloat() {
assertValidParameterForBasicTypesFieldAccess("primitiveFloat", 0.2F);
}
@Test
public void testPrimitiveDouble() {
assertValidParameterForBasicTypesFieldAccess("primitiveDouble", 0.1234);
}
// wrappers of primitive types
@Test
public void testWrapperBoolean() {
assertValidParameterForBasicTypesFieldAccess("wrapperBoolean", Boolean.TRUE);
}
@Test
public void testWrapperByte() {
assertValidParameterForBasicTypesFieldAccess("wrapperByte", (byte) 2);
}
@Test
public void testWrapperCharacter() {
assertValidParameterForBasicTypesFieldAccess("wrapperCharacter", 'c');
}
@Test
public void testWrapperShort() {
assertValidParameterForBasicTypesFieldAccess("wrapperShort", (short) 1);
}
@Test
public void testWrapperInteger() {
assertValidParameterForBasicTypesFieldAccess("wrapperInteger", 1);
}
@Test
public void testWrapperLong() {
assertValidParameterForBasicTypesFieldAccess("wrapperLong", 1L);
}
@Test
public void testWrapperDouble() {
assertValidParameterForBasicTypesFieldAccess("wrapperDouble", 0.00);
}
@Test
public void testWrapperFloat() {
assertValidParameterForBasicTypesFieldAccess("wrapperFloat", 1F);
}
// immutable reference types
@Test
public void testString2Varchar() {
assertValidParameterForBasicTypesFieldAccess("string2Varchar", "foo");
}
@Test
public void testString2Clob() {
assertValidParameterForBasicTypesFieldAccess("string2Clob", "bar");
}
@Test
public void testBigDecimal() {
assertValidParameterForBasicTypesFieldAccess("bigDecimal", new BigDecimal(1));
}
@Test
public void testBigInteger() {
assertValidParameterForBasicTypesFieldAccess("bigInteger", new BigInteger(1, new Random(10L)));
}
// mutable types
@Test
public void testUtilDate() {
assertValidParameterForBasicTypesFieldAccess("utilDate", new Date(System.currentTimeMillis()));
}
@Test
public void testUtilCalendar() {
assertValidParameterForBasicTypesFieldAccess("utilCalendar", Calendar.getInstance());
}
@Test
public void testSqlDate() {
assertValidParameterForBasicTypesFieldAccess("sqlDate", new java.sql.Date(System.currentTimeMillis()));
}
@Test
public void testSqlTime() {
assertValidParameterForBasicTypesFieldAccess("sqlTime", new java.sql.Time(System.currentTimeMillis()));
}
@Test
public void testSqlTimestamp() {
assertValidParameterForBasicTypesFieldAccess("sqlTimestamp", new java.sql.Timestamp(System.currentTimeMillis()));
}
// arrays
@Test
public void testPrimitiveByteArray2Binary() {
assertValidParameterForBasicTypesFieldAccess("primitiveByteArray2Binary", new byte[] { (byte) 1, (byte) 1 });
}
@Test
public void testPrimitiveByteArray2Longvarbinary() {
assertValidParameterForBasicTypesFieldAccess("primitiveByteArray2Longvarbinary", new byte[] { (byte) 1, (byte) 1 });
}
@Test
public void testPrimitiveByteArray2Blob() {
assertValidParameterForBasicTypesFieldAccess("primitiveByteArray2Blob", new byte[] { (byte) 1, (byte) 1 });
}
@Test
public void testPrimitiveCharArray2Varchar() {
assertValidParameterForBasicTypesFieldAccess("primitiveCharArray2Varchar", new char[] { 'c', 'b' });
}
@Test
public void testPrimitiveCharArray2Clob() {
assertValidParameterForBasicTypesFieldAccess("primitiveCharArray2Clob", new char[] { 'c', 'b' });
}
@Test
public void testWrapperByteArray2Binary() {
assertValidParameterForBasicTypesFieldAccess("wrapperByteArray2Binary", new Byte[] { 'c', 'b' });
}
@Test
public void testWrapperByteArray2Longvarbinary() {
assertValidParameterForBasicTypesFieldAccess("wrapperByteArray2Longvarbinary", new Byte[] { 'c', 'b' });
}
@Test
public void testWrapperByteArray2Blob() {
assertValidParameterForBasicTypesFieldAccess("wrapperByteArray2Blob", new Byte[] { 'c', 'b' });
}
@Test
public void testWrapperCharArray2Varchar() {
assertValidParameterForBasicTypesFieldAccess("wrapperCharacterArray2Varchar", new Character[] { 'c', 'b' });
}
@SuppressWarnings("boxing")
@Test
public void testWrapperCharArray2Clob() {
assertValidParameterForBasicTypesFieldAccess("wrapperCharacterArray2Clob", new Character[] { 'c', 'b' });
}
@Test
public void testEnumString() {
assertValidParameterForBasicTypesFieldAccess("enumString", UserDefinedEnum.EMIL);
}
@Test
public void testEnumOrdinal() {
assertValidParameterForBasicTypesFieldAccess("enumOrdinal", UserDefinedEnum.HUGO);
}
}