ODP and RefCursors.... #3
Description
Do you support sys_refcurosrs? I can't seem to get this to work ok. The regular select statement works fine.
Here is my exception:
ORA-06550: line 1, column 123:
PLS-00103: Encountered the symbol "," when expecting one of the following:
. ( * @ % & = - + < / > at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec as between || indicator multiset member
submultiset
Here is my proc and code that is failing:
PROCEDURE MyProc
(
inDate DATE,
RC1 IN OUT SYS_REFCURSOR,
RC2 IN OUT SYS_REFCURSOR,
RC3 IN OUT SYS_REFCURSOR,
RC4 IN OUT SYS_REFCURSOR,
RC5 IN OUT SYS_REFCURSOR,
RC6 IN OUT SYS_REFCURSOR
)
...
var parameters = [
{
name: "inDate",
type: datatypes.DATE,
value: null,
direction: parameterDirection.INPUT
},
{
name: "RC1",
type: datatypes.REFCURSOR,
direction: parameterDirection.OUTPUT
},
{
name: "RC2",
type: datatypes.REFCURSOR,
direction: parameterDirection.OUTPUT
},
{
name: "RC3",
type: datatypes.REFCURSOR,
direction: parameterDirection.OUTPUT
},
{
name: "RC4",
type: datatypes.REFCURSOR,
direction: parameterDirection.OUTPUT
},
{
name: "RC5",
type: datatypes.REFCURSOR,
direction: parameterDirection.OUTPUT
},
{
name: "RC6",
type: datatypes.REFCURSOR,
direction: parameterDirection.OUTPUT
}
];
var cmdProc = new odpnode.OracleCommand("BEGIN MyProc( :inDate, :RC1, :RC2, :RC3, :RC4, :RC5, :RC6 ); END;", cmdType.STOREDPROCEDURE, parameters, con);
cmdProc.executeNonQuery(function(err, rowsAffected, params){
if(err){
console.log(err);
}else{
console.log(params);
}
});
I have also tried:
var cmdProc = new odpnode.OracleCommand("MyProc( :inDate )", cmdType.STOREDPROCEDURE, parameters, con);
and
var cmdProc = new odpnode.OracleCommand("MyProc( :inDate, :RC1, :RC2, :RC3, :RC4, :RC5, :RC6 )", cmdType.STOREDPROCEDURE, parameters, con);
In both of these cases, I get that RC1 is undefined or not bound. Any help would be appreciated.
Activity
bomsy commentedon Apr 23, 2013
Hi,
Try
var cmdProc = new odpnode.OracleCommand("BEGIN MyProc( :inDate, :RC1, :RC2, :RC3, :RC4, :RC5, :RC6 ); END;", cmdType.TEXT, parameters, con);
instead of
var cmdProc = new odpnode.OracleCommand("BEGIN MyProc( :inDate, :RC1, :RC2, :RC3, :RC4, :RC5, :RC6 ); END;", cmdType.STOREDPROCEDURE, parameters, con);
and let me know.
Cheers
wdalrymple commentedon Apr 23, 2013
Thanks! Thats all it was. I would suggest adding this a sample to the descriptor page.
wdalrymple commentedon Apr 23, 2013
spoke to soon, how do I actually open up the cursor to read it afterwards?
I would expect, from your sample: parameters[x].value
Just trying to figure out what I am missing.
Thanks!
wdalrymple commentedon Apr 23, 2013
Ok.. actually looked at your code. I should be using the executereader method (from your lib). Unfortunately, from what I have seen in code is that its limited to a single cursor (or reader).
i.e in your method:
Handle OdpCommand::ExecuteReader(const Arguments& args){
HandleScope scope;
Oracle::DataAccess::Client::OracleDataReader^ reader;
Local callback = Local::Cast(args[0]);
Handlev8::Value error = Undefined();
Handlev8::Value rows;
const unsigned argc = 2;
//unwrap to access the object
OdpCommand* c = ObjectWrap::Unwrap(args.This());
try{
//c->command->Connection->Open();
reader = c->command->ExecuteReader();
rows = ToJSON(reader);
}catch(OracleException ^e){
error = Helpers::String::ToV8String(e->Message);
rows = Undefined();
}
}
I suggest that you create a executeDataset method possibly, or provide a call back with a multiple cursors.
wdalrymple commentedon Apr 23, 2013
Maybe a new method like this?
Handle OdpCommand::ExecuteDataSet(const Arguments& args){
HandleScope scope;
Oracle::DataAccess::Client::OracleDataAdapter* adapter = new Oracle::DataAccess::Client::OracleDataAdapter();
Oracle::DataAccess::Client::OracleDataSet* dataset = new Oracle::DataAccess::Client::OracleDataSet();
}
bomsy commentedon Apr 24, 2013
hi,
Thanks. will look into the dataset.
Did you try this to access your ref cursors
cmdProc.executeNonQuery(function(err, rowsAffected, params){
if(err){
console.log(err);
}else{
console.log(params.RC1); //
console.log(params.RC2);
...
}
});
wdalrymple commentedon Apr 24, 2013
Yes. When I do that all i get in response is the original parameter, without any of the data.
wdalrymple commentedon Apr 24, 2013
Thanks for all the quick support on this!
bomsy commentedon Apr 24, 2013
No probs,
i'm currently working on support for REFCursors based on your request.
The way i'm thinking of going is making the parameters more intelligent
so that it knows if it (a parameter) is a ref cursor and returns its value as json object
representing the cursor.
What do you think?
An update should be out soon.
Cheers
wdalrymple commentedon Apr 24, 2013
That would sound appropriate i would think.
Generally in the .NET world you want to be using a dataset or an individual reader on each cursor.
I think that this would be a nice comprimise and would be in line how you have structured things.
Great idea for a project!
Sent from my BlackBerry device on the Rogers Wireless Network
-----Original Message-----
From: Hubert Boma Manilla notifications@github.com
Date: Wed, 24 Apr 2013 03:29:42
To: bomsy/node-odpnode-odp@noreply.github.com
Reply-To: bomsy/node-odp reply@reply.github.com
Cc: wdalrymplemwdalrymple@Yahoo.com
Subject: Re: [node-odp] ODP and RefCursors.... (#3)
No probs,
i'm currently working on support for REFCursors based on your request.
The way i'm thinking of going is making the parameters more intelligent
so that it knows if it (a parameter) is a ref cursor and returns its value as json object
representing the cursor.
What do you think?
An update should be out soon.
Cheers
Reply to this email directly or view it on GitHub:
#3 (comment)
wdalrymple commentedon Apr 25, 2013
Thanks for looking into this :)
wdalrymple commentedon May 6, 2013
Hey,was wondering how things were going :)
bomsy commentedon May 6, 2013
Hi, bin busy. i've made changes to the code on github. on testing there were small issues. will release an update in few hours.
Though you could pull the current code update from github, test it and let me know.
For REFCursors,
Specify your parameters a RefCursors as usual
Call the executeReader and read the rows parameter of the callback
eg
.executeReader(error, rows){
rows[0][0]["ZONE_ZONECODE"]; // zone_zonecode column of the first row of the first refcursor
}
wdalrymple commentedon May 8, 2013
Still seems to be erroring, unless I am not pulling the right version of the code via npm.
My code looks something like this:
wdalrymple commentedon May 8, 2013
var cmdProc = new odpnode.OracleCommand("BEGIN MyProx( :inDate1, :RC1, :RC2, :RC3, :RC4, :RC5, :RC6 );END;", cmdType.TEXT, parameters, con);
cmdProc.executeReader(function(err, rows){
if(err){
console.log(err);
}else{
console.log(rows[0]);
console.log(rows[1]);
console.log(rows[2]);
console.log(rows[3]);
console.log(rows[4]);
console.log(rows[5]);
At the execute reader statement, it just dies, throwing an exception that it can't even seem to catch.
17 remaining items
wdalrymple commentedon Jul 3, 2013
I am not sure if I am missing something here, but it keeps failing silently for me (i.e. on the execute it crashes node w/o any exceptions that can be caught). Here is my code:
wdalrymple commentedon Jul 3, 2013
It would be handy to have the underlying module to create some sort of error log? To try and capture what is actually failing/dying.
I can execute "select * from .
" statements, so I know that the database connection is good.I am using node-odp version 2.3.
I also forked my own branch off the master and tried that.
bomsy commentedon Jul 3, 2013
pull the updates i made from the master on github
Can you try making your function return only one cursor and test it?
Also does any of the resultsets you are expecting back have characters that are not compatible with json?
wdalrymple commentedon Jul 3, 2013
Ok. I think that I have narrowed it down.
I don't think that your solution can handle 'number' data types properly.
I created a stored proc that generates a large negative and positive #. It seems to be the case that is causing it to crash (doesn't matter if the number is negative or positive). It works if I am just returning strings though so i guess that is some progress.
Here is an sample of two numbers:
-9827569743.16939
7827569743.16939
wdalrymple commentedon Jul 5, 2013
Did this help? Are you able to reproduce the issue with it?
bomsy commentedon Jul 5, 2013
not really. With these numbers it works fine for me.
what are the column names for the data?
wdalrymple commentedon Jul 5, 2013
The column name is "VALUATION1"
bomsy commentedon Jul 5, 2013
pls confirm, this samples
[[{ "VALUATION1": -9827569743.16939 } ]] //this does not work?
[[ { "VALUATION1": "-9827569743.16939" } ]] //this works?
wdalrymple commentedon Jul 5, 2013
Ok. This is very strange
This method works:
PROCEDURE Sample
(
RC1 IN OUT SYS_REFCURSOR
)
IS
inId varchar(2000);
BEGIN
inId :='1234';
END Sample;
But this one then crashes. I can execute this method fine via other means (i.e. pl/sql developer etc).
PROCEDURE Sample
(
RC1 IN OUT SYS_REFCURSOR
)
IS
inId varchar(2000);
BEGIN
inId :='1234';
END Sample;
Where somenumber is column defined as a NUMBER. I believe that your code does not handle this database datatype correctly.
I am really baffled by this.
I can run the following method fine that returns a list of varchars:
PROCEDURE Sample
(
RC1 IN OUT SYS_REFCURSOR
)
IS
inId varchar(2000);
BEGIN
inId :='1234';
END Sample;
I think that it has something to do with the handling of NUMBER. That or I haven't built the node package correctly? I don't know. I don't think that it would half work with varchars if it hadn't build properly (i.e. the wrong version of code).
wdalrymple commentedon Jul 5, 2013
(your sample did work.. if I just did a selection -19219219219219 as valudation1 from dual.)
bomsy commentedon Jul 5, 2013
i think ive figured it out, you are right about the numbers. The issue is valid json does not accept numbers as keys
e.g
{
1000: "bla" //this is invalid json
}
while
{
"1000": "bla" //this is valid json
}
wdalrymple commentedon Jul 6, 2013
I tried this as well: SELECT somenumber as "COLUMN1" FROM schema1.table1 WHERE id = inId AND somefiler='FilterByThis'; to the same effect.
wdalrymple commentedon Jul 15, 2013
any luck?