Use Java functions with Apache Derby - java

I've encountered problems with using functions in Apache Derby, in that I can't get Derby to find my self-defined functions. The typical error message looks like this:
The class 'de.uniba.kinf.projm.hylleblomst.database.sql.utils.GroupConcat' does not exist or is inaccessible.
This can happen if the class is not public.
The documentation states that the method must be public and static. This is what I want to use:
package de.uniba.kinf.projm.hylleblomst.database.sql.utils;
public final class GroupConcat {
public static String groupConcat(String separator, String... arguments) {
StringBuilder result = new StringBuilder("");
for (String arg : arguments) {
result.append(arg + separator + " ");
}
result.delete(result.length() - 2, result.length());
return result.toString();
}
}
Basically I just want to add the GroupConcat functionality to the database which is not provided in Derby by standard. The statement I use to add the function to the DB is this:
CREATE FUNCTION SQL_UTIL.GROUP_CONCAT
( SEPARATOR CHAR, ARGS VARCHAR(255) ... )
RETURNS VARCHAR(2000)
PARAMETER STYLE DERBY
NO SQL LANGUAGE JAVA
EXTERNAL NAME 'de.uniba.kinf.projm.hylleblomst.database.sql.utils.GroupConcat.groupConcat'
I've also packed the GroupConcat class in a jar and added it to the classpath where Derby should be able to find it and added it to the database directly. Here's what I did:
The .jar lies in the lib-folder of the project, it is also part of the build path (I'm using Eclipse). Its entry in the CLASSPATH-file of the project looks like this:
<classpathentry kind="lib" path="lib/groupConcat.jar"/>
And for good measure and some desperation I've also added it to my system's classpath:
. ; ..;%DERBY_HOME%\lib\derby.jar;%DERBY_HOME%\lib\derbytools.jar;C:\Users\workspace\kinf-workspace\General\lib
My error is probably very trivial, but I'm quite new to Derby and databases in general, so I'd appreciate any help.
Thanks in advance!

The problem turned out to be more specific to Eclipse and in its nature trivial. Although the jar containing the Java-class already was in the classpath, Eclipse did not add the jar to the run configurations. Apparently, the classpath is passed on to Derby from there and then of course it can't find the class. So all there was to do was packing the class containing the method in question into a jar, adding it to the project's library, add it to the Run Configuration's classpath and run it.
Lessons learned: Never trust your IDE to do (all of) your work.

I'm not totally sure what's going wrong with your case, but I'd continue to review and check the CLASSPATH and package name handling in your build process.
I took your code, edited out the package statement, and used it in a very trivial example, successfully (as far as I can tell):
C:\Users\Bryan\derby\tests\jfunc>vim GroupConcat.java
C:\Users\Bryan\derby\tests\jfunc>javac GroupConcat.java
Directory of C:\Users\Bryan\derby\tests\jfunc
07/11/2015 08:53 AM 832 GroupConcat.class
07/11/2015 08:53 AM 440 GroupConcat.java
C:\Users\Bryan\derby\tests\jfunc>java -cp \users\bryan\derby\trunk\jars\sane\derbyrun.jar;. org.apache.derby.tools.ij
ij version 10.12
ij> connect 'jdbc:derby:brydb;create=true';
ij> CREATE FUNCTION SQL_UTIL.GROUP_CONCAT
( SEPARATOR CHAR, ARGS VARCHAR(255) ... )
RETURNS VARCHAR(2000)
PARAMETER STYLE DERBY
NO SQL LANGUAGE JAVA
> > > > > EXTERNAL NAME 'GroupConcat.groupConcat';
0 rows inserted/updated/deleted
ij> create table t1 (a int, b int);
0 rows inserted/updated/deleted
ij> insert into t1 values (1, 2);
1 row inserted/updated/deleted
ij> select sql_util.group_concat(a,b) from t1;
ERROR 42821: Columns of type 'CHAR' cannot hold values of type 'INTEGER'.
ij> create table t2 (a varchar(10), b varchar(10));
0 rows inserted/updated/deleted
ij> insert into t2 values ('a', 'b');
1 row inserted/updated/deleted
ij> select sql_util.group_concat(a,b) from t2;
1
--------------------------------------------------------------------------------
b
1 row selected
Now, I expect that you probably expected to see 'ab' as the result, but that's a different issue, I believe, and is probably because I didn't pass a value for 'separator' when I ran your function.
Possibly, running your program with
java -verbose:class
will help you figure out if Derby is simply looking in the wrong place for your class. (A tool like MSDN's ProcessMonitor might also be useful for that)
Good luck, and let us know what you find!

Related

ORA-06502: PL/SQL: numeric or value error when using TO_BINARY_DOUBLE with JDBC

I have a small snippet of code that grabs some data and generates SQL statements to insert them in an Oracle database. These are then executed via a JDBC driver on the Oracle server.
The issue I am running into is that if these statements contain a TO_BINARY_DOUBLE call they always fail for me and not for anyone else in my team, which supposedly have the exact same driver and environment as I do, which is incredibly strange.
CREATE TABLE "SOME_TABLE" (
"_id" BINARY_DOUBLE NOT NULL,
"double" BINARY_DOUBLE,
PRIMARY KEY ("_id")
);
DECLARE
"#value__id" BINARY_DOUBLE;
"#value_double" BINARY_DOUBLE;
BEGIN
"#value__id" := TO_BINARY_DOUBLE('0.0');
"#value_double" := TO_BINARY_DOUBLE('1.2');
INSERT INTO "SOME_TABLE" ("_id", "double")
VALUES(
"#value__id",
"#value_double"
);
END;
And the error:
Unable to execute SQL statement batch: error occurred during batching: ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 5
Hoping someone could shed some light on the source, or point me in the right direction to try find it.
You appear to have different NLS settings to your colleagues; specifically NLS_NUMERIC_CHARACTERS. With that set to '.,' the code works; with it set to ',.' (i.e. expecting a comma as the decimal separator, rather than a period) it throws the error you see.
You can either change your Java environment to match your colleagues', which will probably involve changing the locale, either of your PC or via JVM flags; or override it in the function call:
"#value__id" := TO_BINARY_DOUBLE('0.0', '999D999', 'nls_numeric_characters=''.,''');
"#value_double" := TO_BINARY_DOUBLE('1.2', '999D999', 'nls_numeric_characters=''.,''');
using a format mask that covers whatever string values you might have to deal with - I'm guessing that those values would normally come from a user or a procedure argument. Of course, this then assumes that the string values will always have a period as the decimal separator.
db<>fiddle

tracing a sql server stored procedure not appearing in profiler

I am trying to trace the execution of a sql server stored procedure that gets executed from within a large java application. I first changed the stored procedure to complete the task I needed to do and I tested within sql server and it worked fine, with all triggers working too. However, when I apply the changes and run the code it seems like the changed stored procedure is not executed but just the original version. I tried to use profile to trace the execution but the weird thing is that it does not appear. Again testing the inserts manually does then show the procedure in profiler.
I tried to trace the code that implements this procedure, found it and wrote some trace comments to tag the execution but again the class trace commenting does not occur. As if the class does not get called. I have added the procedure just in case someone sees a fault but like I said it works fine testing in SQL server.
BEGIN
DECLARE #KeepStoreLingerTime int
DECLARE #KeepDeleteLingerTime int
DECLARE #StoreActionID int
DECLARE #insertedID int;
IF #TimeToExecute IS NULL
BEGIN
SELECT #KeepStoreLingerTime = [Value] FROM SystemProperty WHERE [Name] = 'KeepStoreLingerTimeInMinutes'
SELECT #KeepDeleteLingerTime = [Value] FROM SystemProperty WHERE [Name] = 'KeepDeleteLingerTimeInMinutes'
IF (#KeepDeleteLingerTime >= #KeepStoreLingerTime) SET #KeepStoreLingerTime = #KeepDeleteLingerTime+1
SET #TimeToExecute = dateadd(mi, #KeepStoreLingerTime, getutcdate())
END
SELECT #StoreActionID = [ID] FROM StoreActionQueue
WHERE Parameter=#Parameter AND StorageRuleID=#StorageRuleID AND StoreFlags=#StoreFlags
IF #StoreActionID IS NOT NULL AND #StoreFlags != 11
BEGIN
UPDATE StoreActionQueue SET FilterID = #FilterID WHERE [ID] = #StoreActionID
END
ELSE
BEGIN
INSERT INTO StoreActionQueue (TimeToExecute, Operation, Parameter, StorageRuleID, FilterID, StoreFlags)
SELECT #TimeToExecute, #Operation, #Parameter, #StorageRuleID, #FilterID, #StoreFlags FROM Call WHERE [ID]=#Parameter AND Active=0
AND (OnlineCount>0 OR OnlineScreenCount>0 OR (Flags&POWER(2,26)=POWER(2,26))) --bit26 indicates META-DATA-ONLY
---- INSERT if a row is successfully inserted
IF ##ROWCOUNT > 0
IF #StoreFlags = 11
BEGIN
INSERT INTO StoreActionQueue (TimeToExecute, Operation, Parameter,
StorageRuleID, FilterID, StoreFlags)
SELECT DATEADD(mi, 2, GETUTCDATE()), #Operation, #Parameter,
#StorageRuleID, #FilterID, 9 FROM Call
WHERE [ID]=#Parameter AND Active=0
END
END
END
Is there a way to log anything from lets say within the procedure to a file? In java (eclipse) other than looking at call hierarchy etc. is there a suggestion on how to match where the class gets called.
public class ProcessingController extends TimeController implements
TimeObserver {

Hive throws an error while creating table "Cannot validate serde: com.cloudera.hive.serde.JSONSerDe"

Working on apache-hive-0.13.1.
while creating table hive throw an error as below
FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. Cannot validate serde: com.cloudera.hive.serde.JSONSerDe
table structure is
create external table tweets(id BigInt, created_at String, scource String, favorited Boolean, retweet_count int,
retweeted_status Struct <
text:String,user:Struct<
screen_name:String, name:String>>,
entities Struct<
urls:Array<Struct<
expanded_url:String>>,
user_mentions:Array<Struct<
screen_name:String,
name:String>>,
hashtags:Array<Struct<text:String>>>,
text String,
user Struct<
screen_name:String,
name:String,
friends_count:int,
followers_count:int,
statuses_count:int,
verified:boolean,
utc_offset:int,
time_zone:String> ,
in_reply_to_screen_name String)
partitioned by (datehour int)
ROW FORMAT SERDE 'com.cloudera.hive.serde.JSONSerDe'
location '/home/edureka/sachinG'
Added a json-serde-1.3.6-SNAPSHOT-jar-with-dependencies.jar in class to resolved the issue but no success
Finally , got a solution for this. The issue is with json-serde-1.3.6-SNAPSHOT-jar-with-dependencies.jar
Different distribution (Cloudera, Azure, etc ) needed different JSON-Serde jar file. Means, serde jar should be compatible to there distribution.
I changed jar and it worked for me.
I faced a similar issue while working with hive 1.2.1 and hbase 0.98. I followed below steps and the issue was resolved.
1) Copied all the hbase-* files from hbase/lib location to hive/lib directory
2) Verified that the hive-hbase-handler-1.2.1.jar was present in hive/lib
3) Verified that hive-serde-1.2.1.jar was present in hive/lib
4) Verified that zookeeper-3.4.6.jar was present in hive/lib(If not copy from hbase/lib and paste to hive/lib)
5) In the hive-site.xml(If not present use hive-default.xml.template) located at hive/conf under 'both'
a) hive.aux.jars.path field and
b) hive.added.jars.path field
give path '/usr/local/hive/lib/'.
6) Open hive terminal and create the table using below command:-
CREATE TABLE emp_hive (
RowKey_HIVE String,
Employee_No int,
Employee_Name String,
Job String,
Mgr int,
Hiredate String,
Salary int,
Commision int,
Department_No int
)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" =":key,details:Employee_No_hbase,details:Employee_Name_hbase,details:job_hbase,details:Mgr_hbase,details:hiredate_hbase,details:salary_hbase,details:commision_hbase,details:department_no_hbase")
TBLPROPERTIES("hbase.table.name"="emp_hbase");

