#!/usr/bin/perl use strict; use warnings; use Test::More tests => 17; use Test::Exception; use lib qw(t/lib); # dynamically load SQL::Abstract::Test; eval "use SQL::Abstract::Limit::Test; 1" or die $@; =for notes use SQL::Abstract::Limit; my $syntax = 'LimitOffset'; # others include: Top RowNum LimitXY Fetch RowsTo my $sql = SQL::Abstract::Limit->new( limit => $syntax ); my($stmt, @bind) = $sql->select($table, \@fields, \%where, \@order, $limit, $offset); =cut use SQL::Abstract::Limit; my @syntaxes = qw( LimitOffset LimitXY RowsTo Top RowNum GenericSubQ FetchFirst shgfh ); my @not_syntaxes = qw( Rank ); lives_ok { SQL::Abstract::Limit->new( limit => $_ ) for @syntaxes } 'survives constructor'; # query my $table = 'TheTable'; my $fields = [ qw( requestor worker colC colH ) ]; my $where = { requestor => 'inna', worker => ['nwiger', 'rcwe', 'sfz'], status => { '!=', 'completed' }, }; my $order = [ qw( pay age ) ]; my $limit = 10; # 10 per page my $offset = 70; # page 7 my $last = $offset + $limit; my $base_sql = 'requestor, worker, colC, colH FROM TheTable WHERE ( requestor = ? AND status != ? AND ( ( worker = ? ) OR ( worker = ? ) OR ( worker = ? ) ) )'; my @expected_bind = qw/inna completed nwiger rcwe sfz/; my $sql_ab = SQL::Abstract::Limit->new( limit_dialect => 'LimitOffset' ); my ( $stmt, @bind ); # LimitOffset lives_ok { ( $stmt, @bind ) = $sql_ab->select( $table, $fields, $where, $order, $limit, $offset) } 'select LimitOffset'; is_same_sql_bind( $stmt, \@bind, "SELECT $base_sql ORDER BY pay, age LIMIT $limit OFFSET $offset", \@expected_bind, 'LimitOffset SQL', ); # LimitXY lives_ok { ( $stmt, @bind ) = $sql_ab->select( $table, $fields, $where, $order, $limit, $offset, 'LimitXY' ) } 'select LimitXY'; is_same_sql_bind( $stmt, \@bind, "SELECT $base_sql ORDER BY pay, age LIMIT $offset, $limit", \@expected_bind, 'LimitXY SQL', ); # RowsTo lives_ok { ( $stmt, @bind ) = $sql_ab->select( $table, $fields, $where, $order, $limit, $offset, 'RowsTo' ) } 'select RowsTo'; is_same_sql_bind( $stmt, \@bind, "SELECT $base_sql ORDER BY pay, age ROWS $offset TO $last", \@expected_bind, 'RowsTo SQL', ); # Top lives_ok { ( $stmt, @bind ) = $sql_ab->select( $table, $fields, $where, $order, $limit, $offset, 'Top' ) } 'select Top'; is_same_sql_bind( $stmt, \@bind, "SELECT * FROM (" . "SELECT TOP $limit * FROM (" . "SELECT TOP $last $base_sql ORDER BY pay ASC, age ASC" . ") AS foo ORDER BY pay DESC, age DESC" .") AS bar ORDER BY pay ASC, age ASC", \@expected_bind, 'Top SQL', ); # RowNum lives_ok { ( $stmt, @bind ) = $sql_ab->select( $table, $fields, $where, $order, $limit, $offset, 'RowNum' ) } 'select RowNum'; is_same_sql_bind( $stmt, \@bind, "SELECT * FROM (" . "SELECT A.*, ROWNUM r FROM (" . "SELECT $base_sql ORDER BY pay, age" . ") A WHERE ROWNUM < @{[$last + 1]}" .") B WHERE r >= @{[$offset + 1]}", \@expected_bind, 'RowNum SQL', ); # GenericSubQ lives_ok { ( $stmt, @bind ) = $sql_ab->select( $table, $fields, $where, $order, $limit, $offset, 'GenericSubQ' ) } 'select GenericSubQ'; (my $gen_q_base_sql = $base_sql) =~ s/TheTable/TheTable X/; is_same_sql_bind( $stmt, \@bind, "SELECT $gen_q_base_sql AND" . "(SELECT COUNT(*) FROM TheTable WHERE requestor > X.requestor)" . " BETWEEN $offset AND $last ORDER BY requestor DESC", \@expected_bind, 'GenericSubQ SQL', ); # FetchFirst lives_ok { ( $stmt, @bind ) = $sql_ab->select( $table, $fields, $where, $order, $limit, $offset, 'FetchFirst' ) } 'select FetchFirst'; is_same_sql_bind( $stmt, \@bind, "SELECT * FROM (" . "SELECT * FROM (" . "SELECT $base_sql ORDER BY pay ASC, age ASC FETCH FIRST $last ROWS ONLY" . ") foo ORDER BY pay DESC, age DESC FETCH FIRST $limit ROWS ONLY" . ") bar ORDER BY pay ASC, age ASC", \@expected_bind, 'FetchFirst SQL', ); # Skip lives_ok { ( $stmt, @bind ) = $sql_ab->select( $table, $fields, $where, $order, $limit, $offset, 'Skip' ) } 'select Skip'; is_same_sql_bind( $stmt, \@bind, "select skip $offset limit $limit $base_sql ORDER BY pay, age", \@expected_bind, 'Skip SQL', );