diff --git a/jOOQ-examples/jOOQ-oracle-example/README.md b/jOOQ-examples/jOOQ-oracle-example/README.md index 6338bcb72b..144c37540d 100644 --- a/jOOQ-examples/jOOQ-oracle-example/README.md +++ b/jOOQ-examples/jOOQ-oracle-example/README.md @@ -5,7 +5,7 @@ Please visit http://www.jooq.org for more information. Because this example is making use of the Oracle SQL dialect, it does not run with the jOOQ Open Source Edition, which does not support Oracle. In order to run this example, please get a commercial or trial distribution directly from: http://www.jooq.org/download. -Before you run this example, you will need to create the following user: +Before you run this example, you will need to create the following user in your Oracle database: ```sql C:\> sqlplus "/ as sysdba" @@ -29,6 +29,8 @@ SQL> GRANT EXECUTE ON DBMS_AQADM TO SP; ``` +If you do not have the rights to create users, you can also change the user in `config.properties` and in `db-oracle.sql`. + To install and run this example, please use Maven and Java 8 to install the latest distribution of jOOQ Professional Edition: ``` @@ -40,5 +42,7 @@ $ mvn clean install ... $ cd jOOQ-examples/jOOQ-oracle-example ... +$ cp /path/to/ojdbc6.jar lib +... $ mvn clean install ``` diff --git a/jOOQ-examples/jOOQ-oracle-example/lib/.gitignore b/jOOQ-examples/jOOQ-oracle-example/lib/.gitignore new file mode 100644 index 0000000000..e45711a511 --- /dev/null +++ b/jOOQ-examples/jOOQ-oracle-example/lib/.gitignore @@ -0,0 +1 @@ +/ojdbc6.jar diff --git a/jOOQ-examples/jOOQ-oracle-example/pom.xml b/jOOQ-examples/jOOQ-oracle-example/pom.xml index f346727eb9..78e5783973 100644 --- a/jOOQ-examples/jOOQ-oracle-example/pom.xml +++ b/jOOQ-examples/jOOQ-oracle-example/pom.xml @@ -34,6 +34,8 @@ com.oracle ojdbc6 ${db.oracle.version} + system + ${basedir}/lib/ojdbc6.jar @@ -137,6 +139,8 @@ com.oracle ojdbc6 ${db.oracle.version} + system + ${basedir}/lib/ojdbc6.jar @@ -165,10 +169,25 @@ org.jooq.util.DefaultGenerator org.jooq.util.oracle.OracleDatabase - .* - + + # Generate the complete SP user + SP\..* + + # Generate only parts of the geospatial API + | MDSYS\.SDO_GEOM.*? + + + + ST_ANNOTATIONTEXTELEMENT true - SP + + + SP + + + MDSYS + + false @@ -181,6 +200,16 @@ + + + + com.oracle + ojdbc6 + ${db.oracle.version} + system + ${basedir}/lib/ojdbc6.jar + + diff --git a/jOOQ-examples/jOOQ-oracle-example/src/main/resources/db-oracle.sql b/jOOQ-examples/jOOQ-oracle-example/src/main/resources/db-oracle.sql index 4d2273628f..aa2165c597 100644 --- a/jOOQ-examples/jOOQ-oracle-example/src/main/resources/db-oracle.sql +++ b/jOOQ-examples/jOOQ-oracle-example/src/main/resources/db-oracle.sql @@ -204,3 +204,109 @@ BEGIN COMMIT; END; / + + + + + + + + + + +BEGIN + -- Examples can be found here: + -- https://docs.oracle.com/cd/B19306_01/appdev.102/b14255/sdo_objrelschema.htm#SPATL020 + BEGIN + EXECUTE IMMEDIATE 'DROP TABLE cola_markets'; + EXCEPTION WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE (SQLERRM); + END; +END; +/ + + +CREATE TABLE cola_markets ( + mkt_id NUMBER PRIMARY KEY, + name VARCHAR2(32), + shape SDO_GEOMETRY) +/ + +INSERT INTO cola_markets VALUES( + 1, + 'cola_a', + SDO_GEOMETRY( + 2003, -- two-dimensional polygon + NULL, + NULL, + SDO_ELEM_INFO_ARRAY(1,1003,3), -- one rectangle (1003 = exterior) + SDO_ORDINATE_ARRAY(1,1, 5,7) -- only 2 points needed to + -- define rectangle (lower left and upper right) with + -- Cartesian-coordinate data + ) +) +/ + +INSERT INTO cola_markets VALUES( + 2, + 'cola_b', + SDO_GEOMETRY( + 2003, -- two-dimensional polygon + NULL, + NULL, + SDO_ELEM_INFO_ARRAY(1,1003,1), -- one polygon (exterior polygon ring) + SDO_ORDINATE_ARRAY(5,1, 8,1, 8,6, 5,7, 5,1) + ) +) +/ + +INSERT INTO cola_markets VALUES( + 3, + 'cola_c', + SDO_GEOMETRY( + 2003, -- two-dimensional polygon + NULL, + NULL, + SDO_ELEM_INFO_ARRAY(1,1003,1), -- one polygon (exterior polygon ring) + SDO_ORDINATE_ARRAY(3,3, 6,3, 6,5, 4,5, 3,3) + ) +) +/ + +INSERT INTO cola_markets VALUES( + 4, + 'cola_d', + SDO_GEOMETRY( + 2003, -- two-dimensional polygon + NULL, + NULL, + SDO_ELEM_INFO_ARRAY(1,1003,4), -- one circle + SDO_ORDINATE_ARRAY(8,7, 10,9, 8,11) + ) +) +/ + +BEGIN + INSERT INTO user_sdo_geom_metadata + (TABLE_NAME, + COLUMN_NAME, + DIMINFO, + SRID) + VALUES ( + 'cola_markets', + 'shape', + SDO_DIM_ARRAY( -- 20X20 grid + SDO_DIM_ELEMENT('X', 0, 20, 0.005), + SDO_DIM_ELEMENT('Y', 0, 20, 0.005) + ), + NULL -- SRID + ); +EXCEPTION WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE (SQLERRM); +END; +/ + +CREATE INDEX cola_spatial_idx + ON cola_markets(shape) + INDEXTYPE IS MDSYS.SPATIAL_INDEX +/ diff --git a/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/OracleAQExamples.java b/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/OracleAQExamples.java new file mode 100644 index 0000000000..6c0f4ec9f1 --- /dev/null +++ b/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/OracleAQExamples.java @@ -0,0 +1,136 @@ +/** + * Copyright (c) 2009-2013, Data Geekery GmbH (http://www.datageekery.com) + * All rights reserved. + * + * This work is dual-licensed + * - under the Apache Software License 2.0 (the "ASL") + * - under the jOOQ License and Maintenance Agreement (the "jOOQ License") + * ============================================================================= + * You may choose which license applies to you: + * + * - If you're using this work with Open Source databases, you may choose + * either ASL or jOOQ License. + * - If you're using this work with at least one commercial database, you must + * choose jOOQ License + * + * For more information, please visit http://www.jooq.org/licenses + * + * Apache Software License 2.0: + * ----------------------------------------------------------------------------- + * Licensed 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. + * + * jOOQ License and Maintenance Agreement: + * ----------------------------------------------------------------------------- + * Data Geekery grants the Customer the non-exclusive, timely limited and + * non-transferable license to install and use the Software under the terms of + * the jOOQ License and Maintenance Agreement. + * + * This library is distributed with a LIMITED WARRANTY. See the jOOQ License + * and Maintenance Agreement for more details: http://www.jooq.org/licensing + */ +package org.jooq.example; + +import static java.util.stream.Collectors.toList; +import static java.util.stream.IntStream.range; +import static org.jooq.example.db.oracle.sp.Queues.NEW_AUTHOR_AQ; +// ... +// ... +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.jooq.example.db.oracle.sp.udt.records.AuthorTRecord; +import org.jooq.exception.DataAccessException; +import org.jooq.impl.DSL; +// ... +// ... +// ... +// ... + +import org.junit.Test; + +/** + * @author Lukas Eder + */ +public class OracleAQExamples extends Utils { + + // Generate 10 authors + static final List authors = + range(0, 10).mapToObj(i -> new AuthorTRecord(i, "F" + i, "L1" + i, null)).collect(toList()); + + @Test + public void testAQSimple() throws Exception { + dsl.transaction(c -> { + + // Enqueue all authors + authors.stream().forEach(a -> { + DBMS_AQ.enqueue(dsl.configuration(), NEW_AUTHOR_AQ, a); + }); + + // Dequeue them again + authors.stream().forEach(a -> { + assertEquals(a, DBMS_AQ.dequeue(dsl.configuration(), NEW_AUTHOR_AQ)); + }); + }); + } + + @Test + public void testAQOptions() throws Exception { + dsl.transaction(c -> { + MESSAGE_PROPERTIES_T props = new MESSAGE_PROPERTIES_T(); + ENQUEUE_OPTIONS_T enq = new ENQUEUE_OPTIONS_T().visibility(IMMEDIATE); + + // Enqueue two authors + DBMS_AQ.enqueue(c, NEW_AUTHOR_AQ, authors.get(0), enq, props); + DBMS_AQ.enqueue(c, NEW_AUTHOR_AQ, authors.get(1), enq, props); + + // Dequeue them again + DEQUEUE_OPTIONS_T deq = new DEQUEUE_OPTIONS_T().wait(NO_WAIT); + + assertEquals(authors.get(0), DBMS_AQ.dequeue(c, NEW_AUTHOR_AQ, deq, props)); + assertEquals(authors.get(1), DBMS_AQ.dequeue(c, NEW_AUTHOR_AQ, deq, props)); + + // The queue is empty, this should fail + assertThrows(DataAccessException.class, () -> { + DBMS_AQ.dequeue(c, NEW_AUTHOR_AQ, deq, props); + }); + }); + } + + @Test + public void testAQTransactions() throws Exception { + dsl.transaction(c1 -> { + + // Enqueue an author + DBMS_AQ.enqueue(c1, NEW_AUTHOR_AQ, authors.get(0)); + + // This nested transaction is rolled back to its savepoint + assertThrows(RuntimeException.class, () -> { + DSL.using(c1).transaction(c2 -> { + DBMS_AQ.enqueue(c2, NEW_AUTHOR_AQ, authors.get(1)); + throw new RuntimeException(); + }); + }); + + // Dequeue the first author + MESSAGE_PROPERTIES_T props = new MESSAGE_PROPERTIES_T(); + DEQUEUE_OPTIONS_T deq = new DEQUEUE_OPTIONS_T().wait(NO_WAIT); + assertEquals(authors.get(0), DBMS_AQ.dequeue(c1, NEW_AUTHOR_AQ, deq, props)); + + // The queue is empty (due to the rollback), this should fail + assertThrows(DataAccessException.class, () -> { + DBMS_AQ.dequeue(c1, NEW_AUTHOR_AQ, deq, props); + }); + }); + } +} diff --git a/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/OracleProcedureExamples.java b/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/OracleProcedureExamples.java new file mode 100644 index 0000000000..6a02ca83b6 --- /dev/null +++ b/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/OracleProcedureExamples.java @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2009-2013, Data Geekery GmbH (http://www.datageekery.com) + * All rights reserved. + * + * This work is dual-licensed + * - under the Apache Software License 2.0 (the "ASL") + * - under the jOOQ License and Maintenance Agreement (the "jOOQ License") + * ============================================================================= + * You may choose which license applies to you: + * + * - If you're using this work with Open Source databases, you may choose + * either ASL or jOOQ License. + * - If you're using this work with at least one commercial database, you must + * choose jOOQ License + * + * For more information, please visit http://www.jooq.org/licenses + * + * Apache Software License 2.0: + * ----------------------------------------------------------------------------- + * Licensed 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. + * + * jOOQ License and Maintenance Agreement: + * ----------------------------------------------------------------------------- + * Data Geekery grants the Customer the non-exclusive, timely limited and + * non-transferable license to install and use the Software under the terms of + * the jOOQ License and Maintenance Agreement. + * + * This library is distributed with a LIMITED WARRANTY. See the jOOQ License + * and Maintenance Agreement for more details: http://www.jooq.org/licensing + */ +package org.jooq.example; + +import static org.jooq.example.db.oracle.sp.Tables.AUTHORS; +import static org.jooq.example.db.oracle.sp.Tables.BOOKS; +import static org.jooq.impl.DSL.using; + +import org.jooq.example.db.oracle.sp.packages.Library; + +import org.junit.Before; +import org.junit.Test; + +/** + * @author Lukas Eder + */ +public class OracleProcedureExamples extends Utils { + + @Before + public void setup() { + dsl.transaction(ctx -> { + using(ctx).delete(BOOKS).execute(); + using(ctx).delete(AUTHORS).execute(); + + using(ctx).insertInto(AUTHORS, AUTHORS.ID, AUTHORS.FIRST_NAME, AUTHORS.LAST_NAME) + .values(1, "George", "Orwell") + .values(2, "Paulo" , "Coelho") + .execute(); + + using(ctx).insertInto(BOOKS, BOOKS.ID, BOOKS.TITLE, BOOKS.LANGUAGE, BOOKS.AUTHOR_ID) + .values(1, "1984" , "en", 1) + .values(2, "Animal Farm" , "en", 1) + .values(3, "O Alquimista", "pt", 2) + .values(4, "Brida" , "en", 2) + .execute(); + }); + } + + @Test + public void testProcedures() { + // TODO: Work on this nice table unnesting syntax, which currently doesn't work. + // dsl.selectFrom(table(Library.getAuthors(null, 1))) + // .fetch(); + + dsl.select(AUTHORS.FIRST_NAME, AUTHORS.LAST_NAME, Library.getBooks(AUTHORS.ID)) + .from(AUTHORS) + .fetch() + .forEach(author -> { + + System.out.println(); + System.out.println("Author " + author.getValue(AUTHORS.FIRST_NAME) + " " + author.getValue(AUTHORS.LAST_NAME) + " wrote: "); + author.value3().getList().forEach(book -> { + System.out.println(book.getTitle()); + }); + }); + } +} diff --git a/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/OracleSpatialExamples.java b/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/OracleSpatialExamples.java new file mode 100644 index 0000000000..f906f2390c --- /dev/null +++ b/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/OracleSpatialExamples.java @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2009-2013, Data Geekery GmbH (http://www.datageekery.com) + * All rights reserved. + * + * This work is dual-licensed + * - under the Apache Software License 2.0 (the "ASL") + * - under the jOOQ License and Maintenance Agreement (the "jOOQ License") + * ============================================================================= + * You may choose which license applies to you: + * + * - If you're using this work with Open Source databases, you may choose + * either ASL or jOOQ License. + * - If you're using this work with at least one commercial database, you must + * choose jOOQ License + * + * For more information, please visit http://www.jooq.org/licenses + * + * Apache Software License 2.0: + * ----------------------------------------------------------------------------- + * Licensed 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. + * + * jOOQ License and Maintenance Agreement: + * ----------------------------------------------------------------------------- + * Data Geekery grants the Customer the non-exclusive, timely limited and + * non-transferable license to install and use the Software under the terms of + * the jOOQ License and Maintenance Agreement. + * + * This library is distributed with a LIMITED WARRANTY. See the jOOQ License + * and Maintenance Agreement for more details: http://www.jooq.org/licensing + */ +package org.jooq.example; + +import static org.jooq.example.db.oracle.sp.Tables.COLA_MARKETS; +import static org.jooq.impl.DSL.val; + +import org.jooq.Record1; +import org.jooq.example.db.oracle.mdsys.packages.SdoGeom; +import org.jooq.example.db.oracle.sp.tables.ColaMarkets; + +import org.junit.Test; + +/** + * @author Lukas Eder + */ +public class OracleSpatialExamples extends Utils { + + @Test + public void testSDO_GEOM() { + + // These examples were inspired from the examples given in the Oracle + // documentation: + // https://docs.oracle.com/cd/B19306_01/appdev.102/b14255/sdo_objrelschema.htm#SPATL020 + // OTN License restrictions may apply. + + ColaMarkets c_a = COLA_MARKETS.as("c_a"); + ColaMarkets c_b = COLA_MARKETS.as("c_b"); + ColaMarkets c_c = COLA_MARKETS.as("c_c"); + ColaMarkets c_d = COLA_MARKETS.as("c_d"); + + // SELECT SDO_GEOM.SDO_INTERSECTION(c_a.shape, c_c.shape, 0.005) + // FROM cola_markets c_a, cola_markets c_c + // WHERE c_a.name = 'cola_a' AND c_c.name = 'cola_c'; + + System.out.println(); + System.out.println("Return the topological intersection of two geometries."); + System.out.println("------------------------------------------------------"); + + dsl.select(SdoGeom.sdoIntersection2(c_a.SHAPE, c_c.SHAPE, val(0.005))) + .from(c_a, c_c) + .where(c_a.NAME.eq("cola_a")) + .and(c_c.NAME.eq("cola_c")) + .fetch() + .map(Record1::value1) + .forEach(System.out::println); + + // SELECT SDO_GEOM.RELATE(c_b.shape, 'anyinteract', c_d.shape, 0.005) + // FROM cola_markets c_b, cola_markets c_d + // WHERE c_b.name = 'cola_b' AND c_d.name = 'cola_d'; + + System.out.println(); + System.out.println("Do two geometries have any spatial relationship?"); + System.out.println("------------------------------------------------"); + + dsl.select(SdoGeom.relate6(c_b.SHAPE, val("anyinteract"), c_d.SHAPE, val(0.005))) + .from(c_b, c_d) + .where(c_b.NAME.eq("cola_b")) + .and(c_d.NAME.eq("cola_d")) + .fetch() + .map(Record1::value1) + .forEach(System.out::println); + + // -- Return the areas of all cola markets. + // SELECT name, SDO_GEOM.SDO_AREA(shape, 0.005) FROM cola_markets; + + System.out.println(); + System.out.println("Return the areas of all cola markets."); + System.out.println("-------------------------------------"); + + dsl.select(SdoGeom.sdoArea2(c_a.SHAPE, val(0.005))) + .from(c_a) + .fetch() + .map(Record1::value1) + .forEach(System.out::println); + + // SELECT SDO_GEOM.SDO_DISTANCE(c_b.shape, c_d.shape, 0.005) + // FROM cola_markets c_b, cola_markets c_d + // WHERE c_b.name = 'cola_b' AND c_d.name = 'cola_d'; + + System.out.println(); + System.out.println("Return the distance between two geometries."); + System.out.println("-------------------------------------------"); + + dsl.select(SdoGeom.sdoDistance2(c_b.SHAPE, c_d.SHAPE, val(0.005))) + .from(c_b, c_d) + .where(c_b.NAME.eq("cola_b")) + .and(c_d.NAME.eq("cola_d")) + .fetch() + .map(Record1::value1) + .forEach(System.out::println); + } +} diff --git a/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/Utils.java b/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/Utils.java index 187c165a7c..7ac3104a5b 100644 --- a/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/Utils.java +++ b/jOOQ-examples/jOOQ-oracle-example/src/test/java/org/jooq/example/Utils.java @@ -64,7 +64,7 @@ public class Utils { @BeforeClass public static void start() throws Exception { Properties p = new Properties(); - p.load(QueriesWithTypes.class.getResourceAsStream("/config.properties")); + p.load(OracleAQExamples.class.getResourceAsStream("/config.properties")); connection = getConnection(p.getProperty("db.url"), p.getProperty("db.username"), p.getProperty("db.password")); dsl = using(connection);