LCOV - code coverage report
Current view: top level - sql/storage - store_sequence.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 144 166 86.7 %
Date: 2021-10-13 02:24:04 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "monetdb_config.h"
      10             : #include "store_sequence.h"
      11             : #include "sql_storage.h"
      12             : 
      13             : typedef struct store_sequence {
      14             :         sqlid seqid;
      15             :         bit called;
      16             :         lng cur;
      17             :         lng cached;
      18             : } store_sequence;
      19             : 
      20             : static list *sql_seqs = NULL;
      21             : 
      22             : static void
      23         179 : sequence_destroy( void *dummy, store_sequence *s )
      24             : {
      25             :         (void)dummy;
      26         179 :         _DELETE(s);
      27         179 : }
      28             : 
      29             : void*
      30         265 : sequences_init(void)
      31             : {
      32         265 :         sql_seqs = list_create( (fdestroy)sequence_destroy );
      33         265 :         return (void*) sql_seqs;
      34             : }
      35             : 
      36             : void
      37         264 : sequences_exit(void)
      38             : {
      39         264 :         if(sql_seqs) {
      40         264 :                 list_destroy(sql_seqs);
      41         264 :                 sql_seqs = NULL;
      42             :         }
      43         264 : }
      44             : 
      45             : /* lock is held */
      46             : static void
      47             : sql_update_sequence_cache(sqlstore *store, sql_sequence *seq, lng cached)
      48             : {
      49          42 :         store->logger_api.log_sequence(store, seq->base.id, cached);
      50          84 : }
      51             : 
      52             : /* lock is held */
      53             : static store_sequence *
      54         179 : sql_create_sequence(sqlstore *store, sql_sequence *seq )
      55             : {
      56         179 :         lng id = 0;
      57             :         store_sequence *s = NULL;
      58         179 :         s = MNEW(store_sequence);
      59         179 :         if(!s)
      60             :                 return NULL;
      61             : 
      62         179 :         *s = (store_sequence) {
      63         179 :                 .seqid = seq->base.id,
      64         179 :                 .cur = seq->start,
      65             :                 .cached = seq->start,
      66             :         };
      67             : 
      68         179 :         if (!isNew(seq) && store->logger_api.get_sequence(store, seq->base.id, &id ))
      69          18 :                 s->cached = id;
      70         179 :         s -> cur = s->cached;
      71         179 :         return s;
      72             : }
      73             : 
      74             : int
      75          40 : seq_restart(sql_store store, sql_sequence *seq, lng start)
      76             : {
      77             :         node *n = NULL;
      78             :         store_sequence *s;
      79             : 
      80          40 :         assert(!is_lng_nil(start));
      81          40 :         store_lock(store);
      82         422 :         for ( n = sql_seqs->h; n; n = n ->next ) {
      83         389 :                 s = n->data;
      84         389 :                 if (s->seqid == seq->base.id)
      85             :                         break;
      86             :         }
      87          40 :         if (!n) {
      88          33 :                 s = sql_create_sequence(store, seq);
      89          33 :                 if (!s) {
      90           0 :                         store_unlock(store);
      91           0 :                         return 0;
      92             :                 }
      93          33 :                 list_append(sql_seqs, s);
      94             :         } else {
      95           7 :                 s = n->data;
      96             :         }
      97          40 :         s->called = 0;
      98          40 :         s->cur = start;
      99          40 :         s->cached = start;
     100             :         /* handle min/max and cycle */
     101          40 :         if ((seq->maxvalue && s->cur > seq->maxvalue) ||
     102          40 :             (seq->minvalue && s->cur < seq->minvalue))
     103             :         {
     104             :                 /* we're out of numbers */
     105           0 :                 store_unlock(store);
     106           0 :                 return 0;
     107             :         }
     108             :         sql_update_sequence_cache(store, seq, s->cached);
     109          40 :         store_unlock(store);
     110          40 :         return 1;
     111             : }
     112             : 
     113             : int
     114         906 : seq_next_value(sql_store store, sql_sequence *seq, lng *val)
     115             : {
     116             :         lng nr = 0;
     117             :         node *n = NULL;
     118             :         store_sequence *s;
     119             :         int save = 0;
     120             : 
     121         906 :         *val = 0;
     122         906 :         store_lock(store);
     123        5661 :         for ( n = sql_seqs->h; n; n = n ->next ) {
     124        5571 :                 s = n->data;
     125        5571 :                 if (s->seqid == seq->base.id)
     126             :                         break;
     127             :         }
     128         906 :         if (!n) {
     129          90 :                 s = sql_create_sequence(store, seq);
     130          90 :                 if (!s) {
     131           0 :                         store_unlock(store);
     132           0 :                         return 0;
     133             :                 }
     134          90 :                 list_append(sql_seqs, s);
     135             :         } else {
     136         816 :                 s = n->data;
     137         816 :                 if (s->called)
     138         799 :                         s->cur += seq->increment;
     139             :         }
     140             :         /* handle min/max and cycle */
     141         906 :         if ((seq->maxvalue && s->cur > seq->maxvalue) ||
     142         903 :             (seq->minvalue && s->cur < seq->minvalue))
     143             :         {
     144           4 :                 if (seq->cycle) {
     145             :                         /* cycle to the min value again */
     146           3 :                         s->cur = seq->minvalue;
     147             :                         save = 1;
     148             :                 } else { /* we're out of numbers */
     149           1 :                         store_unlock(store);
     150           1 :                         return 0;
     151             :                 }
     152             :         }
     153         905 :         s->called = 1;
     154         905 :         nr = s->cur;
     155         905 :         *val = nr;
     156         905 :         if (save || nr == s->cached) {
     157         902 :                 s->cached = nr + seq->cacheinc*seq->increment;
     158             :                 sql_update_sequence_cache(store, seq, s->cached);
     159         902 :                 store_unlock(store);
     160         902 :                 return 1;
     161             :         }
     162           3 :         assert(nr<s->cached);
     163           3 :         store_unlock(store);
     164           3 :         return 1;
     165             : }
     166             : 
     167             : seqbulk *
     168         135 : seqbulk_create(sql_store store, sql_sequence *seq, BUN cnt)
     169             : {
     170         135 :         seqbulk *sb = MNEW(seqbulk);
     171             :         store_sequence *s;
     172             :         node *n = NULL;
     173             : 
     174         135 :         if (!sb)
     175             :                 return NULL;
     176             : 
     177         135 :         store_lock(store);
     178         135 :         *sb = (seqbulk) {
     179             :                 .seq = seq,
     180             :                 .cnt = cnt,
     181             :         };
     182             : 
     183         457 :         for ( n = sql_seqs->h; n; n = n ->next ) {
     184         406 :                 s = n->data;
     185         406 :                 if (s->seqid == seq->base.id)
     186             :                         break;
     187             :         }
     188         135 :         if (!n) {
     189          51 :                 s = sql_create_sequence(store, seq);
     190          51 :                 if (!s) {
     191           0 :                         _DELETE(sb);
     192           0 :                         store_unlock(store);
     193           0 :                         return NULL;
     194             :                 }
     195          51 :                 list_append(sql_seqs, s);
     196             :         } else {
     197          84 :                 s = n->data;
     198             :         }
     199         135 :         sb->internal_seq = s;
     200         135 :         return sb;
     201             : }
     202             : 
     203             : void
     204         135 : seqbulk_destroy(sql_store store, seqbulk *sb)
     205             : {
     206         135 :         if (sb->save) {
     207          84 :                 sql_sequence *seq = sb->seq;
     208          84 :                 store_sequence *s = sb->internal_seq;
     209             : 
     210          84 :                 sql_update_sequence_cache(store, seq, s->cached);
     211             :         }
     212         135 :         _DELETE(sb);
     213         135 :         store_unlock(store);
     214         135 : }
     215             : 
     216             : int
     217       29230 : seqbulk_next_value(seqbulk *sb, lng *val)
     218             : {
     219             :         lng nr = 0;
     220       29230 :         store_sequence *s = sb->internal_seq;
     221       29230 :         sql_sequence *seq = sb->seq;
     222             : 
     223       29230 :         if (s->called)
     224       29208 :                 s->cur += seq->increment;
     225             : 
     226             :         /* handle min/max and cycle */
     227       29230 :         if ((seq->maxvalue && s->cur > seq->maxvalue) ||
     228       29230 :             (seq->minvalue && s->cur < seq->minvalue))
     229             :         {
     230           0 :                 if (seq->cycle) {
     231             :                         /* cycle to the min value again */
     232           0 :                         s->cur = seq->minvalue;
     233           0 :                         sb->save = 1;
     234             :                 } else { /* we're out of numbers */
     235             :                         return 0;
     236             :                 }
     237             :         }
     238       29230 :         s->called = 1;
     239       29230 :         nr = s->cur;
     240       29230 :         *val = nr;
     241       29230 :         if (nr == s->cached) {
     242       29230 :                 s->cached = nr + seq->cacheinc*seq->increment;
     243       29230 :                 sb->save = 1;
     244       29230 :                 return 1;
     245             :         }
     246           0 :         assert(nr<s->cached);
     247             :         return 1;
     248             : }
     249             : 
     250             : int
     251          22 : seq_get_value(sql_store store, sql_sequence *seq, lng *val)
     252             : {
     253             :         node *n = NULL;
     254             :         store_sequence *s;
     255             : 
     256          22 :         *val = 0;
     257          22 :         store_lock(store);
     258         121 :         for ( n = sql_seqs->h; n; n = n ->next ) {
     259         116 :                 s = n->data;
     260         116 :                 if (s->seqid == seq->base.id)
     261             :                         break;
     262             :         }
     263          22 :         if (!n) {
     264           5 :                 s = sql_create_sequence(store, seq);
     265           5 :                 if (!s) {
     266           0 :                         store_unlock(store);
     267           0 :                         return 0;
     268             :                 }
     269           5 :                 list_append(sql_seqs, s);
     270             :         } else {
     271          17 :                 s = n->data;
     272             :         }
     273          22 :         *val = s->cur;
     274          22 :         if (s->called)
     275          12 :                 *val += seq->increment;
     276             :         /* handle min/max and cycle */
     277          22 :         if ((seq->maxvalue && *val > seq->maxvalue) ||
     278          22 :             (seq->minvalue && *val < seq->minvalue))
     279             :         {
     280           0 :                 if (seq->cycle) {
     281             :                         /* cycle to the min value again */
     282           0 :                         *val = seq->minvalue;
     283             :                 } else { /* we're out of numbers */
     284           0 :                         store_unlock(store);
     285           0 :                         return 0;
     286             :                 }
     287             :         }
     288          22 :         store_unlock(store);
     289          22 :         return 1;
     290             : }
     291             : 
     292             : int
     293          50 : seqbulk_get_value(seqbulk *sb, lng *val)
     294             : {
     295          50 :         store_sequence *s = sb->internal_seq;
     296          50 :         sql_sequence *seq = sb->seq;
     297             : 
     298          50 :         *val = s->cur;
     299          50 :         if (s->called)
     300           9 :                 *val += seq->increment;
     301             :         /* handle min/max and cycle */
     302          50 :         if ((seq->maxvalue && s->cur > seq->maxvalue) ||
     303          50 :             (seq->minvalue && s->cur < seq->minvalue))
     304             :         {
     305           0 :                 if (seq->cycle) {
     306             :                         /* cycle to the min value again */
     307           0 :                         s->cur = seq->minvalue;
     308           0 :                         sb->save = 1;
     309             :                 } else { /* we're out of numbers */
     310             :                         return 0;
     311             :                 }
     312             :         }
     313             :         return 1;
     314             : }
     315             : 
     316             : int
     317           2 : seqbulk_restart(sql_store store, seqbulk *sb, lng start)
     318             : {
     319           2 :         store_sequence *s = sb->internal_seq;
     320           2 :         sql_sequence *seq = sb->seq;
     321             : 
     322           2 :         assert(!is_lng_nil(start));
     323           2 :         s->called = 0;
     324           2 :         s->cur = start;
     325           2 :         s->cached = start;
     326             :         /* handle min/max and cycle */
     327           2 :         if ((seq->maxvalue && s->cur > seq->maxvalue) ||
     328           2 :             (seq->minvalue && s->cur < seq->minvalue))
     329             :         {
     330             :                 return 0;
     331             :         }
     332             :         sql_update_sequence_cache(store, seq, s->cached);
     333           2 :         return 1;
     334             : }

Generated by: LCOV version 1.14