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 {
Related
I have an app where JDBC connections are pooled. This is related to my question. For simplicity let's assume I have 1 connection and I need to set a variable then reset session / context state. However the idea is not reverse / reset the 'app1_ctx' variable particularly as in the actual case users can enter many procedures that set many variables so what I need is one procedure that clears all session related variables or even restart session. (please check this question too to understand the problem )
Below is my procedure:
CREATE OR REPLACE CONTEXT app1_ctx USING app1_ctx_package;
CREATE OR REPLACE PACKAGE app1_ctx_package IS
PROCEDURE set_empno (empno NUMBER);
END;
CREATE OR REPLACE PACKAGE BODY app1_ctx_package IS
PROCEDURE set_empno (empno NUMBER) IS
BEGIN
DBMS_SESSION.SET_CONTEXT('app1_ctx', 'empno', empno);
END;
END;
Then when checking value of 'empno':
select SYS_CONTEXT ('app1_ctx', 'empno') employee_num from dual;
I get employee_num = null
To set the empno variable we run the following:
begin
APP1_CTX_PACKAGE.SET_EMPNO(11);
end;
Then when re-checking value of 'empno', I get employee_num = 11
What we need is to clear all session / package variables after this.
I try to clear session variables using RESET_PACKAGE or the below similar procedures.
begin
DBMS_SESSION.RESET_PACKAGE;
end;
begin
DBMS_SESSION.modify_package_state(DBMS_SESSION.reinitialize);
end;
begin
DBMS_SESSION.MODIFY_PACKAGE_STATE(DBMS_SESSION.FREE_ALL_RESOURCES);
end;
But then when rechecking the variable it still has the same value.
How can I achieve this?
I am not sure how use CLEAR_ALL_CONTEXT procedure.
dbms_session.clear_all_context( 'app1_ctx' );
You'd need to pass the same namespace to clear_all_context that you passed as the first parameter to set_context.
If you don't know all the contexts your application uses but you do know all the schemas it uses
for ctx in (select *
from dba_context
where schema in (<<schemas your application uses>>))
loop
dbms_session.clear_all_context( ctx.namespace );
end loop;
In this example, there are no package variables so there would be no need to call reset_package or modify_package_state.
I'm trying to define a java (written in Kotlin) method that returns multiple result sets when called as a stored procedure. Code is below. the Hsqldb website;s features page indicates that this should be possible, what am I missing? I currently get an array out of bounds error on index 1:
val createProcedure = """
CREATE PROCEDURE GET_CACHED(dir VARCHAR(100), hashCode INT)
MODIFIES SQL DATA
LANGUAGE JAVA
DYNAMIC RESULT SETS 9
EXTERNAL NAME 'CLASSPATH:integration.FileCache.getResultSets'
"""
#JvmStatic
#Throws(SQLException::class)
public fun getResultSets(conn: Connection, dir: String, hashCode: Int, result: Array<ResultSet?>) {
val file = getFile(dir, hashCode, "sql")
//A list of cached sql statements
val sqlList = BufferedReader(InputStreamReader(file.inputStream())).readLines()
val stmt = conn.createStatement()
for(i in sqlList.indices) {
result[i] = stmt.executeQuery(sqlList[i])
}
}
Given that I can set a breakpoint and reach the inside of the function, I don't think I need to add any more of my code, but if that is wrong let me know.
I'm in a quest to find an in-memory database that can handle multiple result sets for testing purposes (We're modernizing an application, setting up tests first, containerized testing is currently out of reach). I've tried H2, sqlite, and now hsqldb, if there's a better solution I'm open to it.
HSQLDB supports multiple result test, but the Guide states :HyperSQL support this method of returning single or multiple result sets from SQL/PSM procedures only via the JDBC CallableStatement interface. Note the reference to SQL/PSM, rather than SQL/JRT. Currently there is no Java mechanism to return multiple result sets from a Java language PROCEDURE.
For test purposes, you could use a text template consisting of an SQL/PSM CREATE PROCEDURE statement written in SQL, with placeholders for the actual SQL statements that you want to execute. Process the template with your test SQL statements from your file and execute the resulting CREATE PROCEDURE statement.
I'm using the statement below to update/insert some data to a table and, if I run it without parameters, it's fine. However, as soon as I try to execute it using parameters it throws:
SQL0418N - A statement contains a use of an untyped parameter marker, the DEFAULT keyword, or a null value that is not valid.
I've read the error information here, but I'm still struggling with why my statement won't execute.
--This statement works
MERGE Into AB.Testing_Table A
USING (VALUES('TEST', 'P')) B(TEST_ID, "ACTION")
ON (A.TEST_ID = B.TEST_ID)
WHEN NOT MATCHED THEN
INSERT (TEST_ID, "ACTION")
VALUES ('TEST', 'P')
WHEN MATCHED THEN
UPDATE SET TEST_ID = 'TEST'
,"ACTION" = 'P';
--This statement fails with error SQL0418N
MERGE Into AB.Testing_Table A
USING (VALUES(#TEST, #ACTION)) B(TEST_ID, "ACTION")
ON (A.TEST_ID = B.TEST_ID)
WHEN NOT MATCHED THEN
INSERT (TEST_ID, "ACTION")
VALUES (#TEST, #ACTION)
WHEN MATCHED THEN
UPDATE SET TEST_ID = #Test
,"ACTION" = #Action;
Thanks in advance for the help!
Basically, DB2 doesn't know what data types you're sending in on those parameters. I'm guessing you're either on an older version of DB2 (less than 9.7 on Linux/Unix/Windows, or on a Mainframe version older than 10.1), which doesn't do a whole lot of "automatic" type conversion. Or you're sending in NULL values (which still have to be "typed", strange as it sounds).
You can fix the problem by creating your parameter markers as typed parameters (I'm assuming data types here, use what would be appropriate):
MERGE INTO AB.TESTING_TABLE A
USING (VALUES (
CAST(#TEST AS CHAR(4))
,CAST(#ACTION AS CHAR(1))
)) B(TEST_ID, "ACTION")
ON (A.TEST_ID = B.TEST_ID)
WHEN NOT MATCHED THEN
INSERT (TEST_ID, "ACTION")
VALUES (B.TEST_ID, B.ACTION)
WHEN MATCHED THEN
UPDATE SET "ACTION" = B.ACTION
Additionally, since you're using the MERGE, you don't have to use parameters in the UPDATE or INSERT parts, you can refer to the values in the USING table you passed in. Also, since you're matching on TEST_ID, you don't need to include that in your UPDATE statement, since it wouldn't be updated, anyway.
I have a PL/SQL function that is called from our Java code.
I have the SQL_ID of the PL/SQL function execution and I have access to V$ views on my read-only DB user. The query takes quite some time to execute? Is there a way to profile the PL/SQL function execution to check where exactly the execution is stuck?
I know how to do this for SQL queries with V$SQL, V$ACTIVE_SESSION_HISTORY and V$SESSION_LONGOPS, but I am unable to figure out how to do this for PL/SQL code.
The PL/SQL function takes 4 minutes to execute, so I can execute quite a few V$ queries manually in that time. What V$ views should I check to find a line in the execution plan/function? Is this even possible?
Maybe you can use DBMS_PROFILER for your problem. But if you want to use this method, you have to install some infrastructure.
I don't want to describe the process how to install "proftab.sql", this link shows how it works.
It also shows some quick examples how to trace a specific function.
I can provide my version of the analyze-query after some testing:
select ppr.runid,
ppr.run_comment1,
decode(nvl(ppd.total_occur, 0), 0, 0, ppd.total_time / ppd.total_occur / 1000000) as Avg_msek,
ppd.total_time / 1000000 totaltime_msek,
ppd.total_occur,
uc.name,
uc.line,
uc.text as Source
from plsql_profiler_data ppd, plsql_profiler_units ppu, user_source uc, plsql_profiler_runs ppr
where ppd.runid = ppu.runid
and ppu.runid = ppr.runid
-- and ppr.run_comment1 = 'MYTEST' --show only a specific testrun
-- and ppr.runid = (select max(runid) from plsql_profiler_runs) /*to get the last run*/
and ppd.unit_number = ppu.unit_number
and ppu.unit_name = uc.name
and ppd.line#(+) = uc.line
and uc.type in ('PACKAGE BODY', 'TYPE BODY')
--order by uc.name, uc.line; --Show all code by line
--order by totaltime_msek desc; --Sort by slowest lines
order by total_occur desc, avg_msek desc --Sort by calls and slowest ones
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!