1 package DBM::Deep::Sector::DBI::Reference;
6 use warnings FATAL => 'all';
8 use base 'DBM::Deep::Sector::DBI';
15 my $e = $self->engine;
17 unless ( $self->offset ) {
18 my $classname = Scalar::Util::blessed( delete $self->{data} );
19 $self->{offset} = $self->engine->storage->write_to(
21 ref_type => $self->type,
22 classname => $classname,
26 my ($rows) = $self->engine->storage->read_from(
27 refs => $self->offset,
31 $self->{type} = $rows->[0]{ref_type};
41 my ($rows) = $self->engine->storage->read_from(
42 datas => { ref_id => $self->offset, key => $args->{key} },
46 return unless $rows->[0]{id};
59 if ( ( $args->{value}->type || 'S' ) eq 'S' ) {
60 $args->{value}{offset} = $self->engine->storage->write_to(
61 datas => $args->{value}{offset},
62 ref_id => $self->offset,
65 value => $args->{value}{data},
68 $args->{value}->reload;
71 # Write the Scalar of the Reference
72 $self->engine->storage->write_to(
74 ref_id => $self->offset,
77 value => $args->{value}{offset},
86 my $old_value = $self->get_data_for({
92 $data = $old_value->data({ export => 1 });
101 my ($rows) = $self->engine->storage->read_from(
102 'refs', $self->offset,
105 return unless @$rows;
106 return $rows->[0]{classname};
109 # Look to hoist this method into a ::Reference trait
115 my $engine = $self->engine;
116 if ( !exists $engine->cache->{ $self->offset } ) {
117 my $obj = DBM::Deep->new({
119 base_offset => $self->offset,
120 storage => $engine->storage,
124 $engine->cache->{$self->offset} = $obj;
126 my $obj = $engine->cache->{$self->offset};
128 # We're not exporting, so just return.
129 unless ( $args->{export} ) {
130 if ( $engine->storage->{autobless} ) {
131 my $classname = $self->get_classname;
132 if ( defined $classname ) {
133 bless $obj, $classname;
140 # We shouldn't export if this is still referred to.
141 if ( $self->get_refcount > 1 ) {
151 # We're not ready to be removed yet.
152 return if $self->decrement_refcount > 0;
154 # Rebless the object into DBM::Deep::Null.
155 eval { %{ $self->engine->cache->{ $self->offset } } = (); };
156 eval { @{ $self->engine->cache->{ $self->offset } } = (); };
157 bless $self->engine->cache->{ $self->offset }, 'DBM::Deep::Null';
158 delete $self->engine->cache->{ $self->offset };
160 $self->engine->storage->delete_from(
161 'datas', { ref_id => $self->offset },
164 $self->engine->storage->delete_from(
165 'datas', { value => $self->offset, data_type => 'R' },
168 $self->SUPER::free( @_ );
171 sub increment_refcount {
173 my $refcount = $self->get_refcount;
175 $self->write_refcount( $refcount );
179 sub decrement_refcount {
181 my $refcount = $self->get_refcount;
183 $self->write_refcount( $refcount );
189 my ($rows) = $self->engine->storage->read_from(
190 'refs', $self->offset,
193 return $rows->[0]{refcount};
199 $self->engine->storage->{dbh}->do(
200 "UPDATE refs SET refcount = ? WHERE id = ?", undef,
210 base_offset => $self->offset,
211 storage => $self->engine->storage,
212 engine => $self->engine,