cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aadamc...@apache.org
Subject [1/6] CAY-1966 SQLTemplate/SQLSelect positional parameter binding
Date Sun, 02 Nov 2014 15:36:52 GMT
Repository: cayenne
Updated Branches:
  refs/heads/master d3c5b72d1 -> 617628c7f


http://git-wip-us.apache.org/repos/asf/cayenne/blob/c8709542/cayenne-server/src/test/java/org/apache/cayenne/velocity/ResultDirectiveIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/velocity/ResultDirectiveIT.java
b/cayenne-server/src/test/java/org/apache/cayenne/velocity/ResultDirectiveIT.java
new file mode 100644
index 0000000..3c291b8
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/velocity/ResultDirectiveIT.java
@@ -0,0 +1,188 @@
+/*****************************************************************
+ *   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.cayenne.velocity;
+
+import org.apache.cayenne.DataRow;
+import org.apache.cayenne.access.DataNode;
+import org.apache.cayenne.access.MockOperationObserver;
+import org.apache.cayenne.access.jdbc.SQLTemplateAction;
+import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.CapsStrategy;
+import org.apache.cayenne.query.SQLTemplate;
+import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.test.jdbc.DBHelper;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+
+import java.sql.Connection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.mockito.Mockito.mock;
+
+/**
+ * Test for Result directive to check if we could use ResultDitrective optionally.
+ */
+@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
+public class ResultDirectiveIT extends ServerCase {
+
+    @Inject
+    private ServerRuntime runtime;
+
+    @Inject
+    private DBHelper dbHelper;
+
+    @Inject
+    private JdbcAdapter dbAdapter;
+
+    @Override
+    protected void setUpAfterInjection() throws Exception {
+        dbHelper.deleteAll("PAINTING_INFO");
+        dbHelper.deleteAll("PAINTING");
+        dbHelper.deleteAll("PAINTING1");
+        dbHelper.deleteAll("ARTIST_EXHIBIT");
+        dbHelper.deleteAll("ARTIST_GROUP");
+        dbHelper.deleteAll("ARTIST");
+        dbHelper.deleteAll("EXHIBIT");
+        dbHelper.deleteAll("GALLERY");
+    }
+
+    public void testWithoutResultDirective() throws Exception {
+        String sql = "SELECT ARTIST_ID, ARTIST_NAME FROM ARTIST";
+        Map<String, Object> artist = insertArtist();
+        Map<String, Object> selectResult = selectForQuery(sql);
+
+        assertEquals(artist.get("ARTIST_ID"), selectResult.get("ARTIST_ID"));
+        assertEquals(artist.get("ARTIST_NAME"), selectResult.get("ARTIST_NAME"));
+    }
+
+    public void testWithOnlyResultDirective() throws Exception {
+        String sql = "SELECT #result('ARTIST_ID' 'java.lang.Integer'),"
+                + " #result('ARTIST_NAME' 'java.lang.String')"
+                + " FROM ARTIST";
+        Map<String, Object> artist = insertArtist();
+        Map<String, Object> selectResult = selectForQuery(sql);
+
+        assertEquals(artist.get("ARTIST_ID"), selectResult.get("ARTIST_ID"));
+        assertEquals(artist.get("ARTIST_NAME"), selectResult
+                .get("ARTIST_NAME")
+                .toString()
+                .trim());
+    }
+
+    public void testWithMixedDirectiveUse1() throws Exception {
+        String sql = "SELECT ARTIST_ID,"
+                + " #result('ARTIST_NAME' 'java.lang.String')"
+                + " FROM ARTIST";
+        Map<String, Object> artist = insertArtist();
+        Map<String, Object> selectResult = selectForQuery(sql);
+
+        assertEquals(artist.get("ARTIST_ID"), selectResult.get("ARTIST_ID"));
+        assertEquals(artist.get("ARTIST_NAME"), selectResult
+                .get("ARTIST_NAME")
+                .toString()
+                .trim());
+    }
+
+    public void testWithMixedDirectiveUse2() throws Exception {
+        String sql = "SELECT #result('ARTIST_ID' 'java.lang.Integer'),"
+                + " ARTIST_NAME "
+                + " FROM ARTIST";
+        Map<String, Object> artist = insertArtist();
+        Map<String, Object> selectResult = selectForQuery(sql);
+
+        assertEquals(artist.get("ARTIST_ID"), selectResult.get("ARTIST_ID"));
+        assertEquals(artist.get("ARTIST_NAME"), selectResult.get("ARTIST_NAME"));
+    }
+
+    private Map<String, Object> selectForQuery(String sql) {
+        SQLTemplate template = new SQLTemplate(Artist.class, sql);
+        template.setColumnNamesCapitalization(CapsStrategy.UPPER);
+        MockOperationObserver observer = new MockOperationObserver();
+        runtime.getDataDomain().performQueries(
+                Collections.singletonList(template),
+                observer);
+
+        List<Map<String, Object>> data = observer.rowsForQuery(template);
+        assertEquals(1, data.size());
+        Map<String, Object> row = data.get(0);
+        return row;
+    }
+
+    /**
+     * Inserts one Artist
+     * 
+     * @return Inserted Artist as a DataRow
+     */
+    private Map<String, Object> insertArtist() throws Exception {
+        Map<String, Object> parameters = new HashMap<String, Object>();
+        parameters.put("id", new Integer(1));
+        parameters.put("name", "ArtistToTestResult");
+        String templateString = "INSERT INTO ARTIST (ARTIST_ID, ARTIST_NAME, DATE_OF_BIRTH)
"
+                + "VALUES (#bind($id), #bind($name), #bind($dob))";
+
+        SQLTemplate template = new SQLTemplate(Object.class, templateString);
+
+        template.setParameters(parameters);
+
+        DataNode node = new DataNode();
+        node.setEntityResolver(runtime.getDataDomain().getEntityResolver());
+        node.setRowReaderFactory(mock(RowReaderFactory.class));
+        node.setAdapter(dbAdapter);
+        
+        SQLTemplateAction action = new SQLTemplateAction(template, node);
+
+        Connection c = runtime
+                .getDataDomain()
+                .getDataNodes()
+                .iterator()
+                .next()
+                .getDataSource()
+                .getConnection();
+        try {
+            MockOperationObserver observer = new MockOperationObserver();
+            action.performAction(c, observer);
+
+            int[] batches = observer.countsForQuery(template);
+            assertNotNull(batches);
+            assertEquals(1, batches.length);
+            assertEquals(1, batches[0]);
+        }
+        finally {
+            c.close();
+        }
+
+        MockOperationObserver observer = new MockOperationObserver();
+        SelectQuery query = new SelectQuery(Artist.class);
+        runtime
+                .getDataDomain()
+                .performQueries(Collections.singletonList(query), observer);
+
+        List<?> data = observer.rowsForQuery(query);
+        assertEquals(1, data.size());
+        DataRow row = (DataRow) data.get(0);
+        return row;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c8709542/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateProcessorChainTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateProcessorChainTest.java
b/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateProcessorChainTest.java
new file mode 100644
index 0000000..d0e812a
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateProcessorChainTest.java
@@ -0,0 +1,221 @@
+/*****************************************************************
+ *   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.cayenne.velocity;
+
+import org.apache.cayenne.access.jdbc.SQLStatement;
+import org.apache.cayenne.velocity.SQLTemplateProcessor;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class SQLTemplateProcessorChainTest {
+
+    @Test
+    public void testProcessTemplateNoChunks() throws Exception {
+        // whatever is inside the chain, it should render as empty if there
+        // is no chunks...
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(
+                "#chain(' AND ') #end",
+                Collections.EMPTY_MAP);
+
+        assertEquals("", compiled.getSql());
+
+        compiled = new SQLTemplateProcessor().processTemplate(
+                "#chain(' AND ') garbage #end",
+                Collections.EMPTY_MAP);
+
+        assertEquals("", compiled.getSql());
+
+        compiled = new SQLTemplateProcessor().processTemplate(
+                "#chain(' AND ' 'PREFIX') #end",
+                Collections.EMPTY_MAP);
+
+        assertEquals("", compiled.getSql());
+        compiled = new SQLTemplateProcessor().processTemplate(
+                "#chain(' AND ' 'PREFIX') garbage #end",
+                Collections.EMPTY_MAP);
+
+        assertEquals("", compiled.getSql());
+    }
+
+    @Test
+    public void testProcessTemplateFullChain() throws Exception {
+        String template = "#chain(' OR ')"
+                + "#chunk($a)$a#end"
+                + "#chunk($b)$b#end"
+                + "#chunk($c)$c#end"
+                + "#end";
+
+        Map map = new HashMap();
+        map.put("a", "[A]");
+        map.put("b", "[B]");
+        map.put("c", "[C]");
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(template, map);
+        assertEquals("[A] OR [B] OR [C]", compiled.getSql());
+    }
+
+    @Test
+    public void testProcessTemplateFullChainAndPrefix() throws Exception {
+        String template = "#chain(' OR ' 'WHERE ')"
+                + "#chunk($a)$a#end"
+                + "#chunk($b)$b#end"
+                + "#chunk($c)$c#end"
+                + "#end";
+
+        Map map = new HashMap();
+        map.put("a", "[A]");
+        map.put("b", "[B]");
+        map.put("c", "[C]");
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(template, map);
+        assertEquals("WHERE [A] OR [B] OR [C]", compiled.getSql());
+    }
+
+    @Test
+    public void testProcessTemplatePartialChainMiddle() throws Exception {
+        String template = "#chain(' OR ' 'WHERE ')"
+                + "#chunk($a)$a#end"
+                + "#chunk($b)$b#end"
+                + "#chunk($c)$c#end"
+                + "#end";
+
+        Map map = new HashMap();
+        map.put("a", "[A]");
+        map.put("c", "[C]");
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(template, map);
+        assertEquals("WHERE [A] OR [C]", compiled.getSql());
+    }
+
+    @Test
+    public void testProcessTemplatePartialChainStart() throws Exception {
+        String template = "#chain(' OR ' 'WHERE ')"
+                + "#chunk($a)$a#end"
+                + "#chunk($b)$b#end"
+                + "#chunk($c)$c#end"
+                + "#end";
+
+        Map map = new HashMap();
+        map.put("b", "[B]");
+        map.put("c", "[C]");
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(template, map);
+        assertEquals("WHERE [B] OR [C]", compiled.getSql());
+    }
+
+    @Test
+    public void testProcessTemplatePartialChainEnd() throws Exception {
+        String template = "#chain(' OR ' 'WHERE ')"
+                + "#chunk($a)$a#end"
+                + "#chunk($b)$b#end"
+                + "#chunk($c)$c#end"
+                + "#end";
+
+        Map map = new HashMap();
+        map.put("a", "[A]");
+        map.put("b", "[B]");
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(template, map);
+        assertEquals("WHERE [A] OR [B]", compiled.getSql());
+    }
+
+    @Test
+    public void testProcessTemplateChainWithGarbage() throws Exception {
+        String template = "#chain(' OR ' 'WHERE ')"
+                + "#chunk($a)$a#end"
+                + " some other stuff"
+                + "#chunk($c)$c#end"
+                + "#end";
+
+        Map map = new HashMap();
+        map.put("a", "[A]");
+        map.put("c", "[C]");
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(template, map);
+        assertEquals("WHERE [A] some other stuff OR [C]", compiled.getSql());
+    }
+
+    @Test
+    public void testProcessTemplateChainUnconditionalChunks() throws Exception {
+        String template = "#chain(' OR ' 'WHERE ')"
+                + "#chunk()C1#end"
+                + "#chunk()C2#end"
+                + "#chunk()C3#end"
+                + "#end";
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(
+                template,
+                Collections.EMPTY_MAP);
+        assertEquals("WHERE C1 OR C2 OR C3", compiled.getSql());
+    }
+
+    @Test
+    public void testProcessTemplateEmptyChain() throws Exception {
+        String template = "#chain(' OR ' 'WHERE ')"
+                + "#chunk($a)$a#end"
+                + "#chunk($b)$b#end"
+                + "#chunk($c)$c#end"
+                + "#end";
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(
+                template,
+                Collections.EMPTY_MAP);
+        assertEquals("", compiled.getSql());
+    }
+
+    @Test
+    public void testProcessTemplateWithFalseOrZero1() throws Exception {
+        String template = "#chain(' OR ' 'WHERE ')"
+                + "#chunk($a)[A]#end"
+                + "#chunk($b)[B]#end"
+                + "#chunk($c)$c#end"
+                + "#end";
+
+        Map map = new HashMap();
+        map.put("a", false);
+        map.put("b", 0);
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(template, map);
+        assertEquals("WHERE [A] OR [B]", compiled.getSql());
+    }
+
+    @Test
+    public void testProcessTemplateWithFalseOrZero2() throws Exception {
+        String template = "#chain(' OR ' 'WHERE ')"
+                + "#chunk($a)$a#end"
+                + "#chunk($b)$b#end"
+                + "#chunk($c)$c#end"
+                + "#end";
+
+        Map map = new HashMap();
+        map.put("a", false);
+        map.put("b", 0);
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(template, map);
+        assertEquals("WHERE false OR 0", compiled.getSql());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c8709542/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateProcessorSelectTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateProcessorSelectTest.java
b/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateProcessorSelectTest.java
new file mode 100644
index 0000000..3481982
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateProcessorSelectTest.java
@@ -0,0 +1,112 @@
+/*****************************************************************
+ *   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.cayenne.velocity;
+
+import org.apache.cayenne.access.jdbc.ColumnDescriptor;
+import org.apache.cayenne.access.jdbc.SQLStatement;
+import org.apache.cayenne.velocity.SQLTemplateProcessor;
+import org.junit.Test;
+
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class SQLTemplateProcessorSelectTest {
+
+    @Test
+    public void testProcessTemplateUnchanged() throws Exception {
+        String sqlTemplate = "SELECT * FROM ME";
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(
+                sqlTemplate,
+                Collections.EMPTY_MAP);
+
+        assertEquals(sqlTemplate, compiled.getSql());
+        assertEquals(0, compiled.getBindings().length);
+        assertEquals(0, compiled.getResultColumns().length);
+    }
+
+    @Test
+    public void testProcessSelectTemplate1() throws Exception {
+        String sqlTemplate = "SELECT #result('A') FROM ME";
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(
+                sqlTemplate,
+                Collections.EMPTY_MAP);
+
+        assertEquals("SELECT A FROM ME", compiled.getSql());
+        assertEquals(0, compiled.getBindings().length);
+        assertEquals(1, compiled.getResultColumns().length);
+        assertEquals("A", compiled.getResultColumns()[0].getName());
+        assertNull(compiled.getResultColumns()[0].getJavaClass());
+    }
+
+    @Test
+    public void testProcessSelectTemplate2() throws Exception {
+        String sqlTemplate = "SELECT #result('A' 'String') FROM ME";
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(
+                sqlTemplate,
+                Collections.EMPTY_MAP);
+
+        assertEquals("SELECT A FROM ME", compiled.getSql());
+        assertEquals(0, compiled.getBindings().length);
+
+        assertEquals(1, compiled.getResultColumns().length);
+        assertEquals("A", compiled.getResultColumns()[0].getName());
+        assertEquals("java.lang.String", compiled.getResultColumns()[0].getJavaClass());
+    }
+
+    @Test
+    public void testProcessSelectTemplate3() throws Exception {
+        String sqlTemplate = "SELECT #result('A' 'String' 'B') FROM ME";
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(
+                sqlTemplate,
+                Collections.EMPTY_MAP);
+
+        assertEquals("SELECT A AS B FROM ME", compiled.getSql());
+        assertEquals(0, compiled.getBindings().length);
+
+        assertEquals(1, compiled.getResultColumns().length);
+        ColumnDescriptor column = compiled.getResultColumns()[0];
+        assertEquals("A", column.getName());
+        assertEquals("B", column.getDataRowKey());
+        assertEquals("java.lang.String", column.getJavaClass());
+    }
+
+    @Test
+    public void testProcessSelectTemplate4() throws Exception {
+        String sqlTemplate = "SELECT #result('A'), #result('B'), #result('C') FROM ME";
+
+        SQLStatement compiled = new SQLTemplateProcessor().processTemplate(
+                sqlTemplate,
+                Collections.EMPTY_MAP);
+
+        assertEquals("SELECT A, B, C FROM ME", compiled.getSql());
+        assertEquals(0, compiled.getBindings().length);
+
+        assertEquals(3, compiled.getResultColumns().length);
+        assertEquals("A", compiled.getResultColumns()[0].getName());
+        assertEquals("B", compiled.getResultColumns()[1].getName());
+        assertEquals("C", compiled.getResultColumns()[2].getName());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c8709542/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateProcessorTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateProcessorTest.java
b/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateProcessorTest.java
new file mode 100644
index 0000000..89f48dc
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateProcessorTest.java
@@ -0,0 +1,235 @@
+/*****************************************************************
+ *   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.cayenne.velocity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.DataObject;
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.access.jdbc.ParameterBinding;
+import org.apache.cayenne.access.jdbc.SQLStatement;
+import org.junit.Test;
+
+public class SQLTemplateProcessorTest {
+
+	@Test
+	public void testProcessTemplateUnchanged1() throws Exception {
+		String sqlTemplate = "SELECT * FROM ME";
+
+		SQLStatement compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate,
+				Collections.<String, Object> emptyMap());
+
+		assertEquals(sqlTemplate, compiled.getSql());
+		assertEquals(0, compiled.getBindings().length);
+	}
+
+	@Test
+	public void testProcessTemplateUnchanged2() throws Exception {
+		String sqlTemplate = "SELECT a.b as XYZ FROM $SYSTEM_TABLE";
+
+		SQLStatement compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate,
+				Collections.<String, Object> emptyMap());
+
+		assertEquals(sqlTemplate, compiled.getSql());
+		assertEquals(0, compiled.getBindings().length);
+	}
+
+	@Test
+	public void testProcessTemplateSimpleDynamicContent() throws Exception {
+		String sqlTemplate = "SELECT * FROM ME WHERE $a";
+
+		Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
+		SQLStatement compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate, map);
+
+		assertEquals("SELECT * FROM ME WHERE VALUE_OF_A", compiled.getSql());
+
+		// bindings are not populated, since no "bind" macro is used.
+		assertEquals(0, compiled.getBindings().length);
+	}
+
+	@Test
+	public void testProcessTemplateBind() throws Exception {
+		String sqlTemplate = "SELECT * FROM ME WHERE "
+				+ "COLUMN1 = #bind($a 'VARCHAR') AND COLUMN2 = #bind($b 'INTEGER')";
+		Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
+		SQLStatement compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate, map);
+
+		assertEquals("SELECT * FROM ME WHERE COLUMN1 = ? AND COLUMN2 = ?", compiled.getSql());
+		assertEquals(2, compiled.getBindings().length);
+		assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
+		assertBindingValue(null, compiled.getBindings()[1]);
+	}
+
+	@Test
+	public void testProcessTemplateBindGuessVarchar() throws Exception {
+		String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
+		Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
+
+		SQLStatement compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate, map);
+
+		assertEquals(1, compiled.getBindings().length);
+		assertBindingType(Types.VARCHAR, compiled.getBindings()[0]);
+	}
+
+	@Test
+	public void testProcessTemplateBindGuessInteger() throws Exception {
+		String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($a)";
+		Map<String, Object> map = Collections.<String, Object> singletonMap("a", 4);
+
+		SQLStatement compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate, map);
+
+		assertEquals(1, compiled.getBindings().length);
+		assertBindingType(Types.INTEGER, compiled.getBindings()[0]);
+	}
+
+	@Test
+	public void testProcessTemplateBindEqual() throws Exception {
+		String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindEqual($a 'VARCHAR')";
+
+		SQLStatement compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate,
+				Collections.<String, Object> emptyMap());
+
+		assertEquals("SELECT * FROM ME WHERE COLUMN IS NULL", compiled.getSql());
+		assertEquals(0, compiled.getBindings().length);
+
+		Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
+
+		compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate, map);
+
+		assertEquals("SELECT * FROM ME WHERE COLUMN = ?", compiled.getSql());
+		assertEquals(1, compiled.getBindings().length);
+		assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
+	}
+
+	@Test
+	public void testProcessTemplateBindNotEqual() throws Exception {
+		String sqlTemplate = "SELECT * FROM ME WHERE COLUMN #bindNotEqual($a 'VARCHAR')";
+
+		SQLStatement compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate,
+				Collections.<String, Object> emptyMap());
+
+		assertEquals("SELECT * FROM ME WHERE COLUMN IS NOT NULL", compiled.getSql());
+		assertEquals(0, compiled.getBindings().length);
+
+		Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
+
+		compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate, map);
+
+		assertEquals("SELECT * FROM ME WHERE COLUMN <> ?", compiled.getSql());
+		assertEquals(1, compiled.getBindings().length);
+		assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
+	}
+
+	@Test
+	public void testProcessTemplateID() throws Exception {
+		String sqlTemplate = "SELECT * FROM ME WHERE COLUMN1 = #bind($helper.cayenneExp($a, 'db:ID_COLUMN'))";
+
+		DataObject dataObject = new CayenneDataObject();
+		dataObject.setObjectId(new ObjectId("T", "ID_COLUMN", 5));
+
+		Map<String, Object> map = Collections.<String, Object> singletonMap("a", dataObject);
+
+		SQLStatement compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate, map);
+
+		assertEquals("SELECT * FROM ME WHERE COLUMN1 = ?", compiled.getSql());
+		assertEquals(1, compiled.getBindings().length);
+		assertBindingValue(new Integer(5), compiled.getBindings()[0]);
+	}
+
+	@Test
+	public void testProcessTemplateNotEqualID() throws Exception {
+		String sqlTemplate = "SELECT * FROM ME WHERE "
+				+ "COLUMN1 #bindNotEqual($helper.cayenneExp($a, 'db:ID_COLUMN1')) "
+				+ "AND COLUMN2 #bindNotEqual($helper.cayenneExp($a, 'db:ID_COLUMN2'))";
+
+		Map<String, Object> idMap = new HashMap<String, Object>();
+		idMap.put("ID_COLUMN1", new Integer(3));
+		idMap.put("ID_COLUMN2", "aaa");
+		ObjectId id = new ObjectId("T", idMap);
+		DataObject dataObject = new CayenneDataObject();
+		dataObject.setObjectId(id);
+
+		Map<String, Object> map = Collections.<String, Object> singletonMap("a", dataObject);
+
+		SQLStatement compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate, map);
+
+		assertEquals("SELECT * FROM ME WHERE COLUMN1 <> ? AND COLUMN2 <> ?", compiled.getSql());
+		assertEquals(2, compiled.getBindings().length);
+		assertBindingValue(new Integer(3), compiled.getBindings()[0]);
+		assertBindingValue("aaa", compiled.getBindings()[1]);
+	}
+
+	@Test
+	public void testProcessTemplateConditions() throws Exception {
+		String sqlTemplate = "SELECT * FROM ME #if($a) WHERE COLUMN1 > #bind($a)#end";
+
+		Map<String, Object> map = Collections.<String, Object> singletonMap("a", "VALUE_OF_A");
+
+		SQLStatement compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate, map);
+
+		assertEquals("SELECT * FROM ME  WHERE COLUMN1 > ?", compiled.getSql());
+		assertEquals(1, compiled.getBindings().length);
+		assertBindingValue("VALUE_OF_A", compiled.getBindings()[0]);
+
+		compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate, Collections.<String,
Object> emptyMap());
+
+		assertEquals("SELECT * FROM ME ", compiled.getSql());
+		assertEquals(0, compiled.getBindings().length);
+	}
+
+	@Test
+	public void testProcessTemplateBindCollection() throws Exception {
+		String sqlTemplate = "SELECT * FROM ME WHERE COLUMN IN (#bind($list 'VARCHAR'))";
+
+		Map<String, Object> map = Collections.<String, Object> singletonMap("list",
Arrays.asList("a", "b", "c"));
+		SQLStatement compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate, map);
+
+		assertEquals("SELECT * FROM ME WHERE COLUMN IN (?,?,?)", compiled.getSql());
+		assertEquals(3, compiled.getBindings().length);
+
+		compiled = new SQLTemplateProcessor().processTemplate(sqlTemplate, map);
+		assertBindingValue("a", compiled.getBindings()[0]);
+		assertBindingValue("b", compiled.getBindings()[1]);
+		assertBindingValue("c", compiled.getBindings()[2]);
+	}
+
+	protected void assertBindingValue(Object expectedValue, Object binding) {
+		assertTrue("Not a binding!", binding instanceof ParameterBinding);
+		assertEquals(expectedValue, ((ParameterBinding) binding).getValue());
+	}
+
+	protected void assertBindingType(int expectedType, Object binding) {
+		assertTrue("Not a binding!", binding instanceof ParameterBinding);
+		assertEquals(expectedType, ((ParameterBinding) binding).getJdbcType());
+	}
+
+	protected void assertBindingPrecision(int expectedPrecision, Object binding) {
+		assertTrue("Not a binding!", binding instanceof ParameterBinding);
+		assertEquals(expectedPrecision, ((ParameterBinding) binding).getScale());
+	}
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c8709542/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateResourceManagerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateResourceManagerTest.java
b/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateResourceManagerTest.java
new file mode 100644
index 0000000..725788c
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/velocity/SQLTemplateResourceManagerTest.java
@@ -0,0 +1,77 @@
+/*****************************************************************
+ *   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.cayenne.velocity;
+
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.Reader;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.RuntimeServices;
+import org.apache.velocity.runtime.parser.node.SimpleNode;
+import org.apache.velocity.runtime.resource.Resource;
+import org.apache.velocity.runtime.resource.ResourceManager;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SQLTemplateResourceManagerTest {
+
+	private SQLTemplateResourceManager rm;
+
+	@Before
+	public void before() throws Exception {
+
+		RuntimeServices rs = mock(RuntimeServices.class);
+		when(rs.parse(any(Reader.class), anyString(), anyBoolean())).thenReturn(new SimpleNode(1));
+		when(rs.parse(any(Reader.class), anyString())).thenReturn(new SimpleNode(1));
+
+		this.rm = new SQLTemplateResourceManager();
+		rm.initialize(rs);
+	}
+
+	@Test
+	public void testFetResource() throws Exception {
+
+		Resource resource = rm.getResource("abc", ResourceManager.RESOURCE_TEMPLATE, RuntimeConstants.ENCODING_DEFAULT);
+
+		assertTrue(resource instanceof Template);
+
+		// must be cached...
+		assertSame(resource,
+				rm.getResource("abc", ResourceManager.RESOURCE_TEMPLATE, RuntimeConstants.ENCODING_DEFAULT));
+
+		// new resource must be different
+		assertNotSame(resource,
+				rm.getResource("xyz", ResourceManager.RESOURCE_TEMPLATE, RuntimeConstants.ENCODING_DEFAULT));
+
+		// after clearing cache, resource must be refreshed
+		rm.clearCache();
+		assertNotSame(resource,
+				rm.getResource("abc", ResourceManager.RESOURCE_TEMPLATE, RuntimeConstants.ENCODING_DEFAULT));
+	}
+}


Mime
View raw message