Avoid Table initialize to create table in Squeryl/Activerecord - scala

I have a database schema defined in mySQL already and I want to work on the play-2 with ActiveRecord application on top of it.
However, when I start up the project, it gives me error:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'user' already exists
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'user' already exists
and it is triggered by
org.squeryl.Schema.create(Schema.scala:181)
models.Tables$.initialize(Tables.scala:7)
This is how it looks in my Tables.scala
object Tables extends ActiveRecordTables with PlaySupport {
val users = table[User]
}
and my User.scala is:
case class User(
override val id: Long,
#Length(max=50) login: String
) extends ActiveRecord {
lazy val role = belongsTo[Role]
}
object User extends ActiveRecordCompanion[User]
I tried to skip this in my global.scala
override def onStart(app: Application) {
//Tables.initialize
}
However, it still give me the same error
Is that anyway I can bypass the create table part?
Many thanks!

Do you already have a user table in your database with a different schema?
Since you are using the PlaySupport trait, I am guessing you are using the Scala ActiveRecord Play2.1 Plugin. As noted in the wiki of that project, add the following settings in conf/play.plugins
9999:com.github.aselab.activerecord.ActiveRecordPlugin
The ActiveRecordPlugin class initializes the tables on startup. So you shouldn't have to do that from your Global onStart

Maybe you use something like MyDatabaseLibrary.create() yourself ?
Check it out. You may try to search the directory for occurences of .create

I figure it out the issue by commenting out some of the table schema in Tables.scala.
I have multiple tables declared in Table object and one of them is not existed in the database, for example:
object Tables extends ActiveRecordTables with PlaySupport {
val users = Table[User]
val role = Table[Role]
val group = Table[Group] //not exist which cause the error!
}
If one of the table is not exist in the database, the framework will create ALL tables in the order that listed in the object.
I did try to arrange the non-existing record to the top and the framework would create the table and failed to run. However, if a situation as listed above, it would give error: table 'user' is already declared and NO table would be created in database.
Would raise as a bug to Activerecord and see if there's a solution.

Related

Best practise for inserting records with slick 3.x

Can someone tell me what the best practice is for inserting records with slick 3.x?
I want a simple pattern of insert a record, and the response should be the model with the updating primary key value.
case class User(int: Int, name: String, email: String)
I want to do the following:
Insert a new record
Return the model (User) with the updating PK value for the id property
Throw an exception if the insert failed, which I believe is when the insert returns less than 0 right?
I am using postgresql if that matters.
The docs have this:
val userWithId =
(users returning users.map(_.id)
into ((user,id) => user.copy(id=Some(id)))
) += User(None, "Stefan", "Zeiger")
Is there a helper function that I could use in my entire DB layer that will also return an exception if the insert failed? i.e. if it is successful, return the user with Id otherwise throw an exception.
As #Laurece Bird mentioned, there's an answer already. Despite the fact that is aimed to slick 2.x, it should work on slick 3.x
Have you tried? Are you having any error?
Still, the logic it's the same, try returning something, and embrace the method on a java try/catch or in a scala Try

OrientDB - Linking Records in a Transaction Does not Work

Scenario
I have two classes. Schema given below;
CLASS B {
PROPERTY name STRING
}
CLASS A {
PROPERTY name STRING
PROPERTY bLinkList LINKLIST B
}
I want to insert a record to Class B, insert a record to Class A and link new record of Class B to the new record of Class A. I want to do this in a transaction.
Code
I'm using a server side function for doing this. Following is the code.
db.begin();
var bRid = db.command("INSERT INTO B (name) VALUES(\"Jack\") RETURN #rid");
db.command("INSERT INTO A (name) VALUES(\"Jack\")");
db.command("UPDATE A ADD bLinkList = " + bRid);
db.commit();
Facts
I'm using OrientDB Version : 2.0.3. My DB is a Document DB
Observation
With in a transaction, this does not work. For bLinkList in Class A, null is inserted
With out the transaction this works.
I've checked the rid returned after insertion with in the transaction and as expected they are temporary rids. As per documentation and few forum posts I've referred, the records are sent to the server and the transaction is re-created in the server side before the commit, hence the consistency of the temporary rids created with in the transaction at client side are maintained.
Unfortunately this does not work. Some help to figure out what's going in here would be highly appreciated.
Cheers!
Omega

