use strict;
use warnings;

BEGIN { $ENV{TABSIZE} = 8 }
use SQL::Steno;

use Test::More tests => 12;



my $sth;
# Fake DBI
my @name = ("a\nz", "b\tc", "d'e", 'b"c', 'x,y', 'f:g', 'Verrrrrrrry long name indeed', 'h<t&m>l', 'a;col');
my @altrows;
{
    package DBI::st::test;
    $sth = bless {
	Active => 1,
	NAME => \@name
    };

    my @rows;

    sub execute {
	@rows = @altrows ? @altrows :
	    ([1..7, '1999-12-31 23:59:59', undef],
	     ['shift', @{$sth->{NAME}}[0..@{$sth->{NAME}}-2]],
	     ["a\r\nz", 12..16, 'x;y', '', '1970-01-01 00:00:00']);
    }

    sub fetchrow_array {
	@rows ? @{shift @rows} : ();
    }
}



sub test($$;$$) {
    $sth->execute;
    open my $fh, '>:utf8', \my $str;
    my $ofh = select $fh;
    eval { no strict 'refs'; &{"SQL::Steno::render_$_[0]"}( $sth, $_[2], $_[3] ) };
    die $@ if $@;
    close $fh;
    select $ofh;
    (my $exp = $_[1]) =~ s/<<</\r/g;
    my $name = join '-', $_[0], $_[3] ? sort keys %{$_[3]} : ();
    is $str, $exp, $name;
}



test table => <<\OUT;
a\nz |b\tc|d'e |b"c|x,y|f:g|Verrrrrrrry long name indeed
     |    |    |   |   |   |   |h<t&m>l                     |a;col    |
-----|----|----|---|---|---|---|----------------------------|---------|
1    |2   |3   |4  |5  |6  |7  |1999-12-31 24:              |ω        |
shift|a\nz|b\tc|d'e|b"c|x,y|f:g|Verrrrrrrry long name indeed|h<t&m>l  |
a\Rz |12  |13  |14 |15 |16 |x;y|                            |1970- 00:|
OUT

test table => <<\OUT, undef, { all => undef };
a\nz  |b\tc|d'e |b"c|x,y|f:g|Verrrrrrrry long name indeed
      |    |    |   |   |   |   |h<t&m>l                     |a;col              |
------|----|----|---|---|---|---|----------------------------|-------------------|
1     |2   |3   |4  |5  |6  |7  |1999-12-31 23:59:59         |NULL               |
shift |a\nz|b\tc|d'e|b"c|x,y|f:g|Verrrrrrrry long name indeed|h<t&m>l            |
a\r\nz|12  |13  |14 |15 |16 |x;y|                            |1970-01-01 00:00:00|
OUT

test table => <<\OUT, undef, { map +($_ => undef), qw(date time crlf null) };
a\nz  |b\tc|d'e |b"c|x,y|f:g|Verrrrrrrry long name indeed
      |    |    |   |   |   |   |h<t&m>l                     |a;col              |
------|----|----|---|---|---|---|----------------------------|-------------------|
1     |2   |3   |4  |5  |6  |7  |1999-12-31 23:59:59         |null               |
shift |a\nz|b\tc|d'e|b"c|x,y|f:g|Verrrrrrrry long name indeed|h<t&m>l            |
a\r\nz|12  |13  |14 |15 |16 |x;y|                            |1970-01-01 00:00:00|
OUT



test csv => <<\OUT;
"a
z",b	c,d'e,"b""c","x,y",f:g,Verrrrrrrry long name indeed,h<t&m>l,a;col
1,2,3,4,5,6,7,1999-12-31 23:59:59,
shift,"a
z",b	c,d'e,"b""c","x,y",f:g,Verrrrrrrry long name indeed,h<t&m>l
"a<<<
z",12,13,14,15,16,x;y,"",1970-01-01 00:00:00
OUT

test csv => <<\OUT, undef, { semi => 0 };
"a
z";b	c;d'e;"b""c";x,y;f:g;Verrrrrrrry long name indeed;h<t&m>l;"a;col"
1;2;3;4;5;6;7;1999-12-31 23:59:59;
shift;"a
z";b	c;d'e;"b""c";x,y;f:g;Verrrrrrrry long name indeed;h<t&m>l
"a<<<
z";12;13;14;15;16;"x;y";"";1970-01-01 00:00:00
OUT

test csv => <<\OUT, undef, { tab => 1 };
"a
z"	"b	c"	d'e	"b""c"	x,y	f:g	Verrrrrrrry long name indeed	h<t&m>l	a;col
1	2	3	4	5	6	7	1999-12-31 23:59:59	
shift	"a
z"	"b	c"	d'e	"b""c"	x,y	f:g	Verrrrrrrry long name indeed	h<t&m>l
"a<<<
z"	12	13	14	15	16	x;y	""	1970-01-01 00:00:00
OUT



test yaml => <<\OUT;
- "a\nz":                       1
  b	c:                      2
  "d'e":                        3
  "b\"c":                       4
  "x,y":                        5
  "f:g":                        6
  Verrrrrrrry long name indeed: 7
  "h<t&m>l":                    "1999-12-31 23:59:59"
  a;col:                        ~
- "a\nz":                       shift
  b	c:                      |2-
    a
    z
  "d'e":                        b	c
  "b\"c":                       "d'e"
  "x,y":                        "b\"c"
  "f:g":                        "x,y"
  Verrrrrrrry long name indeed: "f:g"
  "h<t&m>l":                    Verrrrrrrry long name indeed
  a;col:                        "h<t&m>l"
- "a\nz":                       "a\r\nz"
  b	c:                      12
  "d'e":                        13
  "b\"c":                       14
  "x,y":                        15
  "f:g":                        16
  Verrrrrrrry long name indeed: x;y
  "h<t&m>l":                    
  a;col:                        "1970-01-01 00:00:00"
OUT


@name = qw(date time datetime dateTtime dateTtimeZ dateTtime0 dateTtime1);
@altrows = map [@$_, "@$_", "$_->[0]T$_->[1]", "$_->[0]T$_->[1]Z", "$_->[0]T$_->[1]+00:00", "$_->[0]T$_->[1]-01:15"],
    ['0000-00-00', '00:00'],
    ['0000-00-00', '00:00:00'],
    ['0000-00-00', '00:00:00.000'],
    ['0000-00-00', '00:00:00,000'],
    ['1970-01-01', '01:00'],
    ['1970-01-01', '01:00:00'],
    ['1970-02-01', '01:02:00'],
    ['1970-02-03', '01:02:03.000'],
    ['1970-02-03', '01:02:03.456'],
    ['1970-02-03', '01:02:03,456'],
    ['2015-01-01', '23:59'],
    ['2015-12-01', '23:59:59'],
    ['2015-12-31', '23:59:59.999'],
    ['2015-12-31', '23:59:59,999'];


test table => <<\OUT, undef;
date      |time        |datetime               |dateTtime              |dateTtimeZ              |dateTtime0                 |dateTtime1                   |
----------|------------|-----------------------|-----------------------|------------------------|---------------------------|-----------------------------|
0000-     |00:         |0000- 00:              |0000-T00:              |0000-T00:Z              |0000-T00:+00:              |0000-T00:-01:15              |
0000-     |00:         |0000- 00:              |0000-T00:              |0000-T00:Z              |0000-T00:+00:              |0000-T00:-01:15              |
0000-     |00:         |0000- 00:              |0000-T00:              |0000-T00:Z              |0000-T00:+00:              |0000-T00:-01:15              |
0000-     |00:         |0000- 00:              |0000-T00:              |0000-T00:Z              |0000-T00:+00:              |0000-T00:-01:15              |
1970-     |01:         |1970- 01:              |1970-T01:              |1970-T01:Z              |1970-T01:+00:              |1970-T01:-01:15              |
1970-     |01:         |1970- 01:              |1970-T01:              |1970-T01:Z              |1970-T01:+00:              |1970-T01:-01:15              |
1970-02-  |01:02       |1970-02- 01:02         |1970-02-T01:02         |1970-02-T01:02Z         |1970-02-T01:02+00:         |1970-02-T01:02-01:15         |
1970-02-03|01:02:03    |1970-02-03 01:02:03    |1970-02-03T01:02:03    |1970-02-03T01:02:03Z    |1970-02-03T01:02:03+00:    |1970-02-03T01:02:03-01:15    |
1970-02-03|01:02:03.456|1970-02-03 01:02:03.456|1970-02-03T01:02:03.456|1970-02-03T01:02:03.456Z|1970-02-03T01:02:03.456+00:|1970-02-03T01:02:03.456-01:15|
1970-02-03|01:02:03,456|1970-02-03 01:02:03,456|1970-02-03T01:02:03,456|1970-02-03T01:02:03,456Z|1970-02-03T01:02:03,456+00:|1970-02-03T01:02:03,456-01:15|
2015-     |24:         |2015- 24:              |2015-T24:              |2015-T24:Z              |2015-T24:+00:              |2015-T24:-01:15              |
2015-12-  |24:         |2015-12- 24:           |2015-12-T24:           |2015-12-T24:Z           |2015-12-T24:+00:           |2015-12-T24:-01:15           |
2015-12-31|24:         |2015-12-31 24:         |2015-12-31T24:         |2015-12-31T24:Z         |2015-12-31T24:+00:         |2015-12-31T24:-01:15         |
2015-12-31|24:         |2015-12-31 24:         |2015-12-31T24:         |2015-12-31T24:Z         |2015-12-31T24:+00:         |2015-12-31T24:-01:15         |
OUT


test table => <<\OUT, undef, { map +($_ => undef), qw(date) };
date      |time        |datetime               |dateTtime              |dateTtimeZ              |dateTtime0                 |dateTtime1                   |
----------|------------|-----------------------|-----------------------|------------------------|---------------------------|-----------------------------|
0000-00-00|00:         |0000-00-00 00:         |0000-00-00T00:         |0000-00-00T00:Z         |0000-00-00T00:+00:         |0000-00-00T00:-01:15         |
0000-00-00|00:         |0000-00-00 00:         |0000-00-00T00:         |0000-00-00T00:Z         |0000-00-00T00:+00:         |0000-00-00T00:-01:15         |
0000-00-00|00:         |0000-00-00 00:         |0000-00-00T00:         |0000-00-00T00:Z         |0000-00-00T00:+00:         |0000-00-00T00:-01:15         |
0000-00-00|00:         |0000-00-00 00:         |0000-00-00T00:         |0000-00-00T00:Z         |0000-00-00T00:+00:         |0000-00-00T00:-01:15         |
1970-01-01|01:         |1970-01-01 01:         |1970-01-01T01:         |1970-01-01T01:Z         |1970-01-01T01:+00:         |1970-01-01T01:-01:15         |
1970-01-01|01:         |1970-01-01 01:         |1970-01-01T01:         |1970-01-01T01:Z         |1970-01-01T01:+00:         |1970-01-01T01:-01:15         |
1970-02-01|01:02       |1970-02-01 01:02       |1970-02-01T01:02       |1970-02-01T01:02Z       |1970-02-01T01:02+00:       |1970-02-01T01:02-01:15       |
1970-02-03|01:02:03    |1970-02-03 01:02:03    |1970-02-03T01:02:03    |1970-02-03T01:02:03Z    |1970-02-03T01:02:03+00:    |1970-02-03T01:02:03-01:15    |
1970-02-03|01:02:03.456|1970-02-03 01:02:03.456|1970-02-03T01:02:03.456|1970-02-03T01:02:03.456Z|1970-02-03T01:02:03.456+00:|1970-02-03T01:02:03.456-01:15|
1970-02-03|01:02:03,456|1970-02-03 01:02:03,456|1970-02-03T01:02:03,456|1970-02-03T01:02:03,456Z|1970-02-03T01:02:03,456+00:|1970-02-03T01:02:03,456-01:15|
2015-01-01|24:         |2015-01-01 24:         |2015-01-01T24:         |2015-01-01T24:Z         |2015-01-01T24:+00:         |2015-01-01T24:-01:15         |
2015-12-01|24:         |2015-12-01 24:         |2015-12-01T24:         |2015-12-01T24:Z         |2015-12-01T24:+00:         |2015-12-01T24:-01:15         |
2015-12-31|24:         |2015-12-31 24:         |2015-12-31T24:         |2015-12-31T24:Z         |2015-12-31T24:+00:         |2015-12-31T24:-01:15         |
2015-12-31|24:         |2015-12-31 24:         |2015-12-31T24:         |2015-12-31T24:Z         |2015-12-31T24:+00:         |2015-12-31T24:-01:15         |
OUT


