/* * TestQuotedNumbersInFilters.java * * Created on October 18, 2006, 2:29 PM * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.openjpa.persistence.query; import java.util.Collection; import java.util.HashMap; import java.util.Map; import javax.persistence.Query; import org.apache.openjpa.persistence.query.common.apps.RuntimeTest1; import org.apache.openjpa.persistence.OpenJPAEntityManager; import org.apache.openjpa.persistence.OpenJPAQuery; public class TestQuotedNumbersInFilters2 extends BaseQueryTest { public TestQuotedNumbersInFilters2(String name) { super(name); } public void setUp() { deleteAll(RuntimeTest1.class); OpenJPAEntityManager pm = getEM(); startTx(pm); pm.persist(new RuntimeTest1("foo", 3)); pm.persist(new RuntimeTest1("bar", 15)); pm.persist(new RuntimeTest1("baz", -8)); pm.persist(new RuntimeTest1("baz2", 45)); // 45 is '-' pm.persist(new RuntimeTest1("3", (int) '4')); endTx(pm); endEm(pm); // make sure everything is working as expected for the base case. assertEquals(1, helper("intField = -8")); assertEquals(1, helper("intField = 15")); assertEquals(1, helper("intField = 3")); assertEquals(0, helper("intField = 51")); // the int value of '3' assertEquals(0, helper("intField = 4")); assertEquals(1, helper("intField = 52")); // the int value of '4' assertEquals(1, helper("stringField = \'foo\'")); assertEquals(1, helper("stringField = \'bar\'")); } public void testUnquotedNumbersWithExtraPrecision() { assertEquals(1, helper("intField = 15")); assertEquals(1, helper("intField = -8")); assertEquals(1, helper("intField = 3")); assertEquals(1, helper("intField = 45")); // try { // // test without casting ... some DBs don't like this //// assertEquals(1, helper("intField = 15.0")); //// assertEquals(1, helper("intField = -8.0")); // assertEquals(1, helper("intField = 3.0")); // assertEquals(1, helper("intField = 45.0")); // } catch (Exception jdoe) { // bug(AbstractTestCase.Platform.HYPERSONIC, 414, jdoe, // "Some databases require explicit casts"); // } } public void testSingleQuotedStrings() { assertEquals(1, helper("stringField = 'foo'")); assertEquals(1, helper("stringField = '3'")); } public void testDoubleQuotedStrings() { assertEquals(1, helper("stringField = \'foo\'")); assertEquals(1, helper("stringField = \'3\'")); } /** * Kodo 3.1 and prior treated single-quoted numbers as character literals, * to the degree that prepared statement setInt() calls were made. * Only the first digit of multiple-digit single-quoted numbers was used. * FIX ME: aokeke - commenting this --> applies to kodo 3.1 and prior */ public void testKodo31SingleQuotedMultipleCharacterBehavior() { assertEquals(0, helper31("intField = '15'", true)); // looks like '1' assertEquals(0, helper31("intField = '52'", true)); // looks like '5' assertEquals(1, helper31("intField = '49'", true)); // looks like '4' assertEquals(1, helper31("intField = '-8'", true)); // looks like '-' assertEquals(0, helper31("intField = '15'", false)); assertEquals(0, helper31("intField = '52'", false)); } /** * Kodo 3.1 and prior did not match negative numbers of different types * in in-mem queries. */ public void testKodo31UnquotedInMemBehavior() { assertEquals(1, helper31("intField = 3", false)); assertEquals(1, helper31("intField = -8", false)); assertEquals(1, helper31("intField = 15", false)); assertEquals(1, helper31("intField = 45", false)); } public void testKodo31UnquotedDatastoreBehavior() { assertEquals(1, helper31("intField = 3", false)); assertEquals(1, helper31("intField = -8", false)); assertEquals(1, helper31("intField = 15", false)); assertEquals(1, helper31("intField = 45", false)); } /** * Returns the # of matches to the query. */ private long helper(String filter) { return helper(filter, false); } /** * Returns the # of matches to the query. Returns -1 if shouldFail * is true and the query raised an exception in both in-mem and datastore * queries. */ private long helper(String filter, boolean shouldFail) { OpenJPAEntityManager pm = getEM(); OpenJPAQuery q = pm.createQuery("SELECT r FROM RuntimeTest1 r WHERE r." + filter); long datastore = getResults(q, shouldFail); q.setCandidateCollection((Collection) q.getResultList()); long inmem = getResults(q, shouldFail); if (datastore != inmem) fail("datastore query returned " + datastore + " values; " + "inmem query returned " + inmem); endEm(pm); return datastore; } /** * Returns the # of matches to the query. Performs the query in datastore * or memory as appropriate. */ private long helper31(String filter, boolean datastore) { Map props = new HashMap(); props.put("openjpa.Compatibility", "QuotedNumbersInQueries=true"); OpenJPAEntityManager pm = getEmf(props).createEntityManager(); try { OpenJPAQuery q = pm.createQuery( "SELECT r FROM RuntimeTest1 r WHERE r." + filter); if (!datastore) q.setCandidateCollection((Collection) q.getResultList()); return getResults(q, false); } finally { endEm(pm); } } private long getResults(Query q, boolean shouldFail) { try { Integer result = new Integer(q.getResultList().size()); if (shouldFail) { fail("should have failed"); } return ((Number) result).longValue(); } catch (IllegalArgumentException e) { if (!shouldFail) throw e; return -1; } } }