Entity Framework : map duplicate tables to single entity at runtime?

I have a legacy database with a particular table -- I will call it ItemTable -- that can have billions of rows of data. To overcome database restrictions, we have decided to split the table into "silos" whenever the number of rows reaches 100,000,000. So, ItemTable will exist, then a procedure will run in the middle of the night to check the number of rows. If numberOfRows is > 100,000,000 then silo1_ItemTable will be created. Any Items added to the database from now on will be added to silo1_ItemTable (until it grows to big, then silo2_ItemTable will exist...)
ItemTable and silo1_ItemTable can be mapped to the same Item entity because the table structures are identical, but I am not sure how to set this mapping up at runtime, or how to specify the table name for my queries. All inserts should be added to the latest siloX_ItemTable, and all Reads should be from a specified siloX_ItemTable.
I have a separate siloTracker table that will give me the table name to insert/read the data from, but I am not sure how I can use this with entity framework...
Thoughts?
You could try to use the Entity Inheritance to get this. So you have a base class which has all the fields mapped to ItemTable and then you have descendant classes that inherit from ItemTable entity and is mapped to the silo tables in the db. Every time you create a new silo you create a new entity mapped to that silo table.
[Table("ItemTable")]
public class Item
{
//All the fields in the table goes here
}
[Table("silo1_ItemTable")]
public class Silo1Item : Item
{
}
[Table("silo2_ItemTable")]
public class Silo2Item : Item
{
}
You can find more information on this here
Other option is to create a view that creates a union of all those table and map your entity to that view.
As mentioned in my comment, to solve this problem I am using the SQLQuery method that is exposed by DBSet. Since all my item tables have the exact same schema, I can use the SQLQuery to define my own query and I can pass in the name of the table to the query. Tested on my system and it is working well.
See this link for an explanation of running raw queries with entity framework:
EF raw query documentation
If anyone has a better way to solve my question, please leave a comment.
[UPDATE]
I agree that stored procedures are also a great option, but for some reason my management is very resistant to make any changes to our database. It is easier for me (and our customers) to put the sql in code and acknowledge the fact that there is raw sql. At least I can hide it from the other layers rather easily.
[/UPDATE]
Possible solution for this problem may be using context initialization with DbCompiledModel param:
var builder = new DbModelBuilder(DbModelBuilderVersion.V6_0);
builder.Configurations.Add(new EntityTypeConfiguration<EntityName>());
builder.Entity<EntityName>().ToTable("TableNameDefinedInRuntime");
var dynamicContext = new MyDbContext(builder.Build(context.Database.Connection).Compile());
For some reason in EF6 it fails on second table request, but mapping inside context looks correct on the moment of execution.

EclipseLink “drop-and-create-tables” no added column in inherited class, declired in super class with InheritanceType.TABLE_PER_CLASS

In already existing table structure inheritance I am adding a new column type (I cut some of the code)
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Account {
......
#Column // already existed column
private String name; // get/set also applied
#Column(length=20) // new added column
#Enumerated(EnumType.STRING) // get/set also applied
private AccountType type;
..........
}
#Entity
public User extends Account {
................ // some other already existed fields
}
In my persistence.xml file I am using next strategy policy for DDL generation
property name="eclipselink.ddl-generation" value="drop-and-create-tables"
When DDL generation is processing the new added column type in Account table is successfully created, BUT for User table there is no such kind of column at all (the strategy is TABLE_PER_CLASS).
I fixed that when i drop the database and created it again. After that the current generation of DLL was applied - type in User is also added as a column. Does someone "met" with such kind of issue ? I fixed with with drop and create of the DB but I am not sure that should be the strategy in same cases in future, specially for production DB
Thanks,
Simeon Angelov
DDL generation is for development not production. The problem you are seeing is because when the table already exists, it cannot be created with the new field. Drop and create or the "create-or-extend-tables" feature will work if you are adding to the tables as described here http://wiki.eclipse.org/EclipseLink/DesignDocs/368365

Preceding any database access with specific command in CakePHP