test table => <<\OUT, undef, { map +($_ => undef), qw(time) };
date      |time        |datetime               |dateTtime              |dateTtimeZ              |dateTtime0                   |dateTtime1                   |
----------|------------|-----------------------|-----------------------|------------------------|-----------------------------|-----------------------------|
0000-     |00:00       |0000- 00:00            |0000-T00:00            |0000-T00:00Z            |0000-T00:00+00:00            |0000-T00:00-01:15            |
0000-     |00:00:00    |0000- 00:00:00         |0000-T00:00:00         |0000-T00:00:00Z         |0000-T00:00:00+00:00         |0000-T00:00:00-01:15         |
0000-     |00:00:00.000|0000- 00:00:00.000     |0000-T00:00:00.000     |0000-T00:00:00.000Z     |0000-T00:00:00.000+00:00     |0000-T00:00:00.000-01:15     |
0000-     |00:00:00,000|0000- 00:00:00,000     |0000-T00:00:00,000     |0000-T00:00:00,000Z     |0000-T00:00:00,000+00:00     |0000-T00:00:00,000-01:15     |
1970-     |01:00       |1970- 01:00            |1970-T01:00            |1970-T01:00Z            |1970-T01:00+00:00            |1970-T01:00-01:15            |
1970-     |01:00:00    |1970- 01:00:00         |1970-T01:00:00         |1970-T01:00:00Z         |1970-T01:00:00+00:00         |1970-T01:00:00-01:15         |
1970-02-  |01:02:00    |1970-02- 01:02:00      |1970-02-T01:02:00      |1970-02-T01:02:00Z      |1970-02-T01:02:00+00:00      |1970-02-T01:02:00-01:15      |
1970-02-03|01:02:03.000|1970-02-03 01:02:03.000|1970-02-03T01:02:03.000|1970-02-03T01:02:03.000Z|1970-02-03T01:02:03.000+00:00|1970-02-03T01:02:03.000-01:15|
1970-02-03|01:02:03.456|1970-02-03 01:02:03.456|1970-02-03T01:02:03.456|1970-02-03T01:02:03.456Z|1970-02-03T01:02:03.456+00:00|1970-02-03T01:02:03.456-01:15|
1970-02-03|01:02:03,456|1970-02-03 01:02:03,456|1970-02-03T01:02:03,456|1970-02-03T01:02:03,456Z|1970-02-03T01:02:03,456+00:00|1970-02-03T01:02:03,456-01:15|
2015-     |23:59       |2015- 23:59            |2015-T23:59            |2015-T23:59Z            |2015-T23:59+00:00            |2015-T23:59-01:15            |
2015-12-  |23:59:59    |2015-12- 23:59:59      |2015-12-T23:59:59      |2015-12-T23:59:59Z      |2015-12-T23:59:59+00:00      |2015-12-T23:59:59-01:15      |
2015-12-31|23:59:59.999|2015-12-31 23:59:59.999|2015-12-31T23:59:59.999|2015-12-31T23:59:59.999Z|2015-12-31T23:59:59.999+00:00|2015-12-31T23:59:59.999-01:15|
2015-12-31|23:59:59,999|2015-12-31 23:59:59,999|2015-12-31T23:59:59,999|2015-12-31T23:59:59,999Z|2015-12-31T23:59:59,999+00:00|2015-12-31T23:59:59,999-01:15|
OUT


