Question

My goal is to create a function that will create my MySQL db table (using schema defined via DBIx::Class already) if it hasn't been created yet. Otherwise it simply creates the reference to $schema.

Currently I understand how to create the table if it doesn't exist with the following code:

my $schema = MyApp::Schema->connect(
   $dsn,
   $user,
   $password,
 );

$schema->deploy( { add_drop_table => 1 } );

I need to add some more logic to this so that it will not attempt to add the table if it already exists.

Was it helpful?

Solution 3

I ended up doing it like this, where $schema is a global variable. This solution only works for MySQL (as I understand) due to use of show tables.

sub tableExists {
    my $table = shift;
    my $dbh   = $schema->storage->dbh;    # Get our DBI handle.

    my $sql    = "show tables like '$table'"; #MySQL only
    my $sth    = $dbh->prepare($sql);
    my $exists = undef;
    if ( $sth->execute() ) {

        while ( my $t = $sth->fetchrow_array() ) {
            print $t, $/;
            if ( $t =~ /^$table$/ ) { $exists = 1; }

        }
    }

    if ( defined $exists ) {
        print "found\n";
        return $exists;
    }
    else {
        print "not found\n";
        return $exists;
    }
}

And I call it like this:

$schema = MyApp::Schema->connect(
   $dsn,
   $user,
   $password,
 );

my $table_exists = tableExists("mytable");

if ( !defined $table_exists ) {
    print "Deploying schema...", $/;
    $schema->deploy();
    print "Done", $/;
}

OTHER TIPS

You can use "Drop Table If Exists" in your create table statement if you just want to create it every time. If you don't want to mess with the data then you can always do a "Show tables" and parse the results, something like

my $tables = $dbh->selectall_arrayref(qq|Show tables|) or die "Can't show tables " . $dbh->errstr();
if (@$tables) { 
   foreach my $table (@$tables) {   
      if ($table->[0] eq 'sometablename') {
         # Table sometablename exists
      }
   }
}

This might not be the cheapest check (especially with some DBs) but is somewhat idiomatic for DBIC.

my $schema = MySchema->connect(...);

for my $source_name ( $schema->sources )
{
    eval { $schema->resultset($source_name)->count };
    print $source_name, " is ", $@ ? "missing? $@" : "OK\n";
}

Update, and this is a little ungainly (rejigger rows/single/first/all at your pleasure) but it has the virtue of being quite cheap.

eval {
    $schema->resultset($source_name)
        ->search({},
                 { where => \q{ 1 = 0 },
                   rows => 1 })
        ->single;
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top