I need to build a Ruby on Rails database which can handle multiple “modules” which provide various related sets of functionality. I'd like some way of grouping the module tables by their modules, almost akin to namespaces.
Is the : character safe for use in table names with Ruby on Rails, and if not, what's a good alternative?
That really depends on the database provider. If you're using mysql or some other sql based database, I'd say that : isn't permitted, but what you can do is modify the migration file to name the table something like modulename_modelname. Then in the model itself you can specify the table name by calling set_table_name as documented here:
http://api.rubyonrails.org/classes/ActiveRecord/Base.html#method-c-set_table_name
That just looks dangerous and ugly to me. I'd stick with prepending something with underscores.
admin_users
admin_tools
supervisor_charts
etc
Related
I'm using Knex, because I'm working on an application that I would like to use with multiple database servers, currently Sqlite3, Postgres and MySQL.
I'm realizing that this might be more difficult that I expected.
On MySQL, it appears that this syntax will return an array with an id:
knex('table').insert({ field: 'value'}, 'id');
On postgres I need something like this:
knex('table').insert({ field: 'value'}, 'id').returning(['id']);
In each case, the structure they return is different. The latter doesn't break MySQL, but on SQlite it will throw a fatal error.
The concept of 'insert a record, get an id' seems to exist everywhere though. What am I missing in Knex that lets me write this once and use everywhere?
Way back in 2007, I implemented the database access class for a PHP framework. It was to support MySQL, PostgreSQL, SQLite, Microsoft SQL Server, Oracle, and IBM DB2.
When it came time to support auto-incremented columns, I discovered that all of these implement that feature differently. Some have SERIAL, some have AUTO-INCREMENT (or AUTOINCREMENT), some have SEQUENCE, some have GENERATED, some support multiple solutions.
The solution was to not try to write one implementation that worked with all of them. I wrote classes using the Adapter Pattern, one for each brand of SQL database, so I could implement each adapter class tailored to the features supported by the respective database. The adapter satisfied an interface that I defined in my framework, to allow the primary key column to be defined and the last inserted id to be fetched in a consistent manner. But the internal implementation varied.
This was the only sane way to develop that code, in my opinion. When it comes to variations of SQL implementations, it's a fallacy that one can develop "portable" code that works on multiple brands.
I have a scala application that manages multiple MySQL database schemas, which includes modifying (adding, renaming, etc.) tables. The commands are issued over a connection pool that connects to a generic management database in the database server.
Because the application is designed to be cross-database, I use JOOQ to render SQL queries (execution is done via a separate JDBC module).
I experience issues with JOOQs alterTable(...).renameTo(...) DSL - consider the following example:
We have a table "TestTable" in database "TestDatabase". Let's say I want to rename that table simply to "Foo", keeping it in "TestDatabase".
This code:
...
val context = DSL.using(SQLDialect.MYSQL_5_7)
val query = context
.alterTable(table(name("TestDatabase", "TestDatabase")))
.renameTo(name("TestDatabase", "Foo"))
...
Generates: ALTER TABLE `TestDatabase`.`TestTable` RENAME TO `Foo`
However, since the connection pool I'm using is connected to my management database, it just renames the table to "Foo" and moves it to my management database. I would have expected the SQL to be: ALTER TABLE `TestDatabase`.`TestTable` RENAME TO `TestDatabase`.`Foo`. I tried a variety of alternatives to invoke the .renameTo method and convice it to use the fully qualified name, to no avail:
.renameTo(table(name(...) -> same behaviour.
.renameTo("`TestDatabase`.`Foo`") -> Escapes the name with backticks, treats it as one name instead of a qualified name.
I'm wondering if I'm missing something, if this is intended behaviour, or maybe even a bug or design shortcoming of JOOQ.
Is there a way to rename the table using fully qualified names?
Thank you!
That's a bug in jOOQ: https://github.com/jOOQ/jOOQ/issues/8042
Your workaround is close. This doesn't work:
.renameTo("`TestDatabase`.`Foo`")
As you've noticed, behind the scenes, the DSL.name() API is used to wrap the target name, because the renameTo() method doesn't implement the plain SQL templating API. You can, however, explicitly use plain SQL templating by writing as a workaround:
.renameTo(table("`TestDatabase`.`Foo`"))
I need to update a C# application that imports data into a database using LINQ. I am new to LINQ. The problem I am trying to solve is that there are two versions of the DB. They have the same table names and are 90% identical in structure, but have one table (out of about 60) which has a different definition.
If LINQ were not involved, I would simply select a different query depending on which version of the application (DB) the user wanted to import to, and leave the remainder of the application as is.
My impression is that LINQ is intended for situations in which the DB structure is cast in stone, and that I cannot have two LINQ table definitions having the same name and simply or easily switch between them (or do so at all).
In this case, must I have (at least) a separate entire Linq.DataContext for each version of the DB? Or have I misunderstood something basic here?
You might be able to make that happen using separate mappings. In this case you would have to hand code your mappings as apposed to the attribute-based mapping that the LINQ designer or SqlMetal does for you. I've never done it, but I think it might work. I just googled for "Linq to Sql POCO mapping" and found this: Achieving POCO s in Linq to SQL. This person is loading his mapping from an xml file at runtime. You could conditionally load one of two different mapping files.
Just wondered if there was a secret to do something like Database.Security.Users like AdventureWorks DB is setup. Seems no matter what I do to try to setup "Security.Users", I always get the dbo in front of it and have a hell of a time in C# accessing the info. Am I doing something wrong?
Are you trying to create an object called Security.Users with a dot? (as opposed to Users in the Security schema?) That's probably best avoided as you're seeing, but if you are then the best way to quote the name is probably in square brackets, i.e. [Security.Users].
dbo is the default database schema name. Unless you've configured a different default schema for your users etc. you can usually just ignore it, although it's still needed if you're referencing another database by name.
you first need to create a schema and make that schema the default schema for that user. Examples and more info can be found here: http://msdn.microsoft.com/en-us/library/ms190387.aspx
If you are using the Wizard to create this, you will always get it. Write the SQL statements and you should be fine.
I am working with a MySQL database that has capitalized table/field names like Users, Institutions, etc. Because the operating system of the database host is Linux, identifiers (like the table names) are treated as case sensitive. So, failing to capitalize a table name will result in a table does not exist error.
The problem I am trying to solve is that ActiveRecord always constructs identifiers in lower case. So, for example, if use the "find" method to grab the first record from the Institution table, the resulting SQL will look like:
SELECT `institutions`.* FROM `institutions` LIMIT 1
This, of course, results in a MySQL error in a Linux environment because it is not case sensitive.
Any thoughts on how one might get around this issue?
Thanks in advance!
class Mouse < ActiveRecord::Base
set_table_name "Meece"
end
Should clear you right up I think.
Rails use convention over configuration to determine the name of the table from a model.
But you can always tweak the default to match your legacy databases.
Have a look here:
http://book.opensourceproject.org.cn/lamp/ruby/railscook/opensource/0596527314/i_0596527314_chp_3_sect_20.html
and here:
http://railsapi.com/doc/rails-v3.0.0/classes/ActiveRecord/Base.html#M001129