3 Oracle JDBC Data Cartridge
You can use the Oracle Stream Explorer JDBC data cartridge to execute a SQL query against a database and use the returned results in a CQL query.
When using functionality provided by the cartridge, you are associating a SQL query with a JDBC cartridge function definition. Then, from a CQL query, you can call the JDBC cartridge function, which executes the associated SQL query against the database. The function call must be enclosed in the TABLE clause, which lets you use the SQL query results as a CQL relation in the CQL query making that function call.
Note:
Oracle recommends the Oracle JDBC data cartridge for accessing relational database tables from an Oracle CQL statement.
For information the TABLE clause, see Using the TABLE Clause.
This chapter includes the following sections:
3.1 Understanding the Oracle Stream Explorer JDBC Data Cartridge
Oracle Stream Explorer streams contain streaming data, and a database typically stores historical data. Use the Oracle Stream Explorer JDBC data cartridge to associate historical data (stored in one or more tables) with the streaming data coming from Oracle Stream Explorer streams.
The Oracle Stream Explorer JDBC data cartridge executes arbitrary SQL query against a database and uses the results in the CQL query. This section describes how to associate streaming and historical data using the Oracle Stream Explorer JDBC data cartridge.
This section describes:
3.1.1 Data Cartridge Name
The Oracle Stream Explorer JDBC data cartridge uses the cartridge ID com.oracle.cep.cartridge.jdbc
. This ID is reserved and cannot be used by any other cartridges.
For more information, see Oracle Stream Explorer JDBC Data Cartridge Application Context.
3.1.2 Scope
The Oracle Stream Analytics JDBC data cartridge supports arbitrarily complex SQL statements with the following restrictions:
-
You can use only native SQL types in the
SELECT
list of the SQL query. -
You cannot use user-defined types and complex database types in the
SELECT
list. -
You can provide alias names for every
SELECT
list column in the SQL query. If you provide alias names, make sure the select list is consistent with the return type property names.
Note:
To use the Oracle Stream Analytics JDBC data cartridge, your data source must use Oracle JDBC driver version 11.2 or higher.
3.1.3 Parameter Specification
Use the param
element to specify the parameters for JDBC functions. The parameters are specified as name
and value
pairs. The name
attribute specifies event data of the specified type
. The type
attribute can be any Oracle CQL data type. See Oracle Fusion Middleware Oracle
CQL Language Reference for information about Oracle CQL data types.
The following example shows an example configuration file that uses param
and type
pairs to specify parameters for the getDetailsByOrderIdName
function.
Note:
The RetEvent
class used in the example is an example of how to return a complex type as a table function. The full code for this class is shown in Using the Event Processing JDBC Data Cartridge.
... <jc:jdbc-ctx> <name>JdbcCartridgeOne</name> <data-source>StockDS</data-source> <function name="getDetailsByOrderIdName"> <param name="inpOrderId" type="int" /> <param name="inpName" type="char" /> <return-component-type> com.oracle.cep.example.jdbc_cartridge.RetEvent </return-component-type> <sql><![CDATA[ SELECT Employee.empName as employeeName, Employee.empEmail as employeeEmail, OrderDetails.description as description FROM PlacedOrders, OrderDetails , Employee WHERE PlacedOrders.empId = Employee.empId AND PlacedOrders.orderId = OrderDetails.orderId AND Employee.empName = :inpName AND PlacedOrders.orderId = :inpOrderId ></sql> </function> </jc:jdbc-ctx> ...
3.1.4 Oracle Stream Explorer JDBC Data Cartridge Application Context
To use the Oracle Stream Explorer JDBC data cartridge, you must declare and configure one or more application-scoped JDBC cartridge context while developing an application, as described in the following steps:
3.1.4.1 Declare a JDBC Cartridge Context in the EPN File
To declare a JDBC cartridge context in the EPN file:
- Edit your Oracle Stream Explorer application EPN assembly file to add the required namespace and schema location entries.
- Add an entry with the tag
jdbc-context
in the EPN file and specify theid
attribute. Theid
represents the name of this application-scoped context and is used in CQL queries that reference functions defined in this context. Theid
is also used when this context is configured in the application configuration file.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi" xmlns:wlevs="http://www.bea.com/ns/wlevs/spring" xmlns:jdbc="http://www.oracle.com/ns/ocep/jdbc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd http://www.bea.com/ns/wlevs/spring http://www.bea.com/ns/wlevs/spring/http://www.bea.com/ns/wlevs/spring/ocep-epn.xsd http://www.oracle.com/ns/ocep/jdbc http://www.oracle.com/ns/ocep/jdbc/ocep-jdbc.xsd">
The following example shows how to create an Oracle Stream Explorer JDBC data cartridge application context named JdbcCartridgeOne
in an EPN assembly file.
<jdbc:jdbc-context id="JdbcCartridgeOne"/>
3.1.4.2 Configure the JDBC Cartridge Context in the Application Configuration File
To configure the JDBC cartridge context, add the configuration details in the component configuration file that is typically placed under the application's /wlevs directory. This configuration is similar to configuring other EPN components such as channel and processor.
To configure the JDBC cartridge context in the application configuration file:
3.2 Using the Event Processing JDBC Data Cartridge
The different ways in which an Event Processing JDBC Data Cartridge can be used are explained.
In general, you use the Oracle Event Processing JDBC data cartridge as follows:
3.2.1 Defining SQL Statements: function Element
Within the jc:jdbc-cxt
element in the component configuration file, you can define a JDBC cartridge context function using the function
child element.
... <jc:jdbc-ctx> <name>JdbcCartridgeOne</name> <data-source>StockDS</data-source> <function name="getDetailsByOrderIdName"> <param name="inpOrderId" type="int" /> <param name="inpName" type="char" /> <return-component-type> com.oracle.cep.example.jdbc_cartridge.RetEvent </return-component-type> <sql><![CDATA[ SELECT Employee.empName as employeeName, Employee.empEmail as employeeEmail, OrderDetails.description as description FROM PlacedOrders, OrderDetails , Employee WHERE PlacedOrders.empId = Employee.empId AND PlacedOrders.orderId = OrderDetails.orderId AND Employee.empName = :inpName AND PlacedOrders.orderId = :inpOrderId ></sql> </function> </jc:jdbc-ctx> ...
You may define one or more function
elements within a given jc:jdbc-cxt
element.
This section describes:
3.2.1.1 function Element Attributes
Each function
element supports the attributes that Table 3-1 lists.
Table 3-1 function Element Attributes
Attribute | Description |
---|---|
|
The name of the JDBC cartridge context function. The combination of name and signature must be unique within a given Oracle Stream Analytics JDBC data cartridge application context. For more information, see Overloading JDBC Cartridge Context Functions. |
3.2.1.2 function Element Child Elements
Each function
element supports the following child elements:
3.2.1.2.1 param
The param
child element specifies an optional input parameter.
The SQL statement may take zero or more parameters. Each parameter is defined in a param
element.
The param
child element supports the attributes that Table 3-2 lists.
Table 3-2 param Element Attributes
Attribute | Description |
---|---|
|
The name of the input parameter. A valid parameter name is formed by a combination of A-Z,a-z,0-9 and _ (underscore). |
|
The data type of the parameter. |
Datatype Support – You may specify only Oracle CQL native com.bea.wlevs.ede.api.Type
data types for the input parameter param
element type
attribute.
Note:
Datatype names are case sensitive. Use the case that the com.bea.wlevs.ede.api.Type
class specifies.
For more information, see Table 3-3.
3.2.1.2.2 return-component-type
The return-component-type
child element specifies the return type of the function. This child element is mandatory.
This represents the component type of the collection type returned by the JDBC data cartridge function. Because the function is always called from within an Oracle CQL TABLE
clause, it always returns a collection type.
For more information, see Using the TABLE Clause.
Datatype Support – You may specify any one of the following types as the value of the return-component-type
element:
-
Oracle CQL native
com.bea.wlevs.ede.api.Type
datatype. -
Oracle CQL extensible Java cartridge type, such as a Java bean.
For more information, see:
3.2.1.2.3 sql
The sql
child element specifies a SQL statement. This child element is mandatory.
Each function
element may contain one and only one, single-line, SQL statement. You define the SQL statement itself within a <![CDATA[>
block.
Within the SQL statement, you specify input parameters by param
element name
attribute using a colon (:
) prefix.
Note:
You must provide alias names for every SELECT
list column in the JDBC cartridge context function.
Datatype Support – Table 3-3 lists the SQL types you may use in your Oracle Stream Analytics JDBC data cartridge context functions and their corresponding Oracle Stream Analytics Java type and com.bea.wlevs.ede.api.Type
type.
Table 3-3 SQL Column Types and Oracle Stream Analytics Type Equivalents
SQL Type | Oracle Stream Analytics Java Type | com.bea.wlevs.ede.api.Type |
---|---|---|
|
|
bigdecimal |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Note:
In cases where the size of the Java type exceeds that of the SQL type, your Oracle Stream Analytics application must restrict values to the maximum size of the SQL type. The choice of type to use on the CQL side should be driven by the range of values in the database column. For example, if the SQL column is a number that contains values in the range of integer, use the "int" type on CQL side. If you choose an incorrect type and encounter out-of-range values, Oracle Stream Analytics throws a numeric overflow error.
Note:
The Oracle Stream Analytics JDBC data cartridge does not support Oracle Spatial data types.
For more information, see function Element Usage.
3.2.1.3 function Element Usage
This section provides examples of different JDBC cartridge context functions you can define using the Oracle Stream Explorer JDBC data cartridge, including:
3.2.1.3.1 Multiple Parameter JDBC Cartridge Context Functions
Using the Oracle Stream Explorer JDBC data cartridge, you can define JDBC cartridge context functions that take multiple input parameters.
The following example shows an Oracle Stream Explorer JDBC data cartridge application context that defines an JDBC cartridge context function that takes two input parameters.
... <function name="getDetailsByOrderIdName"> <param name="inpOrderId" type="int" /> <param name="inpName" type="char" /> <return-component-type> com.oracle.cep.example.jdbc_cartridge.RetEvent </return-component-type> <sql><![CDATA[ SELECT Employee.empName as employeeName, Employee.empEmail as employeeEmail, OrderDetails.description as description FROM PlacedOrders, OrderDetails , Employee WHERE PlacedOrders.empId = Employee.empId AND PlacedOrders.orderId = OrderDetails.orderId AND Employee.empName = :inpName AND PlacedOrders.orderId = :inpOrderId ></sql> </function> ...
3.2.1.3.2 Invoking PL/SQL Functions
Using the Oracle Stream Explorer JDBC data cartridge, you can define JDBC cartridge context functions that invoke PL/SQL functions that the database defines.
The following example shows an Oracle Stream Explorer JDBC data cartridge application context that defines a JDBC cartridge context function that invokes PL/SQL function getOrderAmt
.
... <function name="getOrderAmount"> <param name="inpId" type="int" /> <return-component-type> com.oracle.cep.example.jdbc_cartridge.RetEvent </return-component-type> <sql><![CDATA[ SELECT getOrderAmt(:inpId) as orderAmt FROM dual ></sql> </function> ...
3.2.1.3.3 Complex JDBC Cartridge Context Functions
Using the Oracle Stream Explorer JDBC data cartridge, you can define arbitrarily complex JDBC cartridge context functions including subqueries, aggregation, GROUP BY
, ORDER BY
, and HAVING
.
The following example shows an Oracle Stream Explorer JDBC data cartridge application context that defines a complex JDBC cartridge context function.
... <function name="getHighValueOrdersPerEmp"> <param name="limit" type="int"/> <param name="inpName" type="char"/> <return-component-type> com.oracle.cep.example.jdbc_cartridge.RetEvent </return-component-type> <sql><![CDATA[ select description as description, sum(amt) as totalamt, count(*) as numTimes from OrderDetails where orderid in ( select orderid from PlacedOrders where empid in ( select empid from Employee where empName = :inpName ) ) group by description having sum(amt) > :limit ></sql> </function> ...
3.2.1.3.4 Overloading JDBC Cartridge Context Functions
Using the Oracle Stream Explorer JDBC data cartridge, you can define JDBC cartridge context functions with the same name in the same application context provided that each function has a unique signature.
The following example shows an Oracle Stream Explorer JDBC data cartridge application context that defines two JDBC cartridge context functions named getDetails
. Each function is distinguished by a unique signature.
<jc:jdbc-ctx> <name>JdbcCartridgeOne</name> <data-source>StockDS</data-source> <function name="getDetails"> <param name="inpName" type="char" /> <return-component-type> com.oracle.cep.example.jdbc_cartridge.RetEvent </return-component-type> <sql><![CDATA[ SELECT Employee.empName as employeeName, Employee.empEmail as employeeEmail, OrderDetails.description as description FROM PlacedOrders, OrderDetails , Employee WHERE PlacedOrders.empId = Employee.empId AND PlacedOrders.orderId = OrderDetails.orderId AND Employee.empName=:inpName ORDER BY description desc ></sql> </function> <function name="getDetails"> <param name="inpOrderId" type="int" /> <sql><![CDATA[ return-component-type SELECT Employee.empName as employeeName, Employee.empEmail as employeeEmail, OrderDetails.description as description FROM PlacedOrders, OrderDetails , Employee WHERE PlacedOrders.empId= Employee.empId AND PlacedOrders.orderId = OrderDetails.orderId AND PlacedOrders.orderId = :inpOrderId ></sql> </function> </jc:jdbc-ctx>
3.2.2 Defining Oracle CQL Queries With the Oracle Stream Analytics JDBC Data Cartridge
This section describes how to define Oracle CQL queries that invoke SQL statements using the Oracle Stream Analytics JDBC data cartridge, including:
3.2.2.1 Using SELECT List Aliases
Consider the Oracle Stream Explorer JDBC data cartridge context function.
<jc:jdbc-ctx> <name>JdbcCartridgeOne</name> <data-source>StockDS</data-source> <function name="getDetailsByOrderIdName"> <param name="inpOrderId" type="int" /> <param name="inpName" type="char" /> <return-component-type> com.oracle.cep.example.jdbc_cartridge.RetEvent </return-component-type> <sql><![CDATA[ SELECT Employee.empName as employeeName, Employee.empEmail as employeeEmail, OrderDetails.description as description FROM PlacedOrders, OrderDetails , Employee WHERE PlacedOrders.empId = Employee.empId AND PlacedOrders.orderId = OrderDetails.orderId AND Employee.empName = :inpName AND PlacedOrders.orderId = :inpOrderId ></sql> </function> </jc:jdbc-ctx>
You must assign an alias to each column in the SELECT
list. When you invoke the JDBC cartridge context function in an Oracle CQL query, you access the columns in the result set by their SQL SELECT
list aliases.
For more information, see Using the TABLE Clause.
3.2.2.2 Using the TABLE Clause
Consider the Oracle Stream Analytics JDBC data cartridge SQL statement.
... <jc:jdbc-ctx> <name>JdbcCartridgeOne</name> <data-source>StockDS</data-source> <function name="getDetailsByOrderIdName"> <param name="inpOrderId" type="int" /> <param name="inpName" type="char" /> <return-component-type> com.oracle.cep.example.jdbc_cartridge.RetEvent </return-component-type> <sql><![CDATA[ SELECT Employee.empName as employeeName, Employee.empEmail as employeeEmail, OrderDetails.description as description FROM PlacedOrders, OrderDetails , Employee WHERE PlacedOrders.empId = Employee.empId AND PlacedOrders.orderId = OrderDetails.orderId AND Employee.empName = :inpName AND PlacedOrders.orderId = :inpOrderId ></sql> </function> </jc:jdbc-ctx> ...
The Oracle CQL query in the below example invokes the JDBC cartridge context function defined in the above example.
<processor>
<name>Proc</name>
<rules>
<query id="q1"><![CDATA[
RStream(
select
currentOrder.orderId,
details.orderInfo.employeeName,
details.orderInfo.employeeEmail,
details.orderInfo.description
details.orderInfo.getEmployeeNameLength()
from
OrderArrival[now] as currentOrder,
TABLE(getDetailsByOrderIdName@JdbcCartridgeOne(
currentOrder.orderId, currentOrder.empName
) as orderInfo
) as details
)
></query>
</rules>
</processor>
You must wrap the Oracle Stream Analytics JDBC data cartridge context function invocation in an Oracle CQL query TABLE
clause.
You access the result set using:
TABLE_CLAUSE_ALIAS
.JDBC_CARTRIDGE_FUNCTION_ALIAS
.SQL_SELECT_LIST_ALIAS
orTABLE_CLAUSE_ALIAS
.JDBC_CARTRIDGE_FUNCTION_ALIAS
.METHOD_NAME
Where:
-
TABLE_CLAUSE_ALIAS
: the outerAS
alias of theTABLE
clause. -
JDBC_CARTRIDGE_FUNCTION_ALIAS
: the innerAS
alias of the JDBC cartridge context function. -
SQL_SELECT_LIST_ALIAS
: the JDBC cartridge context functionSELECT
list alias. -
METHOD_NAME
: the name of the method that thereturn-component-type
class provides.
You access the JDBC cartridge context function result set in the Oracle CQL query using:
details.orderInfo.employeeName details.orderInfo.employeeEmail details.orderInfo.description details.orderInfo.getEmployeeNameLength()
The component type of the collection type returned by the JDBC data cartridge function is defined by the function
element return-component-type
child element. Because the function is always called from within an Oracle CQL TABLE
clause, it always returns a collection type.
You can access both fields and methods of the return-component-type
in an Oracle CQL query.
package com.oracle.cep.example.jdbc_cartridge; public class RetEvent { String employeeName; String employeeEmail; String description; /* Default constructor is mandatory */ public RetEvent1() {} /* May contain getters and setters for the fields */ public String getEmployeeName() { return this.employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } ... /* May contain other helper methods */ public int getEmployeeNameLength() { return employeeName.length(); } }
This class provides helper methods, like getEmployeeNameLength
, that you can invoke within the Oracle CQL query.
For more information, see return-component-type.
3.2.2.3 Using a Native CQL Type as a return-component-type
Following is a JDBC cartridge context that defines a function that has a native CQL type bigint
as return-component-type.
<jc:jdbc-ctx> <name>JdbcCartridgeOne</name> <data-source>myJdbcDataSource</data-source> <function name="getOrderAmt"> <param name="inpId" type="int" /> <return-component-type>bigint</return-component-type> <!-- native CQL as return component type --> <sql><![CDATA[ SELECT getOrderAmt(:inpId) as orderAmt FROM (select :inpId as iid from dual)> </sql> </function> </jc:jdbc-ctx>
The following example shows how the getOrderAmt
function in the above example can be used in a CQL query.
<query id="q1"><![CDATA[ RStream( select currentOrder.orderId, details.orderInfo as orderAmt from OrderArrival[now] as currentOrder, TABLE(getOrderAmt@JdbcCartridgeTwo(currentOrder.orderId) as orderInfo of bigint) as details ) ></query>
Note that the alias orderInfo
itself is of type bigint
and can be accessed as details.orderInfo as orderAmt
in the select list of the CQL query.
The "of bigint" clause used inside the TABLE construct is optional. If specified, the type mentioned should match the return-component-type.