get records after creation using sequelize raw query - javascript

I am using sequelize for migration. here I execute an INSERT query with following options but its didnot return created records:
const res = oldUsers.map(u => sequelize.query(
`INSERT INTO ${LP_LOCATIONS_TABLE} (name, address, city)
VALUES (
'${u.email}', '${u.address}', '${u.city}');`,
{ type: DataTypes.QueryTypes.INSERT, raw: true },
))
the output is an array of array like below:
[ [[0],[1]] ]
i expect to get created recorders. specially PK. how can I fix it?

I forgot to put RETURNING * at the end of the raw SQL query.

From the doc, you may have to specify the option returning:true to make this happen. I use mySql, so can't test (the returning option is only for postgres).

Related

How to pass an SQL function on bulk insert query in node

I have to execute an INSERT INTO query using mysql or mysql2 in node.js
The values passed into the query utilizes a spatial geometry function ST_GeomFromGeoJSON() on geoMap column which is of type GEOMETRY.
Here is the simplified code:
const insertQuery = `INSERT INTO maps (name, geoMap) VALUES ?`;
const insertData = [];
geoMapList.forEach((geoMap) => {
insertData.push([
geoMap.name,
`ST_GeomFromGeoJSON(${JSON.stringify(geoMap.map)}, 2)`
]);
});
this.connection.query(insertQuery, [insertData]);
The above code does not work and throws the error
Cannot get geometry object from data you send to the GEOMETRY field
I believe this is because the ST_GeomFromGeoJSON() is not parsed as a function but as a string by MySQL.
How can this be resolved?
You can't put MySQL function calls in the parameter array, that data is all treated as literals.
Call the function in the SQL, with the JSON string as its parameter.
I don't think you can use node-mysql's bulk-insert for this, though, so you'll need to insert each row separately.
const insertQuery = `INSERT INTO maps(name, geoMap) VALUES (?, ST_GeomFromGeoJSON(?))`
geoMapList.forEach((geomap) =>
this.connection.query(insertQuery, [geomap.name, JSON.stringify(geomap.map)])
);
To avoid calling query() thousands of times, you can put multiple values lists in the query.
const values = Array(geoMapList.length).fill('(?, ST_GeomFromGeoJSON(?))).join(',');
const insertQuery = `INSERT INTO maps(name, geoMap) VALUES ${values}`;
const params = geoMapList.flatMap(({name, map}) => [name, JSON.stringify(map)]);
this.connection.query(insertquery, params);
Since this will create a very long INSERT query, make sure you increase the MySQL max_allowed_packet setting. You can also split geoMapList into smaller batches, rather than doing everything in a single query.

How do I prevent sql injection on a WHERE IN request with parameterized query? [duplicate]

I am trying to workout how to pass in a comma sepated string of values into a postgres select within in clause query using node-postgres but unfortunately can't seem to get it working and can't find any examples.
I have the following code:
function getUser() {
let inList = "'qwerty', 'qaz'";
const result = await pgPool.query("SELECT name FROM my_table WHERE info IN ($1)", [inList]);
if (result.rowCount == 1) return result.rows.map(row => row.name)
return false
}
Basically want the end result query to process:
SELECT name FROM my_table WHERE info IN ('qwerty', 'qaz')
Unsure if this is actually the correct way of doing this with pgPool?
The right way is in the FAQ on Github --> https://github.com/brianc/node-postgres/wiki/FAQ#11-how-do-i-build-a-where-foo-in--query-to-find-rows-matching-an-array-of-values
You should be able to do it that way :
pgPool.query("SELECT name FROM my_table WHERE info = ANY ($1)", [jsArray], ...);

TypeORM createQueryBuilder: Is possible to use table name as string instead of entity

In my current scenario, a third party will be creating tables dynamically on my DB, and storing the table name as a varchar and column names as jsonb in other table which is defined as an Entity in my NestJS backend.
This is so I can keep track (and query) these tables, since I have no control over its creation.
For this purpose I'd like to use TypeORM's createQueryBuilder instead of using raw queries as its easier for me to play with abstraction.
As far as I know TypeORMs createQueryBuilder needs a defined Entity in the from clause.
Something like this:
return await getManager()
.createQueryBuilder()
.select('*')
.from(MyDefinedModel, 'modelAlias')
.getRawMany();
}
So I'd like to do something like:
const tableName = await getDynamicallyGenetaredTableNames().getFirstOne()
// now tableName points to a string that is a table name, i.e 'table-data-192239'
return await getManager()
.createQueryBuilder()
.select('*')
.from(tableName, 'tableAlias')
.getRawMany();
So passing the table name I point to the right table, but TypeORM (and TS) complains because that tableName is a string, and not an Entity (Class) type
I really don't want to type-cast and start doing nasty things if there is something cleaner to achieve this.
I didn't find any solution in the official docs
Any brilliant ideas out there?
Thanks, y'all
We can pass table name instead of Entity for getRepository.
let tableName = 'user';
let query = getRepository(tableName).createQueryBuilder(tableName);
You can select from a table by its table name without defining an entity before like this:
const res = await manager
.createQueryBuilder()
.select()
.from("tableName", null)
.where("tableName.id = :id", { id: 1 })
.getRawMany();
Be sure that you set the second parameter of the from() explicitly to null.
You could try using a raw query:
import { getManager } from 'typeorm'
const tableName = await getDynamicallyGenetaredTableNames().getFirstOne()
// Use the table name in a raw SQL query
const result = await getManager().query(`SELECT * FROM ${tableName}`)

