-
Notifications
You must be signed in to change notification settings - Fork 77
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
Add feature to bind as SQLWCHAR #292
Comments
I added this code in odbc_connection.cpp on line 4176 instead of usual SQL_CHAR process:
Now it works fine ! Also, I changed the SQL_LONGVARBINARY process on line 3387 to be processed like a SQL_BINARY or a SQL_VARBINARY. It works like a charm ! |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Hi, |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Hello, do you need to recompile the code after change de .cpp? |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Not stale |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Not stale |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
We use HFSQL database which uses native Windows encoding. Accented characters are lost. Big show stopper to work with NodeJS. |
@CienappsDAG We encountered the same issues in our project, here are how we solve it. You need to get all columns of the table and iterate over it on the data type like so: switch (column.dataType) {
case -4:
case -1:
case 1:
case 12:
// Fixed issue when converting empty string
// HFSQl odbc driver doesn't allow null
// Converting to utf leads to null if string is empty
concatQuery.push(
`CASE WHEN TRIM(${column.name}) = '' THEN Char(32)+Char(32) ELSE CONVERT(${column.name
} using 'utf8') END AS ${column.name}`
);
break;
default:
concatQuery.push(column.name);
break;
} Next, you need to decode the converted strings: const enc = new TextDecoder("utf-8");
/**
* Remove null bytes from a string
* @param str - String to remove null bytes from
* @returns
*/
export function removeNullBytesFromString(str: string): string {
return str
.split("")
.filter((c) => c.charCodeAt(0))
.join("");
}
/**
* Format the object to remove null bytes and trim strings
* @param obj - Object to format
*/
export function format(obj: any) {
Object.keys(obj).forEach((key) => {
if (obj[key] instanceof ArrayBuffer) {
obj[key] = enc.decode(obj[key]);
}
if (typeof obj[key] === "string") {
obj[key] = removeNullBytesFromString(obj[key]).trim();
}
}); Hope this works. If you have any questions, don't hesitate to ask me. |
I tried your solution but i encountered the same issue in another layer. The issue is that I have some accented characters in table and column names (I know it's very bad, gotta make due). HFSQL doesn't provide a table like Information_Schema to query directly. Therefore, I encounter the same encoding issue when using the odbc.tables() or odbc.columns() functions. |
My solution for now is to revert back to version 1 of odbc unfortunately. |
Any news about this issue ? |
Would be awesome if this could be added :) |
I made a bruteforce fix in the PR #366 |
Here's how I think the solution would look like: The main crux of the change is here: https://github.com/IBM/node-odbc/blob/main/src/odbc_connection.cpp#L3297-L3326 After the call to switch(column->DataType) {
case SQL_CHAR:
column->DataType = SQL_WCHAR;
break;
// check SQL_VARCHAR, SQL_LONGVARCHAR, etc
} This should handle all the cases correctly, since we already handle the wide types below. The only thing is we need access to that flag. From a user point of view, they would pass the option in on the connection or pool constructor, eg. const connection = await odbc.connect({
connectionString: 'DSN=MYDSN',
utf16Binds: true, // not sure on what best name would be here
}); So then it's only a matter of figuring out how to store the flag so that it can be used later. It's likely a case of saving the option on the ODBCConnection object and then passing the option along to prepare_to_fetch and then on to bind_buffers, assuming that all of those callers have access to the ODBCConnection object. |
Windows is very UTF-16 centric while Node.js is very UTF-8 centric. While it can also handle UTF-16, it does not deal with other encodings well at all (at least in the NAPI addon). As a result, the package has been built as UNICODE since July 2020. This has fixed many encoding issues, since various strings are now passed back and forth using UTF-16 without issue. However, when binding,
SQL_CHAR
,SQL_VARCHAR
, andSQL_CLOB
types are still bound asSQL_C_CHAR
, notSQL_C_WCHAR
. This works most of the time, but there have been many issues when databases are in the native Windows encoding (which outside of an experimental feature is never UTF-8). See #284 #290 and #291 for examples.While some drivers have settings to use UTF-8 instead, that is driver-specific and not all do. It would be much better to either always bind as SQLWCHAR when UNICODE is defined (ie. Windows) or add a runtime option to enable it (enabled by default when UNICODE is?)
The text was updated successfully, but these errors were encountered: