I have a table Server
#Entity(tableName = "servers")
data class ServerDto(
#PrimaryKey
#ColumnInfo(name = "server_id")
var serverId: Long,
#ColumnInfo(name = "address", defaultValue = "")
var serverAddress: String,
#ColumnInfo(name = "description", defaultValue = "")
var serverDescription: String,
#ColumnInfo(name = "file_segment")
var fileSegment: Int
) : Serializable
and a table accounts
#Entity(tableName = "accounts", primaryKeys = ["server_id", "account_id"])
data class AccountDto(
#ColumnInfo(name = "server_id")
val serverId: Long,
#ColumnInfo(name = "account_id")
val accountId: Int,
#ColumnInfo(name = "username", defaultValue = "")
val username: String,
#ColumnInfo(name = "password", defaultValue = "")
val password: String,
#ColumnInfo(name = "first_name", defaultValue = "")
var firstname: String,
#ColumnInfo(name = "last_name", defaultValue = "")
var lastname: String,
#ColumnInfo(name = "email", defaultValue = "")
var email: String,
#ColumnInfo(name = "active")
var active: Int
) : Serializable
I want to transfer 2 columns (username, password) from accounts to server and then remove them from accounts. I wrote the Migrations but i see that Android Studio does not allow to write DROP COLUMN since it underlines it with red. What is wrong with that??
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE servers ADD COLUMN username VARCHAR")
database.execSQL("ALTER TABLE servers ADD COLUMN password VARCHAR")
database.execSQL("UPDATE servers SET username = (SELECT a.username FROM accounts a where a.server_id = servers.server_id and a.active = 1)")
database.execSQL("UPDATE servers SET password = (SELECT a.password FROM accounts a where a.server_id = servers.server_id and a.active = 1)")
database.execSQL("ALTER TABLE accounts ***DROP*** COLUMN username")
database.execSQL("ALTER TABLE accounts ***DROP*** COLUMN password")
}
SQLite doesn't support column deletion straight away.
You will have to do migration steps as follows:
Source: https://www.sqlite.org/faq.html#q11
CREATE TABLE accounts_backup(serverId VARCHAR, accountId VARCHAR, firstname VARCHAR, lastname VARCHAR, email VARCHAR, active VARCHAR);
INSERT INTO accounts_backup SELECT serverId, accountId, firstname, lastname, email, active FROM accounts;
DROP TABLE accounts;
CREATE TABLE accounts(serverId VARCHAR, accountId VARCHAR, firstname VARCHAR, lastname VARCHAR, email VARCHAR, active VARCHAR);
INSERT INTO accounts SELECT serverId, accountId, firstname, lastname, email, active FROM accounts_backup;
DROP TABLE accounts_backup;
Here's a combination of the previous two answers, written in Kotlin for Android:
private val MIGRATION_3_2 = object : Migration(3,2) {
override fun migrate(database: SupportSQLiteDatabase) {
//Drop column isn't supported by SQLite, so the data must manually be moved
with(database) {
execSQL("CREATE TABLE Users_Backup (id INTEGER, name TEXT, PRIMARY KEY (id))")
execSQL("INSERT INTO Users_Backup SELECT id, name FROM Users")
execSQL("DROP TABLE Users")
execSQL("ALTER TABLE Users_Backup RENAME to Users")
}
}
}
Related
I have a composite key with a partition key that is a uuid and a composite key that is a timestamp. Here's my entity.
#Table("send")
class Send(
#PrimaryKey val key: SendKey,
#Column("activity_id")
var activityId: UUID
) : Serializable
#PrimaryKeyClass
class SendKey(
#PrimaryKeyColumn(name = "user_id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
val senderId: UUID,
#PrimaryKeyColumn(name = "created_at", ordinal = 3, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.DESCENDING)
val createdAt: Instant,
#PrimaryKeyColumn(name = "target_post_id", ordinal = 1, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.DESCENDING)
val targetUserId: UUID
): Serializable
Now, I'm trying to retrieve the unique record using sendRepository.findById(SendKey(userId = userId, createdAt = createdAt!!, targetUserId = postId)) but I don't get any results.
Here's the Repository
#Repository
interface SendRepository: ReactiveCassandraRepository<Send, SendKey> {
}
Where did I go wrong?
I'm using Jackson for parsing a default date format. Why can't I find a matching record when I specify the right format and timestamp down to microsecond precision?
Let's say I've got a list of Employees with Employee IDs. In the Create View of the controller, I have:
public ActionResult Create()
{
ViewBag.EmployeeList= db.Employees.ToList().Select(x => new SelectListItem
{
Value = x.EmployeeID.ToString(),
Text = String.Format(x.FirstName + " " + x.LastName)
});
var quote = new Quote();
return View(quote);
}
(sidenote: I'm pretty sure I've implemented the SelectList inefficiently in my code by defining new SelectList again in the Create View)
Then in the Create View itself:
<div class="form-group">
#Html.LabelFor(model => model.EmployeeID, htmlAttributes: new { #class = "control-label col-md-4 employee-list" })
<div class="col-md-8">
#Html.DropDownListFor(model => model.EmployeeID, new SelectList(ViewBag.EmployeeList, "Value", "Text"), new { #class = "form-control employee-list" })
#Html.ValidationMessageFor(model => model.EmployeeID, "", new { #class = "text-danger" })
</div>
</div>
I want to write a JS/JQuery function that gets the value of EmployeeID when the selected Employee changes. At the moment this just gives me the option number:
$(document).ready(function () {
$('.employee-list').change(function () {
console.log($(this).val());
});
});
The purpose here is that I want to use the EmployeeID to populate another DropDownList field in the Create View, such as "Assign to Manager". A Manager would have a list of EmployeeIDs, and an EmployeeID could be assigned to multiple Managers. After selecting an Employee in the Create View, JS would be used to grab the EmployeeID, send it to the backend, query the Managers table for where it's found, return that list of Managers to the JS, and then plugged into the HTML of the page.
It's possible that a subset of the Employees would be used in the DropDownList, with, for example, EmployeeIDs of [3, 5, 11, 15], so I can't just subtract 1 from the option number to get the EmployeeID.
Oops, turns out I need to learn more about SQL.
I was seeding my SQL database with data like this:
context.Employees.AddOrUpdate(x => x.EmployeeID,
new DelegationApprover() { EmployeeID = 0, FirstName = "Eileen", LastName = "Dover" }
new DelegationApprover() { EmployeeID = 1, FirstName = "Wayne", LastName = "Carr" },
new DelegationApprover() { EmployeeID = 2, FirstName = "Richard", LastName = "Head" },
);
I thought I was setting the EmployeeIDs to start from 0, but SQL forces it to start from 1. I was working with the following data, thinking I was working with the former:
context.Employees.AddOrUpdate(x => x.EmployeeID,
new DelegationApprover() { EmployeeID = 1, FirstName = "Eileen", LastName = "Dover" }
new DelegationApprover() { EmployeeID = 2, FirstName = "Wayne", LastName = "Carr" },
new DelegationApprover() { EmployeeID = 3, FirstName = "Richard", LastName = "Head" },
);
When I checked($(this).val()) on Employee change, it looked like it was returning its option number and not the ID value. As it turns out, it was returning the value I wanted the entire time.
I have problem when inserting into database. I use slick version 2.0.1-RC. I have used SourceCodeGenerator for generating source code. I have got this for table MAIN_TC_USER:
case class MainTcUserRow(id: Int, name: Option[String], surname: Option[String], username: Option[String], password: Option[String])
/** GetResult implicit for fetching MainTcUserRow objects using plain SQL queries */
implicit def GetResultMainTcUserRow(implicit e0: GR[Int], e1: GR[Option[String]]): GR[MainTcUserRow] = GR{
prs => import prs._
MainTcUserRow.tupled((<<[Int], <<?[String], <<?[String], <<?[String], <<?[String]))
}
/** Table description of table main_tc_user. Objects of this class serve as prototypes for rows in queries. */
class MainTcUser(tag: Tag) extends Table[MainTcUserRow](tag, "main_tc_user") {
def * = (id, name, surname, username, password) <> (MainTcUserRow.tupled, MainTcUserRow.unapply)
/** Maps whole row to an option. Useful for outer joins. */
def ? = (id.?, name, surname, username, password).shaped.<>({r=>import r._; _1.map(_=> MainTcUserRow.tupled((_1.get, _2, _3, _4, _5)))}, (_:Any) => throw new Exception("Inserting into ? projection not supported."))
/** Database column id PrimaryKey */
val id: Column[Int] = column[Int]("id", O.PrimaryKey)
/** Database column name */
val name: Column[Option[String]] = column[Option[String]]("name")
/** Database column surname */
val surname: Column[Option[String]] = column[Option[String]]("surname")
/** Database column username */
val username: Column[Option[String]] = column[Option[String]]("username")
/** Database column password */
val password: Column[Option[String]] = column[Option[String]]("password")
}
/** Collection-like TableQuery object for table MainTcUser */
lazy val MainTcUser = new TableQuery(tag => new MainTcUser(tag))
I have tried to insert into MainTcUser table
new DBConnection(Tables.profile).connect.withSession{
implicit session =>
Tables.MainTcUser += user
}
or
new DBConnection(Tables.profile).connect.withSession{
implicit session =>
Tables.MainTcUser.map(s => s) += user
}
In both cases I've got error:
Multiple markers at this line
- value += is not a member of
scala.slick.lifted.TableQuery[com.bsi.xpay.Tables.MainTcUser]
- value += is not a member of
scala.slick.lifted.TableQuery[com.bsi.xpay.Tables.MainTcUser]
Thanks for any help
You probably forgot to import .simple._ from you driver.
If that's not it also see Can't access delete method on Slick query which is related.
I am very naive in cassandra & am using astyanax
CREATE TABLE employees (empID int, deptID int, first_name varchar,
last_name varchar, PRIMARY KEY (empID, deptID));
i want to get the values of query:
select * from employees where empID =2 and deptID = 800;
public void read(Integer empID, String deptID) {
OperationResult<ColumnList<String>> result;
try {
columnFamilies = ColumnFamily.newColumnFamily("employees", IntegerSerializer.get(), StringSerializer.get());
result = keyspace.prepareQuery(columnFamilies).getKey(empID).execute();
ColumnList<String> cols = result.getResult();
//Other stuff
}
how should i achieve this
As far as I can find, there isn't a super clean way to do this. You have to do it by executing a cql query and then iterating through the rows. This code is taken from the astynax examples file
public void read(int empId) {
logger.debug("read()");
try {
OperationResult<CqlResult<Integer, String>> result
= keyspace.prepareQuery(EMP_CF)
.withCql(String.format("SELECT * FROM %s WHERE %s=%d;", EMP_CF_NAME, COL_NAME_EMPID, empId))
.execute();
for (Row<Integer, String> row : result.getResult().getRows()) {
logger.debug("row: "+row.getKey()+","+row); // why is rowKey null?
ColumnList<String> cols = row.getColumns();
logger.debug("emp");
logger.debug("- emp id: "+cols.getIntegerValue(COL_NAME_EMPID, null));
logger.debug("- dept: "+cols.getIntegerValue(COL_NAME_DEPTID, null));
logger.debug("- firstName: "+cols.getStringValue(COL_NAME_FIRST_NAME, null));
logger.debug("- lastName: "+cols.getStringValue(COL_NAME_LAST_NAME, null));
}
} catch (ConnectionException e) {
logger.error("failed to read from C*", e);
throw new RuntimeException("failed to read from C*", e);
}
}
You just have to tune the cql query to return what you want. This is a bit frustrating because according to the documentation, you can do
Column<String> result = keyspace.prepareQuery(CF_COUNTER1)
.getKey(rowKey)
.getColumn("Column1")
.execute().getResult();
Long counterValue = result.getLongValue();
However I don't know what rowkey is. I've posted a question about what rowkey can be. Hopefully that will help
I am using cql 3.0.0
I have executed the query:
INSERT INTO emp (empID, deptID, first_name, last_name)
VALUES (104, 15, 'jane', 'smith')
On retrieving this record, I get the following values:
empid = h
deptid = (blank value)
first_name = 'jane'
last_name = 'smith'
On searching for it, I found that h is equivalent to utf-8 character 104. Also 15 in utf-8 is blank.
(Reference Link: http://www.utf8-chartable.de/unicode-utf8-table.pl?utf8=dec&unicodeinhtml=dec )
I have set the column types to int during create table, but on retrieving I am not getting the int values.
How do I get the correct values to be retrieved. I do not want the utf-8 values.
Thanks
I am using cassandra 1.2.4
Below is my code written in phpcassa:
require_once(__DIR__.'/../lib/autoload.php');
use phpcassa\Connection\ConnectionPool;
use phpcassa\ColumnFamily;
use phpcassa\SystemManager;
use phpcassa\Schema\StrategyClass;
use cassandra\Compression;
use cassandra\ConsistencyLevel;
$pool = new ConnectionPool("prod",array('X.X.X.X','X.X.X.X'));
$raw = $pool->get();
$rows = $raw->client->set_cql_version("3.0.0");
$rows = $raw->client->execute_cql3_query('USE prod;', Compression::NONE, ConsistencyLevel::ONE );
$rows = $raw->client->execute_cql3_query('CREATE TABLE emp (
empID int,
deptID int,
first_name varchar,
last_name varchar,
PRIMARY KEY (empID, deptID));
', Compression::NONE, ConsistencyLevel::ONE );
$rows = $raw->client->execute_cql3_query('INSERT INTO emp (empID, deptID, first_name, last_name)
VALUES (104, 15, \'jane\', \'smith\');
', Compression::NONE, ConsistencyLevel::ONE );
$rows = $raw->client->execute_cql3_query('SELECT * FROM emp WHERE empID IN (2,104) ORDER BY deptID ASC;', Compression::NONE, ConsistencyLevel::ONE );
echo "<pre>";
print_r($rows);
echo "<pre>";
The output generated is:
cassandra\CqlRow Object
(
[key] =>
[columns] => Array
(
[0] => cassandra\Column Object
(
[name] => empid
[value] => h
[timestamp] =>
[ttl] =>
)
[1] => cassandra\Column Object
(
[name] => deptid
[value] =>
[timestamp] =>
[ttl] =>
)
[2] => cassandra\Column Object
(
[name] => first_name
[value] => jane
[timestamp] =>
[ttl] =>
)
[3] => cassandra\Column Object
(
[name] => last_name
[value] => smith
[timestamp] =>
[ttl] =>
)
)
)
Though a bit late answer, but I was desperately searching for the solution while writing my own cassandra-wrapper for Yii framework. I came up with something like the following class that eliminates the problem of incorrect binary to different data types in cassandra including integer types:
Yii::import('ext.phpcassa.autoload');
require_once('protected/extensions/phpcassa/autoload.php');
use phpcassa\Connection\ConnectionPool;
use phpcassa\ColumnFamily;
use phpcassa\ColumnSlice;
use phpcassa\SystemManager;
use phpcassa\Schema\StrategyClass;
use phpcassa\Schema\DataType;
class ACassandraConnection extends CApplicationComponent {
protected $_pool = null;
public $keyspace = null;
public $servers = null;
/**
* Establish connection to cassandra cluster
* #return object
*/
private function _get_raw() {
if ($this->_pool === null) {
$this->_pool = new ConnectionPool($this->keyspace, $this->servers);
}
return $this->_pool->get();
}
public function cql_query($query) {
$raw = $this->_get_raw();
$cql_result = $raw->client->execute_cql3_query($query, cassandra\Compression::NONE, cassandra\ConsistencyLevel::ONE);
$this->_pool->return_connection($raw);
return $cql_result;
}
public function cql_get_rows($cql_result) {
if ($cql_result->type == 1) {
$rows = array();
foreach ($cql_result->rows as $rowIndex => $cqlRow) {
$cols = array();
foreach ($cqlRow->columns as $colIndex => $column) {
$type = DataType::get_type_for($cql_result->schema->value_types[$column->name]);
$cols[$column->name] = $type->unpack($column->value);
}
$rows[] = $cols;
}
return $rows;
} else {
return null;
}
}
/**
* Perform garbage collection
*/
public function __destruct() {
if($this->_pool !== null) {
$this->_pool->close();
}
}
}
I will say please review your solution, i have tried exactly the same thing you described as your problem, but its working normal for me. Might be at the time of creation you have used utf-8 as their type.
Schema
CREATE COLUMNFAMILY test(empID int, deptID int, first_name text, last_name text, PRIMARY KEY(empID));
Insert
INSERT INTO emp (empID, deptID, first_name, last_name) VALUES (104, 15, 'jane', 'smith');
Retrieve
SELECT * FROM test ;
empid | deptid | first_name | last_name
-------+--------+------------+-----------
104 | 15 | jane | smith