From: Jess Robinson Date: Wed, 4 Jan 2012 23:11:29 +0000 (+0000) Subject: Updates with changes merged/edited from ribasushis review X-Git-Tag: v1.0~5 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=cd1e0628ed854af5e272e9393b5563d3faf59186;p=dbsrgits%2FDBIx-Class-Manual-SQLHackers.git Updates with changes merged/edited from ribasushis review --- diff --git a/lib/DBIx/Class/Manual/SQLHackers/CREATE.pod b/lib/DBIx/Class/Manual/SQLHackers/CREATE.pod index b2cf26d..27ed269 100644 --- a/lib/DBIx/Class/Manual/SQLHackers/CREATE.pod +++ b/lib/DBIx/Class/Manual/SQLHackers/CREATE.pod @@ -20,12 +20,14 @@ DBIx::Class::Manual::SQLHackers::CREATE - DBIx::Class for SQL Hackers - CREATE =item L +=back + =head1 Database structure -To use DBIx::Class, we need to teach it about the layout of the underlying database. Several methods are supported. The built-in method involves defining your database structure as a set of perl modules. The other oft used method is to import the definitions from an existing database using the module +To use DBIx::Class, we need to teach it about the layout of the underlying database. Several methods are supported. The built-in method involves defining your database structure as a set of perl classes, one per resultsource (table, view, etc). The other oft used method is to import the definitions from an existing database using the module L. -Once a DBIx::Class schema (set of classes describing the database) has been created, built-in methods can be used to export it to SQL using L. +Once a DBIx::Class schema (set of classes describing the database) has been created, built-in methods can be used to export it as SQL DDL using L. =head2 Using Loader @@ -33,14 +35,16 @@ Install L and decide on a name for your schema clas Run the included L script. - dbicdump -Ilib -o dump_directory=./lib \ + dbicdump -o dump_directory=./lib \ -o components='["InflateColumn::DateTime"]' \ -o preserve_case=1 \ - MyApp::Schema dbi:mysql:database=foo user pass '{ quote_char => "`" }' + MyApp::Schema dbi:mysql:database=foo user pass '{ quote_names => 1 }' =head2 Manual Result class creation (and understanding Loader results) +This section covers the common and oft used CREATE DDL statements that DBIx::Class can replaces with Perl classes: B, B and B. The classes can be used to write the actual SQL DDL to the database or disc, if required. + =head3 CREATE TABLE =head4 Standard basic table creation in SQL: @@ -91,28 +95,6 @@ The recommended version: The fully descriptive version is required if you want to have DBIx::Class create your CREATE TABLE sql for you later. Many DBIC components also use settings in the column info hashrefs to decide how to treat the data for those columns. -The snappy version: - - package MyDatabase::Schema::Result::User; - use strict; - use warnings; - - use base 'DBIx::Class::Core'; - - __PACKAGE__->table('users'); - __PACKAGE__->add_columns( - id => { - data_type => 'integer', - is_auto_increment => 1, - }, - qw/username dob realname password/ - ); - __PACKAGE__->set_primary_key('id'); - - 1; - -This shows a minimal Result class to represent our "users" table. DBIx::Class itself does not use or care about the field types or lengths. However many external components exist on CPAN, and some of may use this information. - =head4 Table creation with references: A relational database isn't worth much if we don't actually use references and constraints, so here is an example which constrains the B column to only contain B values from the *users* table. @@ -160,7 +142,9 @@ In DBIx::Class this is achieved by adding Lbelongs_to('user', 'MyDatabase::Schema::Result::User', 'user_id'); 1; -The B relation allows us to refer to the B who authored a post as the object representing the user, rather than as just the integer tha database uses as the linking information. +The B relation creates a B method which returns the user object, as well as storing JOIN information to be used when querying with JOINs. The joined colums on the remote side are taken from the remote PRIMARY KEY value, if not specified, as in this example. + +Relationships may also be specified with completely custom JOIN conditions, using any columns, whether the database has them defined as constraints or not, or literal values. To allow access from the B object back to the posts they have written, we need to define another relationship in the User class: @@ -182,10 +166,14 @@ In DBIx::Class this can have a Result Class of its own: use base qw/DBIx::Class::Core/; + # Defaults to 'DBIx::Class::ResultSource::Table' unless specified like this __PACKAGE__->table_class('DBIx::Class::ResultSource::View'); __PACKAGE__->table('user_posts'); + + # Do not emit SQL DDL for this particular resultsource __PACKAGE__->result_source_instance->is_virtual(1); + __PACKAGE__->result_source_instance->view_definition( "SELECT posts.user_id, users.username, users.dob, users.realname, posts.createddate, posts.title, posts.post FROM users @@ -230,9 +218,9 @@ To add extra unique indexes, add the B call to your Resul __PACKAGE__->add_unique_constraint('username_idx' => ['username']); -=head3 Outputting SQL +=head3 Outputting SQL DDL -Once the DBIC schema has been defined, you can outout the SQL needed to create the schema in the database in one of several ways. +Once the DBIC schema has been defined, you can outout the SQL DDL needed to create the schema in your database (using the RDBMS-specific flavor of SQL DDL) in one of several ways. =head4 Deploy directly to the database @@ -245,16 +233,16 @@ L has the documentation for the deploy method. =head4 Write out SQL files -Create a schema object with the a database connection (any will do), and call the B on it. +Create a schema object with the a database connection (any will do), and call the B method on it. my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db'); $schema->create_ddl_dir(['SQLite', 'MySQL']); -By default this will create an SQL file for MySQL, PostgreSQL and SQLite. More databases are supported by L if necessary. +If called with no arguments, this method will create an SQL file each for MySQL, PostgreSQL and SQLite. More databases are supported by L if necessary. =head4 SQL files for upgrades (ALTER TABLE) -DBIC can also make use of L to write out ALTER TABLE statements when the schema classes are change. +DBIC can also make use of L to write out ALTER TABLE statements when the schema classes are changed. To do this, make sure that you set a B<$VERSION> in your main Schema class, and run B on the initial version to provide a baseline. diff --git a/lib/DBIx/Class/Manual/SQLHackers/DELETE.pod b/lib/DBIx/Class/Manual/SQLHackers/DELETE.pod index 7482289..a1fb5c3 100644 --- a/lib/DBIx/Class/Manual/SQLHackers/DELETE.pod +++ b/lib/DBIx/Class/Manual/SQLHackers/DELETE.pod @@ -53,8 +53,8 @@ variable, if it is not needed later: $schema->resultset('User')->find({ id => 1 })->delete; In the first variant, the $fred_user row object will still contain the -last known contents of Fred's data. The *in\_storage* value will be -set to false (0), showing that the row object is not connected to a +last known contents of Fred's data. A call to L<$fred_user->in_storage|DBIx::Class::Row/in_storage> will return +false (0), showing that the row object is no longer connected to a actual database row. =head2 Delete one or more rows based on a WHERE clause diff --git a/lib/DBIx/Class/Manual/SQLHackers/INSERT.pod b/lib/DBIx/Class/Manual/SQLHackers/INSERT.pod index 8686d5b..87742a9 100644 --- a/lib/DBIx/Class/Manual/SQLHackers/INSERT.pod +++ b/lib/DBIx/Class/Manual/SQLHackers/INSERT.pod @@ -27,7 +27,7 @@ DBIx::Class::Manual::SQLHackers::INSERT - DBIx::Class for SQL Hackers - INSERT =head2 Simple insertion, populating rows -The B method is for inserting chunks of data to pre-populate / initialise a database with a set of known values. In void context it uses DBI's fast "insert_bulk" method. +The B method is for inserting chunks of data to pre-populate / initialise a database with a set of known values. In void context it uses DBI's fast "execute_array" method. In scalar or list context populate is a proxy to the B method (on which more below), and returns Row objects. @@ -37,24 +37,24 @@ In scalar or list context populate is a proxy to the B method (on which my $schema = MyDatabase::Schema->connect('dbi:SQLite:my.db'); -=item 2. Call the B method for the [Source] you wish to insert data into: +=item 2. Call the B method for the ResultSource you wish to insert data into: $schema->populate('User', [ - [ qw/id username, dob, realname, password/ ], + [ qw/id username dob realname password/ ], [ 1, 'fredbloggs', '1910-02-01', 'Fred Bloggs', 'secretpass'], ]); =back -Note that in void context you can skip passing primary key values that will be supplied by the database. However no automatic assignment of foreign key values will be made, nor will any code in your Result classes be run (eg InflateColumn components). +Note that in void context you can skip passing primary key values that will be supplied by the database, and any other values that are allowed to DEFAULT. However no code in your Result classes will be run (eg InflateColumn components). =head2 Inserting with Row objects INSERT INTO users (username, dob, realname, password) VALUES ('fredbloggs', '1910-02-01', 'Fred Bloggs', 'secretpass'); -In the course of your application, you will often want to retrieve data from a user, insert it into the database, then continue to use or manipulate the resulting object. +In the course of your application, you will often want to retrieve data from a user, insert it into the database, then continue to use or manipulate the resulting object (the object represents the state of the corresponding database row immediately after creation) =over @@ -100,7 +100,7 @@ Now *$newuser* is a Row object containing data that represents what is in the da INSERT INTO posts (user_id, created_date, title, post) VALUES (1, '2010-03-24T09:00:00', 'First post!', 'Just testing my blog'); -Now that we have a user, they would like to submit their first blog post. We already have the user object, from creation, or from the session when they logged in, so we can create posts using it. +Now that we have a user, they would like to submit their first blog post. We already have the user object, from creation, or from the session when they logged in, so we can create posts using it. =over @@ -115,7 +115,7 @@ Now that we have a user, they would like to submit their first blog post. We alr =back -This does not require us to dig out the user's database id and pass it to the insert call for the posts table, as it is already contained in the User object. +This does not require us to dig out the user's database id and pass it to the insert call for the posts table, as it is already contained in the $user object. =head2 Insert a new user and their first post @@ -161,7 +161,7 @@ This also can be shortcut using B: ## new+insert in one my $newuser = $schema->resultset('User')->create( $user_and_post ); - + =back =head2 Insert using a SELECT as input: