블로그 이미지
JEEN

서울에 사는 꽃청년의 IT찌질모험기

Rss feed Tistory
IT/Perl 2011.12.17 22:54

[ Perl / AdventCalendar ] 제 기사가 올라갔네요.


  http://advent.perl.kr/2011/2011-12-17.html

  오늘자 제 기사가 공개되었습니다. DBIx::Class 를 사용함에 있어서 회사에서 사용하는 지속적인 유지보수 방법에 대해서 썼습니다. 뭐 대단한 건 아니고 그냥 뭐 DBIx::Class::Schema::Loader 의 건전한 사용방법이라고 보시면 됩니다.

  이 모든 것은 @aanoaa 님의 공덕으로 비롯된 것임을 알려드립니다.
 
신고
IT/Perl 2010.06.24 20:34

[ Perl ] 그리고 거기에 TimeStamp 가 있었다 // DBIx::Class

2008/08/06 - [IT/Perl] - [ Perl ] Perl 에서의 ORM , DBIx::Class에 대해서... #3 - Component

  요즘 출퇴근길에 The Definitive Guide to Catalyst 를 보고 있습니다. 테스트코드의 중요성을 역설하는 많은 부분을 엿볼 수 있었습니다. 아니.. 뭐 그보다 다른 사람들은 어떻게 Catalyst 를 쓰냐는 것이 궁금하기도 해서 여러 소스를 디벼보기도 하며 참고하기도 하는데요. 그런 면도 있는 반면에 저 자신이 2-3년 계속 익숙하게 써오던 구문들을 고집하기도 합니다. 

  위의 링크에서 볼 수 있는 자체정의한 AutoStoreDateTime 부분이 바로 그렇습니다. 
  매번 DBIx::Class 를 사용하는 프로젝트마다 저렇게 따로 정의해놓고 쓰는 습관이 있었습니다. 이게 바로 대표적인 2-3년 동안 계속 써오던 그런 고집이죠.

  The Definitive Guide To catalyst 를 보면서 TimeStamp(=DBIx::Class::TimeStamp) 의 존재를 알게되었고,
  이것이 AutoStoreDateTime 으로 따로 컴포넌트를 정의할 필요성을 박살내버려주었습니다.

 package My::Schema;

 __PACKAGE__->load_components(qw( TimeStamp ... Core ));
 
 __PACKAGE__->add_columns(
    id => { data_type => 'integer' },
    t_created => { data_type => 'datetime', set_on_create => 1 },
    t_updated => { data_type => 'datetime',
        set_on_create => 1, set_on_update => 1 },
 );

  TimeStamp 컴포넌트를 읽어주고 DateTime 타입의 컬럼에다가 
  set_on_create / set_on_update 만 지정해주면 되는 것이죠.

  말 그대로 INSERT 쿼리에서는 set_on_create 가 UPDATE 쿼리에서는 set_on_update 가 지정된 컬럼의 값이 자동으로 갱신됩니다. 

  DBIx::Class::TimeStamp 자체는 사실 DBIx::Class::DynamicDefault 에 조금 손을 댄 것 뿐이니...
  이렇게 저렇게 다른 컬럼에 값을 바꿔보고 싶다든가 할때는 DBIC::DynamicDefault 를 참고해보는 것도 좋지 않을까 합니다.

  // 그런 의미에서 급하게 [개인적인 일]에서 사용되던 코드들을 모조리 DBIx::Class::TimeStamp 로 바꿔버렸습니다.
 역시 쓸데없는 자기전용 컴포넌트 // 네임스페이스 생성은 독입니다. 세상은 꾸준히 바뀌어가니... =3

** 추기 (2010/09/06)
  아, 이건 DBIC 의 bulk_insert(populate) 를 이용했을 시에는 적용되지 않습니다. (당연한가;;)
신고
IT/Perl 2008.08.06 21:24

[ Perl ] Perl 에서의 ORM , DBIx::Class에 대해서... #5 - InflateColumn


 현재 개발중인 프로젝트에 쓰이는 내용을 살짝 다뤄볼까 합니다.

 음... 테이블의 칼럼 수가 많거나, 적거나.. 아직 정해지지 않아서 나중에 추가될 지도 모른다거나... 이런 불안함에서 제대로 테이블을 만들더라도, 나중에 ALTER TABLE 의 폭발을 겪게 되는 경우가 있었습니다. 컬럼을 추가하거나, 지우거나, 바꾸거나 하면서 불안함이 있다는 것이죠. 그래서 YAML 을 그대로 집어넣게 되었습니다.

 이럴때 가볍게 쓸 수 있는 것이 inflate_column 입니다.
 위의 얘기는 잠시 접어두고 그럼 예제를 볼까요? MyTest::User 에 다음과 같은 것을 추가했습니다.

 __PACKAGE__->inflate_column(<br />    user_id => {<br />        inflate => sub {<br />            my ($value, $obj) = @_;<br />            # $obj->$column_name 으로 User Schema Class 의 컬럼을 참조할 수 있습니다.<br />            sprintf "%04d", $value;<br />        },<br />        deflate => sub {<br />            my ($value, $obj) = @_;<br />            $value;<br />        },<br />    });

  이것으로 무엇을 하느냐...

  User 의 user_id 컬럼을 지정해서 user_id 를 처음부터 건드려놓은 상태로 내놓거나(inflate), Table 에 입력을 할 시에도 마찬가지로 입력 직전에 건드린 상태로 쓰기를 수행(deflate) 하는 겁니다.

  위의 예제에서는 User 의 user_id 를 zero-fill 합니다. 1 이라면 0001 이라든가.. 이런 형식으로 나오겠죠?

my $user = $schema->resultset('User')->search({});

while(my $row = $user->next) {
    print $row->user_id."\t".$row->name."\n";
}

  그럼 한번 뽑아볼까요?
사용자 삽입 이미지
  자, 이렇게 나오네요.

  이렇게해서, 예를들면 datetime 의 data type 을 가지고 있는 created_on, updated_on 은 DateTime 인스턴스로 만들어 줄 수도 있겠죠.

  제가 사용하는 경우는 ...

CREATE TABLE test (
   no    INT NOT NULL,
   attributes   TEXT NOT NULL,
   created_on DATETIME NOT NULL,
   updated_on DATETIME NOT NULL,
   primary key(no)
 );

  이런 Schema 가 있다면...

use YAML;
__PACKAGE__->inflate_column(
  attributes => {
     inflate => sub {
        my ($value, $obj) = @_;
        YAML::Load($value);
      },
      deflate => sub {
        my ($value, $obj) = @_;
        YAML::Dump($value);
       },
});

  이렇게 inflate_column 을 설정해두었습니다. 그리고 이런식으로 등록합니다.

 my $obj = {
    irc => {
       perl => {
         saillinux => {
           envy => 'yuni',
           attack => 'JEEN',
           love  => [ 'ero', '하얀_고양이', 'Fate' ],
          },
        },
    },
 };
 
 $schema->resultset('Test')->create( attributes => $obj );

 이렇게 등록된 데이터는 YAML 형식으로 보관되어 있을 겁니다.
 그리고 빼내서 쓸려면 이런식으로 합니다.
 
my $rs = $schema->resultset('Test')->search({})->first;
print $rs->attributes->{irc}->{perl}->{saillinux}->{envy};  # yuni
print for (@{ $rs->attributes->{irc}->{perl}->{saillinux}->{love} }); # ero 하얀_고양이 Fate

  이렇게 사용합니다. :-)

  inflate_column 를 사용하지 않는 경우에는 집어넣을 때는 매번 YAML::Dump 하고...
  뺄때는 매번 YAML::Load 해야 되겠죠.

  이렇게 가볍게 InflateColumn 에 대해서 알아보았습니다.
신고
IT/Perl 2008.08.06 19:42

[ Perl ] Perl 에서의 ORM , DBIx::Class에 대해서... #4 - Relation


 자, 그럼 Relation 에 대한 이야기입니다.

 Relation 은 말그대로 관계입니다. 뭐에 대한 관계냐면, Schema Class 간의 관계이죠.
 
 User, Company, Deathnote 에서 Deathnote 는 User 의 user_id 와 Company 의 company_id 를 가지고 있습니다.
 그럼 어떻게 Deathnote 에서 User 의 name 을 알 수 있을까요?
 ( SQL 스럽게 하면 애들장난같은 얘기라서 접어두겠습니다만 )

  아, 그전에 일단 테스트 용으로 데이터를 집어넣겠습니다.

my $deathnote = $schema->resultset('Deathnote');

while(<DATA>) {
    chomp;
    my @data = split/,/, $_;
    $deathnote->create({
        user_id => $data[0],
        company_id => $data[1],
    });
}

__DATA__
1,1
2,2
3,3
4,4
5,5
6,6
7,7

  자.. 어떻게 할 것인가... 가장 간편하게 이런 방법이 있습니다.
my $deathnote = $schema->resultset('Deathnote')->search({});

while(my $row = $deathnote->next) {

    my $user = $schema->resultset('User')->find($row->user_id);
    print $user->name if $user;
}
 흠? 근데 이건 좀 너무하다 싶지 않나요?

 이렇게 생각하면 Relation 이 나올 때입니다.
 MyTest/Deathnote.pm 을 보겠습니다. 아, 다른 건 다 집어치우고... 그냥 추가된 것만 보죠.

__PACKAGE__->has_one( user => 'MyTest::User', { 'foreign.user_id' => 'self.user_id' } );
__PACKAGE__->has_one( company => 'MyTest::Company', { 'foreign.company_id' => 'self.user_id'
} );

 이렇게 추가했습니다.
  Deathnote 에서 User 로 연결하기 위해서 user 라는 키를 사용하고,
User 와 Deathnote 는  user_id 로 연결된다는 내용입니다. (has_one 이라는 것은 말 그대로 1:1의 관계입니다)
  그리고 Company 역시나 마찬가지입니다.
  이렇게 Relation 을 지정해두면 어떻게 되려나요?

 my $deathnote = $schema->resultset('Deathnote')->search({});

while(my $row = $deathnote->next) {
  print $row->user->name."¥n";
}

  이런 형식으로 간단하게 user의 name 을 얻어올 수 있습니다.
.
.
.
  정말로 그럴까요? 두번째 장에서 하얀_고양이라는 User 를 삭제했기 때문에 세번째 Deathnote 에서는 에러가 발생합니다.

  can't call method "name" on an undefined value at ..

 그러면 이렇게 해주면 됩니다. user 가 있으면 찍어라 라고...

   print $row->user->name if $row->user;

  간단하죠;;;

 근데 User 가 어떤 Company 인지를 알고 싶습니다. 근데 이 정보는 Deathnote 에만 있어요.
 User->Deathnote->Company 식으로 넘어가야되는데요...

  우선은 MyTest/User.pm 을 열어서 한 줄 추가합니다.

__PACKAGE__->belongs_to( note => 'MyTest::Deathnote', { 'foreign.user_id' => 'self.user_id' });

  belongs_to 라는 것은 말 그대로입니다. :-) Deathnote 에 User 가 has_one 으로 Relation 관계를 성립하고 있습니다. belongs_to 로 Deathnote 에 속하게 됩니다. (근데 has_one 으로도 Relation 관계가 성립되더군요;;; 뭔가 일방적인 관계일지도..)

  그러면 User 에서 Company 의 name  을 읽어 볼까요?

my $user = $schema->resultset('User')->search({});

while(my $row = $user->next) {
   
    print $row->name .'=>'.$row->note->company->name."\n" if $row->note && $row->note->company;

}

  이렇게 하면 되겠죠?

  근데 여기서 잠깐... "언제까지 전체 레코드를 읽어올 것인가요. 제대로 SQL 조건도 좀 주고.. 이러고 싶은데.." 라고 saillinux 님께서 사장님 마인드로 또 말씀하십니다.

  그러면서 던져주신 조건이란게 << user_id 가 3 을 넘고, company_id 가 2 를 넘는 것 >> 이라고 하네요.
 근데 User Schema Class 를 사용하라고 합니다. 어라... 분명 User Schema Class 에는 company_id 가 없는 데 말이죠. 역시 사장님 마인드입니다.

  "거기다가 company_id 순으로 정렬하고, 그 중에 딱 2개만 보고 싶어요" 라고 하시는 군요...
  오늘 제대로 뽕을 뽑으시는 군요.

   요건 정의를 다시 해보겠습니다.

    "user_id" 가 3 을 넘고,
    "company_id"  가 2 를 넘고,
    "User" Schema Class 를 사용하고,
    "company_id" 순으로 정렬하고
    "2개" 만 출력한다 입니다.
.
.
.
.
  답은 이렇습니다.  

my $user = $schema->resultset('User')->search({
    'me.user_id' => { '>' => 3 },
    'company.company_id' => { '>' => 2 },
},{
    prefetch => [ { 'note' => 'company' } ], 
    order_by => 'company.company_id asc',
    rows => 2,
});

while(my $row = $user->next) {
    print $row->name. '=>' .$row->note->company->name."\n";
}

  User Schema Class 에서 Company 와는 어떤 관계도 아닙니다. 그럴려면 Deathnote 를 통해서 Company 에 접근할 수 있습니다.
 
   prefetch => [ { 'note' => 'company' } ]

  MyTest::User 에서 note 로 Deathnote 에 갈 수 있고, Deathnote 는 company 로 Company에 접근할 수 있습니다.  Relation 관계는 이미 Schema Class 에서 정의해줬기 때문에 이렇게 간단하게 접근할 수 있습니다.

    order_by => 'company.company_id asc',

  company_id 순이라면 위의 prefetch 에서 이미 길을 텄기때문에 "company.company_id"  로 접근할 수 있습니다.(SQL::Abstract 를 참조하세요)
 
      rows => 2

  단 두줄만 뺀다는 겁니다. MySQL 의 LIMIT 2 같은 사용법이죠.

  물론 Relation은 might_have, has_many 같은 것들도 있습니다. 자세한 내용은 문서를 참조하세요. :-)

  이런저런 빼고 넘어가는 부분들이 많은지라... 조금만 문서를 보시면 금방 아실만한 내용들이 대부분일 겁니다. 모르시면 같이 한번 궁리해보죠 :-)

  흡.. 빠진 부분들(제가 아는 한도에서)은 다음에 DBIC 를 정리하는 차원에서 가볍게 짚고 가도록 하겠습니다.


신고
IT/Perl 2008.08.06 14:22

[ Perl ] Perl 에서의 ORM , DBIx::Class에 대해서... #3 - Component

  이번에는 Component 에 대해서 알아보겠습니다. 일단 예제부터 보고 시작하죠.

  Mytest/Company.pm 을 열어봅니다.

package MyTest::Company;

use strict;
use warnings;

use base 'DBIx::Class';
use AutoStoreDateTime;

__PACKAGE__->load_components("PK::Auto", "+AutoStoreDateTime", "Core");
__PACKAGE__->table("company");
__PACKAGE__->add_columns(
  "company_id",
  { data_type => "INT", default_value => undef, is_nullable => 0, size => 11 },
  "name",
  { data_type => "VARCHAR", default_value => "", is_nullable => 0, size => 255 },
  "created_on",
  { data_type => "DATETIME", default_value => "", is_nullable => 0, size => 19 },
  "updated_on",
  { data_type => "DATETIME", default_value => "", is_nullable => 0, size => 19 },
);
__PACKAGE__->set_primary_key("company_id");


# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-08-05 16:39:27                      
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:DHRIea3OvvtGG+yhaBVTvQ                        


# You can replace this text with custom content, and it will be preserved on regeneration    
1;

 이 중에서 제가 살짝 추가한 부분이 있습니다.

