File Coverage

blib/lib/DBIx/Class/SQLA2.pm
Criterion Covered Total %
statement 50 52 96.1
branch 10 16 62.5
condition 4 8 50.0
subroutine 13 13 100.0
pod 3 4 75.0
total 80 93 86.0


line stmt bran cond sub pod time code
1             package DBIx::Class::SQLA2;
2 5     5   134537 use strict;
  5         11  
  5         189  
3 5     5   23 use warnings;
  5         9  
  5         273  
4 5     5   26 use feature 'postderef';
  5         9  
  5         644  
5 5     5   27 no warnings 'experimental::postderef';
  5         8  
  5         209  
6 5     5   26 use mro 'c3';
  5         10  
  5         54  
7              
8 5         7447 use base qw(
9             DBIx::Class::SQLMaker::ClassicExtensions
10             SQL::Abstract
11             SQL::Abstract::Classic
12 5     5   199 );
  5         10  
13              
14 5     5   111025 use Role::Tiny;
  5         18774  
  5         33  
15              
16             __PACKAGE__->mk_group_accessors(simple => '_connection_info');
17              
18             sub _render_hashrefrefs {
19 5     5   15 my ($self, $list) = @_;
20 5 50       21 my @fields = ref $list eq 'ARRAY' ? @$list : $list;
21             return [
22             map {
23 5         12 ref $_ eq 'REF' && ref $$_ eq 'HASH'
24 5 50 33     28 ? do {
25 5         23 my %f = $$_->%*;
26 5         14 my $as = delete $f{-as};
27             \[
28 5 50       79 $as
29             ? $self->render_expr({ -op => [ 'as', \%f, { -ident => $as } ] })
30             : $self->render_expr(\%f)
31             ];
32             }
33             : $_
34             } @fields
35             ];
36             }
37              
38             sub _recurse_fields {
39 119     119   42385 my ($self, $fields) = @_;
40 119 100 66     414 if (ref $fields eq 'REF' && ref $$fields eq 'HASH') {
41 5         42 return $self->next::method($self->_render_hashrefrefs($fields)->[0]);
42             }
43 114         259 return $self->next::method($fields);
44              
45             }
46              
47             sub select {
48 38     38 1 348665 my ($self, $table, $fields, $where, $rs_attrs, $limit, $offset) = @_;
49              
50 38 50       181 if (my $gb = $rs_attrs->{group_by}) {
51 0         0 $rs_attrs = { %$rs_attrs, group_by => $self->_render_hashrefrefs($gb) };
52             }
53 38         227 $self->next::method($table, $fields, $where, $rs_attrs, $limit, $offset);
54             }
55              
56              
57             sub insert {
58             # TODO - this works, ish. The issue is that if you have rels involved, you may actually
59             # hit `insert` before the intended insert. Not sure what to do but put that on the
60             # user...
61 25     25 1 41558 my ($self, $source, $cols, $attrs) = @_;
62 25   50     297 $attrs ||= {};
63 25 100       166 if (my $extra_attrs = $self->{_sqla2_insert_attrs}) {
64 7         41 $attrs = { %$attrs, %$extra_attrs };
65             }
66 25         170 $self->next::method($source, $cols, $attrs);
67             }
68              
69             sub expand_clause {
70 3     3 0 10 my ($self, $clause, $value) = @_;
71 3         7 my ($probably_key, $expanded) = $self->${ \$self->clause_expander($clause) }(undef, $value);
  3         94  
72 3 50       1513 if ($expanded) {
73 3         14 return ($probably_key => $expanded);
74             } else {
75 0         0 return (undef => $probably_key);
76             }
77             }
78              
79             sub new {
80 10     10 1 3729 my $new = shift->next::method(@_);
81 10 50       2976 unless (grep {m/^with$/} $new->clauses_of('select')) {
  40         241  
82 10         73 $new->plugin("+$_") for qw/ExtraClausesFixed WindowFunctions Upsert BangOverrides CaseExpr/;
83             }
84 10         529 return $new;
85             }
86              
87             our $VERSION = '0.02_1';
88              
89             1;
90              
91             =encoding utf8
92              
93             =head1 NAME
94              
95             DBIx::Class::SQLA2 - SQL::Abstract v2 support in DBIx::Class
96              
97             =head1 SYNOPSIS
98              
99             $schema->connect_call_rebase_sqlmaker('DBIx::Class::SQLA2');
100              
101             =head1 DESCRIPTION
102              
103             This is a work in progress for simplifying using SQLA2 with DBIC. This is for using w/ the
104             most recent version of DBIC.
105              
106             For a simple way of using this, take a look at L.
107              
108             In order to have inserts passthru SQLA2 keys, you should use the
109             L component, which allows you to add a C<-sqla2> key w/ a
110             hashref containing your passthroughs.
111              
112             In order to support SQLA2 keys for bulk inserts (C), use the
113             L component. It adds a second arg to C which
114             allows you to add things to the final query (though you may get undefined behavior if
115             you're creating deep relationships - real world experience would be nice here). In
116             addition, it adds an C method to simplify the case of update on a primary
117             key conflict (see there for more details).
118              
119             B
120              
121             This role itself will add handling of hashref-refs to select lists + group by clauses,
122             which will render the inner hashref as if it had been passed through to SQLA2 rather than
123             doing the recursive function rendering that DBIC does.
124              
125             =head2 Included Plugins
126              
127             This will add the following SQLA2 plugins:
128              
129             =over 2
130              
131             =item L
132              
133             Adds support for CTEs, and other fun new SQL syntax
134              
135             =item L
136              
137             Adds support for window functions and advanced aggregates.
138              
139             =item L
140              
141             Adds support for Upserts (ON CONFLICT clause)
142              
143             =item L
144              
145             Adds some hacky stuff so you can bypass/supplement DBIC's handling of certain clauses
146              
147             =back
148              
149             =head1 AUTHOR
150              
151             Copyright (c) 2022-24 Veesh Goldman
152              
153             =head1 LICENSE
154              
155             This module is free software; you may copy this under the same
156             terms as perl itself (either the GNU General Public License or
157             the Artistic License)
158              
159             =cut