-
Notifications
You must be signed in to change notification settings - Fork 470
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
Problem with Persian/Arabic characters when using input() #1625
Comments
How interesting. Can you confirm what you mean by "doesn't work"? Do you have a minimal set queries / DB structure & data that I can use to replicate the issue? |
Doesn't work = returns 0 rows. If you want to test, here's a simple query to create the db: CREATE DATABASE PersianTest
COLLATE ARABIC_CI_AS USE PersianTest
CREATE TABLE People (ID INT, Name NVARCHAR(20))
INSERT INTO PersianTest.dbo.People (ID, Name) VALUES (1, 'شادی'), (2, 'شادي'), (3, 'علی'), (4, 'علي') |
The same thing happens for procedures: -- using varchar
CREATE PROCEDURE TestPersian @inputField VARCHAR(255) AS BEGIN
SELECT
Name
FROM
People
WHERE
Name = @inputField;
END
GRANT EXEC ON dbo.TestPersian TO PUBLIC
-- using nvarchar
CREATE PROCEDURE NTestPersian @inputField NVARCHAR(255) AS BEGIN
SELECT
Name
FROM
People
WHERE
Name = @inputField;
END
GRANT EXEC ON dbo.NTestPersian TO PUBLIC Using sql directly: /* persian text */
EXEC TestPersian 'علی'; -- ✅
EXEC NTestPersian 'علی'; -- ✅
EXEC TestPersian N'علی'; -- ✅
EXEC NTestPersian N'علی'; -- ❌
/* arabic text */
EXEC TestPersian 'علي'; -- ✅
EXEC NTestPersian 'علي'; -- ✅
EXEC TestPersian N'علي'; -- ✅
EXEC NTestPersian N'علي'; -- ✅ Using js: /* arabic text */
data = await pool.request().input('inputField', VarChar, 'علي').execute('TestPersian'); // ✅
data = await pool.request().input('inputField', VarChar, 'علي').execute('NTestPersian'); // ✅
data = await pool.request().input('inputField', NVarChar, 'علي').execute('TestPersian'); // ✅
data = await pool.request().input('inputField', NVarChar, 'علي').execute('NTestPersian'); // ✅
/* persian text */
data = await pool.request().input('inputField', VarChar, 'علی').execute('TestPersian'); // ❌
data = await pool.request().input('inputField', VarChar, 'علی').execute('NTestPersian'); // ❌
data = await pool.request().input('inputField', NVarChar, 'علی').execute('TestPersian'); // ✅
data = await pool.request().input('inputField', NVarChar, 'علی').execute('NTestPersian'); // ❌ |
OK - this seems to be a problem either with the underlying tedious driver, or SQL as whole. I've just created this test script making use of raw tedious driver and get the same behaviour as I do with const { connect, Request, TYPES } = require('tedious');
function doConnect () {
return new Promise((resolve, reject) => {
const connection = connect({
server: 'localhost',
options: {
encrypt: true,
database: 'PersianTest',
trustServerCertificate: true,
rowCollectionOnRequestCompletion: true
},
authentication: {
type: 'default',
options: {
userName: 'sa',
password: 'yourStrong(!)Password'
}
}
}, (err) => {
if (err) { reject(err) } else { resolve(connection) }
})
})
}
(async () => {
const names = ['شادی', 'شادي', 'علی', 'علي']
const res = await Promise.all(names.map((name) => {
return new Promise(async (resolve, reject) => {
const conn = await doConnect()
const request = new Request(`SELECT * FROM [People] WHERE [Name] = @name`, (err, count, rows) => {
conn.close()
if (err) {
reject(err)
} else {
resolve(rows.map((cols) => {
return cols.reduce((acc, col) => ({
...acc,
[col.metadata.colName]: col.value
}), {})
}, []))
}
})
request.addParameter('name', TYPES.NVarChar, name)
conn.execSql(request)
})
}))
console.log(res)
})().then(() => {
console.log('Done')
}).catch(console.error) Output: [
[],
[ { ID: 1, Name: 'شادي' }, { ID: 2, Name: 'شادي' } ],
[],
[ { ID: 3, Name: 'علي' }, { ID: 4, Name: 'علي' } ]
] If I don't use a parameter, it works as expected: const { connect, Request, TYPES } = require('tedious');
function doConnect () {
return new Promise((resolve, reject) => {
const connection = connect({
server: 'localhost',
options: {
encrypt: true,
database: 'PersianTest',
trustServerCertificate: true,
rowCollectionOnRequestCompletion: true
},
authentication: {
type: 'default',
options: {
userName: 'sa',
password: 'yourStrong(!)Password'
}
}
}, (err) => {
if (err) { reject(err) } else { resolve(connection) }
})
})
}
(async () => {
const names = ['شادی', 'شادي', 'علی', 'علي']
const res = await Promise.all(names.map((name) => {
return new Promise(async (resolve, reject) => {
const conn = await doConnect()
const request = new Request(`SELECT * FROM [People] WHERE [Name] = '${name}'`, (err, count, rows) => {
conn.close()
if (err) {
reject(err)
} else {
resolve(rows.map((cols) => {
return cols.reduce((acc, col) => ({
...acc,
[col.metadata.colName]: col.value
}), {})
}, []))
}
})
conn.execSql(request)
})
}))
console.log(res)
})().then(() => {
console.log('Done')
}).catch(console.error) Output: [
[ { ID: 1, Name: 'شادي' }, { ID: 2, Name: 'شادي' } ],
[ { ID: 1, Name: 'شادي' }, { ID: 2, Name: 'شادي' } ],
[ { ID: 3, Name: 'علي' }, { ID: 4, Name: 'علي' } ],
[ { ID: 3, Name: 'علي' }, { ID: 4, Name: 'علي' } ]
] Would you mind opening an issue with the tedious driver directly? |
I noticed that there's a problem with Persian/Arabic characters when using
.input()
.Note
Both
ی
(Persian) andي
(Arabic) represent the ~same character but with different unicodes.In my database, since there isn't strict formatting rules, both forms exist; for example, both 'شادی' and 'شادي' are possible and acceptable values.
When I directly write the value in my query, it works as desired and both values return data.
Using JS variables works too:
But when I use
input()
to utilize sql variables, only the Arabic text works:Seem like there's an issue with
input()
and how it passes data toquery
, because using variables with both values work in sql (direct query)Expected behaviour:
input()
should behave like direct queries and don't change characters or anything.Software versions
The text was updated successfully, but these errors were encountered: