can I set sysdate as default value on a Slick table's date column - slick

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.

Related

Inserting Timestamp Into Snowflake Using Python 3.8

I have an empty table defined in snowflake as;
CREATE OR REPLACE TABLE db1.schema1.table(
ACCOUNT_ID NUMBER NOT NULL PRIMARY KEY,
PREDICTED_PROBABILITY FLOAT,
TIME_PREDICTED TIMESTAMP
);
And it creates the correct table, which has been checked using desc command in sql. Then using a snowflake python connector we are trying to execute following query;
insert_query = f'INSERT INTO DATA_LAKE.CUSTOMER.ACT_PREDICTED_PROBABILITIES(ACCOUNT_ID, PREDICTED_PROBABILITY, TIME_PREDICTED) VALUES ({accountId}, {risk_score},{ct});'
ctx.cursor().execute(insert_query)
Just before this query the variables are defined, The main challenge is getting the current time stamp written into snowflake. Here the value of ct is defined as;
import datetime
ct = datetime.datetime.now()
print(ct)
2021-04-30 21:54:41.676406
But when we try to execute this INSERT query we get the following errr message;
ProgrammingError: 001003 (42000): SQL compilation error:
syntax error line 1 at position 157 unexpected '21'.
Can I kindly get some help on ow to format the date time value here? Help is appreciated.
In addition to the answer #Lukasz provided you could also think about defining the current_timestamp() as default for the TIME_PREDICTED column:
CREATE OR REPLACE TABLE db1.schema1.table(
ACCOUNT_ID NUMBER NOT NULL PRIMARY KEY,
PREDICTED_PROBABILITY FLOAT,
TIME_PREDICTED TIMESTAMP DEFAULT current_timestamp
);
And then just insert ACCOUNT_ID and PREDICTED_PROBABILITY:
insert_query = f'INSERT INTO DATA_LAKE.CUSTOMER.ACT_PREDICTED_PROBABILITIES(ACCOUNT_ID, PREDICTED_PROBABILITY) VALUES ({accountId}, {risk_score});'
ctx.cursor().execute(insert_query)
It will automatically assign the insert time to TIME_PREDICTED
Educated guess. When performing insert with:
insert_query = f'INSERT INTO ...(ACCOUNT_ID, PREDICTED_PROBABILITY, TIME_PREDICTED)
VALUES ({accountId}, {risk_score},{ct});'
It is a string interpolation. The ct is provided as string representation of datetime, which does not match a timestamp data type, thus error.
I would suggest using proper variable binding instead:
ctx.cursor().execute("INSERT INTO DATA_LAKE.CUSTOMER.ACT_PREDICTED_PROBABILITIES "
"(ACCOUNT_ID, PREDICTED_PROBABILITY, TIME_PREDICTED) "
"VALUES(:1, :2, :3)",
(accountId,
risk_score,
("TIMESTAMP_LTZ", ct)
)
);
Avoid SQL Injection Attacks
Avoid binding data using Python’s formatting function because you risk SQL injection. For example:
# Binding data (UNSAFE EXAMPLE)
con.cursor().execute(
"INSERT INTO testtable(col1, col2) "
"VALUES({col1}, '{col2}')".format(
col1=789,
col2='test string3')
)
Instead, store the values in variables, check those values (for example, by looking for suspicious semicolons inside strings), and then bind the parameters using qmark or numeric binding style.
You forgot to place the quotes before and after the {ct}. The code should be :
insert_query = "INSERT INTO DATA_LAKE.CUSTOMER.ACT_PREDICTED_PROBABILITIES(ACCOUNT_ID, PREDICTED_PROBABILITY, TIME_PREDICTED) VALUES ({accountId}, {risk_score},'{ct}');".format(accountId=accountId,risk_score=risk_score,ct=ct)
ctx.cursor().execute(insert_query)

Convert single UDT object to list of UDT in Cassandra table

I have two userdefined type in Cassandra. First one is using the second object as frozen object inside it.
CREATE TYPE my_keyspace.test (
testid text,
testdate text,
testdata frozen<testdata>
);
CREATE TYPE my_keyspace.testdata (
subject text,
metadata text
);
Now my requirement is to convert this single object to list of UDT . Something like this
CREATE TYPE my_keyspace.test (
testid text,
testdate text,
testdata list<frozen<testdata>>
);
Is it possible to update single object to list of object in Cassandra. Whata are options available to update the schema.
The only way to do it, is to add another field with required type using the ALTER TYPE, and start to use this new field, migrating existing data using some code. Cassandra doesn't allow to change type of the existing fields, and you can't also drop a field from UDT. So your type should be something like this:
CREATE TYPE my_keyspace.test (
testid text,
testdate text,
testdata frozen<testdata>
testdata_lst list<frozen<testdata>>
);
Existing data could be migrated into a list, and then set to null to free the space.

