DBIO

 view release on metacpan or  search on metacpan

lib/DBIO.pm  view on Meta::CPAN

package DBIO;
# ABSTRACT: Native relational mapping for Perl, built on DBI

use strict;
use warnings;

our $VERSION = '0.900002';

use DBIO::Base ();
use DBIO::Skills ();

sub import {
  my ($class, @args) = @_;
  my $caller = caller;

  my ($role, @opts);
  for my $arg (@args) {
    if (defined $arg && $arg =~ /^-/) { push @opts, $arg }
    elsif (!defined $role)            { $role = $arg }
    else                              { push @opts, $arg }
  }

  unless (defined $role) {
    if    ($caller =~ /::Result::[^:]+$/)    { $role = 'Core' }
    elsif ($caller =~ /::ResultSet::[^:]+$/) { $role = 'ResultSet' }
    else                                      { $role = 'Core' }
  }

  my $base = "DBIO::$role";
  eval "require $base; 1"
    or die "use DBIO '$role': cannot load $base: $@";

  {
    no strict 'refs';
    push @{"${caller}::ISA"}, $base unless $caller->isa($base);
  }

  strict->import;
  warnings->import;

  # Schema classes get the skills-override declaration sugar (see DBIO::Skills).
  _install_skill_sugar($caller) if $caller->isa('DBIO::Schema');

  _apply_shortcut($caller, $_) for @opts;
}

# Install the per-schema skills-override sugar into a schema class body:
#
#   skills { 'mysql-database' => $md, ... };   # set/replace the whole map
#   skill  'mysql-database' => $md;            # merge a single entry
#
# Both write the schema's skills() classdata (DBIO::Schema). namespace::clean
# removes the helpers after compilation, so at runtime $schema->skill(...) and
# $schema->skills resolve to the inherited DBIO::Schema accessor/method rather
# than these declaration helpers. The classdata accessor is reached via its
# fully-qualified name to bypass the (still-installed) sugar during the body.
sub _install_skill_sugar {
  my ($caller) = @_;
  no strict 'refs';
  no warnings 'redefine';
  *{"${caller}::skills"} = sub {
    my $map = (@_ == 1 && ref $_[0] eq 'HASH') ? $_[0] : { @_ };
    $caller->DBIO::Schema::skills($map);
  };
  *{"${caller}::skill"} = sub {
    my ($name, $markdown) = @_;
    my $cur = $caller->DBIO::Schema::skills || {};
    $caller->DBIO::Schema::skills({ %$cur, $name => $markdown });
  };
  require namespace::clean;
  namespace::clean->import(-cleanee => $caller, qw(skills skill));
}


sub skill { shift; DBIO::Skills->skill(@_) }


sub skills { shift; DBIO::Skills->skills(@_) }

# Shortcut resolution is two-tier and core never names a single driver:
#
#  1. Explicit stub DBIO::Shortcut::<key> -- a driver ships one for each
#     curated alias (e.g. -pg, -my). It is lazy-loaded here (so it works even
#     "cold") and its apply($caller) decides what to do, usually delegating to
#     DBIO->apply_driver:
#         package DBIO::Shortcut::pg;
#         sub apply { DBIO->apply_driver($_[1], 'PostgreSQL') }
#         1;
#
#  2. No stub? Fall back to an ALREADY-LOADED driver whose name matches the key
#     case-insensitively (-postgresql -> DBIO::PostgreSQL). The correct casing
#     comes from the loaded symbol table, not from guessing. This is why the
#     canonical name "just works" once the driver is loaded, with no stub.
sub _apply_shortcut {
  my ($caller, $opt) = @_;
  (my $key = lc $opt) =~ s/^-//;

  $key =~ /\A[a-z0-9_]+\z/



( run in 0.986 second using v1.01-cache-2.11-cpan-941387dca55 )