When using the Update method on ODSController (ie using GridView / FormView in an ASP.NET application) and passing null values to nullable columns, the nullable column value remains unchanged.
This is due to the way that update method instantiate the ActiveRecord to update:
public void Update(Guid MyKey, ...)
{
MyItem item = new MyItem();
item.MarkOld();
item.IsLoaded = true;
...
item.Save(UserName);
}
By creating an empty MyItem instance (all fields are null) and setting a nullable field to null doesn' t allow the column to finish in the DirtyColumns collection (see ActiveHelper GetUpdateCommand).
Am I going to have write custom update functions for EVERY table in my database to resolve this?
Related
I have an Object that maps column names to values. The columns to be updated are not known beforehand and are decided at run-time.
e.g. map = {col1: "value1", col2: "value2"}.
I want to execute an UPDATE query, updating a table with those columns to the corresponding values. Can I do the following? If not, is there an elegant way of doing it without building the query manually?
db.none('UPDATE mytable SET $1 WHERE id = 99', map)
is there an elegant way of doing it without building the query manually?
Yes, there is, by using the helpers for SQL generation.
You can pre-declare a static object like this:
const cs = new pgp.helpers.ColumnSet(['col1', 'col2'], {table: 'mytable'});
And then use it like this, via helpers.update:
const sql = pgp.helpers.update(data, cs) + /* WHERE clause with the condition */;
// and then execute it:
db.none(sql).then(data => {}).catch(error => {})
This approach will work with both a single object and an array of objects, and you will just append the update condition accordingly.
See also: PostgreSQL multi-row updates in Node.js
What if the column names are not known beforehand?
For that see: Dynamic named parameters in pg-promise, and note that a proper answer would depend on how you intend to cast types of such columns.
Something like this :
map = {col1: "value1", col2: "value2",id:"existingId"}.
db.none("UPDATE mytable SET col1=${col1}, col2=${col2} where id=${id}", map)
I have a table userset
create table IF NOT EXISTS userset (id int primary key, name set, phone set, emails list);
Now I am executing an insert statement through datastax java driver : cassandra-driver-core-3.1.0.jar. Now I have a java.util.List of String say listString
List<String> listString = new ArrayList<String>();
listString.add("NewName");
boundStatement.setList(1, listString);
Here boundStatement is an instance of com.datastax.driver.core.BoundStatement. On index 1 i am setting the value of name in userset.
Even though the backend type of name is set and I am using BoundStatement-> setList it still executes without any errors and inputs the value in the name correctly. Is this a functionality of BoundStatement in datastax driver.
Why doesn't it throw an error when I try to setList for a parameter which is a set in the backend server?
You can say it's a bug in the datastax driver.
When you bind data with boundStatement.setList or boundStatement.setSet both method uses lookupCodec method to find the codec with the column type and don't validate the value.
But If you use statement.bind to bind data, it uses findCodec method to find the codec with column type and it's validate with the given value
if ((cqlType == null || cqlType.getName() == LIST) && value instanceof List) {
//...........
}
if ((cqlType == null || cqlType.getName() == SET) && value instanceof Set) {
//............
}
So I have the following code used as a validation method:
if (TableQuery[UsersTable].filter(_.name === login).exists.run) {
val id = TableQuery[UsersTable].filter(_.name === login).firstOption.get.id
val name = TableQuery[UsersTable].filter(_.id === id).firstOption.get.name
}
if you're wondering, I check to make sure of .exists before I query the next two times because the login value can be equal to two columns in the database.
Anyways, I get [SlickException: Read NULL value (null) for ResultSet column Path s2._5] when attempting to get the id above, and I'm unsure why. There should be a first option there because the code has already validated a row exists for the requirements typed beforehand. No "id" column values are null.
How can I get this id value working correctly?
One of the involved columns is nullable but you didn't specify it as Option[...] in the Table.
I have a requirement on adding a date column to a table with default value is set by oracle's sysdate as follows
EXAMPLE {
...
CREATED_ON DATE DEFAULT SYSDATE
}
I want to use slick table ddl to create the table using
object ExampleTable extends Table[...]("EXAMPLE") {
def createdOn = column[java.sql.Date]("CREATED_ON", Default (?))
}
it seems there is no available sysdate for the default value, should I handle this default value programmatically or is there still a way using Slick?
Thanks,
I don't believe it's possible to use O.Default for your situation. When trying O.Default(new Date()), it would default the field to the date the ddl was executed, and not to sysdate.
I think the easiest workaround would be to use DBType to define the entire column, i.e.
def createdOn = column[java.sql.Date]("CREATED_ON", DBType("date default sysdate"))
You can verify this by inspecting the ExampleTable.ddl object.
An often use-case with Cassandra is storing the data in the column names of the dynamically created column family. In this situation the row values themselves are not needed, and a usual practice is to store nulls there.
However, when dealing with Hector, it seems like there is no way to insert null value, because Hector HColumnImpl does an explicit null-check in the column's constructor:
public HColumnImpl(N name, V value, long clock, Serializer<N> nameSerializer,
Serializer<V> valueSerializer) {
this(nameSerializer, valueSerializer);
notNull(name, "name is null");
notNull(value, "value is null");
this.column = new Column(nameSerializer.toByteBuffer(name));
this.column.setValue(valueSerializer.toByteBuffer(value));
this.column.setTimestamp(clock);
}
Are there any ways to insert nulls via Hector? If not, what is the best practice in the situation when you don't care about column values and need only their names?
Try using an empty byte[], i.e. new byte[0];