test table => <<\OUT, undef, { map +($_ => undef), qw(date time) };
date      |time        |datetime               |dateTtime              |dateTtimeZ              |dateTtime0                   |dateTtime1                   |
----------|------------|-----------------------|-----------------------|------------------------|-----------------------------|-----------------------------|
0000-00-00|00:00       |0000-00-00 00:00       |0000-00-00T00:00       |0000-00-00T00:00Z       |0000-00-00T00:00+00:00       |0000-00-00T00:00-01:15       |
0000-00-00|00:00:00    |0000-00-00 00:00:00    |0000-00-00T00:00:00    |0000-00-00T00:00:00Z    |0000-00-00T00:00:00+00:00    |0000-00-00T00:00:00-01:15    |
0000-00-00|00:00:00.000|0000-00-00 00:00:00.000|0000-00-00T00:00:00.000|0000-00-00T00:00:00.000Z|0000-00-00T00:00:00.000+00:00|0000-00-00T00:00:00.000-01:15|
0000-00-00|00:00:00,000|0000-00-00 00:00:00,000|0000-00-00T00:00:00,000|0000-00-00T00:00:00,000Z|0000-00-00T00:00:00,000+00:00|0000-00-00T00:00:00,000-01:15|
1970-01-01|01:00       |1970-01-01 01:00       |1970-01-01T01:00       |1970-01-01T01:00Z       |1970-01-01T01:00+00:00       |1970-01-01T01:00-01:15       |
1970-01-01|01:00:00    |1970-01-01 01:00:00    |1970-01-01T01:00:00    |1970-01-01T01:00:00Z    |1970-01-01T01:00:00+00:00    |1970-01-01T01:00:00-01:15    |
1970-02-01|01:02:00    |1970-02-01 01:02:00    |1970-02-01T01:02:00    |1970-02-01T01:02:00Z    |1970-02-01T01:02:00+00:00    |1970-02-01T01:02:00-01:15    |
1970-02-03|01:02:03.000|1970-02-03 01:02:03.000|1970-02-03T01:02:03.000|1970-02-03T01:02:03.000Z|1970-02-03T01:02:03.000+00:00|1970-02-03T01:02:03.000-01:15|
1970-02-03|01:02:03.456|1970-02-03 01:02:03.456|1970-02-03T01:02:03.456|1970-02-03T01:02:03.456Z|1970-02-03T01:02:03.456+00:00|1970-02-03T01:02:03.456-01:15|
1970-02-03|01:02:03,456|1970-02-03 01:02:03,456|1970-02-03T01:02:03,456|1970-02-03T01:02:03,456Z|1970-02-03T01:02:03,456+00:00|1970-02-03T01:02:03,456-01:15|
2015-01-01|23:59       |2015-01-01 23:59       |2015-01-01T23:59       |2015-01-01T23:59Z       |2015-01-01T23:59+00:00       |2015-01-01T23:59-01:15       |
2015-12-01|23:59:59    |2015-12-01 23:59:59    |2015-12-01T23:59:59    |2015-12-01T23:59:59Z    |2015-12-01T23:59:59+00:00    |2015-12-01T23:59:59-01:15    |
2015-12-31|23:59:59.999|2015-12-31 23:59:59.999|2015-12-31T23:59:59.999|2015-12-31T23:59:59.999Z|2015-12-31T23:59:59.999+00:00|2015-12-31T23:59:59.999-01:15|
2015-12-31|23:59:59,999|2015-12-31 23:59:59,999|2015-12-31T23:59:59,999|2015-12-31T23:59:59,999Z|2015-12-31T23:59:59,999+00:00|2015-12-31T23:59:59,999-01:15|
OUT