use AutoStoreDateTime;
__PACKAGE__->load_components("PK::Auto", "+AutoStoreDateTime", "Core");

 바로 이부분에 PK::Auto 라는 component 도 불러오라고 지정했습니다. PK::Auto 는 온라인 게임에서 자동으로 PK 를 수행하는   Primary Key Auto Increment 라고 보시면 됩니다. 즉 이 Schema Class 에서는 company_id 가 Primary Key 이니까 자동으로 Auto Increment 해준다는 거죠. (물론 SQL 에서 Auto Increment 를 지정해주면 DBMS 자체적으로 이 행위를 수행하지만, auto increment 가 지정되지 않은 경우에는 PK::Auto가 알아서 해줍니다. 이것을 확인하기 위해서 직접 Company 테이블을 변경해보시길 바랍니다)

  그리고 AutoStoreDateTime 도 있습니다. 근데 이 앞에 +라고 붙었는데.. 이것은 Custom component 입니다. PK::Auto 같은 경우는 DBIx::Class::PK::Auto 라는 모듈을 불러오는 것인데, AutoStoreDateTime 은 DBIC 정식 모듈이 아닌... 여기서 만들어서 쓰겠다라는 것이죠.
use AutoStoreDateTime;

use strict;
use warnings;
use base 'DBIx::Class';

