I am attempting to call the following ANT task
<target name="sqlcall" description="SQLGETTYPEINFO">
<sql
classpath="${sql.classpath}"
driver="${sql.driver}"
url="${sql.url}"
userid="${user.name}"
password="${sql.password}"
print="true"
>
CALL SYSIBM.SQLGETTYPEINFO(1,'');
</sql>
</target>
but ANT is throwing an exception
build.xml:69: com.ibm.db2.jcc.am.SqlSyntaxErrorException:
[jcc][10413][10940][3.63.75] Literal replacement parsing failed for procedure call to DB2 for z/OS.
Failing SQL text CALL SYSIBM.SQLGETTYPEINFO(1,'').
ERRORCODE=-4463, SQLSTATE=42601 at com.ibm.db2.jcc.am.fd.a(fd.java:679)
. . .
I know the root cause is that this needs to use the CallableStatement form. Unfortunately, this is not exposed by the SQL task. Is there a workaround?
Related
I am using DB2 11.5.
I have a stored procedure that will run some complex tasks.
Before running the tasks, it will first check from a log table if the job is already running, if yes, it signal for SQLSTATE 75002 with error meesage.
If it is not already running, it will insert a record of the job with status RUNNING, then run the tasks.
When it finishes, it update the status to FINISHED.
CREATE OR REPLACE PROCEDURE WORK.TEST_SP()
P1: BEGIN
if exists(select 1 from db2inst1.job_log where job='abc' and status='RUNNING' and date=current date) then
SIGNAL SQLSTATE '75002' SET MESSAGE_TEXT = 'Job abc is already running, please wait for it to finish';
end if;
insert into db2inst1.job_log values ('abc', 'RUNNING', current date);
commit;
-- Some complex tasks here
call dbms_lock.sleep(120);
update db2inst1.job_log set job_status='FINISHED' where job_name='abc' and job_date=current date
commit;
END P1
My question is how do I handle sigint when user press ctrl-c that aborted the stored procedure when the complex tasks are running?
I want it to update the job_status to ABORTED when ctrl-c occurs so that the job will not be "running" forever.
#Edit 1
Users run the stored procedure with a windows .bat file on local machine with db2 client installed.
#echo off
#if ""%DB2CLP%""=="""" db2cmd /c /i /w ""%0"" && goto :EOF
db2 connect to mydb user db2inst1 using abc123
db2 "call WORK.TEST_SP()"
IF ERRORLEVEL 1 (echo Job failed) else (echo Job done)
db2 connect reset > nul
pause
If your MS-Windows batch file gets interrupted by a Control-C or other signal, then any already started/running stored-procedures invoked by that app will continue running by default. The stored procedure will be unaware that the client application has terminated. So your batch file (cmd/bat) will terminate but any currently running stored procedure will continue to execute on the Db2-server.
You cannot send operating-system signals directly to a Db2-LUW stored procedure, as they run on the Db2-server in the background and are usually owned by a different account than the userid performing the call.
Your stored-procedure should have its own condition handlers or exit handlers or undo handlers. Usually you want to issue a rollback if a hard error happens from which your procedure itself cannot recover. But Db2 itself will issue a rollback for specific sqlcodes (e.g. -911 ).
Db2-LUW also has a sysproc.cancel_work procedure which an application might use in specific situations. Refer to the Knowledge Centre for details. If WLM (workload management) or equivalent is enabled then stored procedures are subject to its configuration as regards resource consumption, and WLM also offers a wlm_cancel_activity routine.
There is no way to do this in SP.
Control is not passed to an exception handler defined in SP upon forcing a caller off the database, canceling activity and some other conditions (log full, for example).
So, don't put any flag / status management logic into SP exception handlers.
How is the stored procedure run? From the command line (db2)? If so, on what operating systems?
If, for instance, the command is run from bash on Linux, you can use trap myfunc SIGINT in Bash to run a custom Bash function myfunc if the user presses Ctrl-C. myfunc could then change the job status.
On Windows, you will have more control if you switch from plain .bat files to Powershell . Some related Stack Overflow questions:
batch script if user press Ctrl+C do a command before exiting
Gracefully stopping in Powershell
I'm trying to have a job pass in a variable for multiple emails through the command line in SQL Server ManageMent Studio however, it is throwing an error for a specific SET call. FYI, User::gEmailTo is a string in the package.
In my job creation script, I have the following -
--Declaration
:setvar EmailTo "josh#test.com; mike#test.com; earl#test.com; mark#test.com; bill#test.com"
--Syntax throwing the error:
'/SET "\package.Variables[User::gEmailTo].Value";"$(EmailTo)" '
The output in the command line for the job in SSMS shows:
/SET "\"\package.Variables[User::gEmailTo].Value\"";"\"josh#test.com; mike#test.com; earl#test.com; mark#test.com; bill#test.com\""
The error
Argument ""\package.Variables[User::gEmailTo].Value;josh#test.com; mike#test.com; earl#test.com; mark#test.com; bill#test.com"" for option "set" is not valid. The command line parameters are invalid. The step failed.
Following is a trigger:
CREATE OR REPLACE TRIGGER "CMDC"."USER_ROADS_UC"
BEFORE INSERT OR UPDATE OF
ASSOCIATED_PARENT_ROAD
ON USER_ROADS
REFERENCES NEW AS NEW
FOR EACH ROW BEGIN
:new.ASSOCIATED_PARENT_ROAD:=upper(:new.ASSOCIATED_PARENT_ROAD);
EXCEPTION
WHEN OTHERS THEN RETURN;
END;
/
ALTER TRIGGER "CMDC"."USER_ROADS_UC" ENABLE
The above runs perfectly in SQL Developer. However, when I get the following error when I run it using Ant:
[sql] Failed to execute: EXCEPTION WHEN OTHERS THEN RETURN
[sql] java.sql.SQLException: ORA-00900: invalid SQL statement
[sql] Failed to execute: END
[sql] java.sql.SQLException: ORA-00900: invalid SQL statement
[sql] Failed to execute: / ALTER TRIGGER "CMDC"."USER_ROADS_UC" ENABLE
[sql] java.sql.SQLException: ORA-00900: invalid SQL statement
I have already reviewed this question. However, I still couldn't modify the script to work with Ant.
Following is the ant target
<target name="create-db-schema" >
<echo message="############################################################"/>
<echo message="# Create Complete DB Schema #"/>
<echo message="############################################################"/>
<sql onerror="continue" classpathref="project.class.path" driver="${database.driverClassName}"
url="${database.url}" userid="${database.username}" password="${database.password}">
<path>
<fileset dir="${test.dbscripts.dir}/schema/">
<include name="*.sql"/>
</fileset>
</path>
</sql>
</target>
With ant sql tag I couldn't run both SQL and PL/SQL in the same script even though I tried in many ways.
But using an external library I could do this.I've used this library to do that dbmaintain
Add following to your build script.
<path id="dbmaintain-lib"><fileset dir="${dbmaintain.home}/lib"><include name="*.jar"/></fileset></path>
<taskdef resource="dbmaintain-anttasks.xml" classpathref="dbmaintain.lib"/>
<target name="update-db">
<updateDatabase scriptLocations="scripts" autoCreateDbMaintainScriptsTable="true">
<database driverClassName="oracle.jdbc.driver.OracleDriver" userName="user" password="pass" url="jdbc:oracle:thin:#//localhost:1521/XE" schemaNames="SCHEMA"/>
</updateDatabase>
</target>
And everthing works perfectly now without changes to sql scripts files to replace ';'.
Hope this'll help for somebody in need.
I don't have environment to test this solution. But for testing purpose you can try something like this.
<sql
driver="xxx"
url="xxx"
userid="xxx"
password="xxx"
delimiter="/"
delimitertype="row"
><![CDATA[
CREATE OR REPLACE TRIGGER "CMDC"."USER_ROADS_UC"
BEFORE INSERT OR UPDATE OF
ASSOCIATED_PARENT_ROAD
ON USER_ROADS
REFERENCES NEW AS NEW
FOR EACH ROW BEGIN
:new.ASSOCIATED_PARENT_ROAD:=upper(:new.ASSOCIATED_PARENT_ROAD);
EXCEPTION
WHEN OTHERS THEN RETURN;
END;
/
ALTER TRIGGER "CMDC"."USER_ROADS_UC" ENABLE
/
]]></sql>
Important ! Your delimiter now is "/" in new line without any surrounding whitespaces.
I am using ssis of sql 2008 trying to connect to sybase 12 using sybase 15.2 driver, i even tried sybase 12 driver and got same error
error message
[ZZZZZ]
[Message Class: 16]
[Message State: 5]
[Transaction State: 1]
[Server Name: PHXPROD]
[Native Code: 2812]
[ASEOLEDB]Stored procedure 'sp_oledb_datatype_info' not found.
Specify owner.objectname or use sp_help to check whether the object exists (sp_help may produce lots of output). (ASEOLEDB)
attached images showing that i am able to connect but soon after connecting i get the error message
Step 1
Step 2
Error message when i used ADO.NET
Look like you have to investigate more about this problem and by reading in the SyBooks Online it say:
If error 2812 occurs on system stored procedures (as your case sp_oledb_tables and sp_oledb_datatype_info) it may be resolved by running the installmaster script, which installs all system procedures and initializes various other Adaptive Server structures.
How to run the installmaster script?
Using isql, run the new installmaster script included with this release by entering:
isql -Usa -P<sa password> -S<server name> -n -i$SYBASE/$SYBASE_ASE/scripts/installmaster
-o<output file>
Reference: Running the installmaster script
Hope it help you
to execute an .sql script file from ANT it works fine using the following task:
<sql
classpath="${oracle.jar}" driver="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:###{db.hostname}:#{db.port}:#{db.sid}"
userid="#{db.user}"
password="#{db.password}"
src="#{db.sql.script}" />
But if the .sql file not only contains pure SQL but also PL/SQL the task will fail. This could be solved by using the following snippet:
<sql
classpath="${oracle.jar}" driver="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:###{db.hostname}:#{db.port}:#{db.sid}"
userid="#{db.user}"
password="#{db.password}"
delimiter="/"
delimitertype="row"
src="#{db.sql.script}" />
But if my script contains both SQL and PL/SQL then neither ANT task will work. Another solution would be to use the "exec" task with "sqlplus":
<exec executable="sqlplus" failonerror="true" errorproperty="exit.status">
<arg value="${db.user}/${db.password}#${db.hostname}:${db.port}/${db.sid}"/>
<arg value="#${db.sql.script}"/>
</exec>
But unfortunately this task will never fail, hence the build returns always with "SUCCESSFUL" even though the sql script execution failed. The error property which I tried to set would not return any error code.
Any ideas/suggestions how to solve this problem?
Thanks,
Peter
Peter,
Add at the beginning of scripts
WHENEVER SQLERROR EXIT SQL.CODE;
Then sqlplus will exit with exit code != 0.
Pretty late, I guess - but I hope this will help someone:
In general, I think we should perfer using sql rather than exec executable="sqlplus" for many reasons, such as: in case we change DB provider, you don't spend reaources in a new process with sql, "STOPPING" will work as opposed to sqlplus.exe etc.
Anyway, here's a suggestion on how to let both PL/SQL & SQL in same script so that it will work:
myScript.sql:
<copy todir="...">
<fileset dir="...." includes="myScript.sql"/>
<filterchain>
<replaceregex byline="false" pattern=";" replace="{line.separator}/" flags="mg"/>
<replaceregex byline="false" pattern="/[\s]*/" replace=";${line.separator}/" flags="mg"/>
</filterchain>
</copy>
then give the result to:
<sql delimeter="/" src="myScript.sql"/>
explaination:
If you have regular sql commands:
drop table x;
select blah from blue where bli=blee;
They will be transformed to:
drop table x
/
select blah from blue where bli=blee
/
which is equivlant - and the sql command with "/" delimeter can handle them.
On the other hand,
BEGIN
blah
END;
/
will be transformed to:
BEGIN
blas
END/
/
and using the second regex - transformed back to
BEGIN
blas
END;
/
So everybody wins! Hurray!
Good luck.