postgres migration error; unterminated dollar-quoted string

Well this is abit strange, could anyone help me point out where this function may be wrong.
I have a function similar to
CREATE FUNCTION check_password(uname TEXT, pass TEXT)
RETURNS BOOLEAN AS $$
DECLARE passed BOOLEAN;
BEGIN
SELECT (pwd = $2) INTO passed
FROM pwds
WHERE username = $1;
RETURN passed;
END;
$$ LANGUAGE plpgsql
When i run it directly in the pgAdmin sql console, there are no errors but running it in a migration script using db-migration-maven-plugin i get the error.
Error executing: CREATE FUNCTION check_password(uname TEXT, pass TEXT)
RETURNS BOOLEAN AS $$ DECLARE passed BOOLEAN
org.postgresql.util.PSQLException: ERROR: unterminated dollar-quoted
string at or near "$$ DECLARE passed BOOLEAN"
Position: 74
The SQL generated by your migration scripts probably have some kind of $$ quotes in them that gets interpreted as a string somewhere.
A quick and dirty fix could be to change $$ to $func$ or even $check_password$, though there might be other functions further down that suffer the same problem.
The better, more long term approach will be to locate the offending $$.
#ivanorone: There is a bug filed for db-migration-maven-plugin: https://code.google.com/p/c5-db-migration/issues/detail?id=9
There is a patch included but looking at its source, it doesn't really fix the problem properly. Besides that, the project seems to be idling (last commit 2010).
There is another plugin, that I am trying to use instead, Flyway: http://flywaydb.org/ Switching to it was pretty easy and it works fine so far.
Execute your query as single batch(Hint: USE ctrl+F5).When I ran your query in Postgres SQl (Greenplum Interface) I got similiar error as u stated above. I found that db is executing query by splitting it based on termination in our query(Semicolon). As we you have terminated thrice in your query, It executes it one by one statement. So, to execute it as a whole batch run as using execute as single batch in your execution option.
I hope it helps you:):)
Solution for Grails Database Migration Plugin
changeSet(author: "...", id: "...") {
sql(splitStatements: false, '''
CREATE FUNCTION trigger_func() RETURNS TRIGGER AS $$
DECLARE var text;
BEGIN
...
END $$ LANGUAGE plpgsql;
''')
}
The best solution seems to be to tell the plugin to only accept the semicolon as a delimiter when it's on a new line.
This works well where you need to define code blocks like this.
Ref: sql-maven-plugin with multiple delimiters

