Changeset 18090 for ext

Show
Ignore:
Timestamp:
09/22/07 05:09:36 (16 months ago)
Author:
Darren_Duncan
Message:

ext/Muldis-DB/ : rewrote the code and interface docs of Interface.pm

Location:
ext/Muldis-DB
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • ext/Muldis-DB/Changes

    r18088 r18090  
    2929    * Minor updates to all versioned files such that most references to the 
    3030    project name were changed to "Muldis DB" from "Muldis::DB". 
     31 
     32    * (Interface.pm)  Rewrote 90% of the code to provide a substantially 
     33    different, though similar, API.  The new_dbms function of the 
     34    Muldis::DB::Interface module now has a modified version of what code 
     35    used to be in the constructor submethod of ::DBMS (it is the code that 
     36    loads an Engine and invokes it to make a ::DBMS object), rather than 
     37    the former being an optional wrapper for the latter.  All remaining 
     38    ::Interface::\w+ named packages of Interface.pm are now just roles that 
     39    declare method interfaces but don't implement any, and the 
     40    correspondingly named Engine classes must inherit said roles and 
     41    implement the methods; they are no longer wrapper classes that do 
     42    validation on behalf of, and then invoke, the Engines, but rather the 
     43    Engines must do their own input validation now, and user applications 
     44    are now invoking the public Engine classes directly.  The 
     45    ::Engine::Role(|::\w+) roles that used to be in Interface.pm are now 
     46    gone, as they are now redundant; the new ::Interface::\w+ are like what 
     47    they used to be.  The new Interface.pm do not declare constructor 
     48    interfaces, since users should now only be making objects indirectly by 
     49    way of methods of another class.  The ::HostGateVar class/role was 
     50    renamed to ::Var, the ::HostGateRtn was renamed to ::ProcBinding, and a 
     51    similar ::FuncBinding was added.  The ::(DBMS|Var|(Func|Proc)Binding) 
     52    roles were further substantially altered, with some methods renamed and 
     53    others added.  Perhaps the most substantial difference of the new API 
     54    for actual functionality is that there is no distinct "prepare" method 
     55    any more, rather all action methods are of the "execute" (now called 
     56    "call") variety.  How this works is you first call() a DDL routine, its 
     57    argument being the definition of the (now always named) user-defined 
     58    routine you want to compile; then you call() that newly created 
     59    routine.  In a related fashion, if you just want to invoke existing 
     60    system or (already loaded / in-mounted-database) user-defined routines, 
     61    you can just call() them like they were Perl routines, with no separate 
     62    DDL/prepare step.  The (Func|Proc)Binding roles aren't actually needed 
     63    for anything, as the DBMS role provides call_(func|proc) methods, which 
     64    in either case just alias to an already compiled routine, but the 2 
     65    Binding roles are provided for now in case they may add some efficiency 
     66    due to less repeated input validation or such. 
     67 
     68    * (Interface.pm)  Rewrote and/or added 90% of the INTERFACE pod; unlike 
     69    the old API which had practically no documentation, the new API is 
     70    fully documented.  Also added an initial SYNOPSIS documentation block, 
     71    which illustrates invoking the system-defined relational join operator, 
     72    where the arguments and result are Perl-lexical variables; this is the 
     73    first actual example code for using Muldis DB, however contrived. 
    3174 
    3275    * (SeeAlso.pod)  Updated the PROSPECTIVE MULDIS DB EXTENSIONS section 
  • ext/Muldis-DB/lib/Muldis/DB/Interface.pm

    r18088 r18090  
    1111sub new_dbms of Muldis::DB::Interface::DBMS 
    1212        (Str :$engine_name!, Any :$dbms_config!) { 
    13     return ::Muldis::DB::Interface::DBMS.new( 
    14         :engine_name($engine_name), :dbms_config($dbms_config) ); 
    15 } 
    16  
    17 ########################################################################### 
    18  
    19 } # module Muldis::DB::Interface 
    20  
    21 ########################################################################### 
    22 ########################################################################### 
    23  
    24 class Muldis::DB::Interface::DBMS { 
    25     has Any $!dbms_eng; 
    26  
    27     trusts Muldis::DB::Interface::HostGateVar; 
    28     trusts Muldis::DB::Interface::HostGateRtn; 
    29  
    30 ########################################################################### 
    31  
    32 submethod BUILD (Str :$engine_name!, Any :$dbms_config!) { 
    33  
    34     die q{new(): Bad :$engine_name arg; it is not an object of a} 
     13 
     14    die q{new_dbms(): Bad :$engine_name arg; it is not an object of a} 
    3515            ~ q{ Str-doing class, or it is the empty string.} 
    3616        if !$engine_name.defined or !$engine_name.does(Str) 
    3717            or $engine_name eq q{}; 
    3818 
    39     # A class may be loaded due to it being embedded in a non-excl file. 
    40     if (!::($engine_name).does(Class)) { 
     19    # A module may be loaded due to it being embedded in a non-excl file. 
     20    if (!::($engine_name).does(Module)) { 
    4121        # Note: We have to invoke this 'require' in an eval string 
    4222        # because we need the bareword semantics, where 'require' 
     
    4424        eval "require $engine_name;"; 
    4525        if (my $err = $!) { 
    46             die q{new(): Could not load Muldis::DB Engine class} 
     26            die q{new_dbms(): Could not load Muldis DB Engine module} 
    4727                ~ qq{ '$engine_name': $err}; 
    4828        } 
    49 #        die qq{new(): Could not load Muldis::DB Engine class} 
     29#        die qq{new_dbms(): Could not load Muldis DB Engine module} 
    5030#                ~ qq{ '$engine_name': while that file did compile without} 
    51 #                ~ q{ errors, it did not declare the same-named class.} 
    52 #            if !::($engine_name).does(Class); 
    53     } 
    54     die qq{new(): The Muldis::DB root Engine class '$engine_name' is} 
    55             ~ q{ not a Muldis::DB::Engine::Role-doing class.} 
    56         if !::($engine_name).does(::Muldis::DB::Engine::Role); 
    57     my $dbms_eng = undef; 
     31#                ~ q{ errors, it did not declare the same-named module.} 
     32#            if !::($engine_name).does(Module); 
     33    } 
     34#    die qq{new_dbms(): The Muldis DB Engine module '$engine_name' does} 
     35#            ~ q{ not provide the new_dbms() constructor function.} 
     36#        if !::($engine_name).HOW.can('new_dbms'); 
     37    my $dbms = undef; 
    5838    try { 
    59         $dbms_eng = ::($engine_name).new_dbms( 
    60             :dbms_config($dbms_config) ); 
     39        $dbms = &::($engine_name)::new_dbms( :dbms_config($dbms_config) ); 
    6140    }; 
    6241    if (my $err = $!) { 
    63         die qq{new(): The Muldis::DB Engine class '$engine_name' threw} 
    64             ~ qq{ an exception during its new_dbms() execution: $err}; 
    65     } 
    66     die q{new(): The new_dbms() constructor submeth of the Muldis::DB} 
    67             ~ qq{ root Engine class '$engine_name' did not return an} 
    68             ~ q{ object of a Muldis::DB::Engine::Role::DBMS-doing class.} 
    69         if !$dbms_eng.defined 
    70             or !$dbms_eng.does(::Muldis::DB::Engine::Role::DBMS); 
    71  
    72     $!dbms_eng = $dbms_eng; 
    73  
    74     return; 
     42        die qq{new_dbms(): The Muldis DB Engine module '$engine_name'} 
     43            ~ qq{ threw an exception during its new_dbms() exec: $err}; 
     44    } 
     45    die q{new_dbms(): The new_dbms() constructor function of the} 
     46            ~ qq{ Muldis DB Engine module '$engine_name' did not return an} 
     47            ~ q{ object of a Muldis::DB::Interface::DBMS-doing class.} 
     48        if !$dbms.defined or !$dbms.does(::Muldis::DB::Interface::DBMS); 
     49 
     50    return $dbms; 
    7551} 
    7652 
    7753########################################################################### 
    7854 
    79 method new_var of Muldis::DB::Interface::HostGateVar 
    80         (Muldis::DB::Literal::_TypeInvo :$decl_type!) { 
    81     return ::Muldis::DB::Interface::HostGateVar.new( 
    82         :dbms(self), :decl_type($decl_type) ); 
    83 } 
    84  
    85 method prepare of Muldis::DB::Interface::HostGateRtn 
    86         (Muldis::DB::Literal::HostGateRtn :$rtn_ast!) { 
    87     return ::Muldis::DB::Interface::HostGateRtn.new( 
    88         :dbms(self), :rtn_ast($rtn_ast) ); 
    89 } 
    90  
    91 ########################################################################### 
    92  
    93 } # class Muldis::DB::Interface::DBMS 
    94  
    95 ########################################################################### 
    96 ########################################################################### 
    97  
    98 class Muldis::DB::Interface::HostGateVar { 
    99     has Muldis::DB::Interface::DBMS $!dbms; 
    100     has Any                         $!var_eng; 
    101  
    102     trusts Muldis::DB::Interface::HostGateRtn; 
    103  
    104 ########################################################################### 
    105  
    106 submethod BUILD (Muldis::DB::Interface::DBMS :$dbms!, 
    107         Muldis::DB::Literal::_TypeInvo :$decl_type!) { 
    108  
    109     die q{new(): Bad :$dbms arg; it is not an object of a} 
    110             ~ q{ Muldis::DB::Interface::DBMS-doing class.} 
    111         if !$dbms.defined or !$dbms.does(Muldis::DB::Interface::DBMS); 
    112     my $dbms_eng = $dbms!dbms_eng; 
    113     my $dbms_eng_class = $dbms_eng.WHAT; 
    114  
    115     die q{new(): Bad :$decl_type arg; it is not an object of a} 
    116             ~ q{ Muldis::DB::Literal::_TypeInvo-doing class.} 
    117         if !$decl_type.defined 
    118             or !$decl_type.does(Muldis::DB::Literal::_TypeInvo); 
    119  
    120     my $var_eng = undef; 
    121     try { 
    122         $var_eng = $dbms_eng.new_var( :decl_type($decl_type) ); 
    123     }; 
    124     if (my $err = $!) { 
    125         die qq{new(): The Muldis::DB DBMS Eng class '$dbms_eng_class'} 
    126             ~ q{ threw an exception during its new_var()} 
    127             ~ qq{ execution: $err}; 
    128     } 
    129     die q{new(): The new_var() method of the Muldis::DB} 
    130             ~ qq{ DBMS class '$dbms_eng_class' did not return an object} 
    131             ~ q{ of a Muldis::DB::Engine::Role::HostGateVar-doing class.} 
    132         if !$var_eng.defined 
    133             or !$var_eng.does(::Muldis::DB::Engine::Role::HostGateVar); 
    134  
    135     $!dbms    = $dbms; 
    136     $!var_eng = $var_eng; 
    137  
    138     return; 
    139 } 
    140  
    141 ########################################################################### 
    142  
    143 method fetch_ast of Muldis::DB::Literal::Node () { 
    144  
    145     my $val_ast = undef; 
    146     try { 
    147         $val_ast = $!var_eng.fetch_ast(); 
    148     }; 
    149     if (my $err = $!) { 
    150         my $var_eng_class = $!var_eng.WHAT; 
    151         die q{fetch_ast(): The Muldis::DB HostGateVar Engine} 
    152             ~ qq{ class '$var_eng_class' threw an exception during its} 
    153             ~ qq{ fetch_ast() execution: $err}; 
    154     } 
    155  
    156     return $val_ast; 
    157 } 
    158  
    159 ########################################################################### 
    160  
    161 method store_ast (Muldis::DB::Literal::Node :$val_ast!) { 
    162  
    163     die q{store_ast(): Bad :$val_ast arg; it is not an object of a} 
    164             ~ q{ Muldis::DB::Literal::Node-doing class.} 
    165         if !$val_ast.defined or !$val_ast.does(Muldis::DB::Literal::Node); 
    166  
    167     try { 
    168         $!var_eng.store_ast( :val_ast($val_ast) ); 
    169     }; 
    170     if (my $err = $!) { 
    171         my $var_eng_class = $!var_eng.WHAT; 
    172         die q{store_ast(): The Muldis::DB HostGateVar Engine} 
    173             ~ qq{ class '$var_eng_class' threw an exception during its} 
    174             ~ qq{ store_ast() execution: $err}; 
    175     } 
    176  
    177     return; 
    178 } 
    179  
    180 ########################################################################### 
    181  
    182 } # class Muldis::DB::Interface::HostGateVar 
    183  
    184 ########################################################################### 
    185 ########################################################################### 
    186  
    187 class Muldis::DB::Interface::HostGateRtn { 
    188     has Muldis::DB::Interface::DBMS  $!dbms; 
    189     has Muldis::DB::Literal::HostGateRtn $!rtn_ast; 
    190     has Any                          $!rtn_eng; 
    191  
    192 ########################################################################### 
    193  
    194 submethod BUILD (Muldis::DB::Interface::DBMS :$dbms!, 
    195         Muldis::DB::Literal::HostGateRtn :$rtn_ast!) { 
    196  
    197     die q{new(): Bad :$dbms arg; it is not an object of a} 
    198             ~ q{ Muldis::DB::Interface::DBMS-doing class.} 
    199         if !$dbms.defined or !$dbms.does(Muldis::DB::Interface::DBMS); 
    200     my $dbms_eng = $dbms!dbms_eng; 
    201     my $dbms_eng_class = $dbms_eng.WHAT; 
    202  
    203     die q{new(): Bad :$rtn_ast arg; it is not an object of a} 
    204             ~ q{ Muldis::DB::Literal::HostGateRtn-doing class.} 
    205         if !$rtn_ast.defined 
    206             or !$rtn_ast.does(Muldis::DB::Literal::HostGateRtn); 
    207  
    208     my $rtn_eng = undef; 
    209     try { 
    210         $rtn_eng = $dbms_eng.prepare( :rtn_ast($rtn_ast) ); 
    211     }; 
    212     if (my $err = $!) { 
    213         die qq{new(): The Muldis::DB DBMS Eng class '$dbms_eng_class'} 
    214             ~ qq{ threw an exception during its prepare() execution: $err}; 
    215     } 
    216     die q{new(): The prepare() method of the Muldis::DB} 
    217             ~ qq{ DBMS class '$dbms_eng_class' did not return an object} 
    218             ~ q{ of a Muldis::DB::Engine::Role::HostGateRtn-doing class.} 
    219         if !$rtn_eng.defined 
    220             or !$rtn_eng.does(::Muldis::DB::Engine::Role::HostGateRtn); 
    221  
    222     $!dbms    = $dbms; 
    223     $!rtn_ast = $rtn_ast; 
    224     $!rtn_eng = $rtn_eng; 
    225  
    226     return; 
    227 } 
    228  
    229 ########################################################################### 
    230  
    231 method bind_host_params (Array :$upd_args!, Array :$ro_args!) { 
    232  
    233     my Hash $exp_upd_params_map_hoa = $!rtn_ast!upd_params!map_hoa; 
    234     my Hash $exp_ro_params_map_hoa = $!rtn_ast!ro_params!map_hoa; 
    235  
    236     die q{bind_host_params(): Bad :$upd_args arg; it is not an object of a} 
    237             ~ q{ Array-doing class.} 
    238         if !$upd_args.defined or !$upd_args.does(Array); 
    239     my Hash $seen_upd_param_names = {}; 
    240     my Array $upd_arg_engs = []; 
    241     for $upd_args -> $elem { 
    242         die q{bind_host_params(): Bad :$upd_args arg; it is not an object} 
    243                 ~ q{ of a Array-doing class, or it doesn't have 2 elems.} 
    244             if !$elem.defined or !$elem.does(Array) or $elem.elems != 2; 
    245         my ($param_name, $var_intf) = $elem.values; 
    246         die q{bind_host_params(): Bad :$upd_args arg elem; its first} 
    247                 ~ q{ element is not an object of a} 
    248                 ~ q{ Muldis::DB::Literal::EntityName-doing class.} 
    249             if !$param_name.defined 
    250                 or !$param_name.does(Muldis::DB::Literal::EntityName); 
    251         my Str $param_name_text = $param_name.text(); 
    252         die q{bind_host_params(): Bad :$upd_args arg elem; its first} 
    253                 ~ q{ element does not match the name of a} 
    254                 ~ q{ subject-to-update routine param.} 
    255             if !$exp_upd_params_map_hoa.exists($param_name_text); 
    256         die q{bind_host_params(): Bad :$upd_args arg elem; its first elem} 
    257                 ~ q{ is not distinct between the arg elems.} 
    258             if $seen_upd_param_names.exists($param_name_text); 
    259         $seen_upd_param_names{$param_name_text} = 1; 
    260         die q{bind_host_params(): Bad :$upd_args arg elem; its second} 
    261                 ~ q{ element is not an object of a} 
    262                 ~ q{ Muldis::DB::Interface::HostGateVar-doing class.} 
    263             if !$var_intf.defined 
    264                 or !$var_intf.does(Muldis::DB::Interface::HostGateVar); 
    265         $upd_arg_engs.push( [$param_name, $var_intf!var_eng] ); 
    266     } 
    267  
    268     die q{bind_host_params(): Bad :$ro_args arg; it is not an object of a} 
    269             ~ q{ Array-doing class.} 
    270         if !$ro_args.defined or !$ro_args.does(Array); 
    271     my Hash $seen_ro_param_names = {}; 
    272     my Array $ro_arg_engs = []; 
    273     for $ro_args -> $elem { 
    274         die q{bind_host_params(): Bad :$ro_args arg; it is not an object} 
    275                 ~ q{ of a Array-doing class, or it doesn't have 2 elems.} 
    276             if !$elem.defined or !$elem.does(Array) or $elem.elems != 2; 
    277         my ($param_name, $var_intf) = $elem.values; 
    278         die q{bind_host_params(): Bad :$ro_args arg elem; its first} 
    279                 ~ q{ element is not an object of a} 
    280                 ~ q{ Muldis::DB::Literal::EntityName-doing class.} 
    281             if !$param_name.defined 
    282                 or !$param_name.does(Muldis::DB::Literal::EntityName); 
    283         my Str $param_name_text = $param_name.text(); 
    284         die q{bind_host_params(): Bad :$ro_args arg elem; its first} 
    285                 ~ q{ element does not match the name of a} 
    286                 ~ q{ read-only routine param.} 
    287             if !$exp_ro_params_map_hoa.exists($param_name_text); 
    288         die q{bind_host_params(): Bad :$ro_args arg elem; its first elem} 
    289                 ~ q{ is not distinct between the arg elems.} 
    290             if $seen_ro_param_names.exists($param_name_text); 
    291         $seen_ro_param_names{$param_name_text} = 1; 
    292         die q{bind_host_params(): Bad :$ro_args arg elem; its second} 
    293                 ~ q{ element is not an object of a} 
    294                 ~ q{ Muldis::DB::Interface::HostGateVar-doing class.} 
    295             if !$var_intf.defined 
    296                 or !$var_intf.does(Muldis::DB::Interface::HostGateVar); 
    297         $ro_arg_engs.push( [$param_name, $var_intf!var_eng] ); 
    298     } 
    299  
    300     try { 
    301         $!rtn_eng.bind_host_params( 
    302             :upd_args($upd_arg_engs), :ro_args($ro_arg_engs) ); 
    303     }; 
    304     if (my $err = $!) { 
    305         my $rtn_eng_class = $!rtn_eng.WHAT; 
    306         die q{bind_host_params(): The Muldis::DB HostGateRtn Engine} 
    307             ~ qq{ class '$rtn_eng_class' threw an exception during its} 
    308             ~ qq{ bind_host_params() execution: $err}; 
    309     } 
    310  
    311     return; 
    312 } 
    313  
    314 ########################################################################### 
    315  
    316 method execute () { 
    317     try { 
    318         $!rtn_eng.execute(); 
    319     }; 
    320     if (my $err = $!) { 
    321         my $rtn_eng_class = $!rtn_eng.WHAT; 
    322         die q{execute(): The Muldis::DB HostGateRtn Engine} 
    323             ~ qq{ class '$rtn_eng_class' threw an exception during its} 
    324             ~ qq{ execute() execution: $err}; 
    325     } 
    326     return; 
    327 } 
    328  
    329 ########################################################################### 
    330  
    331 } # class Muldis::DB::Interface::HostGateRtn 
    332  
    333 ########################################################################### 
    334 ########################################################################### 
    335  
    336 role Muldis::DB::Engine::Role { 
    337  
    338     submethod new_dbms { 
    339         die q{not implemented by subclass } ~ $?CLASS; 
    340     } 
    341  
    342 } # role Muldis::DB::Engine::Role 
    343  
    344 ########################################################################### 
    345 ########################################################################### 
    346  
    347 role Muldis::DB::Engine::Role::DBMS { 
     55} # module Muldis::DB::Interface 
     56 
     57########################################################################### 
     58########################################################################### 
     59 
     60role Muldis::DB::Interface::DBMS { 
    34861 
    34962    method new_var { 
     
    35164    } 
    35265 
    353     method prepare { 
    354         die q{not implemented by subclass } ~ self.WHAT; 
    355     } 
    356  
    357 } # role Muldis::DB::Engine::Role::DBMS 
    358  
    359 ########################################################################### 
    360 ########################################################################### 
    361  
    362 role Muldis::DB::Engine::Role::HostGateVar { 
     66    method assoc_vars { 
     67        die q{not implemented by subclass } ~ self.WHAT; 
     68    } 
     69 
     70    method new_func_binding { 
     71        die q{not implemented by subclass } ~ self.WHAT; 
     72    } 
     73 
     74    method assoc_func_bindings { 
     75        die q{not implemented by subclass } ~ self.WHAT; 
     76    } 
     77 
     78    method new_proc_binding { 
     79        die q{not implemented by subclass } ~ self.WHAT; 
     80    } 
     81 
     82    method assoc_proc_bindings { 
     83        die q{not implemented by subclass } ~ self.WHAT; 
     84    } 
     85 
     86    method call_func { 
     87        die q{not implemented by subclass } ~ self.WHAT; 
     88    } 
     89 
     90    method call_proc { 
     91        die q{not implemented by subclass } ~ self.WHAT; 
     92    } 
     93 
     94    method trans_nest_level { 
     95        die q{not implemented by subclass } ~ self.WHAT; 
     96    } 
     97 
     98    method start_trans { 
     99        die q{not implemented by subclass } ~ self.WHAT; 
     100    } 
     101 
     102    method commit_trans { 
     103        die q{not implemented by subclass } ~ self.WHAT; 
     104    } 
     105 
     106    method rollback_trans { 
     107        die q{not implemented by subclass } ~ self.WHAT; 
     108    } 
     109 
     110} # role Muldis::DB::Interface::DBMS 
     111 
     112########################################################################### 
     113########################################################################### 
     114 
     115role Muldis::DB::Interface::Var { 
     116 
     117    method assoc_dbms { 
     118        die q{not implemented by subclass } ~ self.WHAT; 
     119    } 
     120 
     121    method decl_type { 
     122        die q{not implemented by subclass } ~ self.WHAT; 
     123    } 
    363124 
    364125    method fetch_ast { 
     
    370131    } 
    371132 
    372 } # role Muldis::DB::Engine::Role::HostGateVar 
    373  
    374 ########################################################################### 
    375 ########################################################################### 
    376  
    377 role Muldis::DB::Engine::Role::HostGateRtn { 
    378  
    379     method bind_host_params { 
    380         die q{not implemented by subclass } ~ self.WHAT; 
    381     } 
    382  
    383     method execute { 
    384         die q{not implemented by subclass } ~ self.WHAT; 
    385     } 
    386  
    387 } # role Muldis::DB::Engine::Role::HostGateRtn 
     133} # role Muldis::DB::Interface::Var 
     134 
     135########################################################################### 
     136########################################################################### 
     137 
     138role Muldis::DB::Interface::FuncBinding { 
     139 
     140    method assoc_dbms { 
     141        die q{not implemented by subclass } ~ self.WHAT; 
     142    } 
     143 
     144    method bind_func { 
     145        die q{not implemented by subclass } ~ self.WHAT; 
     146    } 
     147 
     148    method bound_func { 
     149        die q{not implemented by subclass } ~ self.WHAT; 
     150    } 
     151 
     152    method bind_result { 
     153        die q{not implemented by subclass } ~ self.WHAT; 
     154    } 
     155 
     156    method bound_result { 
     157        die q{not implemented by subclass } ~ self.WHAT; 
     158    } 
     159 
     160    method bind_params { 
     161        die q{not implemented by subclass } ~ self.WHAT; 
     162    } 
     163 
     164    method bound_params { 
     165        die q{not implemented by subclass } ~ self.WHAT; 
     166    } 
     167 
     168    method call { 
     169        die q{not implemented by subclass } ~ self.WHAT; 
     170    } 
     171 
     172} # role Muldis::DB::Interface::FuncBinding 
     173 
     174########################################################################### 
     175########################################################################### 
     176 
     177role Muldis::DB::Interface::ProcBinding { 
     178 
     179    method assoc_dbms { 
     180        die q{not implemented by subclass } ~ self.WHAT; 
     181    } 
     182 
     183    method bind_proc { 
     184        die q{not implemented by subclass } ~ self.WHAT; 
     185    } 
     186 
     187    method bound_proc { 
     188        die q{not implemented by subclass } ~ self.WHAT; 
     189    } 
     190 
     191    method bind_upd_params { 
     192        die q{not implemented by subclass } ~ self.WHAT; 
     193    } 
     194 
     195    method bound_upd_params { 
     196        die q{not implemented by subclass } ~ self.WHAT; 
     197    } 
     198 
     199    method bind_ro_params { 
     200        die q{not implemented by subclass } ~ self.WHAT; 
     201    } 
     202 
     203    method bound_ro_params { 
     204        die q{not implemented by subclass } ~ self.WHAT; 
     205    } 
     206 
     207    method call { 
     208        die q{not implemented by subclass } ~ self.WHAT; 
     209    } 
     210 
     211} # role Muldis::DB::Interface::ProcBinding 
    388212 
    389213########################################################################### 
     
    397221 
    398222Muldis::DB::Interface - 
    399 Common public API for Muldis::DB Engines 
     223Common public API for Muldis DB Engines 
    400224 
    401225=head1 VERSION 
     
    404228 
    405229It also describes the same-number versions for Perl 6 of 
    406 Muldis::DB::Interface::DBMS ("DBMS"), Muldis::DB::Interface::HostGateVar 
    407 ("HostGateVar"), and Muldis::DB::Interface::HostGateRtn ("HostGateRtn"). 
    408  
    409 It also describes the same-number versions for Perl 6 of 
    410 Muldis::DB::Engine::Role, Muldis::DB::Engine::Role::DBMS, 
    411 Muldis::DB::Engine::Role::HostGateVar, and 
    412 Muldis::DB::Engine::Role::HostGateRtn. 
     230Muldis::DB::Interface::DBMS ("DBMS"), Muldis::DB::Interface::Var ("Var"), 
     231Muldis::DB::Interface::FuncBinding ("FuncBinding"), and 
     232Muldis::DB::Interface::ProcBinding ("ProcBinding"). 
    413233 
    414234=head1 SYNOPSIS 
    415235 
     236This simple example declares two Perl variables containing relation data, 
     237then does a (N-ary) relational join (natural inner join) on them, producing 
     238a third Perl variable holding the relation data of the result. 
     239 
    416240    use Muldis::DB::Interface; 
    417241 
    418     # Instantiate a Muldis::DB DBMS / virtual machine. 
    419242    my $dbms = Muldis::DB::Interface::new_dbms( 
    420243        :engine_name('Muldis::DB::Engine::Example'), 
     
    422245    ); 
    423246 
    424     # TODO: Create or connect to a repository and work with it. 
    425  
    426 I<This documentation is pending.> 
     247    my $r1 = $dbms.new_var( :decl_type('sys.Core.Relation.Relation') ); 
     248    my $r2 = $dbms.new_var( :decl_type('sys.Core.Relation.Relation') ); 
     249 
     250    $r1.store_ast( :ast([ 'Relation', 'sys.Core.Relation.Relation', [ 
     251        { 
     252            'x' => [ 'PInt', 'perl_pint', 4 ], 
     253            'y' => [ 'PInt', 'perl_pint', 7 ], 
     254        }, 
     255        { 
     256            'x' => [ 'PInt', 'perl_pint', 3 ], 
     257            'y' => [ 'PInt', 'perl_pint', 2 ], 
     258        }, 
     259    ] ]) ); 
     260 
     261    $r2.store_ast( :ast([ 'Relation', 'sys.Core.Relation.Relation', [ 
     262        { 
     263            'y' => [ 'PInt', 'perl_pint', 5 ], 
     264            'z' => [ 'PInt', 'perl_pint', 6 ], 
     265        }, 
     266        { 
     267            'y' => [ 'PInt', 'perl_pint', 2 ], 
     268            'z' => [ 'PInt', 'perl_pint', 1 ], 
     269        }, 
     270        { 
     271            'y' => [ 'PInt', 'perl_pint', 2 ], 
     272            'z' => [ 'PInt', 'perl_pint', 4 ], 
     273        }, 
     274    ] ]) ); 
     275 
     276    my $r3 = $dbms.call_func( 
     277        :func_name('sys.Core.Relation.join'), 
     278        :args({ 
     279            'topic' => [ 'QuasiSet', 'sys.Core.Spec.QuasiSetOfRelation', [ 
     280                $r1, 
     281                $r2, 
     282            ] ], 
     283        }), 
     284    ); 
     285 
     286    my $r3_ast = $r3.fetch_ast(); 
     287 
     288    # Then $r3_ast contains: 
     289    # [ 'Relation', 'sys.Core.Relation.Relation', [ 
     290    #     { 
     291    #         'x' => [ 'PInt', 'perl_pint', 3 ], 
     292    #         'y' => [ 'PInt', 'perl_pint', 2 ], 
     293    #         'z' => [ 'PInt', 'perl_pint', 1 ], 
     294    #     }, 
     295    #     { 
     296    #         'x' => [ 'PInt', 'perl_pint', 3 ], 
     297    #         'y' => [ 'PInt', 'perl_pint', 2 ], 
     298    #         'z' => [ 'PInt', 'perl_pint', 4 ], 
     299    #     }, 
     300    # ] ] 
     301 
     302For most examples of using Muldis DB, and tutorials, please see the 
     303separate L<Muldis::DB::Cookbook> distribution (when that comes to exist). 
    427304 
    428305=head1 DESCRIPTION 
     
    439316 
    440317The interface of Muldis::DB::Interface is fundamentally object-oriented; 
    441 you use it by creating objects from its member classes, usually invoking 
    442 C<new()> on the appropriate class name, and then invoking methods on those 
    443 objects.  All of their attributes are private, so you must use accessor 
    444 methods. 
    445  
    446 Muldis::DB::Interface also provides the not-exportable wrapper subroutine 
    447 C<Muldis::DB::new_dbms> for the C<Muldis::DB::Interface::DBMS> constructor, 
    448 which has identical parameters, and exists solely as syntactic sugar. 
    449 Similarly, the C<DBMS> methods C<new_var> and C<prepare> exist purely as 
    450 syntactic sugar over the C<HostGateVar> and C<HostGateRtn> constructors. 
    451 I<TODO: Reimplement these as lexical aliases or compile-time macros 
    452 instead, to avoid the overhead of extra routine calls.> 
     318you use it by creating objects from its member classes (or more 
     319specifically, of implementing subclasses of its member roles) and then 
     320invoking methods on those objects.  All of their attributes are private, so 
     321you must use accessor methods. 
     322 
     323To aid portability of your applications over multiple implementing Engines, 
     324the normal way to create Interface objects is by invoking a 
     325constructor-wrapping method of some other object that would provide context 
     326for it; since you generally don't have to directly invoke any package 
     327names, you don't need to change your code when the package names change due 
     328to switching the Engine.  You only refer to some Engine's root package name 
     329once, as a C<Muldis::DB::Interface::new_dbms> argument, and even that can 
     330be read from a config file rather than being hard-coded in your 
     331application. 
    453332 
    454333The usual way that Muldis::DB::Interface indicates a failure is to throw an 
     
    457336value is undefined. 
    458337 
    459 =head2 The Muldis::DB::Interface::DBMS Class 
    460  
    461 I<This d