| 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 | |
| | 60 | role Muldis::DB::Interface::DBMS { |
| 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 | |
| | 138 | role 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 | |
| | 177 | role 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 |
| 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 | |
| | 302 | For most examples of using Muldis DB, and tutorials, please see the |
| | 303 | separate L<Muldis::DB::Cookbook> distribution (when that comes to exist). |