test table => <<\OUT, undef, { map +($_ => undef), qw(all) };
date      |time        |datetime               |dateTtime              |dateTtimeZ              |dateTtime0                   |dateTtime1                   |
----------|------------|-----------------------|-----------------------|------------------------|-----------------------------|-----------------------------|
0000-00-00|00:00       |0000-00-00 00:00       |0000-00-00T00:00       |0000-00-00T00:00Z       |0000-00-00T00:00+00:00       |0000-00-00T00:00-01:15       |
0000-00-00|00:00:00    |0000-00-00 00:00:00    |0000-00-00T00:00:00    |0000-00-00T00:00:00Z    |0000-00-00T00:00:00+00:00    |0000-00-00T00:00:00-01:15    |
0000-00-00|00:00:00.000|0000-00-00 00:00:00.000|0000-00-00T00:00:00.000|0000-00-00T00:00:00.000Z|0000-00-00T00:00:00.000+00:00|0000-00-00T00:00:00.000-01:15|
0000-00-00|00:00:00,000|0000-00-00 00:00:00,000|0000-00-00T00:00:00,000|0000-00-00T00:00:00,000Z|0000-00-00T00:00:00,000+00:00|0000-00-00T00:00:00,000-01:15|
1970-01-01|01:00       |1970-01-01 01:00       |1970-01-01T01:00       |1970-01-01T01:00Z       |1970-01-01T01:00+00:00       |1970-01-01T01:00-01:15       |
1970-01-01|01:00:00    |1970-01-01 01:00:00    |1970-01-01T01:00:00    |1970-01-01T01:00:00Z    |1970-01-01T01:00:00+00:00    |1970-01-01T01:00:00-01:15    |
1970-02-01|01:02:00    |1970-02-01 01:02:00    |1970-02-01T01:02:00    |1970-02-01T01:02:00Z    |1970-02-01T01:02:00+00:00    |1970-02-01T01:02:00-01:15    |
1970-02-03|01:02:03.000|1970-02-03 01:02:03.000|1970-02-03T01:02:03.000|1970-02-03T01:02:03.000Z|1970-02-03T01:02:03.000+00:00|1970-02-03T01:02:03.000-01:15|
1970-02-03|01:02:03.456|1970-02-03 01:02:03.456|1970-02-03T01:02:03.456|1970-02-03T01:02:03.456Z|1970-02-03T01:02:03.456+00:00|1970-02-03T01:02:03.456-01:15|
1970-02-03|01:02:03,456|1970-02-03 01:02:03,456|1970-02-03T01:02:03,456|1970-02-03T01:02:03,456Z|1970-02-03T01:02:03,456+00:00|1970-02-03T01:02:03,456-01:15|
2015-01-01|23:59       |2015-01-01 23:59       |2015-01-01T23:59       |2015-01-01T23:59Z       |2015-01-01T23:59+00:00       |2015-01-01T23:59-01:15       |
2015-12-01|23:59:59    |2015-12-01 23:59:59    |2015-12-01T23:59:59    |2015-12-01T23:59:59Z    |2015-12-01T23:59:59+00:00    |2015-12-01T23:59:59-01:15    |
2015-12-31|23:59:59.999|2015-12-31 23:59:59.999|2015-12-31T23:59:59.999|2015-12-31T23:59:59.999Z|2015-12-31T23:59:59.999+00:00|2015-12-31T23:59:59.999-01:15|
2015-12-31|23:59:59,999|2015-12-31 23:59:59,999|2015-12-31T23:59:59,999|2015-12-31T23:59:59,999Z|2015-12-31T23:59:59,999+00:00|2015-12-31T23:59:59,999-01:15|
OUT