File Coverage

blib/lib/JsonSQL/Param/Field.pm
Criterion Covered Total %
statement 47 50 94.0
branch 19 22 86.3
condition 15 23 65.2
subroutine 6 6 100.0
pod 2 2 100.0
total 89 103 86.4


line stmt bran cond sub pod time code
1             # ABSTRACT: JsonSQL::Param::Field object. Stores a Perl representation of an SQL field expression for use in JsonSQL::Query objects.
2              
3              
4              
5 1     1   5 use strict;
  1         2  
  1         22  
6 1     1   4 use warnings;
  1         2  
  1         18  
7 1     1   12 use 5.014;
  1         6  
8              
9             package JsonSQL::Param::Field;
10              
11             our $VERSION = '0.41'; # VERSION
12              
13 1     1   4 use JsonSQL::Error;
  1         2  
  1         473  
14              
15              
16              
17             sub new {
18 13     13 1 30 my ( $class, $fieldhashref, $queryObj, $default_table_rules ) = @_;
19            
20 13         25 my $fieldName = $fieldhashref->{column};
21 13 50 66     127 if ( defined $fieldName and ($fieldName =~ /^[a-zA-Z_][a-zA-Z0-9_:]*$/ or $fieldName eq '*') ) {
      33        
22 13         37 my $self = {
23             _fieldName => $fieldName
24             };
25              
26             ## These are optional parameters. Store them if they are defined and valid.
27 13         29 my $fieldAlias = $fieldhashref->{alias};
28 13 100 66     40 if ( defined $fieldAlias and $fieldAlias =~ /^[a-zA-Z_][a-zA-Z0-9_]*$/ ) {
29 1         5 $self->{_fieldAlias} = $fieldAlias;
30             }
31            
32 13         22 my $fieldTable = $fieldhashref->{table};
33 13 100 66     37 if ( defined $fieldTable and $fieldTable =~ /^[a-zA-Z_][a-zA-Z0-9_]*$/ ) {
34 4         10 $self->{_fieldTable} = $fieldTable;
35             }
36            
37 13   66     46 my $fieldSchema = $fieldhashref->{schema} || $queryObj->{_defaultSchema};
38 13 100 66     43 if ( defined $fieldSchema and $fieldSchema =~ /^[a-zA-Z_][a-zA-Z0-9_]*$/ ) {
39 4         7 $self->{_fieldSchema} = $fieldSchema;
40             }
41            
42             ## Check if field access is allowed based on $queryObj rule sets.
43 13         26 my $validator = $queryObj->{_validator};
44            
45             ## The table rules for validation can be specified by the caller or can be acquired using the field parameters.
46             ## If both are supplied, the field parameters override the default table rules.
47             ## If none are supplied, the restrictive empty list is used.
48 13   100     29 my $table_rules = $default_table_rules || [];
49 13 100       31 if ( defined $self->{_fieldTable} ) {
50 4         39 $table_rules = $validator->check_table_allowed({ schema => $self->{_fieldSchema}, table => $self->{_fieldTable} });
51 4 50       8 if ( eval { $table_rules->is_error } ) {
  4         31  
52 0         0 return JsonSQL::Error->new("invalid_fields", "Error validating table $self->{_fieldTable} for field $self->{_fieldName}: $table_rules->{message}");
53             }
54             }
55            
56             ## With the appropriate table rules, check to see if access to this field is allowed.
57 13         135 my $allowed_field = $validator->check_field_allowed($table_rules, $self->{_fieldName});
58 13 100       27 if ( eval { $allowed_field->is_error } ) {
  13         160  
59 1         4 return JsonSQL::Error->new("invalid_fields", "Field $self->{_fieldName} not allowed by the table rule set.");
60             } else {
61 12         343 bless $self, $class;
62 12         56 return $self;
63             }
64             } else {
65 0         0 return JsonSQL::Error->new("invalid_fields", "Invalid field name $fieldName.");
66             }
67             }
68              
69              
70             sub get_field_param {
71 12     12 1 26 my ( $self, $queryObj ) = @_;
72              
73             ## First we need to build up the field string, since there are a few possible versions.
74 12         14 my $fieldString;
75            
76             ## Determine the field prefix.
77             # Format as: schema.table.column
78 12 100 66     57 if ( (defined $self->{_fieldSchema}) and (defined $self->{_fieldTable}) ) {
    50          
79 4         11 $fieldString = $queryObj->quote_identifier($self->{_fieldSchema});
80 4         6 $fieldString .= '.' . $queryObj->quote_identifier($self->{_fieldTable}) . '.';
81             }
82             # Format as: table.column
83             elsif (defined $self->{_fieldTable}) {
84 0         0 $fieldString = $queryObj->quote_identifier($self->{_fieldTable}) . '.';
85             }
86            
87             ## Now add the column
88 12 100       28 if ( $self->{_fieldName} eq '*' ) {
89 3         8 $fieldString .= $self->{_fieldName};
90             } else {
91 9         19 $fieldString .= $queryObj->quote_identifier($self->{_fieldName});
92             }
93              
94             ## If an alias has been specified, return a hash ref. If not, return a scalar ref.
95 12 100       26 if (defined $self->{_fieldAlias}) {
96 1         3 return { $fieldString => $queryObj->quote_identifier($self->{_fieldAlias}) };
97             } else {
98 11         37 return $fieldString;
99             }
100             }
101              
102              
103             1;
104              
105             __END__
106              
107             =pod
108              
109             =encoding UTF-8
110              
111             =head1 NAME
112              
113             JsonSQL::Param::Field - JsonSQL::Param::Field object. Stores a Perl representation of an SQL field expression for use in JsonSQL::Query objects.
114              
115             =head1 VERSION
116              
117             version 0.41
118              
119             =head1 SYNOPSIS
120              
121             This module constructs a Perl object representing a field identifier for use in SQL queries. It has a method for
122             extracting the parameters to generate the appropriate SQL string.
123              
124             =head1 DESCRIPTION
125              
126             =head3 Object properties:
127              
128             =over
129              
130             =item _fieldName => <string>
131              
132             =item _fieldAlias => <string>
133              
134             =item _fieldTable => <string>
135              
136             =item _fieldSchema => <string>
137              
138             =back
139              
140             =head3 Generated parameters:
141              
142             =over
143              
144             =item $fieldString => <string>
145              
146             =item $fieldAlias => <string>
147              
148             =back
149              
150             =head1 METHODS
151              
152             =head2 Constructor new($fieldhashref, $queryObj, $default_table_rules)
153              
154             Instantiates and returns a new JsonSQL::Param::Field object.
155              
156             $fieldhashref => A hashref of column/alias/table/schema properties used to construct the object.
157             $queryObj => A reference to the JsonSQL::Query object that will own this object.
158             $default_table_rules => The default whitelist table rules to use to validate access when the table params
159             are not provided to the field object. Usually, these are acquired from the table params
160             of another object (ex: the FROM clause of a SELECT statement).
161              
162             Returns a JsonSQL::Error object on failure.
163              
164             =head2 ObjectMethod get_field_param -> $fieldString || { $fieldString => $fieldAlias }
165              
166             Generates parameters represented by the object for the SQL statement. Returns:
167              
168             $fieldString => The SQL field identifier as a quoted string. Includes schema and table as appropriate.
169             $fieldAlias => The alias to use for the field if specified.
170              
171             =head1 AUTHOR
172              
173             Chris Hoefler <bhoefler@draper.com>
174              
175             =head1 COPYRIGHT AND LICENSE
176              
177             This software is copyright (c) 2017 by Chris Hoefler.
178              
179             This is free software; you can redistribute it and/or modify it under
180             the same terms as the Perl 5 programming language system itself.
181              
182             =cut