File: YAML.pm

package info (click to toggle)
libtangram-perl 2.10-1.1
  • links: PTS
  • area: main
  • in suites: lenny, squeeze, wheezy
  • size: 1,064 kB
  • ctags: 703
  • sloc: perl: 9,665; makefile: 35
file content (140 lines) | stat: -rw-r--r-- 3,440 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

package Tangram::Type::Dump::YAML;

=head1 NAME

Tangram::Type::Dump::YAML - serialise fields of an object via YAML to a column

=head1 SYNOPSIS

   use Tangram::Core;
   use Tangram::Type::Dump::YAML;

   $schema = Tangram::Schema->new(
      classes => { NaturalPerson => { fields => {

      yaml =>
      {
         diary => # diary is a perl hash 
         {
            col => 'diarydata',
            sql => 'TEXT', # better be large enough!  :)

            # YAML dumper control, values here are defaults
            options => {
                Indent => 2,
                UseHeader => 1,
                UseVersion => 1,
                SortKeys => 1,
                UseCode => 0,
                # ... etc, see the YAML man page for more
            },

      }

      }}});

=head1 DESCRIPTION

Tangram::Type::Dump::YAML is very much like Tangram::Type::Dump::Perl, only serialisation
is achieved via YAML and not Data::Dumper.

This is currently untested, but is known to have bugs, largely to do
with the fact that YAML can't serialise blessed references (see
L<http://rt.cpan.org/NoAuth/Bug.html?id=4784>).

=cut

use strict;
use Tangram::Type::Scalar;
use YAML qw(freeze thaw);

use vars qw(@ISA);
@ISA = qw( Tangram::Type::String );

use Set::Object qw(reftype);

$Tangram::Schema::TYPES{yaml} = Tangram::Type::Dump::YAML->new;

sub reschema {

  my ($self, $members, $class, $schema) = @_;

  if (ref($members) eq 'ARRAY') {
      # short form
      # transform into hash: { fieldname => { col => fieldname }, ... }
      $_[1] = map { $_ => { col => $schema->{normalize}->($_, 'colname') } }
	  @$members;
  }

  for my $field (keys %$members) {

      my $def = $members->{$field};
      my $refdef = reftype($def);

      unless ($refdef) {
	  # not a reference: field => field
	  $def = $members->{$field}
	      = { col => $schema->{normalize}->(($def || $field), 'colname') };
	  $refdef = reftype($def);
      }

      die ref($self).": $class\:\:$field: unexpected $refdef"
	  unless $refdef eq 'HASH';

      $def->{col} ||= $schema->{normalize}->($field, 'colname');
      $def->{sql} ||= 'VARCHAR(255)'; # not a great default, but hey, it's
                                      # portable
      $def->{options} ||= { };
      $def->{dumper} = sub {
	  freeze(shift);
      };

  }

  return keys %$members;
}

sub get_importer
{
	my ($self, $context) = @_;
        return("{ my \$x = '--- ' . ((shift \@\$row)||'~').'\n';
                \$obj->{$self->{name}} = eval { YAML::thaw(\$x) };\n"
	       .'die("YAML error; `$@` loading: |\n$x\n...\n") if $@;'
               ."Tangram::Type::Dump::unflatten(\$context->{storage}, "
               ."\$obj->{$self->{name}}) }");
  }

sub get_exporter
  {
	my ($self, $context) = @_;
	my $field = $self->{name};

	return sub {
	  my ($obj, $context) = @_;
	  Tangram::Type::Dump::flatten($context->{storage},
				 $obj->{$field});
	  my $text = $self->{dumper}->($obj->{$field});
          $text =~ s{\A--- *|\n\Z}{}g;
	  Tangram::Type::Dump::unflatten($context->{storage},
				   $obj->{$field});
	  return $text;
	};
  }

sub save {
  my ($self, $cols, $vals, $obj, $members, $storage) = @_;
  
  my $dbh = $storage->{db};
  
  foreach my $member (keys %$members) {
    my $memdef = $members->{$member};
    
    next if $memdef->{automatic};
    
    push @$cols, $memdef->{col};
    push @$vals, $dbh->quote(&{$memdef->{dumper}}($obj->{$member}));
  }
}

1;