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
Related
When I execute a SQL query from Java and store the boolean returned, the query always returns true which shouldn't be the case at all. So I emptied the table and fired the query again, and yet it returns true for the emptied table. I have attached a picture of the table. I want the query to return true or false, so I can store it in Java. Can someone please specify an alternate code for this, please?
This is my code on java for the query.
boolean avail = st.execute("SELECT EXISTS(SELECT * from sales WHERE product='"+n+"' AND ord_date='"+sqlDate+"');");
And this is my code for result set
Statement st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
This is the table, name of the table is 'sales'
I'm new to MySQL, a more specific approach is appreciated.
Statement.execute will return true regardless of what the query returns. You are still supposed to retrieve the actual result of the query.
Returns
true if the first result is a ResultSet object; false if it is an update count or there are no results
As you execute an EXISTS statement, there will always be a result (true or false). The actual value still has to be retrieved:
You must then use the methods getResultSet or getUpdateCount to retrieve the result, and getMoreResults to move to any subsequent result(s).
For reference: https://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html#execute-java.lang.String-String
Also note that you are directly embedding strings into your query, this will leave you vulnerable to SQL injections. Please read: How can prepared statements protect from SQL injection attacks?. Recommended reading: Introduction to JDBC
The return value of Statement.execute() signals whether the query produces a result set (true) or - possibly - an update count (false). The query you execute is a select which will always produce a result set (even if empty). In other words, it will always return true for a select.
If you want to get the result of your query, then the recommend approach is to use executeQuery. However, you are also concatenating values into your query string, which is a bad idea because it leave you vulnerable to SQL injection. The recommended approach is to switch to prepared statements:
try (PreparedStatement pstmt = con.prepareStatement(
"SELECT EXISTS(SELECT * from sales WHERE product = ? AND ord_date = ?)")) {
pstmt.setString(1, n);
pstmt.setDate(2, sqlDate);
try (ResultSet rs = st.executeQuery() {
boolean avail = rs.next() && rs.getBoolean(1);
// use avail...
}
}
I have two sql statements to be executed with a validity check. My need is that I execute the 1st query and store the response in one object and check the object is empty or not and execute the second query if it is not empty.
So, I have tried something like
In rolerepository.scala=>
override val allQuery = s"""
select UserRoles.* from
(select CASE rbac.roleTypeID
ELSE rbac.name JOIN dirNetworkInfo ni
ON UserRoles.PersonID = ni.PersonID
where ni.Loginname = {loginName}
and UserRoles.roleName in ( 'Business User ','Administrator')"""
(This is just some sample of the query - it is not fully written here.)
Then I map it to an object with model class written outside
override def map2Object(implicit map: Map[String, Any]):
HierarchyEntryBillingRoleCheck = {
HierarchyEntryBillingRoleCheck(str("roleName"), oint("PersonID")) }
Then I have written the getall method to execute the query
override def getAll(implicit loginName: String):
Future[Seq[HierarchyEntryBillingRoleCheck]] = {
doQueryIgnoreRowErrors(allQuery, "loginName" -> loginName) }
Then I have written the method to check whether the response from the 1st sql is empty or not. This is were I'm stuck and not able to proceed further.
def method1()= {
val getallresponse = HierarchyEntryBillingRoleCheck
getallresponse.toString
if (getallresponse != " ")
billingMonthCheckRepository.getrepo()
}
I am getting an error (type mismatch) in last closing brace and I don't know what other logic can be used here.
Can any one of you please explain and give me some solution for this?
And i also tried to use for loop in controller but not getting how to do that.
i tried ->
def getAll(implicit queryParams: QueryParams,
billingMonthmodel:Seq[HierarchyEntryBillingRoleCheck]):
Action[AnyContent] = securityService.authenticate() { implicit request
=> withErrorRecovery { req =>
toJson {
repository.getAll(request.user.loginName)
for {
rolenamecheck <- billingMonthmodel
}yield rolenamecheck
}}}}
You don't say which db access method you are using. (I'm assuming anorm). One way of approaching this is:
Create a case class matching your table
Create a parser matching your case class
use Option (or Either) to return a row for a specific set of parameters
For example, perhaps you have:
case class UserRole (id:Int, loginName:String, roleName:String)
And then
object UserRole {
val sqlFields = "ur.id, ur.loginName, ur.roleName"
val userRoleParser = {
get[Int]("id") ~
get[String]("loginName") ~
get[String]("roleName") map {
case id ~ loginName ~ roleName => {
UserRole(id, loginName, roleName)
}
}
}
...
The parser maps the row to your case class. The next step is creating either single row methods like findById or findByLoginName and multi-row methods, perhaps allForRoleName or other generic filter methods. In your case there might (assuming a single role per loginName) be something like:
def findByLoginName(loginName:String):Option[UserRole) = DB.withConnection { implicit c =>
SQL(s"select $sqlFields from userRoles ur ...")
.on('loginName -> loginName)
.as(userRoleParser.singleOpt)
}
The .as(parser... is key. Typically, you'll need at least:
as(parser.singleOpt) which returns an Option of your case class
as(parser *) which returns a List of your case class (you'll need this if multiple roles could exist for a login
as(scalar[Long].singleOpt) which returns an Option[Long] and which is handy for returning counts or exists values
Then, to eventually return to your question a little more directly, you can call your find method, and if it returns something, continue with the second method call, perhaps like this:
val userRole = findByLoginName(loginName)
if (userRole.isDefined)
billingMonthCheckRepository.getrepo()
or, a little more idiomatically
findByLoginName(loginName).map { userRole =>
billingMonthCheckRepository.getrepo()
...
I've shown the find method returning an Option, but in reality we find it more useful to return an Either[String,(your case class)], and then the string contains the reason for failure. Either is cool.
On my version of play (2.3.x), the imports for the above are:
import play.api.db._
import play.api.Play.current
import anorm._
import anorm.SqlParser._
You're going to be doing this sort of thing a lot so worth finding a set of patterns that works for you.
WOW I don't know what's happening with the formatting here, I am really attempting to use the code formatter on the toolbar but I don't know why it won't format it, even when pressed multiple times. I invite the community to edit my code formatting because I can't figure it out. Apologies to OP.
Because I find Play's documentation to be very tough to trudge through if you're unfamiliar with it, I won't just leave a link to it only.
You have to inject an instance of your database into your controller. This will then give it to you as a global variable:
#Singleton
class LoginRegController #Inject()(**myDB: Database**, cc: ControllerComponents ) {
// do stuff
}
But, it's bad practice to actually use this connection within the controller, because the JDBC is a blocking operation, so you need to create a Model which takes the db as a parameter to a method. Don't set the constructor of the object to take the DB and store it as a field. For some reason this creates connection leaks and the connections won't release when they are done with your query. Not sure why, but that's how it is.
Create a Model object that you will use to execute your query. Instead of passing the DB through the object's constructor, pass it through the method you will create:
object DBChecker {
def attemptLogin(db:Database, password:String): String = {
}}
In your method, use the method .withConnection { conn => to access your JDBC connection. So, something like this:
object DBChecker {
def attemptLogin(db:Database, password:String):String = {
var username: String = ""
db.withConnection{ conn =>
val query:String = s"SELECT uploaded_by, date_added FROM tableName where PASSWORD = $password ;"
val stmt = conn.createStatement()
val qryResult:ResultSet = stmt.executeQuery(query)
// then iterate over your ResultSet to get the results from the query
if (qryResult.next()) {
userName = qryResult.getString("uploaded_by")
}
}
}
return username
}
// but note, please look into the use of PreparedStatement objects, doing it this way leaves you vulnerable to SQL injection.
In your Controller, as long as you import the object, you can then call that object's methods from your controller you made in Step 1.
import com.path.to.object.DBChecker
#Singleton
class LoginRegController #Inject()(myDB: Database, cc: ControllerComponents ) { def attemptLogin(pass:String) = Action {
implicit request: Request[AnyContent] => {
val result:String = DbChecker.attemptLogin(pass)
// do your work with the results here
}
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.
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.
I have a mysql query that returns this type of data:
{"id"=>1, "serviceCode"=>"1D00", "price"=>9.19}
{"id"=>2, "serviceCode"=>"1D01", "price"=>9.65}
I need to return the id field based on a match of the serviceCode.
i.e. I need a method like this
def findID(serviceCode)
find the row that has the service code and return the ID
end
I was thinking of having a serviceCodes.each do |row| method and loop through and essentially go
if row == serviceCode
return row['id']
end
is there a faster / easier way?
You can use the method Enumerable#find:
service_codes = [
{"id"=>1, "serviceCode"=>"1D00", "price"=>9.19},
{"id"=>2, "serviceCode"=>"1D01", "price"=>9.65}
]
service_codes.find { |row| row['serviceCode'] == '1D00' }
# => {"id"=>1, "serviceCode"=>"1D00", "price"=>9.19}
If you use Rails Active Record as ORM and your Model named Product (only for example),
you can use something like this:
def findID(serviceCode)
Product.select(:id).where(serviceCode: serviceCode).first
end
If you have plain SQL Query in plain ruby class (not recommended), you should change this query to get only the id, as Luiggi mentioned. But aware of SQL Injections if your serviceCode coming from external Requests.