I am a newbie to wewb2py,is it possible to create at runtime a model of a legacy database, for using DAL with it? I saw that there are some scripts that create the model file, but I do not know whether it is correct to put this file in the model directory of my application, I think not, I did some experiments, I can connect to the database with DAL querying its tables and for every table I can get the definition of the fields, the I tried to define the table with define_table,it works but try to create the table on the database and return an error because the table already exists; this is the relevant part of my code:
conn_string = "mysql://{0}:{1}#{2}/{3}".format(user,pwd,host,db_name)
db = DAL(conn_string)
db.define_table('test1',Field('prova','string'))
it works only the first time, when the table test1 does not exist yet on the database, I do not need to create the tables only work with their data, can you put me on the right way?
db = DAL(conn_string, migrate_enabled=False)
The above will prevent web2py from doing any migrations, including attempting to create any tables.
Related
I have access to a remote database, and I would like to dump the schema and data of several views onto my local machine and load this into my local database as tables in a quick and easy way.
I lack the user privileges to run CREATE TABLE AS (SELECT * FROM target_view), otherwise this would be trivial to solve. In other words, I want to retrieve and recreate the "composite" schema of target_view as if it were a table.
I do not want the output of SHOW CREATE VIEW, as this only shows a complex SELECT statement with joins to various tables on remote I have limited ability to access. And a problem I'm seeing in MySQL 8.x is when I run SHOW CREATE TABLE on the view, this command simply acts as an alias of SHOW CREATE VIEW (which is reasonable).
Frustratingly, I can run DESCRIBE and see the schema of these views as they were tables. I really just need to convert this information into a CREATE TABLE statement without actually being able to run CREATE TABLE.
In case it weren't obvious, the key is to avoid manual reconstruction of these views' tabular schemas (as they may change in the future). I also want to avoid the solution of reverse engineering a generic table construction of 20-30 generic VARCHAR or TEXT columns from a CSV dump.
I don't know of any way to display the metadata of a result set in CREATE TABLE syntax.
What I would do given your circumstance is first create on your local MySQL instance the base table and the view, then you can use the CREATE TABLE AS SELECT ... syntax to produce a concrete table to match the metadata of the view result set.
I have an old app built in Rails 3 using MongoDB for the database (Mongoid as the adapter).
I am moving it to Rails 4 and using MySQL. My plan is to map the collections into their own tables through a script and copy the data. I'm comfortable doing that part. What I cannot for the life of me figure out is how to connect to the MySQL DB.
I have created the new app in Rails 4 and the new DB and, as an example, a table for Contacts which maps to the collection in the MongoDB. What I want to do is find all contacts in Mongo, then connect to the MySQL DB and insert the records into the table.
How do I do that last part?
Thanks
Robin
I managed to do this as follows.
1) Created the db schema in the new application. At this stage I didn't worry about associations as I would be setting association ids manually.
2) In a file I called transition.rb in the old app, I defined migration classes for each of the classes I wanted to transfer e.g. for the class Product, I defined a transition class called NewProduct using the following pattern:
class NewProduct < ActiveRecord::Base
file = File.open("#{Rails.root}" + "/config/database.yml")
dbconfig = YAML::load(file)
establish_connection(dbconfig["development"])
self.table_name = "products"
end
By adding the mysql2 gem to the old MongoDB application, I was able to use this pattern to connect to the relevant tables in the new application.
3) For each of the classes, I then iterated over the existing records, mapping them to the new tables through the migration classes. There are some challenges where MySQL doesn't have the columns available to map directly e.g. no Array column type in MySQL. For these situations, I created a separate class and manually created associations.
There were certainly some parts of trial and error but on the whole it has worked quite well. The only part I couldn't complete programatically was associating uploaded images and documents back to the relevant products however due to the file naming structure for those uploads, it won't be a huge amount of manual effort to create the associations.
For those who are interested this is the gist of the file I used.
I'm a beginner in Rails and I have a complete database designed with a database design tool. (For a startup so quite confidential)
Can I write all the tables and their columns straigth into the migration file and then migrate or should I run the >> rails generate model ... for every table in my database?
And what about the join tables? Do I need to create them to or do they get created when I write the table classes for association?
I have some experience in MySQL from school so things are a litle strange switching to Rails.
Thanks!
I think you need to read more about migrations, specially for join-table, association-tables.
For your question to create all databases, and all tables in one migration file, I think that is valid, but that is bad, you can write code as the following:
class CreateTables < ActiveRecord::Migration
def change
create :table_1 do |t1|
t1.string :name
end
create :table_2 do |t2|
t2.string :name
end
# this for join table
create_join_table :table_1, :table_2
# this for associations
add_reference :table_1, :table_2, index: true
end
end
But this tables will create in your database that is called database.yml file, and you can see your tables using mysql, but if you want to use active-record functions as(new, create, update, save, validations, ...), so you'll need to create model for these tables
rails generate model is just a template generator to create
a migration file under db/migrate
a model file under app/models with some template
some related test files
All of these can be done manually.
In your case, you can create your migration file (for building the tables) and model file separately, no need to stick with generate function.
(1)Can I write all the tables and their columns straight into the migration file and then migrate?
Yes, you can, but I would not recommend it. Because at first you need to create migration files in the db/migrate directory and definition migration class by yourself, I think it is very boring. If Rails can help you do this , you doesn't need to do it yourself, but you should understand how migration works. Secondly, create you needed tables at present unless just a test or small rails application, because customer(maybe yourself) needs and expectations are changing. Perhaps the end you doesn't use some tables at all or change tables frequently.
(2)should I run the >> rails generate model ... for every table in my database?
You are a beginner in Rails, so am I. I suggest you use the rails generate command to create tables, models, controllers..., this is the foundation of Rails learning, and it is very convenience.
(3)And what about the join tables? Do I need to create them to or do they get created when I write the table classes for association?
You can create it by yourself, can also use rails generate command.
Rails guide can provide you with direction and help.
I am using Laravel 4 to build a site that uses a large number of mysql databases, where each database has multiple tables. The structure and organization of the databases is not within my control.
I need to be able to replicate a table from one database in another database at run time (the source database and destination database (and the specific table within the source database are dependent on choices made by the user).
Duplicating a table is easy to do with mysql:
CREATE TABLE database2.new_table LIKE database1.original_table;
INSERT INTO database2.new_table SELECT * FROM database1.original_table;
but I cannot figure out how to do it with Laravel.
I can easily access each database by creating their own connections ('mysql1' and 'mysql2') but I can't figure out how to construct the statement to use both. The following doesn't work
$success = DB::connection('mysql2')->statement('CREATE TABLE new_table LIKE database1.original_table);
because I am trying to access database1 directly without using the 'mysql1' connection, and Laravel generates an error saying that database1.original_table doesn't exist.
I feel like the solution should be obvious but don't have enough experience with Laravel to figure it out. Any guidance would be greatly appreciated.
I would like to implement a custom database initialization strategy so that I can:
generate the database if not exists
if model change create only new tables
if model change create only new fields without dropping the table and losing the data.
Thanks in advance
You need to implement IDatabaseInitializer interface.
Eg
public class MyInitializer : IDatabaseInitializer<MyDbContext>
{
public void InitializeDatabase(MyDbContext context)
{
//your logic here
}
}
And then set your initializer at your application startup
Database.SetInitializer<ProductCatalog>(new MyInitializer());
Here's an example
You will have to manually execute commands to alter the database.
context.ObjectContext.ExecuteStoreCommand("ALTER TABLE dbo.MyTable ADD NewColumn VARCHAR(20) NULL");
You can use a tool like SQL Compare to script changes.
There is a reason why this doesn't exist yet. It is very complex and moreover IDatabaseInitializer interface is not very prepared for such that (there is no way to make such initialization database agnostic). Your question is "too broad" to be answered to your satisfaction. With your reaction to #Eranga's correct answer you simply expect that somebody will tell you step by step how to do that but we will not - that would mean we will write the initializer for you.
What you need to do what you want?
You must have very good knowledge of SQL Server. You must know how does SQL server store information about database, tables, columns and relations = you must understand sys views and you must know how to query them to get data about current database structure.
You must have very good knowledge of EF. You must know how does EF store mapping information. You must be able to explore metadata get information about expected tables, columns and relations.
Once you have old database description and new database description you must be able to write a code which will correctly explore changes and create SQL DDL commands for changing your database. Even this look like the simplest part of the whole process this is actually the hardest one because there are many other internal rules in SQL server which cannot be violated by your commands. Sometimes you really need to drop table to make your changes and if you don't want to lose data you must first push them to temporary table and after recreating table you must push them back. Sometimes you are doing changes in constraints which can require temporarily turning constrains off, etc. There is good reason why tools which do this on SQL level (comparing two databases) are probably all commercial.
Even ADO.NET team doesn't implemented this and they will not implement it in the future. Instead they are working on something called migrations.
Edit:
That is true that ObjectContext can return you script for database creation - that is exactly what default initializers are using. But how it could help you? Are you going to parse that script to see what changed? Are you going to execute that script in another connection to use the same code as for current database to see its structure?
Yes you can create a new database, move data from the old database to a new one, delete the old one and rename a new one but that is the most stupid solution you can ever imagine and no database administrator will ever allow that. Even this solution still requires analysis of changes to create correct data transfer scripts.
Automatic upgrade is a wrong way. You should always prepare upgrade script manually with help of some tools, test it and after that execute it manually or as part of some installation script / package. You must also backup your database before you are going to do any changes.
The best way to achieve this is probably with migrations:
http://nuget.org/List/Packages/EntityFramework.SqlMigrations
Good blog posts here and here.