Update database row by id fails - kotlin

I'm trying to update a specific row by ID :
fun updateEmployeeInfo(id:Int, firstName:String): Int {
val db = this.writableDatabase
var cv = ContentValues()
cv.put(COL_FIRSTNAME, firstName )
val result = db.update(TABLE_NAME, cv, COL_FIRSTNAME+"=?", arrayOf(firstName))
return result
}
Running this with an ID that already exists in the database it isn't updating.
screenshot of the database

You are saying update the rows with the provided (passed) first name by changing the first name to the very same first name (effectively doing nothing).
I believe that you want to use:-
val result = db.update(TABLE_NAME, cv, COL_ID+"=?", arrayOf(id.toString))
assuming that COL_ID holds the value of the id column name.
or you could use the more concise return db.update(TABLE_NAME, cv, COL_ID+"=?", arrayOf(id.toString))
This is then saying update the row where the id is the provided/passed id changing the first name, whatever it is, to the provided/passed first name.

Related

GORM query - how to use calculated field in the query and filter according to its value

Currently, I have a GORM query that calculates a counter for each table entry using a second table and returns the first table with a new field "locks_total" which doesn't exist in the original.
Now, what I want to achieve is the same table returned (with the new "locks_total" field) but filtered with "locks_total" = 0.
I can't seem to make it happen because it doesn't recognize this field in the table, what can I do to make it happen? is it possible to run the query and then execute the filter on the new result table?
This is how we currently do it-
txn := dao.postgresManager.DB().Model(&models.SecretMetadataResponse{})
txn.Table(dao.firstTableName + " as s").
Select("s.*, (SELECT COUNT(*) FROM " + dao.secondTableName + " as l where s.id = l.secret_id) locks_total ")
var secretsTotal int64
var metadataResponseEntries []models.SecretMetadataResponse
txn = txn.Count(&secretsTotal). // Saving the count before trimming according to the pagination parameters
Limit(params.Limit).
Offset(params.Offset).
Order(constants.FieldName).
Order(constants.FieldId).
Find(&metadataResponseEntries)
When the SecretMetadataResponse contains the SecretMetadata which is the same fields as in the table and the LocksTotal is the new calculated field that we want to have.
type SecretMetadataResponse struct {
SecretMetadata
LocksTotal int `json:"locks_total"`
}
Thanks in advance :)

How to write Azure storage table queries for non-existent columns

We have a storage table where we want to add a new integer column (It is in fact an enum of 3 values converted to int). We want a row to be required when:
It is an older row and the column does not exist
It is a new row and the column exists and does not match a particular value
When I just use a not equal operator on the column the old rows do not get returned. How can this be handled?
Update
Assuming a comparison always returns false for the non-existent column I tried somethinglike below (the value of the property will be always > 0 when it exists), which does not work either:
If the (Prop GreaterThanOrEqual -1) condition returns false I assume the value is null.
If not then, the actual comparison happens.
string propNullCondition = TableQuery.GenerateFilterConditionForInt(
"Prop",
QueryComparisons.GreaterThanOrEqual,
-1);
propNullCondition = $"{TableOperators.Not}({propNullCondition})";
string propNotEqualValueCondition = TableQuery.CombineFilters(
propNullCondition,
TableOperators.Or,
TableQuery.GenerateFilterConditionForInt(
"Prop",
QueryComparisons.NotEqual,
XXXX));
Note: The table rows written so far do not have "Prop" and only new rows will have this column. And expectation is the query should return all old rows and the new ones only when Prop != XXXX.
It seems that your code is correct, maybe there is a minor error there. You can follow my code below, which works fine as per my test:
Note: in the filter, the column name is case-sensitive.
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
CloudTable table = tableClient.GetTableReference("test1");
string propNullCondition = TableQuery.GenerateFilterConditionForInt(
"prop1", //note the column name shoud be case-sensitive here.
QueryComparisons.GreaterThanOrEqual,
-1);
propNullCondition = $"{TableOperators.Not}({propNullCondition})";
TableQuery<DynamicTableEntity> propNotEqualValueCondition = new TableQuery<DynamicTableEntity>()
.Where(
TableQuery.CombineFilters(
propNullCondition,
TableOperators.Or,
TableQuery.GenerateFilterConditionForInt(
"prop1",//note the column name shoud be case-sensitive here.
QueryComparisons.NotEqual,
2)));
var query = table.ExecuteQuery(propNotEqualValueCondition);
foreach (var q in query)
{
Console.WriteLine(q.PartitionKey);
}
The test result:
Here is my table in azure:

Filter result from database where row is null

I want to display all rows from database where row at specified column is empty (data is not inserted). To do that, in my onCreateLoader I wrote following code:
override fun onCreateLoader(p0: Int, p1: Bundle?): Loader<Cursor> {
val projection = arrayOf(
WalletEntry._ID,
WalletEntry.KEY_TITLE,
WalletEntry.KEY_MONEY,
WalletEntry.KEY_LAST_DATE,
WalletEntry.KEY_LAST_EXPENSE,
WalletEntry.KEY_LAST_TRANSACTION_TITLE,
WalletEntry.KEY_LOCALES,
WalletEntry.KEY_CURRENCY
)
val selection = "${WalletEntry.KEY_CURRENCY} = ?"
val selectionArgs = arrayOf("")
return applicationContext?.let { context ->
CursorLoader(context,
WalletEntry.CONTENT_URI,
projection,
selection,
selectionArgs,
null)
}!!
}
Where I want to display all results where WalletEntry.KEY_CURRENCY has no signed value, is empty. I tried to specify selectionArgs as null but it neither worked. So, how am I suppose to write selectionArgs to display all results where given row is empty?
To make my situation more clear I'll provide an app target. I'm learning kotlin and decided to write something like "bank" application where you can add different wallets and specify currencies. If you add a new currency it's being instantly added to the database to the column WalletEntry.KEY_CURRENCY. Then I have a list containing all "wallets", in which after adding a new currency an empty extra wallet appears. To avoid that I want to filter results and display only those, which do not have value passed in WalletEntry.CURRENCY column.
If you're looking for NULL values in that database column, I think you might be looking for:
val selection = "${WalletEntry.KEY_CURRENCY} IS NULL"
val selectionArgs = null
If the selectionArgs argument is not nullable, try setting it to emptyArray<String>()

Can Slick's insertOrUpdate modify a subset of columns in the event the record already exists?

In my use case I have a createdDate field that I would like to preserve in the event that the record already exists.
case class Record(id:Long, value:String, createdDate:DateTime, updateDate:DateTime)
Is it possible to use a TableQuery.insertOrUpdate(record) such that only parts of the record are updated in the event the record already exists?
In my case I'd want only the value and updateDate fields to change. Using plain SQL in a stored procedure I'd do something like:
merge Record r
using (
select #id,
#value
) as source (
id,
value
)
on r.id = source.id
when matched then
update set value = source.value, updateDate = getDate()
when not matched then
insert (id, value, createdDate, updatedDate) values
(id, value, getDate(), getDate()
Can Slick's insertOrUpdate modify a subset of columns?
No, I don't believe this is possible with the insertOrUpdate function. This has been requested as a feature but it is not currently implemented.
How can we work around this?
Since the update function does support updating a specific list of columns, we can write our own upsert logic instead of using the insertOrUpdate function. It might work like this:
def insertOrUpdate(record: Record): Future[Int] = {
val insertOrUpdateAction = for {
recordOpt <- records.filter(_.id === record.id).result.headOption
updateAction = recordOpt.map(_ => updateRecord(record))
action <- updateAction.getOrElse(insertRecord(record))
} yield action
connection.run(insertOrUpdateAction)
}
private def updateRecord(record: Record) = {
val query = for {
r <- records.filter(_.id === record.id)
} yield (r.value, r.updatedDate) // list of columns which can be updated
query.update(record.value, record.updatedDate)
}
private def insertRecord(record: Record) = records += record

How to use where in list items

I have a database as below:
TABLE_B:
ID Name LISTID
1 NameB1 1
2 NameB2 1,10
3 NameB3 1025,1026
To select list data of table with ID. I used:
public static List<ListData> GetDataById(string id)
{
var db = Connect.GetDataContext<DataContext>("NameConnection");
var sql = (from tblB in db.TABLE_B
where tblB.LISTID.Contains(id)
select new ListData
{
Name= tblB.Name,
});
return sql.ToList();
}
When I call the function:
GetDataById("10") ==> Data return "NameB2, NameB3" are not correct.
The data correct is "NameB2". Please help me about that?
Thanks!
The value 10 will cause unintended matches because LISTID is a string/varchar type, as you already saw, and the Contains function does not know that there delimiters that should be taken into account.
The fix could be very simple: surround both the id that you are looking for and LISTID with extra commas.
So you will now be looking for ,10,.
The value ,10, will be found in ,1,10, and not in ,1025,1026,
The LINQ where clause then becomes this:
where ("," + tblB.LISTID + ",").Contains("," + id + ",")