File Coverage

blib/lib/JsonSQL/Param/Insert.pm
Criterion Covered Total %
statement 61 61 100.0
branch 14 14 100.0
condition n/a
subroutine 9 9 100.0
pod 3 3 100.0
total 87 87 100.0


line stmt bran cond sub pod time code
1             # ABSTRACT: JsonSQL::Param::Insert object. Stores a Perl representation of an INSERT statement used by the JsonSQL Insert query object.
2              
3              
4              
5 1     1   5 use strict;
  1         8  
  1         23  
6 1     1   4 use warnings;
  1         1  
  1         22  
7 1     1   14 use 5.014;
  1         3  
8              
9             package JsonSQL::Param::Insert;
10              
11             our $VERSION = '0.4'; # VERSION
12              
13 1     1   5 use JsonSQL::Error;
  1         1  
  1         19  
14 1     1   215 use JsonSQL::Param::Table;
  1         2  
  1         23  
15 1     1   222 use JsonSQL::Param::InsertValues;
  1         1  
  1         354  
16              
17              
18              
19             sub new {
20 7     7 1 16 my ( $class, $inserthashref, $queryObj ) = @_;
21            
22 7         11 my $self = {};
23 7         10 my @insert_errors;
24            
25             # Construct _insertTable property.
26 7         25 my $inserttable = JsonSQL::Param::Table->new($inserthashref->{table}, $queryObj);
27 7 100       12 if ( eval { $inserttable->is_error } ) {
  7         60  
28 2         7 push(@insert_errors, "Error creating table $inserthashref->{table}->{table} for INSERT: $inserttable->{message}");
29             } else {
30 5         114 $self->{_insertTable} = $inserttable;
31             }
32            
33             # Construct _insertValues property.
34 7         35 my $insertvalues = JsonSQL::Param::InsertValues->new($inserthashref->{values}, $queryObj, $self->{_insertTable}->{_tableRules});
35 7 100       12 if ( eval { $insertvalues->is_error } ) {
  7         64  
36 1         5 push(@insert_errors, "Error parsing VALUES parameters for INSERT: $insertvalues->{message}");
37             } else {
38 6         138 $self->{_insertValues} = $insertvalues;
39             }
40            
41             ## SMELL: this is a little bit of a hack and should be redone properly at some point.
42             ## Requires support for CTEs.
43 7 100       19 if ( defined $inserthashref->{returning} ) {
44 1         2 $self->{_insertReturning} = $inserthashref->{returning};
45             }
46            
47 7 100       17 if ( @insert_errors ) {
48 3         4 my $err = "Could not construct INSERT statement: \n\t";
49 3         10 $err .= join("\n\t", @insert_errors);
50 3         10 return JsonSQL::Error->new("invalid_inserts", $err);
51             } else {
52 4         8 bless $self, $class;
53 4         34 return $self;
54             }
55             }
56              
57              
58             sub get_returning_param_string {
59 4     4 1 6 my ( $self, $queryObj ) = @_;
60              
61 4 100       15 if (defined $self->{_insertReturning}) {
62 1         1 my @returningParam;
63              
64 1         3 for my $returnvalue (@{ $self->{_insertReturning} }) {
  1         2  
65 2         6 my $column = $queryObj->quote_identifier($returnvalue->{column});
66 2         6 my $alias = $queryObj->quote_identifier($returnvalue->{as});
67              
68 2 100       5 if ( defined $alias ) {
69 1         3 push(@returningParam, "$column AS $alias");
70             } else {
71 1         3 push(@returningParam, "$column");
72             }
73             }
74              
75 1         4 return join(",", @returningParam);
76             }
77             }
78              
79              
80             sub get_insert_stmt {
81 4     4 1 9 my ( $self, $queryObj ) = @_;
82            
83 4         12 my $table = $self->{_insertTable}->get_table_param($queryObj);
84 4         11 my ($columns, $placeholders, $values) = $self->{_insertValues}->get_insert_param_strings($queryObj);
85 4         10 my $returning = $self->get_returning_param_string($queryObj);
86            
87 4         11 my $insertSql = "INSERT INTO $table ($columns) VALUES ($placeholders)";
88              
89 4 100       7 if ( $returning ) {
90 1         2 my $insertWrapper = "WITH insert_q AS (\n";
91 1         4 $insertWrapper .= $insertSql . "\n";
92 1         2 $insertWrapper .= "RETURNING " . $returning . "\n)\n";
93 1         2 $insertWrapper .= "SELECT * FROM insert_q";
94              
95 1         3 return ($insertWrapper, $values);
96             } else {
97 3         9 return ($insertSql, $values);
98             }
99             }
100              
101              
102             1;
103              
104             __END__
105              
106             =pod
107              
108             =encoding UTF-8
109              
110             =head1 NAME
111              
112             JsonSQL::Param::Insert - JsonSQL::Param::Insert object. Stores a Perl representation of an INSERT statement used by the JsonSQL Insert query object.
113              
114             =head1 VERSION
115              
116             version 0.4
117              
118             =head1 SYNOPSIS
119              
120             This module constructs a Perl object representing an SQL INSERT statement and has methods for generating the appropriate SQL statement
121             and bind values for use with the L<DBI> module.
122              
123             =head1 DESCRIPTION
124              
125             =head3 Object properties:
126              
127             =over
128              
129             =item _insertTable => L<JsonSQL::Param::Table>
130              
131             =item _insertValues => L<JsonSQL::Param::InsertValues>
132              
133             =item _insertReturning => <string>
134              
135             ( Note: not currently whitelist validated due to the way this is implemented. Will change in future. )
136              
137             =back
138              
139             =head3
140              
141             Structure of INSERT statement:
142              
143             INSERT INTO <table> ( <columns> ) VALUES ( <parameterized values> )
144              
145             =head3 RETURNING clause
146              
147             When using the RETURNING clause, the INSERT statement is wrapped in a WITH CTE, so your database has to support this.
148              
149             WITH insert_q AS (
150             INSERT INTO <table> ( <columns> ) VALUES ( <parameterized values> )
151             RETURNING <return columns>
152             )
153             SELECT * FROM insert_q
154              
155             =head1 METHODS
156              
157             =head2 Constructor new($inserthashref, $queryObj)
158              
159             Instantiates and returns a new JsonSQL::Param::Insert object.
160              
161             $inserthashref => A hashref with the properties needed to construct the object.
162             $queryObj => A reference to the JsonSQL::Query object that will own this object.
163              
164             Returns a JsonSQL::Error object on failure.
165              
166             =head2 ObjectMethod get_returning_param_string -> $returningParam
167              
168             Generates the RETURNING clause from the _insertReturning property.
169              
170             =head2 ObjectMethod get_insert_stmt -> ( $sql, $binds )
171              
172             Generates the SQL statement represented by the object. Returns:
173              
174             $sql => An SQL INSERT string.
175             $binds => An arrayref of parameterized values to pass with the query.
176              
177             =head1 AUTHOR
178              
179             Chris Hoefler <bhoefler@draper.com>
180              
181             =head1 COPYRIGHT AND LICENSE
182              
183             This software is copyright (c) 2017 by Chris Hoefler.
184              
185             This is free software; you can redistribute it and/or modify it under
186             the same terms as the Perl 5 programming language system itself.
187              
188             =cut