LCOV - code coverage report
Current view: top level - gdk - gdk_cross.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 108 121 89.3 %
Date: 2024-10-07 21:21:43 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "gdk.h"
      15             : #include "gdk_private.h"
      16             : 
      17             : /* Calculate a cross product between bats l and r with optional
      18             :  * candidate lists sl for l and sr for r.
      19             :  * The result is two bats r1 and r2 which contain the OID (head
      20             :  * values) of the input bats l and r.
      21             :  * If max_one is set, r can have at most one row. */
      22             : static gdk_return
      23       45344 : BATcrossci(BAT **r1p, BAT **r2p, struct canditer *ci1, struct canditer *ci2)
      24             : {
      25       45344 :         BAT *bn1, *bn2 = NULL;
      26       45344 :         oid *restrict p;
      27       45344 :         BUN i, j;
      28             : 
      29       45344 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
      30             : 
      31             :         /* first some special cases */
      32       45346 :         if (ci1->ncand == 0 || ci2->ncand == 0) {
      33       24211 :                 if ((bn1 = BATdense(0, 0, 0)) == NULL)
      34             :                         return GDK_FAIL;
      35       23995 :                 if (r2p) {
      36       23381 :                         if ((bn2 = BATdense(0, 0, 0)) == NULL) {
      37           0 :                                 BBPreclaim(bn1);
      38           0 :                                 return GDK_FAIL;
      39             :                         }
      40       23410 :                         *r2p = bn2;
      41             :                 }
      42       24024 :                 *r1p = bn1;
      43       24024 :                 return GDK_SUCCEED;
      44             :         }
      45       21135 :         if (ci2->ncand == 1) {
      46       14273 :                 if ((bn1 = canditer_slice(ci1, 0, ci1->ncand)) == NULL)
      47             :                         return GDK_FAIL;
      48       13985 :                 if (r2p) {
      49       13533 :                         if (ci1->ncand == 1) {
      50        4422 :                                 bn2 = canditer_slice(ci2, 0, ci2->ncand);
      51             :                         } else {
      52        9111 :                                 bn2 = BATconstant(0, TYPE_oid, &ci2->seq, ci1->ncand, TRANSIENT);
      53             :                         }
      54       13508 :                         if (bn2 == NULL) {
      55           0 :                                 BBPreclaim(bn1);
      56           0 :                                 return GDK_FAIL;
      57             :                         }
      58       13508 :                         *r2p = bn2;
      59             :                 }
      60       13960 :                 *r1p = bn1;
      61       13960 :                 return GDK_SUCCEED;
      62             :         }
      63        6862 :         if (ci1->ncand == 1) {
      64        2099 :                 bn1 = BATconstant(0, TYPE_oid, &ci1->seq, ci2->ncand, TRANSIENT);
      65        2085 :                 if (bn1 == NULL)
      66             :                         return GDK_FAIL;
      67        2085 :                 if (r2p) {
      68        1894 :                         bn2 = canditer_slice(ci2, 0, ci2->ncand);
      69        1886 :                         if (bn2 == NULL) {
      70           0 :                                 BBPreclaim(bn1);
      71           0 :                                 return GDK_FAIL;
      72             :                         }
      73        1886 :                         *r2p = bn2;
      74             :                 }
      75        2077 :                 *r1p = bn1;
      76        2077 :                 return GDK_SUCCEED;
      77             :         }
      78             : 
      79        4763 :         bn1 = COLnew(0, TYPE_oid, ci1->ncand * ci2->ncand, TRANSIENT);
      80        4756 :         if (r2p)
      81        4513 :                 bn2 = COLnew(0, TYPE_oid, ci1->ncand * ci2->ncand, TRANSIENT);
      82        4754 :         if (bn1 == NULL || (r2p && bn2 == NULL)) {
      83           0 :                 BBPreclaim(bn1);
      84           0 :                 BBPreclaim(bn2);
      85           0 :                 return GDK_FAIL;
      86             :         }
      87        4754 :         if (ci1->ncand > 0 && ci2->ncand > 0) {
      88        4754 :                 BATsetcount(bn1, ci1->ncand * ci2->ncand);
      89        4761 :                 bn1->tsorted = true;
      90        4761 :                 bn1->trevsorted = ci1->ncand <= 1;
      91        4761 :                 bn1->tkey = ci2->ncand <= 1;
      92        4761 :                 bn1->tnil = false;
      93        4761 :                 bn1->tnonil = true;
      94        4761 :                 p = (oid *) Tloc(bn1, 0);
      95      258539 :                 for (i = 0; i < ci1->ncand; i++) {
      96      253797 :                         GDK_CHECK_TIMEOUT_BODY(qry_ctx, GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
      97      254031 :                         oid x = canditer_next(ci1);
      98     8712440 :                         for (j = 0; j < ci2->ncand; j++) {
      99     8204631 :                                 *p++ = x;
     100             :                         }
     101             :                 }
     102        4742 :                 BATtseqbase(bn1, ci2->ncand == 1 ? *(oid *) Tloc(bn1, 0) : oid_nil);
     103             : 
     104        4723 :                 if (bn2) {
     105        4495 :                         BATsetcount(bn2, ci1->ncand * ci2->ncand);
     106        4498 :                         bn2->tsorted = ci1->ncand <= 1 || ci2->ncand <= 1;
     107        4498 :                         bn2->trevsorted = ci2->ncand <= 1;
     108        4498 :                         bn2->tkey = ci1->ncand <= 1;
     109        4498 :                         bn2->tnil = false;
     110        4498 :                         bn2->tnonil = true;
     111        4498 :                         p = (oid *) Tloc(bn2, 0);
     112      222492 :                         for (i = 0; i < ci1->ncand; i++) {
     113      217986 :                                 GDK_CHECK_TIMEOUT_BODY(qry_ctx, GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
     114     2186126 :                                 for (j = 0; j < ci2->ncand; j++) {
     115     1968011 :                                         *p++ = canditer_next(ci2);
     116             :                                 }
     117      218115 :                                 canditer_reset(ci2);
     118             :                         }
     119        4506 :                         BATtseqbase(bn2, ci1->ncand == 1 ? *(oid *) Tloc(bn2, 0) : oid_nil);
     120             :                 }
     121             :         }
     122        4731 :         *r1p = bn1;
     123        4731 :         if (r2p)
     124        4503 :                 *r2p = bn2;
     125        4731 :         if (r2p)
     126        4503 :                 TRC_DEBUG(ALGO, "BATsubcross()=(" ALGOBATFMT "," ALGOBATFMT ")\n", ALGOBATPAR(bn1), ALGOBATPAR(bn2));
     127             :         else
     128         228 :                 TRC_DEBUG(ALGO, "BATsubcross()=(" ALGOBATFMT ")\n", ALGOBATPAR(bn1));
     129             :         return GDK_SUCCEED;
     130             : 
     131           8 :   bailout:
     132           8 :         BBPreclaim(bn1);
     133           8 :         BBPreclaim(bn2);
     134             :         return GDK_FAIL;
     135             : }
     136             : 
     137             : gdk_return
     138       45082 : BATsubcross(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, bool max_one)
     139             : {
     140       45082 :         struct canditer ci1, ci2;
     141             : 
     142       45082 :         canditer_init(&ci1, l, sl);
     143       45061 :         canditer_init(&ci2, r, sr);
     144       45094 :         if (max_one && ci1.ncand > 0 && ci2.ncand > 1) {
     145          54 :                 GDKerror("more than one match");
     146          54 :                 return GDK_FAIL;
     147             :         }
     148       45040 :         return BATcrossci(r1p, r2p, &ci1, &ci2);
     149             : }
     150             : 
     151             : /* [left] outer cross */
     152             : gdk_return
     153         366 : BAToutercross(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, bool max_one)
     154             : {
     155         366 :         struct canditer ci1, ci2;
     156             : 
     157         366 :         canditer_init(&ci1, l, sl);
     158         366 :         canditer_init(&ci2, r, sr);
     159         366 :         if (max_one && ci1.ncand > 0 && ci2.ncand > 1) {
     160           0 :                 GDKerror("more than one match");
     161           0 :                 return GDK_FAIL;
     162             :         }
     163             : 
     164         366 :         if (ci1.ncand == 0) {
     165          30 :                 BAT *bn = COLnew(0, TYPE_void, 0, TRANSIENT);
     166          30 :                 if (bn == NULL)
     167             :                         return GDK_FAIL;
     168          30 :                 BATtseqbase(bn, oid_nil);
     169          30 :                 *r1p = bn;
     170          30 :                 if (r2p) {
     171          30 :                         bn = COLnew(0, TYPE_void, 0, TRANSIENT);
     172          30 :                         if (bn == NULL) {
     173           0 :                                 BBPreclaim(*r1p);
     174           0 :                                 return GDK_FAIL;
     175             :                         }
     176          30 :                         BATtseqbase(bn, oid_nil);
     177          30 :                         *r2p = bn;
     178             :                 }
     179          30 :                 return GDK_SUCCEED;
     180             :         }
     181         336 :         if (ci2.ncand == 0) {
     182          18 :                 BAT *bn = canditer_slice(&ci1, 0, ci1.ncand);
     183          18 :                 if (bn == NULL)
     184             :                         return GDK_FAIL;
     185          18 :                 *r1p = bn;
     186          18 :                 if (r2p) {
     187          18 :                         BAT *bn = COLnew(0, TYPE_void, ci1.ncand, TRANSIENT);
     188          18 :                         if (bn == NULL)
     189             :                                 return GDK_FAIL;
     190          18 :                         BATtseqbase(bn, oid_nil);
     191          18 :                         BATsetcount(bn, ci1.ncand);
     192          18 :                         *r2p = bn;
     193             :                 }
     194          18 :                 return GDK_SUCCEED;
     195             :         }
     196         318 :         return BATcrossci(r1p, r2p, &ci1, &ci2);
     197             : }

Generated by: LCOV version 1.14