Oracle DB Java Stored Procedure: line starting with hash sign # - oracle

I have inherited an old Oracle 12c database, which I'm running on a local Oracle 19c server. The database contains the following Java Stored Procedure
create or replace and compile java source named fill_share_content as
import java.io.*;
import java.sql.*;
public class Fill_Share_Content
{
public static void execute(String directory) throws SQLException
{
File path = new File( directory );
String[] list = path.list();
String separator = path.separator;
for(int i = 0; i < list.length; i++)
{
String filename = list[i];
File datei = new File( directory + separator + filename );
if ( datei.isFile() )
{
Timestamp filedate = new Timestamp( datei.lastModified() );
#sql { insert into Share_Content (filename, filedate) values (:filename, :filedate) };
}
}
}
};
/
The problem occurs when attempting to execute the statement to create and compile the Java SP: line 20
#sql { insert into Share_Content (filename, filedate) values (:filename, :filedate) };
throws an error
error: illegal character: '#'
Generally I am able to create, compile and execute Java Stored Procedures on the database. Questions:
What is the meaning of the line starting with the hash sign? I am not familiar with such a construct in Java, something specific to Java stored procedures in Oracle?
How can I get I create and compile the Java stored procedure? Allegedly the code is already running on another instance, so the code should work.

The code is SQLJ and is documented here.
However, from Oracle 12.2, Oracle does not support running SQLJ.
You need to convert the SQLJ code to JDBC if you want to run it in Oracle 19.
This should give you a start:
CREATE AND COMPILE JAVA SOURCE NAMED fill_share_content as
import java.io.*;
import java.sql.*;
import oracle.jdbc.driver.OracleDriver;
public class Fill_Share_Content
{
public static void execute(String directory) throws SQLException
{
Connection con = null;
try {
OracleDriver ora = new OracleDriver();
con = ora.defaultConnection();
} catch (SQLException e) {
return;
}
Timestamp filedate = new Timestamp(System.currentTimeMillis());
PreparedStatement ps = con.prepareStatement(
"insert into Share_Content (filename, filedate) values (:filename, :filedate)"
);
ps.setString(1, directory);
ps.setTimestamp(2, filedate);
ps.execute();
}
};
/
db<>fiddle here

Related

How to create a dummy function in H2 embbeded db for integration test

I have a spring boot application that connects to an oracle database. The project contains a service class (userService) that calls the function VALIDATEUSER(USERNAME IN VARCHAR2,PASSWD IN VARCHAR2) in oracle and return 1 if user is valid and 0 invalid.
I need to create the same function in h2 db that always return true for my integration test.
Basically I wanted to created the function in sql script and load it during integration test as follows:
#Test
#Sql(scripts={"classpath:/sql/createFunction.sql"})
public void testUserInfo() throws Exception {
// userService calls VALIDATEUSER function
userService.isUserValid("testdb", "testdb");
}
How to create the function VALIDATEUSER in h2?
Thanks in advance.
You can execute the following SQL in H2 to create a function that accepts two VARCHAR parameters and returns an INTEGER result 1.
CREATE ALIAS VALIDATEUSER AS $$int validateUser(String name, String password) { return 1; }$$
Try this
CREATE ALIAS functionName AS 'int methodName(String name, String password) { return 1; }'
in Java you can use like this
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection(
"jdbc:h2:mem:", "sa", "");
Statement stat = conn.createStatement();
// Using a custom Java function
stat.execute("CREATE ALIAS functionName AS 'int methodName(String name, String password) { return 1; }' ");
stat.close();
conn.close();

"ALTER TABLE IF EXISTS t1 RENAME TO t2" in HiveQL?

