Insert json to mysql row in nodejs - mysql

I'm currently developing a program that connects to various external APIs for transactions.
The APIs returns a JSON that I want to store completely in a MySQL database column. I don't want to create a column for every data returned as that means I'll have to create different rows for every different JSON response, and that's not scalable.
I also want to keep them stored as JSON as they would be easy to process in a query and in code. So in my database I have a table where I store the external transaction info and an external_extra column where I want to store the JSON Object.´
My code
connection.acquire(function(err, con) {
console.log('inserting: ' + [transactionId, externalReference,
externalTransactionStatus, externalExtra]);
con.query('insert into external_transaction (transaction, external_reference, status,' +
'external_extra) ' +
'values (?,?,?,?)', [transactionId, externalReference,
externalTransactionStatus, externalExtra],
function(err, result) {
con.release();
if(err) console.log(err);
cb(result.insertId);
});
Where externalExtra is the JSON received from the API. Running that code gives me an error as it uses the JSON to add more fields to the insert instead of inserting the json. Example: if the json has a structure like:
{
type: 'internal_transaction',
address: 'rDLwhx2M9YfbNfZWDq5opJMttQjh7xtvh5',
sequence: 42,
id: 98,
specification: 'created with rrDL55JshyMtlIU sequence'
}
I get the error: Error:
ER_BAD_FIELD_ERROR: Unknown column 'type' in 'field list' as it takes 'type' as a column for the table.
Any help on this would be appreciated.

I don't know much about mySql, but had a similar error using a postgresSql database, this seems to be some kind of parsing error, why not try to parse the json object to string doing JSON.stringify(externalExtra)

Related

Pass variables to DATABASE preventing mysql injection node and mysql

So, I started to develop in nodejs and mysql. I read in some forums that the correct way to do the insertion in mysql would be using variables to prevent mysql injection, however I tried in several ways to insert them and I couldn't. I was only able to do them manually as follows:
db.query('UPDATE spreadsheetUsers SET weight="1" WHERE weekDay="1" AND idStudent="1" ', (error,results) =>
How could I do to insert them using variables?
The way I was trying was like this:
db.query('UPDATE spreadsheetUsers SET weight=? WHERE weekDay=? AND idStudent=? '
,{weight:value[0], weekDay:daySelected, idStudent:idStudent }, (error,results) =>
I guess im missing something, could someone help?
https://github.com/mysqljs/mysql#escaping-query-values
{weight:value[0], weekDay:daySelected, idStudent:idStudent }, (error,results) =>
the parameterized query should be array not object
db.query('UPDATE spreadsheetUsers SET weight=? WHERE weekDay=? AND idStudent=?'
,[value[0], daySelected, idStudent], (error,results) =>
You can use this style also
db.query({
sql: 'UPDATE spreadsheetUsers SET weight=? WHERE weekDay=? AND idStudent=?',
values: [value[0], daySelected, idStudent']
}, function (error, results, fields) {
// error will be an Error if one occurred during the query
// results will contain the results of the query
// fields will contain information about the returned results fields (if any)
});

MySQL binding multiple parameters to a single query

I have a MySql database, and I'm connecting to it from a .Net app using Dapper. I have the following code:
await connection.ExecuteAsync(
"DELETE FROM my_data_table WHERE somedata IN (#data)",
new { data = datalist.Select(a => a.dataitem1).ToArray() },
trans);
When I do this with more than a single value, I get the following error:
MySqlConnector.MySqlException: 'Operand should contain 1 column(s)'
Is what I'm trying to do possible in MySql / Dapper, or do I have to issue a query per line I wish to delete?
Your original code was almost fine. You just need to remove the parentheses around the parameter. Dapper will insert those for you:
await connection.ExecuteAsync(
"DELETE FROM my_data_table WHERE somedata IN #data",
new { data = datalist.Select(a => a.dataitem1).ToArray() },
trans);

Spring CriteriaBuilder query JSONArray data

I have used a table for storing JSON data. For a specific client I create records for 12 months and store the data of the 12 months in JSONArray format. In that way I create one row per client.
The approved field can be true, false or null. What I need to do is, check whether the approved value is true and that the data is not null. I tried to search for queries JSON data but couldn't find solution.
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<ClientData> clientQuery = cb.createQuery(ClientData.class);
Root<ClientData> clientMaster = clientQuery.from(ClientData.class);
..
..
..
predicates.add(cb.isTrue(cb.function("json_contains", Boolean.class,
clientMaster.get("Data"), cb.literal("approved"))));
predicates.add(cb.isNotNull(cb.function("json_contains", Double.class,
clientMaster.get("Data"), cb.literal("data"))));
But this gave me error:-
com.mysql.jdbc.MysqlDataTruncation: Data truncation: Invalid JSON text in argument 2 to function json_contains: "Invalid value." at position 1.
I'm using MySQL version 5.7.31. Any help would be appreciated.
try this way
if(!CommonUtils.checkIsNullOrEmpty(filterDto.getProduct()) ) {
String a=(String.join(",",filterDto.getProduct()));
predicates.add(cb.isTrue(cb.function("json_contains", Boolean.class,
userRoot.get("product"), cb.literal("\"" + a + "\""))));
// predicates.add(userRoot.get("product").in(a));
}

What's could be wrong with this code posting a object in the database?

I'm trying to make a post request to a table, using Express, Sequelize, MySQL and Postman to test the request. I'm getting an error with Sequelize not recognizing a field.
The query is not inserting the field IdProduto, I don't know why, I've checked the spelling a million times, checked all the files related and also the database table.
Executing (default):
SELECT `idPedidos`, `idCliente_fk`, `idRestaurante_fk`, `valorCompra`, `horarioChegada`, `statusPedido`, `IdProduto`
FROM `Pedidos`
AS `Pedidos`;
Executing (default):
INSERT INTO `Pedidos` (`idPedidos`,`valorCompra`,`horarioChegada`,`statusPedido`,`createdAt`,`updatedAt`,`idCliente_fk`,`idRestaurante_fk`)
VALUES (DEFAULT,40,30,'Feito','2019-05-29 23:03:41','2019-05-29 23:03:41',14,16);`
Unhandled rejection SequelizeDatabaseError: Field 'IdProduto' doesn't
have a default value
Here is my code that make the post.
exports.post = (req, res, next) => {
models.Pedidos.create({
IdProduto: req.body.IdProduto,
idCliente_fk: req.body.idCliente_fk,
idRestaurante_fk: req.body.idRestaurante_fk,
valorCompra: req.body.valorCompra,
horarioChegada: req.body.horarioChegada,
statusPedido: req.body.statusPedido
}).then((result) => res.json(result))
};
Here is the json I'm using in postman.
{
"idRestaurante_fk":16,
"valorCompra":40,
"horarioChegada":30,
"statusPedido":"Feito",
"idCliente_fk":14,
"IdProduto":2
}
Also I've checked the names in the table, and it's all right. I was thinking about setting the default value in the database myself, but it will not work, because in the console the INSERT query executed shows that the IdProduto is not getting inserted. Not sure what can be wrong here.

How to fix Slick Exception of single AutoInc column returned on INSERT

I tried to implement the akka-http rest example provided at
https://github.com/ArchDev/akka-http-rest
but I'm stuck with the
slick.SlickException: This DBMS allows only a single column to be returned from an INSERT, and that column must be an AutoInc column.
at slick.jdbc.JdbcStatementBuilderComponent$JdbcCompiledInsert.buildReturnColumns(JdbcStatementBuilderComponent.scala:67)
Here is the Scala Code:
Signup API:
path("signUp") {
pathEndOrSingleSlash {
post {
entity(as[UsernamePasswordEmail]) { userEntity =>
complete(Created -> signUp(userEntity.username, userEntity.email, userEntity.password))
}
}
}
}
AuthService.scala
def signUp(login: String, email: String, password: String): Future[AuthToken] =
authDataStorage
.saveAuthData(AuthData(UUID.randomUUID().toString, login, email, password.sha256.hex))
.map(authData => encodeToken(authData.id))
AuthDataStorage.scala
...
override def saveAuthData(authData: AuthData): Future[AuthData] =
db.run((auth returning auth).insertOrUpdate(authData)).map(_ => authData)
...
Since I'm new to Scala and Slick, can anyway provide the information why this exception is occurring even though I've defined O.AutoInc in Model. I'm using MySQL RDBMS
The problem is with returning auth. Instead of returning auth i.e complete object, Just return the auto-increment Id id. Slick does not support returning the complete object, though it compiles correctly. It does not generate a valid sql query.
Once you can get access to the auto-increment id then you can build the AuthData using the argument of the function.
Code:
(auth returning auth.map(_.id)).insertOrUpdate(authData)).map(id => authData.copy(id = id))
The exception is the result of a MySQL behavior. As the Slick documentation states:
Many database systems only allow a single column to be returned which must be the table’s auto-incrementing primary key. If you ask for other columns a SlickException is thrown at runtime (unless the database actually supports it).
Change the saveAuthData method to return the id column on an upsert:
override def saveAuthData(authData: AuthData): Future[AuthData] =
db.run((auth returning auth.map(_.id)).insertOrUpdate(authData))
.map(idFromDb => authData.copy(id = idFromDb.getOrElse(authData.id)))
In the above code, idFromDb is a Some[Int] for an insert and a None for an update.