I'm new to CakePHP and using version 1.3.
How can I dynamically change the 'schema' property as found in DATABASE_CONFIG prior to any database operation? What is the class where I could have the postgres-specific command "set search_path to 'schema_xyz'" executed before any database interaction?
I want to use Postgres' ability to maintain multiple distinct namespaces (aka schema in postgres parlance) within a single database to implement multi-tenancy in my application. That is, every namespace will contain the same set of tables, but evidently with different content. Here, it's important not to understand schema as meaning table metadata, but rather as the postgres-specific concept of namespace where a schema is a container for tables. The exact Postgres command isn't important. What is, is the mechanism by which it can be invoked, and steering clear of Cake's typical meaning of table description, as seen in the SchemaShell. The only place I have found where Cake exposes the concept of namespace is in the database.php file, which is then used when the DB connection is first established. See: api13.cakephp.org/view_source/dbo-postgres/#line-113 (new user link limit, sorry)
if ($this->connection) {
$this->connected = true;
$this->_execute("SET search_path TO " . $config['schema']);
I want to set that search_path before ALL DB queries, not just at connection time as is currently done.
As a proof of concept, I have tried setting $useDbConfig in my models, but according to the debug output where the SQL commands are printed, this only seems to affect a subset of all queries. I've moved this up into app_model.php with the same result. As did augmenting that with creating a db_config instance on the fly and passing to the ConnectionManager through loadDataSource. Maybe I should slap that code in all flavors of before... methods.
I have seen many posts online where people discuss using one of several DB configurations in database.php to use different databases for dev, lab and production environments. But I have a single database with multiple namespaces/schemas. Also, my number of such namespaces will be too high and dynamic to make hardcoding a new variable in database.php practical.
Thus, where is the spot in CakePHP where I could insert something to set the search_path prior to any database command? I'll deal with optimizing that later. Remember that I'm new to Cake, so try to be as specific as you can. Let me know if I can clarify this question.
Thanks in advance. Here's the partially working code snippet:
class AppModel extends Model {
function beforeFind($queryData)
{
App::import("ConnectionManager");
$cm = &ConnectionManager::getInstance();
$namespace = 'xyz_namespace'; //name of the new schema/namespace/search path
$new_db_config_name = 'new_config'; //name for the new DB config to be used in the ConnectionManager
$new_db_config = $cm->config->default; //copy the 'default' DB config into an array
$new_db_config['schema'] = $namespace; //change/add the new schema/namespace/search path
$cm->create($new_db_config_name, $new_db_config); //turn the array into a DbConfig object
$cm->loadDataSource($new_db_config_name); //load the new DbConfig into the ConnectionManager
$this->useDbConfig = $new_db_config_name; //tell the model to new use the Db Config
return $queryData;
}
}
There is a very simple way in PostgreSQL if you want to switch schema per login role:
ALTER ROLE foo SET search_path=bar, public;
ALTER ROLE baz SET search_path=bam, public;
Thus a connection initiated by that role has that search_path set automatically.
If your login names are the same as the desired schema names, there is an even simpler way, I quote the fine manual:
If one of the list items is the special value $user, then the schema
having the name returned by SESSION_USER is substituted, if there is
such a schema. (If not, $user is ignored.)
But be advised that - the fine manual again:
Role-specific variable settings take effect only at login; SET ROLE
and SET SESSION AUTHORIZATION do not process role-specific variable
settings.
If I understand your question correctly, (bear with me, I know little about Postgres but basically I think you mean, reloading the schema whenever the table perspective changes?), here's how to dynamically switch schemas in your controller:
// Model::getDataSource()->configKeyName holds whichever db config you're using
if ($this->Model->getDataSource()->configKeyName != 'default') {
// do something...
$this->loadModel("Special")
$this->Model->table = "extras";
$this->Model->schema(true);
} else {
// predictably, Model::setDataSource($configKey) changes configs
$this->Model->setDataSource("offsite"); // this could be a string variable
}
Or from the model, $this->getDataSource()->configKeyName and $this->schema(true) and so forth. Note $this->schema(true) actually reloads the model schema and registers it with cake. app_model, a component, or config/bootstrap might be an appropriate place for this. I'm not sure where Cake would have defined the search_path the first time, but it would almost certainly be a property of the dataSource object and could be redefined there just like the table name, etc. And then reload Cake's schema to register the changed path. It is necessary to ensure Cake unloads any default it may have picked up, and load the correct schema based on the currently defined table. (It sounds like this may have been the only step you were missing.)
If this does not answer your question or if I misunderstood, let me know. HTH. :)