there are 3 problems, you are outputing N + 1 rows of output, but you say you want N (7) for the seven lines. Which implies you should drop the finalizer, as it's giving you the extra row. OR you do want the n+1 so you can have all the before and the final after, where as you code code is writing after, and a fake before (but afterwards). If you want the before, write the before in the initializer.
second problem, your array is 4 wide, and you want all four values changed, but you are modulating by 3. That needs to go to 4 it would seem.
And lastly, all your output values appear to be the make value, because you are assigning the "reference" to the array as the result. So you need to clone the array to make clean new data. This question implies slice is a good way to go thus:
so sticking with the N+1 way I would use:
I have made a tiny change to your set to -1
to sub 1, so we can see the wrap-round is working:
CREATE OR REPLACE FUNCTION "SUMMER"(INF FLOAT)
RETURNS TABLE (NUM float, NUM2 array)
LANGUAGE JAVASCRIPT
AS '{
processRow: function (row, rowWriter, context) {
//this.ar[this.index]=-1; -- tweaked to show it working
this.ar[this.index] -=1;
rowWriter.writeRow( {NUM: this.index, NUM2: this.ar.slice(0)});
this.index=(this.index+1)%4;
},
finalize: function (rowWriter, context) {
rowWriter.writeRow({NUM: 0, NUM2: [0,0,0,0]});
},
initialize: function(argumentInfo, context) {
this.ar=[0,0,0,0];
this.index = 0;
}}';
SELECT *
FROM (VALUES (1),(2),(3),(4),(5),(6),(7) ) as v(c1),
TABLE(SUMMER(v.c1::FLOAT))
ORDER BY 1;
gives:
C1 |
NUM |
NUM2 |
1 |
0 |
[ -1, 0, 0, 0 ] |
2 |
1 |
[ -1, -1, 0, 0 ] |
3 |
2 |
[ -1, -1, -1, 0 ] |
4 |
3 |
[ -1, -1, -1, -1 ] |
5 |
0 |
[ -2, -1, -1, -1 ] |
6 |
1 |
[ -2, -2, -1, -1 ] |
7 |
2 |
[ -2, -2, -2, -1 ] |
null |
0 |
[ 0, 0, 0, 0 ] |
so if you want to have the last row first, push the NULLS FIRST
SELECT *
FROM (VALUES (1),(2),(3),(4),(5),(6),(7) ) as v(c1),
TABLE(SUMMER(v.c1::FLOAT))
ORDER BY 1 NULLS FIRST;
gives:
C1 |
NUM |
NUM2 |
null |
0 |
[ 0, 0, 0, 0 ] |
1 |
0 |
[ -1, 0, 0, 0 ] |
2 |
1 |
[ -1, -1, 0, 0 ] |
3 |
2 |
[ -1, -1, -1, 0 ] |
4 |
3 |
[ -1, -1, -1, -1 ] |
5 |
0 |
[ -2, -1, -1, -1 ] |
6 |
1 |
[ -2, -2, -1, -1 ] |
7 |
2 |
[ -2, -2, -2, -1 ] |
Another option:
So if you really are trying to build an array of zeros and negative ones, you can just do it in SQL:
SELECT c1
,ARRAY_CONSTRUCT(0,0,0,0) as zeros
,ARRAY_CONSTRUCT(-1,-1,-1,-1) as negs
,LEAST(c1-1, 4) as nf
,ARRAY_SLICE(negs, 0, nf) as np
,ARRAY_SLICE(zeros, nf, 4) as zp
,ARRAY_CAT(np, zp) as answer
FROM VALUES (1),(2),(3),(4),(5),(6),(7) as v(c1)
ORDER BY 1;
gives:
C1 |
ZEROS |
NEGS |
NF |
NP |
ZP |
ANSWER |
1 |
[ 0, 0, 0, 0 ] |
[ -1, -1, -1, -1 ] |
0 |
[] |
[ 0, 0, 0, 0 ] |
[ 0, 0, 0, 0 ] |
2 |
[ 0, 0, 0, 0 ] |
[ -1, -1, -1, -1 ] |
1 |
[ -1 ] |
[ 0, 0, 0 ] |
[ -1, 0, 0, 0 ] |
3 |
[ 0, 0, 0, 0 ] |
[ -1, -1, -1, -1 ] |
2 |
[ -1, -1 ] |
[ 0, 0 ] |
[ -1, -1, 0, 0 ] |
4 |
[ 0, 0, 0, 0 ] |
[ -1, -1, -1, -1 ] |
3 |
[ -1, -1, -1 ] |
[ 0 ] |
[ -1, -1, -1, 0 ] |
5 |
[ 0, 0, 0, 0 ] |
[ -1, -1, -1, -1 ] |
4 |
[ -1, -1, -1, -1 ] |
[] |
[ -1, -1, -1, -1 ] |
6 |
[ 0, 0, 0, 0 ] |
[ -1, -1, -1, -1 ] |
4 |
[ -1, -1, -1, -1 ] |
[] |
[ -1, -1, -1, -1 ] |
7 |
[ 0, 0, 0, 0 ] |
[ -1, -1, -1, -1 ] |
4 |
[ -1, -1, -1, -1 ] |
[] |
[ -1, -1, -1, -1 ] |
and that can be done in a one line wonder:
SELECT c1
,ARRAY_CAT(
ARRAY_SLICE(ARRAY_CONSTRUCT(-1,-1,-1,-1), 0, LEAST(c1-1, 4)),
ARRAY_SLICE(ARRAY_CONSTRUCT(0,0,0,0), LEAST(c1-1, 4), 4)
) as answer
FROM VALUES (1),(2),(3),(4),(5),(6),(7) as v(c1)
ORDER BY 1;
gives:
C1 |
ANSWER |
1 |
[ 0, 0, 0, 0 ] |
2 |
[ -1, 0, 0, 0 ] |
3 |
[ -1, -1, 0, 0 ] |
4 |
[ -1, -1, -1, 0 ] |
5 |
[ -1, -1, -1, -1 ] |
6 |
[ -1, -1, -1, -1 ] |
7 |
[ -1, -1, -1, -1 ] |