use DateTime;

sub insert {
    my $self = shift;
   
    $self->created_on( DateTime->now( time_zone => 'Asia/Seoul' ) )
                             if $self->result_source->has_column('created_on');
                      
    $self->next::method(@_);
}

sub update {
    my $self = shift;

    $self->updated_on( DateTime->now( time_zone => 'Asia/Seoul' ) )
                           if $self->result_source->has_column('updated_on');
    $self->next::method(@_);
}

1;

  이와 같은 컴포넌트 모듈을 만들었습니다. 이것을 AutoStoreDateTime.pm 이라고 저장하고 MyTest.pm 과 같은 디렉토리에 놓습니다.
  그럼 어떤 결과를 보이는 지 확인해 볼까요?
my $company = $schema->resultset('Company');

while(<DATA>) {
    chomp;
    $company->create({
        'name'    => $_,
    });
}

__DATA__
I company
N company
D company
E company
A company
Y company

  이렇게 Company.name 을 만들도록합니다. company_id 도 지정하지 않았고, created_on 도 지정하지 않았습니다. 등록날짜도 모르면 어떻게 하려고 이럴까요?
사용자 삽입 이미지
  하지만 이렇게 created_on 은 create 한 시점의 날짜/시간을 가지고 있습니다. company_id 도 물론 지정하지 않았는데 이렇게 생겼네요(SQL에서 auto increment 가 있으면 뭐 그게 그거입니다만).

 근데 사장 마인드를 가지신 saillinux 님께서 짝수 회사번호를 가진 회사는 전부 소문자로 표기하고 싶다는 얼토당토 않은 요구를 하고 있습니다. 어쩔 수 있나요. 까라면 까야지..

my $company = $schema->resultset('Company')->search({});

while(my $row = $company->next) {
    if ($row->company_id % 2 == 0) {
        $row->name(lcfirst $row->name);
        $row->update;
    }
}

  이렇게 하면 되겠죠?
사용자 삽입 이미지
  그러면 update 된 레코드만 updated_on 이 지정되게 되죠.  어때요? 참 쉽죠?

 이렇게 DBIC 의 Component 활용에 대해서 알아보았습니다. :-) 직접 Component 를 만들어서 보다 편하게 DB 를 주물러 보심은 어떠실런지요?

  다음에는 Relation 에 대해서 살짝 알아보겠습니다. 

* 참고
 - **** Project



신고
IT/Perl 2008.08.05 20:15

[ Perl ] Perl 에서의 ORM , DBIx::Class에 대해서... #2 - DBIC 의 간단한 사용


  그럼, DBIC::Schema::Loader 로 만든 Schema Class 는 어떻게 사용하는 것일까요?

use strict;
use warnings;
use MyTest;  # 앞서 정의한 Schema Class
use DateTime;

my $schema = MyTest->connect(
    'dbi:mysql:mytest',
    'root',
    'PASSWORD');  # DBI 의 connect_info 랑 같습니다.

my $user = $schema->resultset('User');

while(<DATA>) {
    chomp;
    my @data = split /,/, $_;
    $user->create({
        'user_id' => $data[0],
        'name'    => $data[1],
        'created_on' => $dt->ymd. ' '. $dt->hms,
    });  # INSERT INTO..
}

__DATA__
1,JEEN
2,saillinux
3,하얀_고양이
4,a3r0
5,yuni
6,keedi
7,pung96
8,song
9,ssie
10,amorette

  이 스크립트를 MyTest.pm 과 같은 장소에 놓으시고... 적당한 이름으로 저장해서 실행해봅니다.
  아무것도 안나올겁니다. 그렇다면... DB 를 확인해볼까요?
사용자 삽입 이미지
이렇게 제대로 들어가 있네요 :-)
그러면 이렇게 입력된 데이터를 가지고 놀아 볼까요?

use strict;
use warnings;
use MyTest;
use DateTime;

my $schema = MyTest->connect(
    'dbi:mysql:mytest',
    'root',
    'PASSWORD');

my $user = $schema->resultset('User')->search({
    'user_id' => { '<' => 5 },
});  # SELECT * FROM user WHERE user_id < 5;

while(my $row = $user->next) {
 print $row->name."\n";
}
 위의 주석처럼 user_id 가 5보다 작은 사람들을 불러모읍니다. :-)
 JEEN
 saillinux
 하얀_고양이
 a3r0
 결과는 이처럼 나오겠죠?
 
  ->search 로 데이터를 줏어올 때는 기본적으로 복수로 가정합니다. 그러니 $user->next 같은 것으로 루프를 돌려주는 것입니다. $user->all 같은 것을 사용하면 말 그대로 전체 데이터를 ARRAY 로 받습니다.

 여기에서 생각난 예제:
 근데 전 하얀_고양이 님을 별로 좋아하지 않습니다. 그래서 지워버리고 싶어요.

use utf8;

my $user = $schema->resultset('User')->find({
    'name' => '하얀_고양이',
});    # find 를 사용할 경우 하나의 레코드만을 얻어옵니다.

print $user->name;
$user->delete;
 
  혹은
use utf8;
my $user = $schema->resultset('User')->search({});

while(my $row = $user->next) {
  $row->delete if $row->name eq '하얀_고양이';  # 이렇게도 삭제할 수 있죠 :-)
}

  이렇게 해서 하얀_고양이님을 지웠습니다.
  그러니 IRC #perl 에 계신 분들이 모두 기뻐하셔서 빵글이를 붙이고 싶다는 데요. :-)
  그럼 어떻게 할까요?
my $user = $schema->resultset('User')->search({});

while(my $row = $user->next) {
    $row->name($row->name . '_^^');
    $row->update;
}
 
사용자 삽입 이미지

 과연.. 모두들 기뻐하시는 군요 :-)

 이런식으로 직감적으로 DB의 데이터를 조작할 수 있는 것이 바로 DBIC 의 강점입니다.
 이에관한 예제는 DBIx::Class 페이지에서 쉽게 찾아볼 수 있고, 보다 다양한 예제를 제공해줍니다.
  그리고 보다 자세한 SELECT 구문에 대한 예제는 앞으로도 계속 적어나가도록 하겠습니다.

  다음번에는 Component 에 대해서 간단하게 알아보겠습니다. 

신고
IT/Perl 2008.08.05 16:46

[ Perl ] Perl 에서의 ORM , DBIx::Class에 대해서... #1 - DBIC::Schema::Loader

: 요 근래 잠깐 깜빡하고 Catalyst 에 관한 글을 쓰지도 못하고 있었네요.

