Brief history
I have a JavaScript object which stores query templates with $nameParam so that it can be replaced with string.replace(). Issue is that until now I needed $nameParam to be in quotation marks and now I need to get rid of them. Depending on when they are added, the query either works or not. I have observed some interesting behaviour:
Method which replaces string
This method basically calls database and gets records. You can see the longest line - it's responsible for replacing $nameParam with the provided parameter.
function setupEndpoint(app) {
app.get('/neo4jdb/:queryType',
async (req, res) => {
const session = driver.session();
res.on('finish', () => session.close());
try {
const response = await session.run(queryTemplates[req.params.queryType],
{ nameParam: req.query.name });
let statement = response.summary.query.text.replace('$nameParam', `"${response.summary.query.parameters.nameParam}"`);
statement = statement.replace('RETURN', '\nRETURN');
console.info(`Neo4j statement: ${statement}`);
res.send({ rawItems: response.records, statement });
} catch (err) {
console.error('Error connecting Neo4j', configs);
console.error(err);
res.send({ error: 'Error connecting Neo4j' });
}
});
}
Working example
Query template
const queryTemplates = {
getShipsForCompany: `MATCH (A:Company) -[RELATIONSHIP]-> (B:Ship) MATCH (B:Ship)-[RD]-()
WHERE A.name=$nameParam RETURN B as Ship, A as Company, type(RELATIONSHIP) as R, count(RD) as degree limit 50`
};
Replacement
response.summary.query.text.replace('$nameParam', `"${response.summary.query.parameters.nameParam}"`);
Produced output
Neo4j statement: MATCH (A:Company) -[RELATIONSHIP]-> (B:Ship) MATCH (B:Ship)-[RD]-() WHERE A.name="TRINITY HOUSE"
RETURN B as Ship, A as Company, type(RELATIONSHIP) as R, count(RD) as degree limit 50
Not-working example
Query template
const queryTemplates = {
getShipsForCompany: `MATCH (A:Company) -[RELATIONSHIP]-> (B:Ship) MATCH (B:Ship)-[RD]-()
WHERE A.name="$nameParam" RETURN B as Ship, A as Company, type(RELATIONSHIP) as R, count(RD) as degree limit 50`
};
Replacement
response.summary.query.text.replace('$nameParam', `${response.summary.query.parameters.nameParam}`);
Produced output
Neo4j statement: MATCH (A:Company) -[RELATIONSHIP]-> (B:Ship) MATCH (B:Ship)-[RD]-() WHERE A.name="TRINITY HOUSE"
RETURN B as Ship, A as Company, type(RELATIONSHIP) as R, count(RD) as degree limit 50
Summary
Both produced output queries are the same. Why first one returns results and second one is empty? (2nd one copied to DB engine works fine)
Neo4j cypher syntax is below.
WHERE A.name=$nameParam
It should NOT have double quotes on the parameter name. Thus, the 2nd example is syntax error during runtime.
Related
I have a case where I am trying to get the name from a discord channel. I use:
message.channel.name
and this works just fine, except for 4-byte encoded names, typically things like some Asian language characters, and some emojis. as an example:
🏀sports (fails)
¡§™sports (works)
Here is an example from my Windows PowerShell(v7) output of my sql insert error:
INSERT INTO serverdata (channel_name, isChannelActive) VALUES ('🏀sports',1) ON DUPLICATE KEY UPDATE channel_name='🏀sports', isChannelActive = 1
throw err; // Rethrow non-MySQL errors
^
Error: ER_TRUNCATED_WRONG_VALUE_FOR_FIELD: Incorrect string value: '\xF0\x9F\x8F\x80sp...' for column 'channel_name' at row 1
Powershell puts up the "?" for the basketball, but I think this is just a console issue and not related to my execution flow.
I have chased through much of the internet searches...all my files are encoded for UTF8(mb4 where possible to specify), I use VS Code to edit.
I believe I have no place where UTF8MB3 is being used. I also can take the exact SQL string, put it in the MYSQL workbench, and execute a script directly, and the syntax works fine. This leads me to believe it is some kind of interaction between discord and node.js?
Any advice? TIA!
Code source in JS that shows the issue
var tempBuf = message.channel.name;
// var tempBuf = Buffer.from(message.channel.name);
// var tempBufLen = tempBuf.write(message.channel.name);
// var tempBufLen = tempBuf.length + 1;
// tempBuf = tempBuf.toString('utf8',0,tempBufLen)
// tempBuf = tempBuf.toLocaleString();
// console.log("buffer : " + `${tempBuf}`);
// console.log("buffer length : " + tempBufLen);
// console.log("buffer (len) character : " + tempBuf.toString('utf8', 0, tempBufLen));
// insert into the server database
let sql = (`INSERT INTO serverdata (channel_name, isChannelActive) VALUES ('${tempBuf}',${onOrOff}) ON DUPLICATE KEY UPDATE channel_name='${ tempBuf}', isChannelActive = ${onOrOff}`);
console.log(sql)
// execute the insert statment
connection.query(sql, function (err) { if (err) throw err });
If you require emoji support, ensure each MySQL table that includes them is configured with CHARSET=utf8mb4. You will also need to ensure your connection config in the node app includes the related option with matching value.
const mysql = require('mysql');
const connection = mysql.createPool({
connectionLimit: 10,
host: process.env.DB_HOST || '127.0.0.1',
user: process.env.DB_USER || 'local_user',
password: process.env.DB_PASSWORD || 'local_password',
database: process.env.DB_NAME || 'local_database',
charset: 'utf8mb4' // necessary for emoji character support
});
I'm trying to make a irc bot that takes input like this user: +1 I want to have a end result where I can have a main number being added to, from the # someone types with +#.
expected output: #x added: 1 rep: 1 executed[+] second execution
#x added: 1 rep: 2 executed[+]
actual output #x added: +1 rep: +1undefined executed[+] second is identical.
I've tried using Number(commandName), along with toString().replace(/\D\s/g,'') I got some promising results but they seemed to have some problems so I scrapped that code...
so in conclusion how can I add the numbers together and avoid the +?
const tmi = require('tmi.js');
// Define configuration options
const opts = {
identity: {
username: "x",
password: "x"
},
channels: [
"#x"
]
};
// Create a client with our options
const client = new tmi.client(opts);
// Register our event handlers (defined below)
client.on('message', onMessageHandler);
client.on('connected', onConnectedHandler);
// Connect to Twitch:
client.connect();
const totalnum = 0;
// Called every time a message comes in
function onMessageHandler(target, context, msg, self) {
if (self) {
return;
} // Ignore messages from the bot
// Remove whitespace from chat message
let commandName = msg.trim();
var regexadd = /([+]\d*)[^+\s]/;
// If the command is known, let's execute it
if (regexadd.exec(commandName)) {
var totalnum = addem(commandName, totalnum);
console.log(target, `added:`, commandName, `rep:`, totalnum, `executed[+]`)
} else {
console.log(`* Unknown command ${commandName}`);
}
function addem(x, y) {
return (x + y);
}
}
// Called every time the bot connects to Twitch chat
function onConnectedHandler(addr, port) {
console.log(`* Connected to ${addr}:${port}`);
}
I found a few things that appear to be wrong with your code:
You're not adding numbers. addem()'s first parameter is the name of the command, it should be the number captured in your regex capture group.
Your regex includes the + sign in the capture group, you probably wanted to exclude it
You should parse the result of exec to a hint either with ParseInt() or implicitly with +
You use RegExp.prototype.exec() instead of RegExp.prototype.match() to retrieve a capture group.
Here's what this could look like
var regexadd = /\+(\d*)[^+\s]/;
if (regexadd.exec(commandName)) {
var totalnum = addem(+commandName.match(regexadd)[1], totalnum);
console.log(target, `added:`, commandName, `rep:`, totalnum, `executed[+]`)
}
I also think it would be best to use RegExp.prototype.test() instead of RegExp.prototype.exec() for your if statement - you will limit results to true or false.
So I have this weird issue with node js right now and can not find any solution...
Im trying to insert values to my mssql table and some of the values includes the swedish characters "åäö". Anyhow when I do this they appear as "??????". Each special character appear as two question marks ("ö" -> "??").
Some details:
*Package I'm using is in js: msnodesqlv8
var sql = require('msnodesqlv8');
const connectionString = "server=host;Database=MyDb;Trusted_Connection=Yes;Driver={SQL Server Native Client 11.0}"
q = "Insert into [MyDb].[dbo].[MyTable] (testCol) values ('ö')"
sql.query(connectionString, q, (err,data) => {
if (err) {
console.log(err);
}
else {
console.log('Imported row to table.');
}
})
*The columns in the db table that will retrieve values containing "åäö" is defined as datatype nvarchar(50)
I have also trid with N'ö' in variable q and these characters (within the double quotes) appear in db table "ᅢᄊ"
*console.log('ö') prints ö in console as expected
*I have tried all conversions i can think about in js (for example utf-8, latin1, etc...)
*Collation in db is Finnish_Swedish_CI_AS
*I have tried to read out swedish chrs from another table and it works fine through the package msnodesqlv8
The problem to me seems to be somewhere when sending the query from js (everything looks fine here), through package msnodesqlv8 and when mssql shall interpret the values. Im very glad if someone can help me.
Is there some reason you're not using a prepared statement? It takes care of the encoding for you, e.g.:
const sql = require('msnodesqlv8')
const connectionString = "server=YourServerIp,YourServerPort;Database=StackOverflow;Trusted_Connection=Yes;Driver={SQL Server Native Client 11.0};"
console.log('Connecting...')
sql.open(connectionString, (err, conn) => {
console.log('Dropping...')
conn.query('drop table if exists [dbo].[Swedish]', (err,) => {
console.log('Creating...')
conn.query('create table [dbo].[Swedish] (testCol nvarchar(50))', (err) => {
console.log('Inserting...')
conn.prepare('insert [dbo].[Swedish] (testCol) values (?)', (err, ps) => {
ps.preparedQuery(['ö'], (err) => {
ps.free();
console.log('Selecting...')
conn.query('select * from [dbo].[Swedish]', (err, rows) => {
console.log(`${JSON.stringify(rows)}`)
})
})
})
})
})
})
Which yields...
> node .\swedish.js
Connecting...
Dropping...
Creating...
Inserting...
Selecting...
[{"testCol":"ö"}]
The same character is present when queried via SSMS.
I have a query thats being fed into MySQL. I added a new component.. a LIKE.
It works fine for a singular item, but when I pass in multiples... it does some weird escape of the single quotes.
Here is what the sql passed in looks like (from the console.log below):
sql: 'select name, street, numbers from' +
"`HOMES` where " +
"year='2020' and vals in ('2.2.3\\',\\'2.4.5')",
values: [ '2020', "2.2.3','2.4.5"]
Here is how I build the vals:
sql += " and vals in (?)";
var newStr = filterText.myItems.split(",".join("','");
sqlParams.push(newStr);
filterText.myItems is entered by the user as a comma separated value. For example: "2.2.3,2.4.5"
The query going into MySQL is built like this:
exports.query = function(sql, params, resultHandler, errorHandler) {
function _handleError(err) {
errorHandler(config.mysql.errorMessage || err);
}
pool.getConnection(function(err, conn) {
if(err) {
_handleError(err);
return;
}
var query22 = conn.query(sql, params, function(err,results) {
if(err) {
_handleError(err);
} else {
resultHandler(results);
}
conn.release();
});
//this prints out the sql and values displayed above.
console.log("FINAL QUERY:"+util.inspect(query22));
}
}
Needless to say... this fails to execute as I guess MySQL has no idea what the \\' actually is.
For whatever reason the query adds the leading and trailing single quotes. This is why I add the ',' in between the numbers.
Anyone know what might be causing this or how I can remove it before it executes?
thanks!
After messing around some more I finally got it to work. Here is how.
The sql was built and params passed in like this:
sql = "select name, street, numbers from ?? where year=?",
sqlParams = [this.tableName, this.year]
I was dynamically adding to my sql with the in clause. However, when I made it part of the main sql and passed in the vals there it worked!
sql = "select name, street, numbers from ?? where year=? and vals in (?)",
sqlParams = [this.tableName, this.year, filterText.myItems.split(',')]
The sql going in now looks like this and works great:
sql: 'select name, street, numbers from' +
"`HOMES` where " +
"year='2020' and vals in ('2.2.3','2.4.5')",
values: [ '2020', ['2.2.3','2.4.5'] ]
I am opening a URL from javascript. I need to look for the term "colour: x" and then retrieve the value x.
request.get("URL", function (error, res, body)
val = body.indexOf('colour') -> works
which means that web page has the string "colour".
Web page looks like this
size: 8 colour: 1
So, Here I need to retrieve the value of the key 'colour'.
To search for a pattern in any general text:
You can use a regular expression if you know how your information is written.
This regular expression should do the job :
/\bcolour:\s+(\d+)/
(the word "colour:" followed by any space, and then by any number of digits (\d+).
It captures the digits, so this will be the value of the first capture group (found[1]) in my example.
body = `size: 8 colour: 1`
let regex = /\bcolour:\s+(\d+)/;
let found = body.match(regex);
console.log(found[1]);
In the case there is no match (i.e., no 'colour: xx' in the page), the found result will be null, so you should of course check for it before, for safety.
body = `size: 8 but unfortunately, no colour here`
let regex = /\bcolour:\s+(\d+)/;
let found = body.match(regex);
//console.log(found[1]); // Uncaught TypeError: Cannot read property '1' of null
// This snippet below is safe to use :
if (found) {
console.log(found[1]);
} else {
console.log('not found');
}