Changeset: 59327df64a2e for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=59327df64a2e
Modified Files:
        gdk/gdk_analytic.c
        gdk/gdk_analytic.h
        sql/backends/monet5/sql_rank.c
        sql/backends/monet5/sql_rank.h
        sql/backends/monet5/sql_rank.mal
        sql/backends/monet5/sql_rank.mal.sh
        sql/common/sql_types.c
        sql/server/sql_scan.c
        sql/test/analytics/Tests/analytics01.sql
        sql/test/analytics/Tests/analytics01.stable.err
        sql/test/analytics/Tests/analytics01.stable.out
Branch: analytics
Log Message:

Implemented first_value and last_value on a window.


diffs (truncated from 1064 to 300 lines):

diff --git a/gdk/gdk_analytic.c b/gdk/gdk_analytic.c
--- a/gdk/gdk_analytic.c
+++ b/gdk/gdk_analytic.c
@@ -205,6 +205,231 @@ finish:
 #undef ANALYTICAL_NTILE_IMP
 #undef NTILE_CALC
 
+#define ANALYTICAL_FIRST_IMP(TPE)                 \
+       do {                                          \
+               TPE *rp, *rb, *restrict bp, *end, curval; \
+               rb = rp = (TPE*)Tloc(r, 0);               \
+               bp = (TPE*)Tloc(b, 0);                    \
+               curval = *bp;                             \
+               end = rp + cnt;                           \
+               if (p) {                                  \
+                       np = (bit*)Tloc(p, 0);                \
+                       for(; rp<end; np++, rp++, bp++) {     \
+                               if (*np) {                        \
+                                       if(is_##TPE##_nil(curval))    \
+                                               has_nils = true;          \
+                                       for (;rb < rp; rb++)          \
+                                               *rb = curval;             \
+                                       curval = *bp;                 \
+                               }                                 \
+                       }                                     \
+                       if(is_##TPE##_nil(curval))            \
+                               has_nils = true;                  \
+                       for (;rb < rp; rb++)                  \
+                               *rb = curval;                     \
+               } else {                                  \
+                       if(is_##TPE##_nil(curval))            \
+                               has_nils = true;                  \
+                       for(; rp<end; rp++)                   \
+                               *rp = curval;                     \
+               }                                         \
+       } while(0);
+
+gdk_return
+GDKanalyticalfirst(BAT *r, BAT *b, BAT *p, BAT *o, int tpe)
+{
+       int (*atomcmp)(const void *, const void *);
+       const void *nil;
+       bool has_nils = false;
+       BUN i, j, cnt = BATcount(b);
+       bit *restrict np;
+       gdk_return gdk_res = GDK_SUCCEED;
+
+       (void)o;
+       switch(ATOMstorage(tpe)) {
+               case TYPE_bit:
+                       ANALYTICAL_FIRST_IMP(bit)
+                       break;
+               case TYPE_bte:
+                       ANALYTICAL_FIRST_IMP(bte)
+                       break;
+               case TYPE_sht:
+                       ANALYTICAL_FIRST_IMP(sht)
+                       break;
+               case TYPE_int:
+                       ANALYTICAL_FIRST_IMP(int)
+                       break;
+               case TYPE_lng:
+                       ANALYTICAL_FIRST_IMP(lng)
+                       break;
+#ifdef HAVE_HUGE
+               case TYPE_hge:
+                       ANALYTICAL_FIRST_IMP(hge)
+                       break;
+#endif
+               case TYPE_flt:
+                       ANALYTICAL_FIRST_IMP(flt)
+                       break;
+               case TYPE_dbl:
+                       ANALYTICAL_FIRST_IMP(dbl)
+                       break;
+               default: {
+                       BATiter bpi = bat_iterator(b);
+                       void *restrict curval = BUNtail(bpi, 0);
+                       nil = ATOMnilptr(tpe);
+                       atomcmp = ATOMcompare(tpe);
+                       if (p) {
+                               np = (bit*)Tloc(p, 0);
+                               for(i=0,j=0; i<cnt; i++, np++) {
+                                       if (*np) {
+                                               if((*atomcmp)(curval, nil) == 0)
+                                                       has_nils = true;
+                                               for (;j < i; j++) {
+                                                       if ((gdk_res = 
BUNappend(r, curval, false)) != GDK_SUCCEED)
+                                                               goto finish;
+                                               }
+                                               curval = BUNtail(bpi, i);
+                                       }
+                               }
+                               if((*atomcmp)(curval, nil) == 0)
+                                       has_nils = true;
+                               for (;j < i; j++) {
+                                       if ((gdk_res = BUNappend(r, curval, 
false)) != GDK_SUCCEED)
+                                          goto finish;
+                               }
+                       } else { /* single value, ie no ordering */
+                               if((*atomcmp)(curval, nil) == 0)
+                                       has_nils = true;
+                               for(i=0; i<cnt; i++) {
+                                       if ((gdk_res = BUNappend(r, curval, 
false)) != GDK_SUCCEED)
+                                               goto finish;
+                               }
+                       }
+               }
+       }
+finish:
+       BATsetcount(r, cnt);
+       r->tnonil = !has_nils;
+       r->tnil = has_nils;
+       return gdk_res;
+}
+
+#undef ANALYTICAL_FIRST_IMP
+
+#define ANALYTICAL_LAST_IMP(TPE)                  \
+       do {                                          \
+               TPE *rp, *rb, *restrict bp, *end, curval; \
+               rb = rp = (TPE*)Tloc(r, 0);               \
+               bp = (TPE*)Tloc(b, 0);                    \
+               end = rp + cnt;                           \
+               if (p) {                                  \
+                       np = (bit*)Tloc(p, 0);                \
+                       for(; rp<end; np++, rp++, bp++) {     \
+                               if (*np) {                        \
+                                       curval = *(bp - 1);           \
+                                       if(is_##TPE##_nil(curval))    \
+                                               has_nils = true;          \
+                                       for (;rb < rp; rb++)          \
+                                               *rb = curval;             \
+                               }                                 \
+                       }                                     \
+                       curval = *(bp - 1);                   \
+                       if(is_##TPE##_nil(curval))            \
+                               has_nils = true;                  \
+                       for (;rb < rp; rb++)                  \
+                               *rb = curval;                     \
+               } else {                                  \
+                       curval = *(bp + cnt - 1);             \
+                       if(is_##TPE##_nil(curval))            \
+                               has_nils = true;                  \
+                       for(; rp<end; rp++)                   \
+                               *rp = curval;                     \
+               }                                         \
+       } while(0);
+
+gdk_return
+GDKanalyticallast(BAT *r, BAT *b, BAT *p, BAT *o, int tpe)
+{
+       int (*atomcmp)(const void *, const void *);
+       const void *nil;
+       bool has_nils = false;
+       BUN i, j, cnt = BATcount(b);
+       bit *restrict np;
+       gdk_return gdk_res = GDK_SUCCEED;
+
+       (void)o;
+       switch(ATOMstorage(tpe)) {
+               case TYPE_bit:
+                       ANALYTICAL_LAST_IMP(bit)
+                       break;
+               case TYPE_bte:
+                       ANALYTICAL_LAST_IMP(bte)
+                       break;
+               case TYPE_sht:
+                       ANALYTICAL_LAST_IMP(sht)
+                       break;
+               case TYPE_int:
+                       ANALYTICAL_LAST_IMP(int)
+                       break;
+               case TYPE_lng:
+                       ANALYTICAL_LAST_IMP(lng)
+                       break;
+#ifdef HAVE_HUGE
+               case TYPE_hge:
+                       ANALYTICAL_LAST_IMP(hge)
+                       break;
+#endif
+               case TYPE_flt:
+                       ANALYTICAL_LAST_IMP(flt)
+                       break;
+               case TYPE_dbl:
+                       ANALYTICAL_LAST_IMP(dbl)
+                       break;
+               default: {
+                       BATiter bpi = bat_iterator(b);
+                       void *restrict curval;
+                       nil = ATOMnilptr(tpe);
+                       atomcmp = ATOMcompare(tpe);
+                       if (p) {
+                               np = (bit*)Tloc(p, 0);
+                               for(i=0,j=0; i<cnt; i++, np++) {
+                                       if (*np) {
+                                               curval = BUNtail(bpi, i - 1);
+                                               if((*atomcmp)(curval, nil) == 0)
+                                                       has_nils = true;
+                                               for (;j < i; j++) {
+                                                       if ((gdk_res = 
BUNappend(r, curval, false)) != GDK_SUCCEED)
+                                                               goto finish;
+                                               }
+                                       }
+                               }
+                               curval = BUNtail(bpi, cnt - 1);
+                               if((*atomcmp)(curval, nil) == 0)
+                                       has_nils = true;
+                               for (;j < i; j++) {
+                                       if ((gdk_res = BUNappend(r, curval, 
false)) != GDK_SUCCEED)
+                                               goto finish;
+                               }
+                       } else { /* single value, ie no ordering */
+                               curval = BUNtail(bpi, cnt - 1);
+                               if((*atomcmp)(curval, nil) == 0)
+                                       has_nils = true;
+                               for(i=0; i<cnt; i++) {
+                                       if ((gdk_res = BUNappend(r, curval, 
false)) != GDK_SUCCEED)
+                                               goto finish;
+                               }
+                       }
+               }
+       }
+finish:
+       BATsetcount(r, cnt);
+       r->tnonil = !has_nils;
+       r->tnil = has_nils;
+       return gdk_res;
+}
+
+#undef ANALYTICAL_LAST_IMP
+
 #define ANALYTICAL_LIMIT_IMP(TPE, OP)                        \
        do {                                                     \
                TPE *rp, *rb, *restrict bp, *end, curval;            \
diff --git a/gdk/gdk_analytic.h b/gdk/gdk_analytic.h
--- a/gdk/gdk_analytic.h
+++ b/gdk/gdk_analytic.h
@@ -18,6 +18,8 @@
 
 gdk_export gdk_return GDKanalyticaldiff(BAT *r, BAT *b, BAT *c, int tpe);
 gdk_export gdk_return GDKanalyticalntile(BAT *r, BAT *b, BAT *p, BAT *o, int 
tpe, ptr ntile);
+gdk_export gdk_return GDKanalyticalfirst(BAT *r, BAT *b, BAT *p, BAT *o, int 
tpe);
+gdk_export gdk_return GDKanalyticallast(BAT *r, BAT *b, BAT *p, BAT *o, int 
tpe);
 gdk_export gdk_return GDKanalyticalmin(BAT *r, BAT *b, BAT *p, BAT *o, int 
tpe);
 gdk_export gdk_return GDKanalyticalmax(BAT *r, BAT *b, BAT *p, BAT *o, int 
tpe);
 gdk_export gdk_return GDKanalyticalcount(BAT *r, BAT *b, BAT *p, BAT *o, const 
bit *ignore_nils, int tpe);
diff --git a/sql/backends/monet5/sql_rank.c b/sql/backends/monet5/sql_rank.c
--- a/sql/backends/monet5/sql_rank.c
+++ b/sql/backends/monet5/sql_rank.c
@@ -620,6 +620,18 @@ SQLanalytical_func(Client cntxt, MalBlkP
 }
 
 str
+SQLfirst_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
+{
+       return SQLanalytical_func(cntxt, mb, stk, pci, "sql.first_value", 
SQLSTATE(42000) "first_value(:any_1,:bit,:bit)", GDKanalyticalfirst);
+}
+
+str
+SQLlast_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
+{
+       return SQLanalytical_func(cntxt, mb, stk, pci, "sql.last_value", 
SQLSTATE(42000) "last_value(:any_1,:bit,:bit)", GDKanalyticallast);
+}
+
+str
 SQLmin(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
 {
        return SQLanalytical_func(cntxt, mb, stk, pci, "sql.min", 
SQLSTATE(42000) "min(:any_1,:bit,:bit)", GDKanalyticalmin);
diff --git a/sql/backends/monet5/sql_rank.h b/sql/backends/monet5/sql_rank.h
--- a/sql/backends/monet5/sql_rank.h
+++ b/sql/backends/monet5/sql_rank.h
@@ -18,6 +18,8 @@ sql5_export str SQLdense_rank(Client cnt
 sql5_export str SQLpercent_rank(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci);
 sql5_export str SQLcume_dist(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci);
 sql5_export str SQLntile(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci);
+sql5_export str SQLfirst_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci);
+sql5_export str SQLlast_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci);
 sql5_export str SQLmin(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci);
 sql5_export str SQLmax(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci);
 sql5_export str SQLcount(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci);
diff --git a/sql/backends/monet5/sql_rank.mal b/sql/backends/monet5/sql_rank.mal
--- a/sql/backends/monet5/sql_rank.mal
+++ b/sql/backends/monet5/sql_rank.mal
@@ -64,6 +64,22 @@ pattern batsql.cume_dist(b:bat[:any_1], 
 address SQLcume_dist
 comment "return the accumulated distribution of the number of rows per group 
to the total number of partition rows";
 
+pattern sql.first_value(b:any_1, p:bit, o:bit, unit:int, s:int, e:int, 
excl:int) :any_1
+address SQLfirst_value
+comment "return the first value of groups";
+
+pattern batsql.first_value(b:bat[:any_1], p:any_2, o:any_3, unit:int, s:int, 
e:int, exl:int) :bat[:any_1]
+address SQLfirst_value
+comment "return the first value of groups";
+
+pattern sql.last_value(b:any_1, p:bit, o:bit, unit:int, s:int, e:int, 
excl:int) :any_1
+address SQLlast_value
+comment "return the last value of groups";
+
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to