sqlite where clause "AND" and "IN"

Objective:
I am trying to do bulk delete in sqlite table, instead of deleting each data with for loop. So, I am trying to use "IN".
Case:
I have two parameters in executing the query. First is type and second is order_id. I want to delete data where the type is "order_book" and order_id are ["B001", "B002", ...].
What I've try but not working:
window.sqlitePlugin.openDatabase({ name: 'dbname.db', location: 'default' }).executeSql("DELETE FROM table_name WHERE type='order_book' AND order_id IN ('B001', 'B002')", [], (res) => { console.log(res.rows); });
// => this is not work
What I've try and works, but, it miss the type parameter:
window.sqlitePlugin.openDatabase({ name: 'dbname.db', location: 'default' }).executeSql("DELETE FROM table_name WHERE order_id IN ('B001', 'B002')", [], (res) => { console.log(res.rows); });
// => data with order_id B001 and B002 deleted
So, whats wrong here? I need to also define what is the type because different type may have same order_id (don't ask why this is happen ...)
Thanks in advance for anyhelp!
If data is stored in mixed case or upper case in the type column then SQLite's case sensitive comparison will not find it. You could check against the data stored or compare strings like this:
WHERE type='order_book' COLLATE NOCASE ...

Format count query parameters with BookshelfJS

I'm just getting up to speed with BookshelfJS, so I'm probably missing something, but I'm wondering how to get query parameters to be formatted correctly for doing a count. For example, if I want my JS objects to use camelCase, and the database rows to use snake_case, I know I can use the format() and parse() functions on the model like so: http://bookshelfjs.org/#parse-and-format
But how do I get query parameters for a count to be converted from camelCase to snake_case before they're run as queries on the DB?
Example:
const Book = bookshelf.Model.extend({
tableName: 'books',
parse: function(response) {
return _.mapKeys(response, function(value, key) {
return _.camelCase(key);
});
},
format: function(attributes) {
return _.mapKeys(attributes, function(value, key) {
return _.snakeCase(key);
});
}
});
Now let's say the books database table has author_name as a column, but, if this is being used in an API, we want users to query on the authorName parameter.
Doing this converts the query parameters just fine:
Book.forge({authorName: 'Clark'}).fetch()
And it queries the DB on author_name instead of authorName. But the analogous:
Book.forge({authorName: 'Clark'}).count()
doesn't work as expected, because it's not converting authorName to author_name before querying. How do I get bookshelf to use the format() function I wrote to do this?

Categories

Resources