Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there SQLBindParameter() equivalent of node ODBC #69

Open
SabaKauser opened this issue Jun 9, 2019 · 5 comments
Open

Is there SQLBindParameter() equivalent of node ODBC #69

SabaKauser opened this issue Jun 9, 2019 · 5 comments

Comments

@SabaKauser
Copy link

Hello,
Does this driver has any SQLBindparameter() equivalent to allow developers to explicitly bind the parameters by passing the input C and SQL type?
or
Is there a way to bind a file to parameter instead of the actual value? i.e I have some data in a file and I would like to bind this file to a parameter marker in my SQL instead of reading the contents and passing it.
e.g:
var callStatement = "call mySP('par1',?);
// file filename has contents that I want to bind to second parameter
ibmdb.query(callStatement, [filename],function (err, result){
if (err) {
console.log(err);
return cb("Error " + err, "-1");
}
else {
console.log("Affected rows = " + result);
//In some cases closing of StatementHandle is also needed stmt.closeSync();
// result.closeSync();
return cb("success", "Rows affected : " + result);
}

Thanks in Advance!

@markdirish
Copy link
Collaborator

Hi @SabaKauser ,

(Everything below is in reference to v2.0 and above, which is a complete rewrite of odbc for Node.js. I have v2.0.0 done, and will release it later today):

Does this driver has any SQLBindparameter() equivalent to allow developers to explicitly bind the parameters by passing the input C and SQL type?

Just for clarification, odbc downloaded from npm is not a driver, it is an application that talks to the driver manager, which uses the driver you have downloaded for your database. There is currently no mechanism to explicitly bind C and SQL type. I know in idb-connector, which is an older connector for IBM i, you had to explicitly define them, but that is no longer needed in this case.

When interacting with a table or a view with .query, the program calls SQLDescribeCol() for each column, which (among other things) returns the column's data type, making it unnecessary to explicitly specify SQL type (unless you wanted to create a mismatch, which I believe the driver will rectify anyways). For the C type, it is specified based on the SQL type, (SQL_DOUBLE -> SQL_C_DOUBLE, etc.). Is there are reason you would need to specify either of these explicitly?

Is there a way to bind a file to parameter instead of the actual value? i.e I have some data in a file and I would like to bind this file to a parameter marker in my SQL instead of reading the contents and passing it.

Currently there is no way to do this. It would be difficult to determine whether the String passed was intended as a String, or indicated a file name. The best thing to do would probably be to use the built-in File System APIs in Node.js and fs.readFile to get your file in a String or Buffer representation, which can then be bound to the parameter.

As a side note, I notice that you are calling a stored procedure with .query. In v2.0.0, there is a .callProcedure function, which allows you to just pass the catalog/schema/name of the procedure and the parameters, and it will create the call query for you behind the scenes. Using .query is ok, but to ODBC there are some small subtle differences between regular queries and calling procedures.

@asztal
Copy link

asztal commented Jun 10, 2019

ODBC supports SQLPutData and SQLGetData to stream large objects into and out of the database - of course that's even more work than SQLBindParameter.

I did have both SQLBindParameter and SQLGetData working in the ODBC library I wrote, but it's very out of date now and was too low-level to use for most use cases.

@SabaKauser
Copy link
Author

@markdirish Thank you!
While invoking the call, as you said, the sqltype is as we get from server in describe information and I wanted to override it to non-w char equivalent. I found that I can do so by removing the UNICODE define from the binding.gyp and can now get the non-unicode sqltype.
I would be interested to know if you have examples of .callProcedure and SQLPutData for your application somewhere for me to refer.

Thanks in advance!

@markdirish
Copy link
Collaborator

The odbc connector does not use SQLPutData anywhere in the code: Parameters are expected to be bound with SQLBindParameter (and are done in the C++ code when a parameter array is passed to .query or .callProcedure).

.callProcedure documentation can be found in the 2.0 README, but it looks like the callback example doesn't actually document it, I will fix. Promise example work though.

To use .callProcedure, you call:

const result = await connection.callProcedure(<catalog>, <schema>, <procedureName>, [<parameters>]);

When passing the array of parameters, the size of the array must match the number of parameters expected by the procedure called. OUT parameters still have to be passed, but can be passed as undefined or null. The result object will contain the result set, but it also has a property parameters that will contain the values of all parameters: IN parameters unchanged, IN/OUT and OUT parameters with their new values.

[ statement: '{ CALL MIRISH.MAXBAL (?) }',
  parameters: [ 3987.5 ],
  return: undefined,
  count: 0,
  columns: [] ]

In the above example, I passed in [undefined] as my parameter, and because its an OUT parameter in the procedure, the value is placed in the result array's 'parameters' array

NOTE It looks like the version on npm has a double free issue that regressed when I was fixing memory leaks. I have solved the problem on my local branch and look to push it today

@ugate
Copy link

ugate commented Feb 26, 2020

@markdirish in reference to the question/answer regarding binding file parameters...

Is there a way to bind a file to parameter instead of the actual value? i.e I have some data in a file and I would like to bind this file to a parameter marker in my SQL instead of reading the contents and passing it.
Currently there is no way to do this. It would be difficult to determine whether the String passed was intended as a String, or indicated a file name. The best thing to do would probably be to use the built-in File System APIs in Node.js and fs.readFile to get your file in a String or Buffer representation, which can then be bound to the parameter.

Is there any plan to allow binding a ReadStream using fs.createReadStream? It would seem that instead of using a file path string the ODBC module could use bindParameter instanceof ReadStream?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants