Select all with Squeryl scala - scala

I'm trying to select ALL of some table in a query. I have to specify a where clause (or so I tihnk), so what goes in there?
def all() = transaction { from(AppDB.users)(s => where(WHAT GOES HERE?) select(s)).toIndexedSeq }

This should do it.
from(AppDB.users)(s => select(s))

Related

Migration on two schemas

I have 2 schemas on my db:schema1 and public and I want to create some tables there. I tried code like this in my migration:
return knex.schema
.raw('CREATE SCHEMA IF NOT EXISTS schema1;')
.createTableIfNotExists('table1', table => {
table.increments('id')
})
.withSchema('public')
.createTableIfNotExists('table2', table => {
table.increments('id')
})
And I hoped to have: schema1.table1 and public.table2 but I don't. Any ideas how to do that?
Belayer is quite correct in the comments, but I'll expand into an answer to demonstrate the syntax. You'll also need to avoid doing things like:
createTableIfNotExists('schema1.table1', table => {
per Identifier Syntax, this won't work: just get into the habit of always using withSchema.
Further, I don't recommend issuing subsequent createTables without waiting for the previous one to finish. While it might work, I think you'll run into trouble with relations etc. That makes your original code more like:
exports.up = knex =>
knex
.raw("CREATE SCHEMA IF NOT EXISTS schema1")
.then(() =>
knex.withSchema("schema1").createTableIfNotExists("table1", table => {
table.increments("id");
})
)
.then(() =>
knex.withSchema("public").createTableIfNotExists("table2", table => {
table.increments("id");
})
);

Slick - Update query with multiple tables

I'm currently facing an issue with my update query in my scala-slick3 project. I have a Report-Class, which contains multiple Products and each Product contains multiple Parts. I want to implement a function that marks every Part of every Product within this Report as assessed.
I thought about doing something like this:
def markProductPartsForReportAsAssessed(reportId: Int) = {
val query = for {
(products, parts) <- (report_product_query filter(_.reportId === reportId)
join (part_query filter(_.isAssessed === false))
on (_.productId === _.productId))
} yield parts.isAssessed
db.run(query.update(true))
}
Now, when I run this code slick throws this exception:
SlickException: A query for an UPDATE statement must resolve to a comprehension with a single table.
I already looked at similiar problems of which their solutions (like this or this) weren't really satisfying to me.
Why does slick throw this excpetion or why is it a problem to begin with? I was under the impression that my yield already takes care of not "updating multiple tables".
Thanks in advance!
I guess it's because the UPDATE query requires just one table. If you write SQL for the above query, it can be
UPDATE parts a SET isAccessed = 'true'
WHERE a.isAccessed = 'false' and
exists(select 'x' from products b
where a.productId = b.producId and b.reportId = reportId)
Therefore, you can put conditions related with 'Product' table in the filter as follows.
val reportId = "123" // some variable
val subQuery = (reportId:Rep[String], productId:Rep[String]) =>
report_product_query.filter(r => r.report_id === reportId && r.product_id === productId)
val query = part_query.filter(p => p.isAccesssed === false:Rep[Boolean] &&
subQuery(reportId, p.productId).exists).map(_.isAccessed)
db.run(query.update(true))

Inner actions are not getting executed inside transaction in slick

I have requirement where i have to insert into book table and based on auto Id generated , I have to insert into bookModules table.For every bookModule autoincrement Id , I have to insert into bookAssoc table. But bookModule is populated using seq[bookMods] and bookAssociation data is populated using Seq[userModRoles].
I have written below code to achieve this but it is only executing action1. My inner actions are not getting executed. Please help me .
val action1 =bookDao.insert(book)
val action2 = action1.map { id => DBIO.sequence(
bookMods.map { bookMod =>
bookModDao.insert(new bookModule(None, id, bookMod.moduleId, bookMod.isActive))
.map { bookModId =>
userModRoles.map { userModRole =>
bookAssocDao.insert(new bookAssociation(None, bookModId, userModRole.moduleId, userModRole.roleId))
}
}
})
}
db.run(action2.transactionally)
EDIT 1: Adding code in for comphrension
val action1 = for{
bookId<-bookDao.insert(book) // db transaction
bookMod<-bookModules// this is scala collection // Iterate each element and Insert into tables
bookModId<-bookModDao.insert(new bookModule(None, bookId, bookMod.moduleId, bookMod.isActive))
userModRole<-userModRoles //// this is scala collection // Iterate each element and Insert into tables
bookAssocDao.insert(new bookAssociation(None, bookModId, userModRole.moduleId, userModRole.roleId))
}yield()
db.run(action2.transactionally)
You need to split your logic into two parts.
1) DBIO
2) iterates over collections.
In that case, a solution should be easy. But without using for comprehension.
bookModules.map{ bookMod =>
userModRoles.map{ userModRole =>
db.run(bookDao.insert(book).flatMap{ bookId =>
bookModDao.inser(new bookModule(None, bookId, bookMod.moduleId, bookMod.isActive)).map{ bookModId =>
bookAssocDao.insert(new bookAssociation(None, bookModId, userModRole.moduleId, userModRole.roleId))
}
}).transactionally
}
}
Try something like this. It should work. You can think about move db.run to Dao classes. And here, probably it's service you should work on Futures.
And sorry if I make some mistake with parenthesis, but here it's difficult to have everything clear :)

Updating queries with Slick 3.0.2/Scala

Need to update table in slick 3.0.2 while using scala/playframework.
form.fold (
errForm => {
BadRequest();
},
data => {
** update each column of the table after running db.run
}
)
suppose your form object has 3 fields a, b, and c. then your update statement will look like
val query = db_user_info.filter(_.username === data.username).map(r => (r.a, r.b, r.c)).update(form.a, form.b, form.c)

Can I optimize this: Programmatically prepare two DataFrame's for a Union

This is under the understanding that withColumn can only take one column at a time, so if I'm wrong there I'm going to be embarrassed, but I'm worried about the memory performance of this because the DF's are likely to be very large in production. Essentially the idea is to do a union on the column arrays (Array[String]), distinct the result, and foldLeft over that set updating the accumulated DF's as I go. I'm looking for a programatic way to match the columns on the two DF's so I can perform a union afterwards.
val (newLowerCaseDF, newMasterDF): (DataFrame,DataFrame) = lowerCaseDFColumns.union(masterDFColumns).distinct
.foldLeft[(DataFrame,DataFrame)]((lowerCaseDF, masterDF))((acc: (DataFrame, DataFrame), value: String) =>
if(!lowerCaseDFColumns.contains(value)) {
(acc._1.withColumn(value,lit(None)), acc._2)
}
else if(!masterDFColumns.contains(value)) {
(acc._1, acc._2.withColumn(value, lit(None)))
}
else{
acc
}
)
Found out that it's possible to select hardcoded null columns, so my new solution is:
val masterExprs = lowerCaseDFColumns.union(lowerCaseMasterDFColumns).distinct.map(field =>
//if the field already exists in master schema, we add the name to our select statement
if (lowerCaseMasterDFColumns.contains(field)) {
col(field.toLowerCase)
}
//else, we hardcode a null column in for that name
else {
lit(null).alias(field.toLowerCase)
}
)
val inputExprs = lowerCaseDFColumns.union(lowerCaseMasterDFColumns).distinct.map(field =>
//if the field already exists in master schema, we add the name to our select statement
if (lowerCaseDFColumns.contains(field)) {
col(field.toLowerCase)
}
//else, we hardcode a null column in for that name
else {
lit(null).alias(field.toLowerCase)
}
)
And then you're able to do a union like so:
masterDF.select(masterExprs: _*).union(lowerCaseDF.select(inputExprs: _*))