Cassandra: Set collection boolean, how to?

I am making a columnfamily that will save values of different sensors.
Sensor_04 will have boolean values of 4 different doors. door1, door2, door3,door4.
The goal is to be able to query and ask for is door1,2,3 or 4 true or false?
How is the syntax done for this? Cause i know my example is false:
CREATE COLUMNFAMILY lockSystem (sID int, sNamn text, doors set<boolean>, PRIMARY KEY(sID));
Wrong --->
INSERT INTO lockSystem (sID, sNamn, doors) VALUES (4,'Sensor_04' {'door1:True','door2:False','door3:False','door4:false'});
I hope my question makes sense, my goal is something like this:
Sensor_4: sID int, sName text, set: door1 bool, door2 bool, door3 bool, door4 bool
You could assume that if a door is present in your set then its value is true, and then yuo can use the filtering capabilities of C* to query your data.
So I'd change the model to something like:
CREATE TABLE lockSystem (
sID int,
sNamn text,
doors set<text>,
PRIMARY KEY(sID)
);
where the doors set has been changed to a set of text. You then add data into your set when one door alarm gets "high" with:
UPDATE lockSystem SET doors = doors + { '1' } WHERE sID = ?;
To filter you data you can then use:
SELECT * FROM lockSystem WHERE doors CONTAINS '1';
Have a look at the using the set type documentation, and on how to filter data in a collection.

Update time and remaining time to leave for cassandra row

How can I tell when a certain row was written, when is it going to be discarded?
I've searched for that info but couldnt find it.
Thanks.
Using the WRITETIME function in a SELECT statement will return the date/time in microseconds that the column was written to the database.
For example:
select writetime(login) from user;
Will return something like:
writetime(login)
------------------
1439082127862000
When you insert a row with a TTL (time-to-live) in seconds, for example:
INSERT INTO user(login) VALUES ('admin') USING TTL 60;
Using the TTL function in a SELECT statement will return the amount of seconds the data inserted has to live.
For example:
select ttl(login) from user;
Will return something like:
ttl(login)
------------------
59
If you don't specify a TTL, the above query will return:
ttl(login)
------------------
null
If you're in Casandra 2.2+, you can create a user-defined function (UDF) to convert the microseconds returned by WRITETIME to a more readable format.
To use user-defined functions, enable_user_defined_functions must be set to true in cassandra.yaml file.
Then, in cqlsh create a function like the following:
CREATE OR REPLACE FUNCTION microsToFormattedDate (input bigint) CALLED ON NULL INPUT RETURNS text LANGUAGE java AS 'return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS").format( new java.util.Date(input / 1000) );';
User-defined functions are defined within a keyspace. If no keyspace is defined, the current keyspace is used.
Now using the function:
select microsToFormattedDate( writetime(login) ) from user;
Will return something like this:
social.microstoformatteddate(writetime(login))
-----------------------------------------------
2015-08-08 20:02:07,862
Use writetime method in cql to get the time the column was written.
select writetime(column) from tablename where clause

Alter a Column with migration file?

Using orchad 1.6 in the migration file I have just altered a table and added a column. I need this column to be NotNull, but it doesnt allow you to alter a table enter a NotNull type, so i've used Nullable and entered data into the existing columns.
I then want to edit this column and change it to a Nullable, but am unsure how....
public int UpdateFrom37()
{
SchemaBuilder.AlterTable("ManufacturedProductOrders", table => table
.AddColumn<DateTime>("DateOrdered", c => c.Nullable())
);
return 38;
}
public int UpdateFrom38()
{
SchemaBuilder.AlterTable("ManufacturedProductOrders", table => table
.AlterColumn("DateOrdered", c => c.WithType(dbType.???????????
);
}
I guess you want to change from NULL to NOT NULL, right? The code above clearly states that you already have a nullable column.
AlterColumn command does not currently allow changing column 'nullability'.
Your best option is to issue a manual ALTER TABLE command through SchemaBuilder.ExecuteSql() or directly in the database. You can read about it eg. here.

Resources