Cannot Execute Stored Procedure using JDBC

I use sybase database and am trying to update some values into the database.
While trying to run this it throws an exception as :
com.sybase.jdbc2.jdbc.SybSQLException: The identifier that starts with 'WeeklyStudentEventClassArchiv' is too long. Maximum length is 30.
This table is in another database and thus i have to use the database name along with the table name as dhown below:
StudActive..WeeklyStudentEventClassArchiv which apparently exceeds 30 characters.
I have to use the databasename..tablename in the stored procudure but its throwing an exception.
This happens even if i physically embed the sql in the java code.
How can this be solved.
The Stored Procedue is as shown:
create proc dbo.sp_getStudentList(
#stDate int,
#endDate int
)
as
begin
set nocount on
select distinct studCode
StudActive..WeeklyStudentEventClassArchive
where studCode > 0
and courseStartDate between #stDate and #endDate
end
StudActive..WeeklyStudentEventClassArchiv which apparently exceeds 30
characters.
Yes - I count 41.
Rename the table and/or the stored proc and you should be fine. It wounds like a limitation of either the JDBC driver or the database.
Your JDBC driver is out of date. Updating to a later version might help solve your problem.
First download a more recent jConnect driver from the Sybase website. Then update your code to use the new driver package. You will also need to change your code, as the package name of the driver changes for each new version of the specification. (The current package is com.sybase.jdbcx...)
Take a look at the programmers reference for more information.

Categories

Resources