I want to rename a Hive table if it exists, and not generate an error if it doesn't.
I need something like
ALTER TABLE IF EXISTS t1 RENAME TO t2;
but this doesn't run ("cannot recognize input near 'if' 'exists' 'rename' in alter table statement"), and neither do the variations that I've tried. This isn't covered in the docs (https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-RenameTable), maybe because it's not possible.
Does anyone know how to do this, or a workaround (e.g. try/catch, if it existed in Hive)?
I'm on Hive 1.2.
IF EXIST clause does not work in Hive CLI as of now. You can write program something like below for condition checking.
public class HiveAlterRenameTo {
private static String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver";
public static void main(String[] args) throws SQLException {
// Register driver and create driver instance
Class.forName(driverName);
// get connection
Connection con = DriverManager.getConnection("jdbc:hive://localhost:10000/userdb", "", "");
// create statement
Statement stmt = con.createStatement();
// execute statement
Resultset res = stmt.executeQuery("SELECT count(*) FROM <Table_name> ;");
if (res > 0) {
// execute statement
stmt.executeQuery("ALTER TABLE employee RENAME TO emp;");
System.out.println("Table Renamed Successfully");
}
else {
System.out.println("Table Not exist");
}
con.close();
}

How to run JDBC update query without knowing column type

I have to run a jdbc update query using preparedstatement/statement without knowing the column type.
I have a query say ' update table set status=? where id=? '
and i am getting a map of values like {("status"="123"), ("id"="546")}
Now I don't know the column type, is there any generic way to run this query using jdbc?
Instead of running - ps.setString(1,map.get(("status"));
beacause i don't know the column type of status field in DB (it may be a int also)
Please help me in solving this without using spring jdbc templates.
ps.setString(1,map.get(("status")) will work for integer also, you just has to take care that value you are putting in integer column is of int type.
Following code explains that:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class SOJDBC
{
public static void main(String rgs[])
{
Connection con = DBConnection.getConnection("TEMP");
try
{
PreparedStatement pstmt = con.prepareStatement("insert into STUDENT(ROLLNO,NAME,AGE) values(?,?,?)");
pstmt.setString(1, "1"); //column type is integer, will work because the value is of int type
pstmt.setString(2, "Bhushan");
pstmt.setString(3, "25"); //column type is integer, will work because the value is of int type
pstmt.executeUpdate();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}

NHib 3 Configuration & Mapping returning empty results?

Note: I'm specifically not using Fluent NHibernate but am using 3.x's built-in mapping style. However, I am getting a blank recordset when I think I should be getting records returned.
I'm sure I'm doing something wrong and it's driving me up a wall. :)
Background / Setup
I have an Oracle 11g database for a product by IBM called Maximo
This product has a table called workorder which lists workorders; that table has a field called "wonum" which represents a unique work order number.
I have a "reporting" user which can access the table via the maximo schema
e.g. "select * from maximo.workorder"
I am using Oracle's Managed ODP.NET DLL to accomplish data tasks, and using it for the first time.
Things I've Tried
I created a basic console application to test this
I added the OracleManagedClientDriver.cs from the NHibernate.Driver on the master branch (it is not officially in the release I'm using).
I created a POCO called WorkorderBriefBrief, which only has a WorkorderNumber field.
I created a class map, WorkorderBriefBriefMap, which maps only that value as a read-only value.
I created a console application with console output to attempt to write the lines of work orders.
The session and transaction appear to open correct,
I tested a standard ODP.NET OracleConnection to my connection string
The Code
POCO: WorkorderBriefBrief.cs
namespace PEApps.Model.WorkorderQuery
{
public class WorkorderBriefBrief
{
public virtual string WorkorderNumber { get; set; }
}
}
Mapping: WorkorderBriefBriefMap.cs
using NHibernate.Mapping.ByCode;
using NHibernate.Mapping.ByCode.Conformist;
using PEApps.Model.WorkorderQuery;
namespace ConsoleTests
{
public class WorkorderBriefBriefMap : ClassMapping<WorkorderBriefBrief>
{
public WorkorderBriefBriefMap()
{
Schema("MAXIMO");
Table("WORKORDER");
Property(x=>x.WorkorderNumber, m =>
{
m.Access(Accessor.ReadOnly);
m.Column("WONUM");
});
}
}
}
Putting it Together: Program.cs
namespace ConsoleTests
{
class Program
{
static void Main(string[] args)
{
NHibernateProfiler.Initialize();
try
{
var cfg = new Configuration();
cfg
.DataBaseIntegration(db =>
{
db.ConnectionString = "[Redacted]";
db.Dialect<Oracle10gDialect>();
db.Driver<OracleManagedDataClientDriver>();
db.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
db.BatchSize = 500;
db.LogSqlInConsole = true;
})
.AddAssembly(typeof(WorkorderBriefBriefMap).Assembly)
.SessionFactory().GenerateStatistics();
var factory = cfg.BuildSessionFactory();
List<WorkorderBriefBrief> query;
using (var session = factory.OpenSession())
{
Console.WriteLine("session opened");
Console.ReadLine();
using (var transaction = session.BeginTransaction())
{
Console.WriteLine("transaction opened");
Console.ReadLine();
query =
(from workorderbriefbrief in session.Query<WorkorderBriefBrief>() select workorderbriefbrief)
.ToList();
transaction.Commit();
Console.WriteLine("Transaction Committed");
}
}
Console.WriteLine("result length is {0}", query.Count);
Console.WriteLine("about to write WOs");
foreach (WorkorderBriefBrief wo in query)
{
Console.WriteLine("{0}", wo.WorkorderNumber);
}
Console.WriteLine("DONE!");
Console.ReadLine();
// Test a standard connection below
string constr = "[Redacted]";
OracleConnection con = new OracleConnection(constr);
con.Open();
Console.WriteLine("Connected to Oracle Database {0}, {1}", con.ServerVersion, con.DatabaseName.ToString());
con.Dispose();
Console.WriteLine("Press RETURN to exit.");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("Error : {0}", ex);
Console.ReadLine();
}
}
}
}
Thanks in advance for any help you can give!
Update
The following code (standard ADO.NET with OracleDataReader) works fine, returning the 16 workorder numbers that it should. To me, this points to my use of NHibernate more than the Oracle Managed ODP.NET. So I'm hoping it's just something stupid that I did above in the mapping or configuration.
// Test a standard connection below
string constr = "[Redacted]";
OracleConnection con = new Oracle.ManagedDataAccess.Client.OracleConnection(constr);
con.Open();
Console.WriteLine("Connected to Oracle Database {0}, {1}", con.ServerVersion, con.DatabaseName);
var cmd = new OracleCommand();
cmd.Connection = con;
cmd.CommandText = "select wonum from maximo.workorder where upper(reportedby) = 'MAXADMIN'";
cmd.CommandType = CommandType.Text;
Oracle.ManagedDataAccess.Client.OracleDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader.GetString(0));
}
con.Dispose();
When configuring NHibernate, you need to tell it about your mappings.
I found the answer -- thanks to Oskar's initial suggestion, I realized it wasn't just that I hadn't added the assembly, I also needed to create a new mapper.
to do this, I added the following code to the configuration before building my session factory:
var mapper = new ModelMapper();
//define mappingType(s) -- could be an array; in my case it was just 1
var mappingType = typeof (WorkorderBriefBriefMap);
//use AddMappings instead if you're mapping an array
mapper.AddMapping(mappingType);
//add the compiled results of the mapper to the configuration
cfg.AddMapping(mapper.CompileMappingForAllExplicitlyAddedEntities());
var factory = cfg.BuildSessionFactory();

Jython zxJDBC cursor.tables() always returns None

I am using Jython 2.2.1 and MySQL Connector/J 5.1 to access a MySQL database. I would like to use zxJDBC's cursor.tables() method to retrieve a list of tables in that database. However, this method always returns None.
According to the zxJDBC documentation, cursor.tables() is the same as Java's DatabaseMetaData.getTables(). When I call this Java method from Jython, it works as expected, but using the zxJDBC package doesn't work for me. Here's what I have tried:
import java.sql.*;
public class TableTest {
public static void tables(String url) {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, "root", null);
DatabaseMetaData meta = conn.getMetaData();
ResultSet rs = meta.getTables(null, null, "%",
new String[] {"TABLE"});
while (rs.next()) {
System.out.println(rs.getString("TABLE_NAME"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
When I call this from Jython, it is all fine.
from com.ziclix.python.sql import zxJDBC
import TableTest
url = 'jdbc:mysql://localhost/jythontest'
print 'Java:'
TableTest.tables(url);
print 'Python:'
conn = zxJDBC.connect(url, 'root', None, 'com.mysql.jdbc.Driver')
cursor = conn.cursor()
print cursor.tables(None, None, '%', ('TABLE',))
There are two tables in my test database called 'table_a' and 'table_b'. The output is:
Java:
table_a
table_b
Python:
None
I have tried this on Linux and on MacOS with the same result. Before I try to figure out what's wrong with zxJDBC, I wanted to know whether there is anything wrong in the way I am using this package.
Thank you.
Try a print cursor.fetchall() after your cursor.tables()
from com.ziclix.python.sql import zxJDBC
import TableTest
url = 'jdbc:mysql://localhost/jythontest'
print 'Java:'
TableTest.tables(url);
print 'Python:'
conn = zxJDBC.connect(url, 'root', None, 'com.mysql.jdbc.Driver')
cursor = conn.cursor()
print cursor.tables(None, None, '%', ('TABLE',))
print cursor.fetchall()
(tested with Informix and jython 2.5 beta)
i assume:
cursor.tables() excutes the query in
python
cursor.fetchall() returns the
results

Resources