일단 그전에 미리 Template Toolkit 같은 Template Engine 이나
DBIx::Class 같은 ORM 같은 것을 알아놓고 가는 게 좋겠다는 생각에...
잠시 얘기가 빙빙 겉돌고 있습니다.

 일단 DBIx::Class, 통칭 DBIC 라고 불리는 것부터 알고 나중에 차근차근 Catalyst 내용을 이어가도록 하겠습니다.

 ORM 이라고 아시죠? Object-Relation Mappings 라고...
 자세한 내용은 검색해보시면 짠 하고 나올겁니다. ( 검색 예 )

 Perl 에서 ORM 을 얘기하면 DBIC 가 대표적인 예가 될 것입니다. 그외 여러가지 있지만 안써봐서 생략합니다.

 DBIC 를 제대로 사용하려면 Schema 클래스를 만들어야 합니다.

 만들어야한다에 대한 제대로 다시 정의를 하자면, "만들게 해야합니다" 입니다.

 DBIx::Class::Schema::Loader 가 이 일을 해주는데요. 그런고로 한번 만들게 해보겠습니다.
 CREATE TABLE user (
   user_id  int not null auto_increment,
   name    varchar(255) not null,
   created_on datetime not null,
   updated_on datetime not null,
   primary key(user_id)
 );

 CREATE TABLE company (
   company_id int not null auto_increment,
   name           varchar(255) not null,
   created_on datetime not null,
   updated_on datetime not null,
   primary key(company_id)
 );

 CREATE TABLE deathnote (
   death_id int not null auto_increment,
   user_id   int not null,
   company_id int not null,
   created_on datetime not null,
   updated_on datetime not null,
   primary key(death_id)
 );

 이와같은 SQL 을 깨작거렸습니다. 우선 mytest 라는 DB 를 만들고 위의 user 와 company와 deathnote 라는 테이블을 생성합니다.

use strict;
use warnings;

use DBIx::Class::Schema::Loader (qw/make_schema_at/);

make_schema_at(
    'MyTest', {
        components => [],
        dump_directory => './',
    },
    \@ARGV,
    );

 그리고 이와같은 스크립트를 만들었습니다.(schema-loader.pl)

 perl schema-loader.pl dbi:mysql:mytest "mysql user" "mysql pass"

 그런 다음에는 이렇게 명령을 내립니다. (DBI 에서 connect_info 설정해주는 그것입니다)

Dumping manual schema for MyTest to directory ./ ...
Schema dump completed.
  그러면 이렇게 Schema dump 가 끝났다고 말해주죠.
 
사용자 삽입 이미지
  그러면 이처럼 Schema 클래스가 생성되게 됩니다.

package MyTest;

use strict;
use warnings;

use base 'DBIx::Class::Schema';

__PACKAGE__->load_classes;


# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-08-05 16:25:30        
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:P0OGC/gBKsOEyhe8yV+xsA          


# You can replace this text with custom content, and it will be preserved on re\
generation                                                                     
1;

  MyTest.pm 은 이처럼 썰렁합니다만..

package MyTest::User;

use strict;
use warnings;

use base 'DBIx::Class';

__PACKAGE__->load_components("Core");
__PACKAGE__->table("user");
__PACKAGE__->add_columns(
  "user_id",
  { data_type => "INT", default_value => undef, is_nullable => 0, size => 11 },
  "name",
  { data_type => "VARCHAR", default_value => "", is_nullable => 0, size => 255 },
  "created_on",
  { data_type => "DATETIME", default_value => "", is_nullable => 0, size => 19 },
  "updated_on",
  { data_type => "DATETIME", default_value => "", is_nullable => 0, size => 19 },
);
__PACKAGE__->set_primary_key("user_id");


# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-08-05 16:25:30                      
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:wV7hRdze6zdTrll+QAg4fw                        


# You can replace this text with custom content, and it will be preserved on regeneration    
1;

  MyTest/User.pm (MyTest::User) 는 이처럼 속이 꽉찼습니다. 처음에 SQL 로 정의해준 내용들이 그대로 정의되어 DBIC Schema 를 구성하게 됩니다.

  Catalyst 에서는 위의 스크립트(schema-loader.pl)를 쓸 필요없이...
./script/[App]_create.pl model MyTest DBIC::Schema MyTest create=static dbi:mysql:mytest *** ****
 이런식으로 하면 Schema Class 가 생성됩니다.

 다음에는 DBIC 를 이용해서 어떻게 데이터를 다루는 가에 대해서 알아보겠습니다.

 -- 참고
 * DBIx::Class
 * DBIx::Class::Schema::Loader
 
신고
TOTAL 488,144 TODAY 13

티스토리 툴바