Skip to content

Instantly share code, notes, and snippets.

@afair
Created August 2, 2011 17:58
Show Gist options
  • Save afair/1120790 to your computer and use it in GitHub Desktop.
Save afair/1120790 to your computer and use it in GitHub Desktop.
Perl methods to parse and create PostgreSQL hstore column data
##----------------------------------------------------------------
## HSTORE: PostgreSQL key-value store column type
##----------------------------------------------------------------
# Double-quotes the value, escaping embedded double-quotes. This is NOT the
# same as db quoting (which uses apostrophes), and any value here must also
# be quote()'ed before sending to the database.
sub double_quote {
my ($self, $v) = @_;
$v =~ s/"/\\"/g;
"\"$v\"";
}
# Takes a hash ptr or hash, and returns an hstore string of the data
sub hash_to_hstore {
my $self = shift; # Not needed, but good for namespacing
my $h = ref($_[0]) eq 'HASH' ? shift : {@_}; # get hash ref or hash
my $s = '';
foreach my $k (sort keys %$h) {
next unless $k; # Empty keys?
$s .= ($k =~ /\W/ ? $self->double_quote($k) : $k) . '=>';
if (!defined $h->{$k}) {
$s .= 'NULL,';
}
elsif (!$h->{$k}) {
$s .= '"",';
}
else {
$s .= ($h->{$k} =~ /\W/ ? $self->double_quote($h->{$k}) : $h->{$k}) . ',';
}
}
$s =~ s/,$//;
$s;
}
# Takes the current hstore data strong and splits off the first token, returing (token, remainder)
sub hstore_token {
my ($data) = @_;
my $token;
$data =~ s/^\s*//;
if ($data =~ /^\"/ && $data =~ /^"(.*?)(?<!\\)"\s*(.*)/s) { # Quoted string w/ escaped \"
($token, $data) = ($1, $2);
$token =~ s/\\"/"/g;
return ($token, $data);
}
elsif ($data =~ /^([^\w\"\s]+)\s*(.*)/s) { # Operators: => ,
return ($1, $2);
}
elsif ($data =~ /^(\w[^=,\s]*)\s*(.*)/s) { # Word 0-9a-z until = , or space
return ($1, $2);
}
return ('', ''); # Unknown: return end of string
}
# Parses string of: key=>value,... and returns hash ptr to data.
sub hstore_to_hash {
my ($self, $data) = @_;
my $h = {};
my ($k, $v, $token);
while ($data) {
($k, $data) = hstore_token($data);
($k, $data) = hstore_token($data) if $k eq ',';
($token, $data) = hstore_token($data); # =>
($v, $data) = hstore_token($data);
$h->{$k} = $v if $k;
}
$h;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment