File Coverage

blib/lib/Persistence/Entity.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             package Persistence::Entity;
2              
3 18     18   1037028 use strict;
  18         44  
  18         1026  
4 18     18   108 use warnings;
  18         38  
  18         853  
5 18     18   133 use vars qw(@EXPORT_OK %EXPORT_TAGS $VERSION);
  18         56  
  18         1406  
6              
7 18     18   2776 use Abstract::Meta::Class ':all';
  18         51981  
  18         3722  
8 18     18   144 use base qw(Exporter SQL::Entity);
  18         51  
  18         15776  
9             use Carp 'confess';
10              
11             use SQL::Entity ':all';
12              
13             @EXPORT_OK = qw(
14             sql_relationship
15             sql_column
16             sql_lob
17             sql_index
18             sql_cond
19             sql_and
20             sql_or
21             );
22              
23              
24             %EXPORT_TAGS = (all => \@EXPORT_OK);
25              
26             $VERSION = 0.07;
27              
28             =head1 NAME
29              
30             Persistence::Entity - Persistence API for perl classes.
31              
32             =cut
33              
34             =head1 CLASS HIERARCHY
35              
36             SQL::Entity::Table
37             |
38             +----SQL::Entity
39             |
40             +----Persistence::Entity
41              
42              
43             =head1 SYNOPSIS
44              
45             use Persistence::Entity ':all';
46              
47             my $membership_entity = Persistence::Entity->new(
48             name => 'wsus_user_service',
49             alias => 'us',
50             primary_key => ['user_id', 'service_id'],
51             columns => [
52             sql_column(name => 'user_id'),
53             sql_column(name => 'service_id'),
54             sql_column(name => 'agreement_flag')
55             ],
56             );
57              
58             my $user_entity = Persistence::Entity->new(
59             name => 'wsus_user',
60             alias => 'ur',
61             primary_key => ['id'],
62             columns => [
63             sql_column(name => 'id'),
64             sql_column(name => 'username'),
65             sql_column(name => 'password'),
66             sql_column(name => 'email'),
67             ],
68             to_many_relationships => [sql_relationship(target_entity => $membership_entity, join_columns => ['user_id'])]
69             );
70              
71             $entity_manager->add_entities($membership_entity, $user_entity);
72              
73             LOB's support
74              
75             my $photo_entity = Persistence::Entity->new(
76             name => 'photo',
77             alias => 'ph',
78             primary_key => ['id'],
79             columns => [
80             sql_column(name => 'id'),
81             sql_column(name => 'name', unique => 1),
82             ],
83             lobs => [
84             sql_lob(name => 'blob_content', size_column => 'doc_size'),
85             ]
86             );
87              
88              
89             =head1 DESCRIPTION
90              
91             This class represents database entity.
92              
93             =head2 EXPORT
94              
95             sql_relationship
96             sql_column
97             sql_lob
98             sql_index
99             sql_cond
100             sql_and
101             sql_or by ':all' tag
102              
103             =head2 ATTRIBUTES
104              
105             =over
106              
107             =item trigger
108              
109             Defines tigger that will execute on one of the following event
110             before_insert after_insert before_update after_update before_delete after_delete, on_fetch
111             Takes event name as first parameter, and callback as secound parameter.
112              
113              
114             $entity->trigger(before_insert => sub {
115             my ($self) = @_;
116             #do stuff
117             });
118              
119              
120             =cut
121              
122             {
123              
124             has '%.triggers' => (
125             transistent => 1,
126             item_accessor => 'trigger',
127             on_change => sub {
128             my ($self, $attribute, $scope, $value, $key) = @_;
129             if($scope eq 'mutator') {
130             my $hash = $$value;
131             foreach my $k (keys %$hash) {
132             $self->validate_trigger($k, $hash->{$k});
133             }
134             } else {
135             $self->validate_trigger($key. $$value);
136             }
137             $self;
138             },
139             );
140             }
141              
142              
143             =item entity_manager
144              
145             =cut
146              
147             has '$.entity_manager' => (
148             transistent => 1,
149             associated_class => 'Persistence::Entity::Manager',
150             the_other_end => 'entities',
151             );
152              
153              
154             =item value_generators
155              
156             Hash that contains pair of column and its value generator.
157              
158             =cut
159              
160             has '%.value_generators' => (
161             item_accessor => 'value_generator'
162             );
163              
164              
165              
166             =item filter_condition_values
167              
168             Hash ref that contains filter values, that values will be used as condition values
169              
170             =cut
171              
172             has '%.filter_condition_values';
173              
174              
175             =item dml_filter_values
176              
177             Hash ref that contains columns values that will be added to all dml operations.
178              
179             =cut
180              
181             has '%.dml_filter_values';
182              
183              
184             =back
185              
186             =head2 METHODS
187              
188             =over
189              
190             =item find
191              
192             Returns list of objects or resultsets.
193             Takes class name to which resultset will be casted, (if class name is undef then hash ref will be return instead),
194             list of names parameters that will be used as condition or condition object.
195             Condition object always should use entity column.
196              
197              
198             my $entity = $entity_manager->entity('emp');
199             my ($emp) = $entity->find('Employee', ename => 'adrian');
200             or
201             my @emp = $entity->find('Employee', sql_cond('ename', 'LIKE', 'a%'));
202             #array of Employee objects.
203              
204              
205             =cut
206              
207             sub find {
208             my ($self, $class_name, @args) = (@_);
209             my $entity_manager = $self->entity_manager;
210             my $condition = $entity_manager->condition_converter($class_name, @args, $self->filter_condition_values);
211             my ($sql, $bind_variables) = $self->query(undef, $condition);
212             $self->_execute_query($sql, $bind_variables, $class_name);
213             }
214              
215              
216             =item search
217              
218             Returns list of objects or resultsets.
219             Takes array ref of requested column to projection, class name to which resultset will be casted,
220             (if class name is undef then hash ref will be return instead),
221             list of names parameters that will be used as condition or condition object.
222             Condition object always should use entity column.
223              
224              
225             my $entity = $entity_manager->entity('emp');
226             my ($emp) = $entity->find('Employee', ename => 'adrian');
227             or
228             my @emp = $entity->find('Employee', sql_cond('ename', 'LIKE', 'a%'));
229             #array of Employee objects.
230              
231              
232             =cut
233              
234             sub search {
235             my ($self, $requested_columns, $class_name, @args) = @_;
236             my $entity_manager = $self->entity_manager;
237             my $condition = $entity_manager->condition_converter($class_name, @args, $self->filter_condition_values);
238             my ($sql, $bind_variables) = $self->query($requested_columns, $condition);
239             $self->_execute_query($sql, $bind_variables, $class_name);
240             }
241              
242              
243             =item lock
244              
245             Returns and locks list and of objects or resultsets.
246             Takes entity name, class name to which resultset will be casted, (if class name is undef then hash ref will be return instead),
247             list of names parameters that will be used as condition or condition object.
248             Condition object always should use entity column.
249             Locking is forced by SELECT ... FOR UPDATE clause
250              
251              
252             my $entity = $entity_manager->entity('emp');
253             my ($emp) = $entity->lock('Employee', ename => 'adrian');
254             or
255             my @emp = $entity->lock('Employee', sql_cond('ename', 'LIKE', 'a%'));
256             #array of Employee objects.
257             or
258             my @emp = $entity->lock(undef, sql_cond('ename', 'LIKE', 'a%'));
259             #array of resultset (hash ref)
260              
261              
262             =cut
263              
264             sub lock {
265             my ($self, $class_name, @args) = (@_);
266             my $entity_manager = $self->entity_manager;
267             my $condition = $entity_manager->condition_converter($class_name, @args, $self->filter_condition_values);
268             my ($sql, $bind_variables) = $self->SUPER::lock(undef, $condition);
269             $self->_execute_query($sql, $bind_variables, $class_name);
270             }
271              
272              
273             =item relationship_query
274              
275             Return rows for relationship.
276             Takes relationship_name, class_name, target_class_name, condition arguments as parameters.
277              
278              
279             $user_entity->add_to_many_relationships(sql_relationship(target_entity => $membership_entity, join_columns => ['user_id']));
280             my $entity_manager = Persistence::Entity::Manager->new(connection_name => 'my_connection');
281             $entity_manager->add_entities($membership_entity, $user_entity);
282             my @membership = $user_entity->relationship_query('wsus_user_service', undef => undef, username => 'test');
283             # returns array of hash refs.
284             or
285             my @membership = $user_entity->relationship_query('wsus_user_service', 'User' => 'ServiceMembership', username => 'test');
286             # returns array of ServiceMembership objects
287              
288              
289             =cut
290              
291             sub relationship_query {
292             my ($self, $relation_name, $class_name, $target_class_name, @args) = @_;
293             my $relationship = $self->relationship($relation_name);
294             my $target_entity = $relationship->target_entity;
295             my $condition = $self->entity_manager->condition_converter($class_name, @args);
296             my ($sql, $bind_variables) = $self->SUPER::relationship_query($relation_name, $condition);
297             $self->_execute_query($sql, $bind_variables, $target_class_name);
298             }
299              
300              
301             =item insert
302              
303             Inserts the entity row
304             Takes list of field values.
305              
306             $entity->insert(col1 => 'val1', col2 => 'val2');
307              
308              
309             =cut
310              
311             sub insert {
312             my ($self, %fields_values) = @_;
313             $self->_autogenerated_values(\%fields_values);
314             my ($sql, $bind_variables) = $self->SUPER::insert(%fields_values, $self->dml_filter_values);
315             $self->_execute_statement($sql, $bind_variables, "insert", \%fields_values);
316             $self->_update_lobs(\%fields_values);
317             \%fields_values;
318             }
319              
320              
321             =item relationship_insert
322              
323             Inserts the relation rows.
324             Takes relation name, dataset that represents the entity row, array ref where item
325             can be either object or hash ref that represents row to be asssociated .
326              
327             $user_entity->relationship_insert('wsus_user_service', {username => 'test'} , {service_id => 1}, {service_id => 9});
328             #or
329             my $user = User->new(...);
330             my $membership1 = Membership->new(...);
331             my $membership2 = Membership->new(...);
332             $user_entity->relationship_insert('wsus_user_service', $user, $membership1, $membership2);
333              
334             =cut
335              
336             sub relationship_insert {
337             my ($self, $relation_name, $dataset, @to_insert) = @_;
338             my $operation = $self->to_one_relationship($relation_name)
339             ? '_to_one_relationship_merge'
340             : '_to_many_relationship_insert';
341             $self->$operation($relation_name, $dataset, @to_insert);
342             }
343              
344              
345             =item update
346              
347             Updates the entity row.
348             Takes field values as hash ref, condition values as hash reference.
349              
350              
351             $entity->update({col1 => 'val1', col2 => 'val2'}, {the_rowid => 'xx'});
352              
353             my $lob = _load_file('t/bin/data1.bin');
354             $photo_entity->insert(id => "1", name => "photo1", blob_content => $lob);
355              
356              
357             =cut
358              
359             sub update {
360             my ($self, $fields_values, $condition_values) = @_;
361             my ($sql, $bind_variables) = $self->SUPER::update({%$fields_values, $self->dml_filter_values}, $condition_values);
362             $self->_execute_statement($sql, $bind_variables, "update", $fields_values) if $sql;
363             $self->_update_lobs($fields_values, $condition_values);
364             }
365              
366              
367             =item merge
368              
369             Merges the entity row.
370             Takes field values to merge as named parameteres,
371              
372              
373             $entity->merge(col1 => 'val1', col2 => 'val2', the_rowid => '0xAAFF');
374              
375              
376             =cut
377              
378             sub merge {
379             my ($self, %fields_values) = @_;
380             my %condition_values = $self->unique_condition_values(\%fields_values, 1);
381             my (@result) = $self->find(undef, %condition_values);
382             unless(@result) {
383             $self->insert(%fields_values);
384             } else {
385             my %condition_values = $self->unique_condition_values(\%fields_values, 1);
386             $self->update(\%fields_values, \%condition_values);
387             }
388             }
389              
390              
391             =item relationship_merge
392              
393             Merges the relation rows.
394             Takes relation name, dataset that represents the entity row, list of
395             either object or hash ref that represent asssociated row to merge.
396              
397              
398             $user_entity->relationship_merge('wsus_user_service',
399             {username => 'test'} ,
400             {service_id => 1, agreement_flag => 1}, {service_id => 5, agreement_flag => 1}
401             );
402              
403              
404             =cut
405              
406             sub relationship_merge {
407             my ($self, $relation_name, $dataset, @to_merge) = @_;
408             my $operation = $self->to_one_relationship($relation_name)
409             ? '_to_one_relationship_merge'
410             : '_to_many_relationship_merge';
411             $self->$operation($relation_name, $dataset, @to_merge);
412             }
413              
414              
415             =item delete
416              
417             Delete entity row.
418             Takes list of condition values.
419              
420              
421             $entity->delete(the_rowid => 'xx');
422              
423              
424             =cut
425              
426             sub delete {
427             my ($self, %condition_values) = @_;
428             my ($sql, $bind_variables) = $self->SUPER::delete(%condition_values, $self->dml_filter_values);
429             $self->_execute_statement($sql, $bind_variables, "delete", \%condition_values);
430             }
431              
432              
433             =item relationship_delete
434              
435             Deletes associated rows.
436             Takes relation name, dataset that represents the entity row, list of
437             either associated object or hash ref that represent asssociated row.
438              
439              
440             $user_entity->relationship_insert('wsus_user_service', {username => 'test'} , {service_id => 1}, {service_id => 9});
441             $user_entity->relationship_insert('wsus_user_service', $user, $membership1, $membership1);
442              
443              
444             =cut
445              
446             sub relationship_delete {
447             my ($self, $relation_name, $dataset, @to_delete) = @_;
448             my $operation = $self->to_one_relationship($relation_name)
449             ? '_to_one_relationship_delete'
450             : '_to_many_relationship_delete';
451             $self->$operation($relation_name, $dataset, @to_delete);
452             }
453              
454              
455             =item primary_key_values
456              
457             Returns primary key values.
458             Takes field values that will be used as condition to retrive primary key values
459             in case they are not contain primary key values.
460              
461             =cut
462              
463             sub primary_key_values {
464             my ($self, $dataset, $validate) = @_;
465             my $result;
466             my @primary_key = $self->primary_key;
467             if(! $self->has_primary_key_values($dataset)) {
468             #only if has pk or unique values
469             my $unique_values = $self->unique_condition_values($dataset);
470             $result = $self->retrive_primary_key_values($unique_values) if (%$unique_values);
471             if ($result) {
472             $result = {map { $_ => $result->{$_}} @primary_key};
473             }
474              
475             } else {
476             $result = {map { $_ => $dataset->{$_}} @primary_key};
477             }
478             confess "cant retrive " .$self->name . "'s primary key values ["
479             . join(",", map { $_ => ($dataset->{$_} || '') } keys %$dataset) . "]"
480             if ! $result && $validate;
481             $result;
482             }
483              
484              
485             =item has_primary_key_values
486              
487             Returns true if passed in dataset contains primary key values.
488              
489             =cut
490              
491             sub has_primary_key_values {
492             my ($self, $dataset) = @_;
493             $dataset ||= {};
494             my @primary_key = $self->primary_key;
495             for (@primary_key) {
496             return if (! exists($dataset->{$_}) || ! defined $dataset->{$_});
497             }
498             $self;
499             }
500              
501              
502             =item fetch_lob
503              
504             Fetchs LOBs value.
505             Takes lob column name, condition values.
506              
507             my $blob = $photo_entity->fetch_lob('blob_content', {id => 10});
508              
509             =cut
510              
511             sub fetch_lob {
512             my ($self, $column, $condition_values) = @_;
513             my $entity_manager = $self->entity_manager;
514             if(ref($condition_values) ne 'HASH') {
515             my $orm = $entity_manager->find_entity_mappings($condition_values);
516             }
517             my $pk_values = $self->primary_key_values($condition_values, 1);
518             my $lob = $self->lob($column);
519             my $connection = $self->entity_manager->connection;
520             $connection->fetch_lob($self->name, $lob->name, $pk_values, $lob->size_column);
521              
522             }
523              
524             =back
525              
526             =head2 PRIVATE METHODS
527              
528             =over
529              
530             =item is_refresh_required
531              
532             Returns true if refreshis required
533              
534             =cut
535              
536             sub is_refresh_required {
537             my ($self, $fields_values) = @_;
538             my $has_primary_key_flag = $self->has_primary_key_values($fields_values, 1);
539             ! $has_primary_key_flag ;
540             }
541              
542              
543             =item run_event
544              
545             Executes passed in even.
546             Takes event name, event parameters.
547              
548             =cut
549              
550             sub run_event {
551             my ($self, $name, @args) = @_;
552             my $event = $self->trigger($name);
553             $event->(@args) if $event;
554             }
555              
556              
557             =item validate_trigger
558              
559             Validates triggers types.
560             The following trigger types are supported: before_insert, after_insert, before_update, after_update, before_delete, after_delete, on_fetch.
561              
562             =cut
563              
564             {
565             my @triggers = qw(before_insert after_insert before_update after_update before_delete after_delete on_fetch);
566             sub validate_trigger {
567             my ($self, $name, $value) = @_;
568             confess "invalid trigger name: $name , must be one of " . join(",", @triggers)
569             unless (grep {$name eq $_} @triggers);
570             confess "secound parameter must be a callback"
571             unless ref($value) eq 'CODE';
572             }
573             }
574              
575              
576             =item _update_lobs
577              
578             Updates LOB value.
579              
580             $entity->_update_lobs({name => "photo1", blob_content => $bin_data}, {id => 1,});
581              
582             =cut
583              
584             sub _update_lobs {
585             my ($self, $fields_values, $condition_values) = @_;
586             $condition_values ||= $fields_values;
587             my $lobs = $self->_extract_lob_values($fields_values);
588             return if (! $lobs || ! %$lobs);
589             my $connection = $self->entity_manager->connection;
590             my $primary_key_values = $self->primary_key_values($condition_values, 1);
591             for my $k (keys %$lobs) {
592             my $lob = $self->lob($k);
593             $connection->update_lob($self->name, $lob->name, $lobs->{$k}, $primary_key_values, $lob->size_column);
594             }
595             }
596              
597              
598             =item _extract_lob_values
599              
600             =cut
601              
602             sub _extract_lob_values {
603             my ($self, $fields_values) = @_;
604             my $lobs = $self->lobs;
605             my $result = {map {($_ => $fields_values->{$_})} keys %$lobs};
606             wantarray ? @$result : $result;
607             }
608              
609              
610             =item _autogenerated_values
611              
612             Adds autogenerated values. Takes hash ref to field values
613              
614             =cut
615              
616             sub _autogenerated_values {
617             my ($self, $field_values) = @_;
618             my $value_generators = $self->value_generators;
619             for my $k(keys %$value_generators) {
620             next if defined $field_values->{$k};
621             my $generator = Persistence::ValueGenerator->generator($value_generators->{$k});
622             $field_values->{$k} = $generator->nextval();
623             }
624             }
625              
626              
627             =item _to_many_relationship_insert
628              
629             Insert data to many relationship.
630             Takes relationship name, hashref of the fileds values for the entity,
631             list of hash ref that contians fileds values of the entities to associate.
632              
633             =cut
634              
635             sub _to_many_relationship_insert {
636             my ($self, $relation_name, $dataset, @to_insert) = @_;
637             my $entity_manager = $self->entity_manager;
638             my $relation = $self->relationship($relation_name);
639             my %join_values = $self->_join_columns_values($relation, $dataset);
640             my $target_entity = $relation->target_entity;
641             for my $item (@to_insert) {
642             my $orm = $entity_manager->find_entity_mappings($item);
643             if ($orm) {
644             $orm->update_object($item, \%join_values);
645             $entity_manager->insert($item, \%join_values);
646            
647             } else {
648             $target_entity->insert(%$item, %join_values);
649             }
650             }
651             }
652              
653              
654             =item _to_one_relationship_merge
655              
656             Merges data to one relationship.
657             Takes relationship name, hashref of the fileds values for the entity,
658             list of hash ref that contians values fileds of the entities to associate.
659              
660             =cut
661              
662             sub _to_one_relationship_merge {
663             my ($self, $relation_name, $dataset, $to_merge) = @_;
664             my $entity_manager = $self->entity_manager;
665             my $relation = $self->relationship($relation_name);
666             my $target_entity = $relation->target_entity;
667             my $column_values = {};
668             if($to_merge) {
669             my $orm = $entity_manager->find_entity_mappings($to_merge);
670             if ($orm) {
671             $entity_manager->merge($to_merge);
672             } else {
673             $target_entity->merge(%$to_merge);
674             }
675             $column_values = $orm->unique_values($to_merge, $target_entity);
676             }
677             my $join_values = $self->_join_columns_values($relation, $column_values);
678             $self->_merge_datasets($join_values, $dataset);
679             }
680              
681              
682              
683             =item _merge_datasets
684              
685             Mergers tow passed in dataset.
686             Takes source hash_ref, target hash_ref.
687              
688             =cut
689              
690             sub _merge_datasets {
691             my ($self, $source_dataset, $target_dataset) = @_;
692             $target_dataset->{$_} = defined $source_dataset->{$_} ? $source_dataset->{$_} : $target_dataset->{$_}
693             for keys %$source_dataset;
694             }
695              
696              
697             =item _join_columns_values
698              
699             Returns join columns values for passed in relation
700              
701             =cut
702              
703             sub _join_columns_values {
704             my ($self, $relation, $dataset, $validation) = @_;
705             my $entity = $self->to_one_relationship($relation->name) ? $relation->target_entity : $self;
706             my @join_columns = $relation->join_columns;
707             my @primary_key = $entity->primary_key;
708             my $primary_key_values = $entity->primary_key_values($dataset, $validation);
709             my %result;
710             for my $i (0 .. $#primary_key) {
711             $result{$join_columns[$i]} = $primary_key_values->{$primary_key[$i]};
712             }
713             wantarray ? (%result) : \%result;
714             }
715              
716              
717             =item _to_many_relationship_merge
718              
719             Marges to many relationship rows (insert/update).
720             Takes relationship name, hashref of the fileds values for the entity,
721             list of hash ref that contians values fileds of the entities to merge.
722              
723             =cut
724              
725             sub _to_many_relationship_merge {
726             my ($self, $relation_name, $dataset, @to_merge) = @_;
727             my $entity_manager = $self->entity_manager;
728             my $relation = $self->relationship($relation_name);
729             my %join_values = $self->_join_columns_values($relation, $dataset, 1);
730             my @existing_dataset = $self->relationship_query($relation_name, undef => undef, %join_values);
731             my $target_entity = $relation->target_entity;
732             my %rows_pk;
733             my $column_values;
734             for my $item (@to_merge) {
735             my $orm = $entity_manager->find_entity_mappings($item);
736             if ($orm) {
737             $orm->update_object($item, \%join_values);
738             $entity_manager->merge($item, \%join_values);
739             $column_values = $orm->unique_values($item, $target_entity);
740             } else {
741             $column_values = {%$item, %join_values};
742             $target_entity->merge(%$item, %join_values);
743             }
744            
745             my $pk_values = $target_entity->primary_key_values($column_values, 1);
746             $rows_pk{join("-", %$pk_values)} = 1;
747             }
748            
749             #deletes all rows that are not part of the assocaition.
750             for my $record (@existing_dataset) {
751             my $pk_values = $target_entity->primary_key_values($record, 1);
752             next if $rows_pk{join("-", %$pk_values)};
753             $target_entity->delete(%$pk_values);
754             }
755             }
756              
757              
758             =item _to_many_relationship_delete
759              
760             Deletes to many relationship association.
761             Takes relationship name, hashref of the fileds values for the entity,
762             list of hash ref that contians values fileds of the entities to delete.
763              
764             =cut
765              
766             sub _to_many_relationship_delete {
767             my ($self, $relation_name, $dataset, @to_delete) = @_;
768             my $entity_manager = $self->entity_manager;
769             my $relation = $self->relationship($relation_name);
770             my %join_values = $self->_join_columns_values($relation, $dataset, 1);
771             my $target_entity = $relation->target_entity;
772             for my $item (@to_delete) {
773             my $orm = $entity_manager->find_entity_mappings($item);
774             if($orm) {
775             $orm->update_object($item, \%join_values);
776             $entity_manager->delete($item);
777             } else {
778             $target_entity->delete($target_entity->unique_condition_values({%$item, %join_values}, 1));
779             }
780             }
781             }
782              
783              
784             =item _to_one_relationship_delete
785              
786             Deletes to one relationship association.
787             Takes relationship name, hashref of the fileds values for the entity,
788             list of hash ref that contians values fileds of the entities to delete.
789              
790             =cut
791              
792             sub _to_one_relationship_delete {
793             my ($self, $relation_name, $dataset, $to_delete) = @_;
794             my $entity_manager = $self->entity_manager;
795             my $relation = $self->relationship($relation_name);
796             my $target_entity = $relation->target_entity;
797             my $column_values = {};
798             if($to_delete) {
799             my $orm = $entity_manager->find_entity_mappings($to_delete);
800             if ($orm) {
801             $entity_manager->delete($to_delete);
802             } else {
803             $target_entity->delete(%$to_delete);
804             }
805             }
806             }
807              
808              
809             =item retrive_primary_key_values
810              
811             Retrieves primary key values.
812             Takes hash ref of the entity field values.
813              
814             =cut
815              
816             sub retrive_primary_key_values {
817             my ($self, $dataset) = @_;
818             my $primary_key = $self->primary_key or confess "primary key must be defined for entity " . $self->id;
819             my @result = $self->find($primary_key, %$dataset);
820             $result[0];
821             }
822              
823              
824             =item _execute_statement
825              
826             Executes passed in sql statements with all callback defined by decorators (triggers)
827             Takes sql, array ref of the bind varaibles,r event name, event parameters.
828              
829             =cut
830              
831             sub _execute_statement {
832             my ($self, $sql, $bind_variables, $event_name, @event_parameters) = @_;
833             my $connection = $self->entity_manager->connection;
834             $self->run_event("before_${event_name}", @event_parameters);
835             $connection->execute_statement($sql, @$bind_variables);
836             $self->run_event("after_${event_name}", @event_parameters);
837             }
838              
839              
840             =item _execute_query
841              
842             Executes query.
843             Takes sql, array ref of the bind varaibles, optionally class name.
844              
845             =cut
846              
847             sub _execute_query {
848             my ($self, $sql, $bind_variables, $class_name) = @_;
849             my $entity_manager = $self->entity_manager;
850             my $connection = $entity_manager->connection;
851             my @result;
852             my $cursor = $connection->query_cursor(sql => $sql);
853             my %result_set;
854             $cursor->execute($bind_variables, \%result_set);
855             while ($cursor->fetch()) {
856             my $result = ($class_name ? $entity_manager->_deseralize_object($class_name, \%result_set) : {%result_set});
857             $self->run_event('on_fetch', $result);
858             push @result, $result;
859             }
860             @result;
861             }
862              
863              
864             1;
865              
866             __END__