sub _RowNumberOver {
my ($self, $sql, $order, $rows, $offset ) = @_;
+ # get the select to make the final amount of columns equal the original one
+ my ($select) = $sql =~ /^ \s* SELECT \s+ (.+?) \s+ FROM/ix
+ or croak "Unrecognizable SELECT: $sql";
+
# get the order_by only (or make up an order if none exists)
my $order_by = $self->_order_by(
(delete $order->{order_by}) || $self->_rno_default_order
);
- # whatever is left
+ # whatever is left of the order_by
my $group_having = $self->_order_by($order);
my $qalias = $self->_quote ($self->{_dbic_rs_attrs}{alias});
- $sql = sprintf (<<'EOS', $qalias, $order_by, $sql, $group_having, $qalias, $offset + 1, $offset + $rows, );
+ $sql = sprintf (<<EOS, $offset + 1, $offset + $rows, );
-SELECT * FROM (
- SELECT %s.*, ROW_NUMBER() OVER(%s ) AS rno__row__index FROM (%s%s) %s
-) rno_subq WHERE rno__row__index BETWEEN %d AND %d
+SELECT $select FROM (
+ SELECT $qalias.*, ROW_NUMBER() OVER($order_by ) AS rno__row__index FROM (
+ ${sql}${group_having}
+ ) $qalias
+) $qalias WHERE rno__row__index BETWEEN %d AND %d
EOS
return undef;
}
+# Informix specific limit, almost like LIMIT/OFFSET
+sub _SkipFirst {
+ my ($self, $sql, $order, $rows, $offset) = @_;
+
+ $sql =~ s/^ \s* SELECT \s+ //ix
+ or croak "Unrecognizable SELECT: $sql";
+
+ return sprintf ('SELECT %s%s%s%s',
+ $offset
+ ? sprintf ('SKIP %d ', $offset)
+ : ''
+ ,
+ sprintf ('FIRST %d ', $rows),
+ $sql,
+ $self->_order_by ($order),
+ );
+}
+
+# Firebird specific limit, reverse of _SkipFirst for Informix
+sub _FirstSkip {
+ my ($self, $sql, $order, $rows, $offset) = @_;
+
+ $sql =~ s/^ \s* SELECT \s+ //ix
+ or croak "Unrecognizable SELECT: $sql";
+
+ return sprintf ('SELECT %s%s%s%s',
+ sprintf ('FIRST %d ', $rows),
+ $offset
+ ? sprintf ('SKIP %d ', $offset)
+ : ''
+ ,
+ $sql,
+ $self->_order_by ($order),
+ );
+}
+
# Crappy Top based Limit/Offset support. Legacy from MSSQL.
sub _Top {
my ( $self, $sql, $order, $rows, $offset ) = @_;
# which is sadly understood only by MySQL. Change default behavior here,
# until SQLA2 comes with proper dialect support
if (! $_[0] or (ref $_[0] eq 'HASH' and !keys %{$_[0]} ) ) {
- return "INSERT INTO ${table} DEFAULT VALUES"
+ my $sql = "INSERT INTO ${table} DEFAULT VALUES";
+
+ if (my $ret = ($_[1]||{})->{returning} ) {
+ $sql .= $self->_insert_returning ($ret);
+ }
+
+ return $sql;
}
$self->SUPER::insert($table, @_);
$self->_sqlcase($func),
$self->_recurse_fields($args),
$as
- ? sprintf (' %s %s', $self->_sqlcase('as'), $as)
+ ? sprintf (' %s %s', $self->_sqlcase('as'), $self->_quote ($as) )
: ''
);
}
}
+sub _generate_join_clause {
+ my ($self, $join_type) = @_;
+
+ return sprintf ('%s JOIN ',
+ $join_type ? ' ' . uc($join_type) : ''
+ );
+}
+
sub _recurse_from {
my ($self, $from, @join) = @_;
my @sqlf;
$join_type = $self->{_default_jointype} if not defined $join_type;
- my $join_clause = sprintf ('%s JOIN ',
- $join_type ? ' ' . uc($join_type) : ''
- );
- push @sqlf, $join_clause;
+ push @sqlf, $self->_generate_join_clause( $join_type );
if (ref $to eq 'ARRAY') {
push(@sqlf, '(', $self->_recurse_from(@$to), ')');
}
}
-sub _quote {
- my ($self, $label) = @_;
- return '' unless defined $label;
- return $$label if ref($label) eq 'SCALAR';
- return "*" if $label eq '*';
- return $label unless $self->{quote_char};
- if(ref $self->{quote_char} eq "ARRAY"){
- return $self->{quote_char}->[0] . $label . $self->{quote_char}->[1]
- if !defined $self->{name_sep};
- my $sep = $self->{name_sep};
- return join($self->{name_sep},
- map { $self->{quote_char}->[0] . $_ . $self->{quote_char}->[1] }
- split(/\Q$sep\E/,$label));
- }
- return $self->SUPER::_quote($label);
-}
-
sub limit_dialect {
my $self = shift;
$self->{limit_dialect} = shift if @_;