From d0e014cdfd4e9ad801e7d2814584ff4b1892a08c Mon Sep 17 00:00:00 2001 From: Christoph Berg Date: Tue, 1 Nov 2022 19:16:21 +0100 Subject: [PATCH] Fix compatibility with PG15 spi.c: parse_variable_parameters -> setup_parse_variable_parameters spi_1.out: Accept "ERROR: cursor can only scan forward" and differing portal numbers time.c: interval2tm -> interval2itm horology_1.out: Accept "ERROR: unit "dow" not supported for type time without time zone" Close #10. --- expected/horology_1.out | 606 ++++++++++++++++++++++++++++++++++++++++ expected/spi_1.out | 262 +++++++++++++++++ src/spi.c | 4 + src/time.c | 18 ++ 4 files changed, 890 insertions(+) create mode 100644 expected/horology_1.out create mode 100644 expected/spi_1.out diff --git a/expected/horology_1.out b/expected/horology_1.out new file mode 100644 index 0000000..170b314 --- /dev/null +++ b/expected/horology_1.out @@ -0,0 +1,606 @@ +-- +\set VERBOSITY terse +-- +-- 1. Input of datetime values from table form. +set timezone = 'GMT'; +set datestyle = 'ISO,YMD'; +do language pllua $$ + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamptz{ year=2419, month=4, day=22, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamptz{ year=1919, month=4, day=22, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamptz{ year=1819, month=4, day=22, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamptz{ year=1019, month=4, day=22, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamptz{ year=-2019, month=4, day=22, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamptz{ year=-4713, month=12, day=1, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=34, usec=123456 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1, msec=1, usec=1 }); +$$; +INFO: 2019-04-22 12:23:34.1+00 +INFO: 2419-04-22 12:23:34.1+00 +INFO: 1919-04-22 12:23:34.1+00 +INFO: 1819-04-22 12:23:34.1+00 +INFO: 1019-04-22 12:23:34.1+00 +INFO: 2020-04-22 12:23:34.1+00 BC +INFO: 4714-12-01 12:23:34.1+00 BC +INFO: 2019-04-22 12:23:34.123456+00 +INFO: 2019-04-22 12:23:34.101001+00 +do language pllua $$ + print(pgtype.timestamptz{ epoch=0 }); + print(pgtype.timestamptz{ epoch=1555891200 }); + print(pgtype.timestamptz{ epoch=1555891200.000001 }); + print(pgtype.timestamptz{ epoch_msec=1555891200001 }); + print(pgtype.timestamptz{ epoch_usec=1555891200000001 }); + print(pgtype.timestamptz{ epoch=1555891200, msec=1, usec=1 }); + print(pgtype.timestamptz{ epoch=1555891200, msec=-1, usec=1 }); + print(pgtype.timestamptz{ epoch=-1555891200 }); + print(pgtype.timestamptz{ epoch=-1555891200, msec=1, usec=-1 }); + print(pgtype.timestamptz{ epoch=-1555891200, msec=-1, usec=1 }); + print(pgtype.timestamptz{ epoch_msec=-1555891200001 }); + print(pgtype.timestamptz{ epoch_usec=-1555891200000001 }); +$$; +INFO: 1970-01-01 00:00:00+00 +INFO: 2019-04-22 00:00:00+00 +INFO: 2019-04-22 00:00:00.000001+00 +INFO: 2019-04-22 00:00:00.001+00 +INFO: 2019-04-22 00:00:00.000001+00 +INFO: 2019-04-22 00:00:00.001001+00 +INFO: 2019-04-21 23:59:59.999001+00 +INFO: 1920-09-12 00:00:00+00 +INFO: 1920-09-12 00:00:00.000999+00 +INFO: 1920-09-11 23:59:59.999001+00 +INFO: 1920-09-11 23:59:59.999+00 +INFO: 1920-09-11 23:59:59.999999+00 +do language pllua $$ + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1, timezone=10800 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1, timezone=-10800 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1, timezone="+0300" }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1, timezone="-0300" }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1, timezone="+1400" }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1, timezone="-1400" }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1, timezone="America/Los_Angeles" }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1, timezone="Pacific/Auckland" }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1, timezone="Asia/Kathmandu" }); + print(pgtype.timestamptz{ year=2018, month=10, day=28, hour=1, min=30, sec=0, timezone="Europe/London" }); + print(pgtype.timestamptz{ year=2018, month=10, day=28, hour=1, min=30, sec=0, isdst=true, timezone="Europe/London" }); + print(pgtype.timestamptz{ year=2018, month=10, day=28, hour=1, min=30, sec=0, isdst=false, timezone="Europe/London" }); +$$; +INFO: 2019-04-22 09:23:34.1+00 +INFO: 2019-04-22 15:23:34.1+00 +INFO: 2019-04-22 09:23:34.1+00 +INFO: 2019-04-22 15:23:34.1+00 +INFO: 2019-04-21 22:23:34.1+00 +INFO: 2019-04-23 02:23:34.1+00 +INFO: 2019-04-22 19:23:34.1+00 +INFO: 2019-04-22 00:23:34.1+00 +INFO: 2019-04-22 06:38:34.1+00 +INFO: 2018-10-28 01:30:00+00 +INFO: 2018-10-28 00:30:00+00 +INFO: 2018-10-28 01:30:00+00 +do language pllua $$ + print(pgtype.timestamptz{ epoch=1/0 }); + print(pgtype.timestamptz{ epoch=-1/0 }); +$$; +INFO: infinity +INFO: -infinity +do language pllua $$ + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=1, usec=59000000 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=-1 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=-60 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=-61 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=60 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=61 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=23, sec=120 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=0, sec=3661 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=0, sec=43201 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=0, sec=-43201 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=0, sec=864000 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=12, min=720, sec=3661 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=24, min=0, sec=0 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=24, min=0, sec=1 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=240, min=0, sec=1 }); + print(pgtype.timestamptz{ year=2019, month=4, day=22, hour=-1, min=0, sec=1 }); + print(pgtype.timestamptz{ year=2019, month=-4, day=22, hour=12, min=23, sec=34 }); + print(pgtype.timestamptz{ year=2019, month=16, day=22, hour=12, min=23, sec=34 }); +$$; +INFO: 2019-04-22 12:24:00+00 +INFO: 2019-04-22 12:22:59+00 +INFO: 2019-04-22 12:22:00+00 +INFO: 2019-04-22 12:21:59+00 +INFO: 2019-04-22 12:24:00+00 +INFO: 2019-04-22 12:24:01+00 +INFO: 2019-04-22 12:25:00+00 +INFO: 2019-04-22 13:01:01+00 +INFO: 2019-04-23 00:00:01+00 +INFO: 2019-04-21 23:59:59+00 +INFO: 2019-05-02 12:00:00+00 +INFO: 2019-04-23 01:01:01+00 +INFO: 2019-04-23 00:00:00+00 +INFO: 2019-04-23 00:00:01+00 +INFO: 2019-05-02 00:00:01+00 +INFO: 2019-04-21 23:00:01+00 +INFO: 2018-08-22 12:23:34+00 +INFO: 2020-04-22 12:23:34+00 +do language pllua $$ + print(pgtype.timestamp{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamp{ year=2419, month=4, day=22, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamp{ year=1919, month=4, day=22, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamp{ year=1819, month=4, day=22, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamp{ year=1019, month=4, day=22, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamp{ year=-2019, month=4, day=22, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamp{ year=-4713, month=12, day=1, hour=12, min=23, sec=34.1 }); + print(pgtype.timestamp{ year=2019, month=4, day=22, hour=12, min=23, sec=34, usec=123456 }); + print(pgtype.timestamp{ year=2019, month=4, day=22, hour=12, min=23, sec=34.1, msec=1, usec=1 }); +$$; +INFO: 2019-04-22 12:23:34.1 +INFO: 2419-04-22 12:23:34.1 +INFO: 1919-04-22 12:23:34.1 +INFO: 1819-04-22 12:23:34.1 +INFO: 1019-04-22 12:23:34.1 +INFO: 2020-04-22 12:23:34.1 BC +INFO: 4714-12-01 12:23:34.1 BC +INFO: 2019-04-22 12:23:34.123456 +INFO: 2019-04-22 12:23:34.101001 +do language pllua $$ + print(pgtype.timestamp{ epoch=0 }); + print(pgtype.timestamp{ epoch=1555891200 }); + print(pgtype.timestamp{ epoch=1555891200.000001 }); + print(pgtype.timestamp{ epoch_msec=1555891200001 }); + print(pgtype.timestamp{ epoch_usec=1555891200000001 }); + print(pgtype.timestamp{ epoch=1555891200, msec=1, usec=1 }); + print(pgtype.timestamp{ epoch=1555891200, msec=-1, usec=1 }); + print(pgtype.timestamp{ epoch=-1555891200 }); + print(pgtype.timestamp{ epoch=-1555891200, msec=1, usec=-1 }); + print(pgtype.timestamp{ epoch=-1555891200, msec=-1, usec=1 }); + print(pgtype.timestamp{ epoch_msec=-1555891200001 }); + print(pgtype.timestamp{ epoch_usec=-1555891200000001 }); + print(pgtype.timestamp{ epoch=1555891200, timezone="America/Los_Angeles" }); + print(pgtype.timestamp{ epoch=1555891200, timezone="Pacific/Auckland" }); + print(pgtype.timestamp{ epoch=1555891200, timezone="Asia/Kathmandu" }); +$$; +INFO: 1970-01-01 00:00:00 +INFO: 2019-04-22 00:00:00 +INFO: 2019-04-22 00:00:00.000001 +INFO: 2019-04-22 00:00:00.001 +INFO: 2019-04-22 00:00:00.000001 +INFO: 2019-04-22 00:00:00.001001 +INFO: 2019-04-21 23:59:59.999001 +INFO: 1920-09-12 00:00:00 +INFO: 1920-09-12 00:00:00.000999 +INFO: 1920-09-11 23:59:59.999001 +INFO: 1920-09-11 23:59:59.999 +INFO: 1920-09-11 23:59:59.999999 +INFO: 2019-04-21 17:00:00 +INFO: 2019-04-22 12:00:00 +INFO: 2019-04-22 05:45:00 +do language pllua $$ + print(pgtype.date{ year=2019, month=4, day=22 }); + print(pgtype.date{ year=2419, month=2, day=22 }); + print(pgtype.date{ year=1919, month=1, day=22 }); + print(pgtype.date{ year=1819, month=3, day=22 }); + print(pgtype.date{ year=1019, month=5, day=22 }); + print(pgtype.date{ year=-2019, month=4, day=22 }); + print(pgtype.date{ year=-4713, month=12, day=1 }); + print(pgtype.date{ year=2019, month=4, day=22, hour=24 }); + print(pgtype.date{ year=2019, month=4, day=22, hour=24, min=1 }); +$$; +INFO: 2019-04-22 +INFO: 2419-02-22 +INFO: 1919-01-22 +INFO: 1819-03-22 +INFO: 1019-05-22 +INFO: 2020-04-22 BC +INFO: 4714-12-01 BC +INFO: 2019-04-22 +INFO: 2019-04-23 +do language pllua $$ + print(pgtype.date{ epoch=0 }); + print(pgtype.date{ epoch=1555891200 }); + print(pgtype.date{ epoch=1555891200.000001 }); + print(pgtype.date{ epoch_msec=1555891200001 }); + print(pgtype.date{ epoch_usec=1555891200000001 }); + print(pgtype.date{ epoch=1555891200 }); + print(pgtype.date{ epoch=-1555891200 }); + print(pgtype.date{ epoch_msec=-1555891200001 }); + print(pgtype.date{ epoch_usec=-1555891200000001 }); + print(pgtype.date{ epoch=1555891200, timezone="America/Los_Angeles" }); + print(pgtype.date{ epoch=1555891200, timezone="Pacific/Auckland" }); + print(pgtype.date{ epoch=1555891200, timezone="Asia/Kathmandu" }); +$$; +INFO: 1970-01-01 +INFO: 2019-04-22 +INFO: 2019-04-22 +INFO: 2019-04-22 +INFO: 2019-04-22 +INFO: 2019-04-22 +INFO: 1920-09-12 +INFO: 1920-09-11 +INFO: 1920-09-11 +INFO: 2019-04-21 +INFO: 2019-04-22 +INFO: 2019-04-22 +do language pllua $$ + print(pgtype.time{ hour=12, min=23, sec=34.1 }); + print(pgtype.time{ hour=12, min=120, sec=1 }); + print(pgtype.time{ hour=24, min=23, sec=34.1 }); + print(pgtype.time{ hour=25, min=23, sec=34.1 }); + print(pgtype.time{ hour=12, min=23, sec=34, usec=123456 }); + print(pgtype.time{ hour=12, min=23, sec=34.1, msec=1, usec=1 }); +$$; +INFO: 12:23:34.1 +INFO: 14:00:01 +INFO: 00:23:34.1 +INFO: 01:23:34.1 +INFO: 12:23:34.123456 +INFO: 12:23:34.101001 +do language pllua $$ + print(pgtype.time{ epoch=0 }); + print(pgtype.time{ epoch=3601 }); + print(pgtype.time{ epoch=86400 }); + print(pgtype.time{ epoch=1555891200 }); +$$; +INFO: 00:00:00 +INFO: 01:00:01 +INFO: 00:00:00 +INFO: 00:00:00 +do language pllua $$ + print(pgtype.timetz{ hour=12, min=23, sec=34.1, timezone=7200 }); +$$; +INFO: 12:23:34.1+02 +do language pllua $$ + print(pgtype.timetz{ epoch=0, timezone=3600 }); + print(pgtype.timetz{ epoch=3601, timezone=-3600 }); + print(pgtype.timetz{ epoch=86400, timezone=-43200 }); + print(pgtype.timetz{ epoch=1555891200, timezone=0 }); +$$; +INFO: 00:00:00+01 +INFO: 01:00:01-01 +INFO: 00:00:00-12 +INFO: 00:00:00+00 +do language pllua $$ + print(pgtype.interval{ year=0, month=0, day=0, hour=0, min=0, sec=0, usec=0 }); + print(pgtype.interval{ year=100 }); + print(pgtype.interval{ month=100 }); + print(pgtype.interval{ day=100 }); + print(pgtype.interval{ hour=100 }); + print(pgtype.interval{ min=100 }); + print(pgtype.interval{ sec=100 }); + print(pgtype.interval{ usec=1 }); + print(pgtype.interval{ year=1, month=2, day=3, hour=4, min=5, sec=6, usec=7 }); +$$; +INFO: @ 0 +INFO: @ 100 years +INFO: @ 8 years 4 mons +INFO: @ 100 days +INFO: @ 100 hours +INFO: @ 1 hour 40 mins +INFO: @ 1 min 40 secs +INFO: @ 0.000001 secs +INFO: @ 1 year 2 mons 3 days 4 hours 5 mins 6.000007 secs +do language pllua $$ + print(pgtype.interval{ epoch=0 }); + print(pgtype.interval{ epoch=120 }); + print(pgtype.interval{ epoch=43200 }); + print(pgtype.interval{ epoch=86400 }); +$$; +INFO: @ 0 +INFO: @ 2 mins +INFO: @ 12 hours +INFO: @ 24 hours +-- input error cases. +do language pllua $$ print(pgtype.interval{ hour="foo" }); $$; +ERROR: pllua: invalid value in field 'hour' +do language pllua $$ print(pgtype.interval{ hour=1.2 }); $$; +ERROR: pllua: invalid value in field 'hour' +do language pllua $$ print(pgtype.interval{ hour=0/0 }); $$; +ERROR: pllua: invalid value in field 'hour' +do language pllua $$ print(pgtype.interval{ hour=1/0 }); $$; +ERROR: pllua: infinite values not permitted for this type +do language pllua $$ print(pgtype.interval{ sec=1/0 }); $$; +ERROR: pllua: infinite values not permitted for this type +do language pllua $$ print(pgtype.interval{ usec=1/0 }); $$; +ERROR: pllua: infinite values not permitted for this type +do language pllua $$ print(pgtype.timestamptz{ year=1/0, month=1, day=-1/0 }); $$; +ERROR: pllua: invalid value in field 'day' +do language pllua $$ print(pgtype.timestamp{ epoch=0, timezone="1234" }); $$; +ERROR: invalid timezone specified +do language pllua $$ print(pgtype.timestamp{ epoch=0, timezone=1234.5 }); $$; +ERROR: pllua: invalid value in field 'timezone' +do language pllua $$ print(pgtype.timestamp{ epoch=0, timezone=function() end }); $$; +ERROR: pllua: invalid value in field 'timezone' +do language pllua $$ print(pgtype.timestamptz{ epoch=0, epoch_msec=0 }); $$; +ERROR: pllua: cannot specify multiple epoch fields +do language pllua $$ print(pgtype.timestamptz{ epoch=0, year=2019 }); $$; +ERROR: pllua: cannot specify both epoch and date fields +do language pllua $$ print(pgtype.timestamptz{ epoch=0, hour=20 }); $$; +ERROR: pllua: cannot specify both epoch and time fields +do language pllua $$ print(pgtype.timestamptz{ year=2019 }); $$; +ERROR: pllua: missing datetime field 'mon' +do language pllua $$ print(pgtype.timestamptz{ year=2019, month=4 }); $$; +ERROR: pllua: missing datetime field 'day' +do language pllua $$ print(pgtype.time{ min=10 }); $$; +ERROR: pllua: missing datetime field 'hour' +do language pllua $$ print(pgtype.time{ hour=20, sec=10 }); $$; +ERROR: pllua: missing datetime field 'min' +do language pllua $$ print(pgtype.timetz{ hour=20, timezone="America/Los_Angeles" }); $$; +ERROR: pllua: non-numeric timezones not supported for 'timetz' +do language pllua $$ print(pgtype.time{ hour=20, timezone="America/Los_Angeles" }); $$; +ERROR: pllua: cannot specify timezone for this type +do language pllua $$ print(pgtype.date{ year=2019, month=4, day=22, timezone="America/Los_Angeles" }); $$; +ERROR: pllua: cannot specify timezone for this type +do language pllua $$ print(pgtype.timestamp{ year=2019, month=4, day=22, hour=20, timezone="America/Los_Angeles" }); $$; +ERROR: pllua: cannot specify timezone for this type +do language pllua $$ print(pgtype.timestamptz{ epoch=-300000000000 }); $$; +ERROR: timestamp out of range +do language pllua $$ print(pgtype.timestamptz{ year=-5000, month=1, day=1 }); $$; +ERROR: could not convert to timestamp +do language pllua $$ print(pgtype.date{ year=-5000, month=1, day=1 }); $$; +INFO: 4760-06-20 BC +-- 2. output of values in table form. +do language pllua $$ + local function prt(t,z) + print(t) + local rt = t:as_table(z) + local o = {} + for k,_ in pairs(rt) do o[1+#o] = k end + table.sort(o) + for _,k in ipairs(o) do print(k,rt[k]) end + end + prt(pgtype.timestamptz('2019-04-22 10:20:30+00')) + prt(pgtype.timestamptz('2019-04-22 10:20:30+00'),'America/Los_Angeles') + prt(pgtype.timestamptz('2019-04-22 10:20:30+00'),'Asia/Kathmandu') + prt(pgtype.timestamp('2019-04-22 10:20:30+00')) + prt(pgtype.date('2019-04-22')) + prt(pgtype.time('10:20:30')) + prt(pgtype.timetz('10:20:30+04')) + prt(pgtype.interval('P1Y2M3DT4H5M6S')) +$$; +INFO: 2019-04-22 10:20:30+00 +INFO: day 22 +INFO: hour 10 +INFO: isdst false +INFO: min 20 +INFO: month 4 +INFO: sec 30 +INFO: timezone 0 +INFO: timezone_abbrev GMT +INFO: usec 0 +INFO: year 2019 +INFO: 2019-04-22 10:20:30+00 +INFO: day 22 +INFO: hour 3 +INFO: isdst true +INFO: min 20 +INFO: month 4 +INFO: sec 30 +INFO: timezone -25200 +INFO: timezone_abbrev PDT +INFO: usec 0 +INFO: year 2019 +INFO: 2019-04-22 10:20:30+00 +INFO: day 22 +INFO: hour 16 +INFO: isdst false +INFO: min 5 +INFO: month 4 +INFO: sec 30 +INFO: timezone 20700 +INFO: timezone_abbrev +0545 +INFO: usec 0 +INFO: year 2019 +INFO: 2019-04-22 10:20:30 +INFO: day 22 +INFO: hour 10 +INFO: min 20 +INFO: month 4 +INFO: sec 30 +INFO: usec 0 +INFO: year 2019 +INFO: 2019-04-22 +INFO: day 22 +INFO: month 4 +INFO: year 2019 +INFO: 10:20:30 +INFO: hour 10 +INFO: min 20 +INFO: sec 30 +INFO: usec 0 +INFO: 10:20:30+04 +INFO: hour 10 +INFO: min 20 +INFO: sec 30 +INFO: timezone 14400 +INFO: usec 0 +INFO: @ 1 year 2 mons 3 days 4 hours 5 mins 6 secs +INFO: day 3 +INFO: hour 4 +INFO: min 5 +INFO: month 2 +INFO: sec 6 +INFO: usec 0 +INFO: year 1 +-- error +do language pllua $$ print(pgtype.timestamp('2019-04-22 10:20:30+00'):as_table('Europe/London')) $$; +ERROR: pllua: [string "DO-block"]:1: cannot specify timezone parameter for this type +-- 3. Field access +-- note, fields come out in session timezone, so set that: +set timezone = 'Europe/London'; +do language pllua $$ + local t = pgtype.timestamptz('1968-05-10 03:45:01.234567+01') + + for _,k in ipairs{ 'century', 'day', 'decade', 'dow', 'doy', + 'epoch', 'epoch_msec', 'epoch_usec', + 'hour', 'isodow', 'isoweek', 'isoyear', + 'julian', 'microseconds', 'millennium', + 'milliseconds', 'minute', 'month', + 'quarter', 'second', 'timezone', + 'timezone_hour', 'timezone_minute', + 'week', 'year' } do + print(k, t[k]) + end +$$; +INFO: century 20 +INFO: day 10 +INFO: decade 196 +INFO: dow 5 +INFO: doy 131 +INFO: epoch -51916498.765433 +INFO: epoch_msec -51916498765.433 +INFO: epoch_usec -51916498765433 +INFO: hour 3 +INFO: isodow 5 +INFO: isoweek 19 +INFO: isoyear 1968 +INFO: julian 2439987 +INFO: microseconds 1234567 +INFO: millennium 2 +INFO: milliseconds 1235 +INFO: minute 45 +INFO: month 5 +INFO: quarter 2 +INFO: second 1.234567 +INFO: timezone 3600 +INFO: timezone_hour 1 +INFO: timezone_minute 0 +INFO: week 19 +INFO: year 1968 +set timezone = 'UTC'; +do language pllua $$ + local t = pgtype.timestamp('1968-05-10 03:45:01.234567') + + for _,k in ipairs{ 'century', 'day', 'decade', 'dow', 'doy', + 'epoch', 'epoch_msec', 'epoch_usec', + 'hour', 'isodow', 'isoweek', 'isoyear', + 'julian', 'microseconds', 'millennium', + 'milliseconds', 'minute', 'month', + 'quarter', 'second', + 'week', 'year' } do + print(k, t[k]) + end +$$; +INFO: century 20 +INFO: day 10 +INFO: decade 196 +INFO: dow 5 +INFO: doy 131 +INFO: epoch -51912898.765433 +INFO: epoch_msec -51912898765.433 +INFO: epoch_usec -51912898765433 +INFO: hour 3 +INFO: isodow 5 +INFO: isoweek 19 +INFO: isoyear 1968 +INFO: julian 2439987 +INFO: microseconds 1234567 +INFO: millennium 2 +INFO: milliseconds 1235 +INFO: minute 45 +INFO: month 5 +INFO: quarter 2 +INFO: second 1.234567 +INFO: week 19 +INFO: year 1968 +do language pllua $$ + local t = pgtype.date('1968-05-10') + + for _,k in ipairs{ 'century', 'day', 'decade', 'dow', 'doy', + 'epoch', 'epoch_msec', 'epoch_usec', + 'hour', 'isodow', 'isoweek', 'isoyear', + 'julian', 'microseconds', 'millennium', + 'milliseconds', 'minute', 'month', + 'quarter', 'second', + 'week', 'year' } do + print(k, string.format("%.18g",t[k])) + end +$$; +INFO: century 20 +INFO: day 10 +INFO: decade 196 +INFO: dow 5 +INFO: doy 131 +INFO: epoch -51926400 +INFO: epoch_msec -51926400000 +INFO: epoch_usec -51926400000000 +INFO: hour 0 +INFO: isodow 5 +INFO: isoweek 19 +INFO: isoyear 1968 +INFO: julian 2439987 +INFO: microseconds 0 +INFO: millennium 2 +INFO: milliseconds 0 +INFO: minute 0 +INFO: month 5 +INFO: quarter 2 +INFO: second 0 +INFO: week 19 +INFO: year 1968 +do language pllua $$ + local t = pgtype.time('03:45:01.234567') + + for _,k in ipairs{ 'epoch', 'epoch_msec', 'epoch_usec', + 'hour', 'microseconds', + 'milliseconds', 'minute', 'second' } do + print(k, t[k]) + end +$$; +INFO: epoch 13501.234567 +INFO: epoch_msec 13501234.567 +INFO: epoch_usec 13501234567 +INFO: hour 3 +INFO: microseconds 1234567 +INFO: milliseconds 1235 +INFO: minute 45 +INFO: second 1.234567 +do language pllua $$ + local t = pgtype.timetz('03:45:01.234567+01') + + for _,k in ipairs{ 'epoch', 'epoch_msec', 'epoch_usec', + 'hour', 'microseconds', + 'milliseconds', 'minute', 'second', + 'timezone', 'timezone_hour', + 'timezone_minute', } do + print(k, t[k]) + end +$$; +INFO: epoch 9901.234567 +INFO: epoch_msec 9901234.567 +INFO: epoch_usec 9901234567 +INFO: hour 3 +INFO: microseconds 1234567 +INFO: milliseconds 1235 +INFO: minute 45 +INFO: second 1.234567 +INFO: timezone 3600 +INFO: timezone_hour 1 +INFO: timezone_minute 0 +do language pllua $$ + local t = pgtype.interval('P1Y2M3DT4H5M6.789001S') + + for _,k in ipairs{ 'century', 'day', 'decade', + 'epoch', 'epoch_msec', 'epoch_usec', + 'hour', 'microseconds', 'millennium', + 'milliseconds', 'minute', 'month', + 'quarter', 'second', + 'year' } do + print(k, t[k]) + end +$$; +INFO: century 0 +INFO: day 3 +INFO: decade 0 +INFO: epoch 37015506.789001 +INFO: epoch_msec 37015506789.001 +INFO: epoch_usec 37015506789001 +INFO: hour 4 +INFO: microseconds 6789001 +INFO: millennium 0 +INFO: milliseconds 6789 +INFO: minute 5 +INFO: month 2 +INFO: quarter 1 +INFO: second 6.789001 +INFO: year 1 +-- errors (not worth testing many combinations, they all share a code path) +do language pllua $$ print(pgtype.time('03:45:01.234567').dow) $$; +ERROR: unit "dow" not supported for type time without time zone +--end diff --git a/expected/spi_1.out b/expected/spi_1.out new file mode 100644 index 0000000..6e981ed --- /dev/null +++ b/expected/spi_1.out @@ -0,0 +1,262 @@ +-- +\set VERBOSITY terse +-- +-- Test of SPI-related functionality. +create temp table tsttab ( + id integer primary key, + a integer, + b text, + c numeric, + d date +); +insert into tsttab(id, a,b,c,d) + values (1, 1,'foo',2.34,'2017-01-01'), + (2, 2,'bar',2.34,'2017-02-01'), + (3, 3,'baz',2.34,'2017-03-01'), + (4, 4, 'fred',2.34,'2017-04-01'), + (5, 5,'jim',2.34,'2017-05-01'), + (6, 6,'sheila',2.34,'2017-06-01'); +-- basics +do language pllua $$ + local tbl + tbl = spi.execute([[ select 1 as a, 'foo'::text as b ]]) + print(#tbl,tbl[1],type(tbl[1])) + print(tbl[1].a,tbl[1].b) + tbl = spi.execute([[ select i, 'foo'::text as b from generate_series(1,10000) i ]]) + print(#tbl,tbl[1],tbl[10000]) + tbl = spi.execute([[ select * from tsttab order by id ]]) + for i = 1,#tbl do print(tbl[i]) end +$$; +INFO: 1 (1,foo) userdata +INFO: 1 foo +INFO: 10000 (1,foo) (10000,foo) +INFO: (1,1,foo,2.34,01-01-2017) +INFO: (2,2,bar,2.34,02-01-2017) +INFO: (3,3,baz,2.34,03-01-2017) +INFO: (4,4,fred,2.34,04-01-2017) +INFO: (5,5,jim,2.34,05-01-2017) +INFO: (6,6,sheila,2.34,06-01-2017) +-- statements +do language pllua $$ + local stmt,tbl + stmt = spi.prepare([[ select * from tsttab where id=$1 ]], {"integer"}) + tbl = stmt:execute(1) + print(tbl[1]) + -- __call metamethod + tbl = stmt(6) + print(tbl[1]) + stmt = spi.prepare([[ select * from tsttab where id = ANY ($1) order by id ]], + {pgtype.array.integer}) + tbl = stmt:execute(pgtype.array.integer(1,nil,3)) + print(#tbl,tbl[1],tbl[2]) + -- type deduction: + stmt = spi.prepare([[ select 1 + $1 as a, pg_typeof($1) ]]) + tbl = stmt:execute(1) + print(#tbl,tbl[1]) +$$; +INFO: (1,1,foo,2.34,01-01-2017) +INFO: (6,6,sheila,2.34,06-01-2017) +INFO: 2 (1,1,foo,2.34,01-01-2017) (3,3,baz,2.34,03-01-2017) +INFO: 1 (2,integer) +-- iterators +do language pllua $$ + for r in spi.rows([[ select * from tsttab order by id ]]) do + print(r) + end + stmt = spi.prepare([[ select * from tsttab where id = ANY ($1) ]], + {pgtype.array.integer}) + for r in stmt:rows(pgtype.array.integer(1,nil,3)) do + print(r) + end +$$; +INFO: (1,1,foo,2.34,01-01-2017) +INFO: (2,2,bar,2.34,02-01-2017) +INFO: (3,3,baz,2.34,03-01-2017) +INFO: (4,4,fred,2.34,04-01-2017) +INFO: (5,5,jim,2.34,05-01-2017) +INFO: (6,6,sheila,2.34,06-01-2017) +INFO: (1,1,foo,2.34,01-01-2017) +INFO: (3,3,baz,2.34,03-01-2017) +do language pllua $$ + local c = spi.newcursor('curs1') + local stmt = spi.prepare([[ select * from tsttab order by id for update ]]) + c:open(stmt) + for r in c:rows() do + print(r) + if r.id == 3 then + spi.execute([[ update tsttab set c = c + 10 where current of curs1 ]]) + end + end + c:move(0, 'absolute') + for r in c:rows() do + print(r) + end + for r in spi.rows([[ select * from tsttab order by id ]]) do + print(r) + end + spi.execute([[ update tsttab set c = c - 10 where id=3 ]]) + c:close() +$$; +INFO: (1,1,foo,2.34,01-01-2017) +INFO: (2,2,bar,2.34,02-01-2017) +INFO: (3,3,baz,2.34,03-01-2017) +INFO: (4,4,fred,2.34,04-01-2017) +INFO: (5,5,jim,2.34,05-01-2017) +INFO: (6,6,sheila,2.34,06-01-2017) +ERROR: cursor can only scan forward +-- cursors +begin; +declare foo scroll cursor for select * from tsttab order by id; +do language pllua $$ + local c = spi.findcursor("foo") + local tbl + tbl = c:fetch(1,'next') + print(#tbl,tbl[1]) + tbl = c:fetch(2,'forward') -- same as 'next' + print(#tbl,tbl[1],tbl[2]) + tbl = c:fetch(1,'absolute') + print(#tbl,tbl[1]) + tbl = c:fetch(4,'relative') + print(#tbl,tbl[1]) + tbl = c:fetch(1,'prior') -- same as 'backward' + print(#tbl,tbl[1]) + tbl = c:fetch(1,'backward') + print(#tbl,tbl[1]) + print(c:isopen()) + spi.execute("close foo") + print(c:isopen()) +$$; +INFO: 1 (1,1,foo,2.34,01-01-2017) +INFO: 2 (2,2,bar,2.34,02-01-2017) (3,3,baz,2.34,03-01-2017) +INFO: 1 (1,1,foo,2.34,01-01-2017) +INFO: 1 (5,5,jim,2.34,05-01-2017) +INFO: 1 (4,4,fred,2.34,04-01-2017) +INFO: 1 (3,3,baz,2.34,03-01-2017) +INFO: true +INFO: false +commit; +do language pllua $$ + local c = spi.newcursor("bar") + c:open([[ select * from tsttab where id >= $1 order by id ]], 3) + local tbl + tbl = c:fetch(1,'next') + print(#tbl,tbl[1]) + for k,v in ipairs(spi.execute([[ select name, statement from pg_cursors ]])) do + print(v.name, v.statement) + end + c:close() + for k,v in ipairs(spi.execute([[ select name, statement from pg_cursors ]])) do + print(v.name, v.statement) + end + c:open([[ select * from tsttab where id < $1 order by id desc ]], 3) + tbl = c:fetch(3,'next') + print(#tbl,tbl[1],tbl[2]) + for k,v in ipairs(spi.execute([[ select name, statement from pg_cursors ]])) do + print(v.name, v.statement) + end + c:close() +$$; +INFO: 1 (3,3,baz,2.34,03-01-2017) +INFO: bar select * from tsttab where id >= $1 order by id +INFO: 2 (2,2,bar,2.34,02-01-2017) (1,1,foo,2.34,01-01-2017) +INFO: bar select * from tsttab where id < $1 order by id desc +-- cursor options on statement +do language pllua $$ + local stmt = spi.prepare([[ select * from tsttab where id >= $1 order by id ]], + {"integer"}, { scroll = true, fast_start = true, generic_plan = true }) + local stmt2 = spi.prepare([[ select * from tsttab where id >= $1 order by id ]], + {"integer"}, { no_scroll = true }) + local c = stmt:getcursor(4) + local tbl + tbl = c:fetch(3,'next') + print(#tbl,tbl[1],tbl[2]) + c:move(0,'absolute') + tbl = c:fetch(3,'next') + print(#tbl,tbl[1],tbl[2]) + for k,v in ipairs(spi.execute([[ select name, statement, is_scrollable from pg_cursors ]])) do + print(v.name, v.statement, v.is_scrollable) + end + c:close() + c = stmt2:getcursor(4) + local c2 = spi.findcursor(c:name()) + print(c:name(), rawequal(c,c2)) + for k,v in ipairs(spi.execute([[ select name, statement, is_scrollable from pg_cursors ]])) do + print(v.name, v.statement, v.is_scrollable) + end + c:close() +$$; +INFO: 3 (4,4,fred,2.34,04-01-2017) (5,5,jim,2.34,05-01-2017) +INFO: 3 (4,4,fred,2.34,04-01-2017) (5,5,jim,2.34,05-01-2017) +INFO: select * from tsttab where id >= $1 order by id true +INFO: true +INFO: select * from tsttab where id >= $1 order by id false +-- check missing params are OK +do language pllua $$ + local stmt = spi.prepare([[ select * from generate_series($1::integer, $3) i ]]); + print(stmt:argtype(1):name()) + print(type(stmt:argtype(2))) + print(stmt:argtype(3):name()) +$$; +INFO: integer +INFO: nil +INFO: integer +-- check execute_count +do language pllua $$ + local q = [[ select * from generate_series($1::integer,$2) i ]] + local r1 = spi.execute_count(q, 2, 1, 5) + print(#r1) + local s = spi.prepare(q, {"integer","integer"}) + r1 = s:execute_count(3,1,5) + print(#r1) +$$; +INFO: 2 +INFO: 3 +-- cursors as parameters and return values +create function do_fetch(c refcursor) returns void language pllua as $$ + while true do + local r = (c:fetch())[1] + if r==nil then break end + print(r) + end +$$; +create function do_exec(q text, n text) returns refcursor language pllua as $$ + local s = spi.prepare(q) + local c = spi.newcursor(n) + return c:open(s):disown() +$$; +begin; +declare mycur cursor for select * from tsttab order by id; +select do_fetch('mycur'); +INFO: (1,1,foo,2.34,01-01-2017) +INFO: (2,2,bar,2.34,02-01-2017) +INFO: (3,3,baz,2.34,03-01-2017) +INFO: (4,4,fred,2.34,04-01-2017) +INFO: (5,5,jim,2.34,05-01-2017) +INFO: (6,6,sheila,2.34,06-01-2017) + do_fetch +---------- + +(1 row) + +commit; +begin; +select do_exec('select * from tsttab order by id desc', 'mycur2'); + do_exec +--------- + mycur2 +(1 row) + +do language pllua $$ collectgarbage() $$; -- check cursor stays open +fetch all from mycur2; + id | a | b | c | d +----+---+--------+------+------------ + 6 | 6 | sheila | 2.34 | 06-01-2017 + 5 | 5 | jim | 2.34 | 05-01-2017 + 4 | 4 | fred | 2.34 | 04-01-2017 + 3 | 3 | baz | 2.34 | 03-01-2017 + 2 | 2 | bar | 2.34 | 02-01-2017 + 1 | 1 | foo | 2.34 | 01-01-2017 +(6 rows) + +commit; +--end diff --git a/src/spi.c b/src/spi.c index 73203f9..9fd0da2 100644 --- a/src/spi.c +++ b/src/spi.c @@ -272,7 +272,11 @@ static void pllua_spi_prepare_checkparam_hook(ParseState *pstate, static void pllua_spi_prepare_parser_setup_hook(ParseState *pstate, void *arg) { pllua_spi_statement *stmt = arg; +#if PG_VERSION_NUM >= 150000 + setup_parse_variable_parameters(pstate, &stmt->param_types, &stmt->param_types_len); +#else parse_variable_parameters(pstate, &stmt->param_types, &stmt->param_types_len); +#endif } static pllua_spi_statement *pllua_spi_make_statement(lua_State *L, diff --git a/src/time.c b/src/time.c index 1a741ef..4399635 100644 --- a/src/time.c +++ b/src/time.c @@ -920,15 +920,33 @@ pllua_time_as_table(lua_State *L) case INTERVALOID: { +#if PG_VERSION_NUM >= 150000 + struct pg_itm itm = { 0 }; +#endif Interval *itmp = DatumGetIntervalP(val); PLLUA_TRY(); { +#if PG_VERSION_NUM >= 150000 + /* PG15 removes interval2tm, use interval2itm and copy the result to tm */ + interval2itm(*itmp, &itm); + tm.tm_sec = itm.tm_sec; + tm.tm_min = itm.tm_min; + tm.tm_hour = itm.tm_hour; + tm.tm_mday = itm.tm_mday; + tm.tm_mon = itm.tm_mon; + tm.tm_year = itm.tm_year; +#else if (interval2tm(*itmp, &tm, &fsec) != 0) elog(ERROR, "interval output failed"); +#endif } PLLUA_CATCH_RETHROW(); +#if PG_VERSION_NUM >= 150000 + microsecs = FSEC_T_SCALE(itm.tm_usec); +#else microsecs = FSEC_T_SCALE(fsec); +#endif } break; }