NodeJS - Sequelize updating issue - mysql

I have a problem with updating method.
I am doing this:
// Char is outside the object where update method is...
Char = db.define('characters', {}, {
tableName: 'characters',
updatedAt: false,
createdAt: false
});
//... part of the whole object
update: function ( columns, callback ) {
Char.update( columns, { where: { id: this.get('char_id') } } )
.complete( function ( err, res ) {
f.log(res, 'd');
});
},
When I define updatedAt to be false, the updates stop working at all and I don't know how to prevent that, except to add a column in my database. It throws me "Query was empty".
So I tried to define updatedAt as 'created_at' - an existing column in my table and then the updates have worked, but not at all. The query updating only 'created_at' with the timestamp, but not my preferred columns.
Example that I receive in the console:
Executing (default): UPDATE characters SET created_at='2015-02-03 21:03:00' WHERE id='1'
It should be:
Executing (default): UPDATE characters SET health = ..., created_at='2015-02-03 21:03:00' WHERE id='1'
I debug whether the columns parameter is valid parameter. Yes, it is - I send an object and receive an object.
Can someone help me. I tried old ways, new ways, read posts, but nothing.
EDIT:
I found where I'm wrong. I should define all fields which I want to update/insert.
Because of my english I didn't understand right the define function in documentation. I thought that when you define the fields you'll recreate your table structure, but now I realize, that that would happen if run sync() method.

I found where I'm wrong. I should define all fields which I want to update/insert. Because of my english I didn't understand right the define function in documentation. I thought that when you define the fields you'll recreate your table structure, but now I realize, that that would happen if run sync() method.

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)
});

TypeORM integer entity in MySQL to 'enum string' representation in JSON

I have an existing MySQL database table userdo that has a column userType of type integer, such that an administrator user is represented as value 0, and so on.
When I work with my TypeORM userdo entity object, I wish for its JSON form to represent the userType property in a string enumeration form. For example, if the userType is 0 in the table, then when serializing/deserializing to JSON (say, when getting a userdo instance as a result of a findOne() and sending it via res.json()), I want:
{
...
userType: 'ADMIN',
...
}
There are several ways I have considered trying to do this:
Using the entity enum type. This doesn't seem to solve my problem because at runtime the enum is just a normal JavaScript integer and so it is printed in the JSON as such.
Use a ValueTransformer. I haven't investigated this much yet, but I believe this would entail writing some code to marshal between a set of strings ('ADMIN', ...) and respective integer values.
Use the library https://github.com/typestack/class-transformer. I am not certain yet if this will achieve what I want.
From what I know of SQL, I don't think there is a way of doing that with SQL. Which means I wouldn't think that TypeORM can do that.
Anyway, the way I would do it is to declare a const object that can do the translation for you. If you're using numbers, then maybe even an array:
const typeToWord = {
0: "ADMIN",
1: "SUPERADMIN",
/*... and so on*/
};
// or: ["ADMIN", "SUPERADMIN"]
const typeToNumber = {
"ADMIN": 0,
"SUPERADMIN": 1,
/* ... */
};
And the idea is to use that right after the query, so the rest of your code uses the "translation", i.e "ADMIN"

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.

Anorm insert with trigger

I have a table with a trigger that updates a column in the table after the insert. Problem is this is returning false:
def insert(user: User, token: String) = {
DB.withConnection {
implicit connection =>
SQL(INSERT_STMT).on("user_id" -> user.id, "token" -> token).execute()
}
}
The values get inserted correctly after the call but the function returns false. Any clues?
You should use .executeUpdate() for DML's DDL's which return rowcounts/nothing
Learn more from here.
I wish I knew more about SQL and Scala - so for the time I'll leverage my Google skills and take a shot at this - I believe this guy solved your question:
https://groups.google.com/forum/#!topic/play-framework/r2Iueso3yGQ
From the API, it would appear you get back false - if the result type is a rowcount:
Returns:
true if the first result is a ResultSet object; false if the first result is an update count or there is no result

Cannot add an identity that already exists

I'm using C#4.0 in a simple expense recording app. I'm trying to save to a table with an auto incremented id field, set as the primary key. It works fine the first time I use it, but the second and subsequent time, I get the "Cannot add an identity that already exists" error.
Here's the code I'm having trouble with
public bool SaveClaim(Claim newClaim, bool blNew)
{
bool blSuccess = true;
try
{
expContext.Claims.InsertOnSubmit(newClaim);
expContext.SubmitChanges();
claim = null;
}
catch (Exception e)
{
blSuccess = false;
MessageBox.Show(e.ToString());
}
return blSuccess;
}
I've been working on this all morning, and it's driving me daft. I'd be glad for any help.
Ensure you have the following properties set in your dbml for the identity column of Claim:
Auto Generated Value = true
Auto-Sync = OnInsert
Also ensure that your new Claim object is actually a new object, and not a reuse of the one you previously added.
Maybe you should try updating your designer.
Remove the table Claim, update the server explorer, and add it again.
At least that's what I do when I get this error. It usually shows when I set the identity column on the database after compiling.
Maybe you are trying to UPDATE newClaim using the INSERT method.
If newClaim has an ID and the method expContext.Claims.InsertOnSubmit(newClaim) is trying to insert a record with that ID. That could be the issue.
if (blNew)
expContext.Claims.InsertOnSubmit(newClaim);
else
expContext.Claims.UpdateOnSubmit(newClaim); //-- Assumed method
Additional
Here is a useful thread: MSDN Forums
if (blNew)
{
expContext.Claims.InsertOnSubmit(newClaim);
}