Coverage for oc_ocdm/counter_handler/sqlite_counter_handler.py: 86%

35 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2025-05-30 22:05 +0000

1#!/usr/bin/python 

2# -*- coding: utf-8 -*- 

3# Copyright (c) 2023, Arcangelo Massari <arcangelo.massari@unibo.it> 

4# 

5# Permission to use, copy, modify, and/or distribute this software for any purpose 

6# with or without fee is hereby granted, provided that the above copyright notice 

7# and this permission notice appear in all copies. 

8# 

9# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 

10# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 

11# FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, 

12# OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 

13# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 

14# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 

15# SOFTWARE. 

16 

17import sqlite3 

18 

19from oc_ocdm.counter_handler.counter_handler import CounterHandler 

20 

21 

22class SqliteCounterHandler(CounterHandler): 

23 """A concrete implementation of the ``CounterHandler`` interface that persistently stores 

24 the counter values within a SQLite database.""" 

25 

26 def __init__(self, database: str) -> None: 

27 """ 

28 Constructor of the ``SqliteCounterHandler`` class. 

29 

30 :param database: The name of the database 

31 :type info_dir: str 

32 """ 

33 sqlite3.threadsafety = 3 

34 self.con = sqlite3.connect(database) 

35 self.cur = self.con.cursor() 

36 self.cur.execute("""CREATE TABLE IF NOT EXISTS info( 

37 entity TEXT PRIMARY KEY,  

38 count INTEGER)""") 

39 

40 def set_counter(self, new_value: int, entity_name: str) -> None: 

41 """ 

42 It allows to set the counter value of provenance entities. 

43 

44 :param new_value: The new counter value to be set 

45 :type new_value: int 

46 :param entity_name: The entity name 

47 :type entity_name: str 

48 :raises ValueError: if ``new_value`` is a negative integer. 

49 :return: None 

50 """ 

51 entity_name = str(entity_name) 

52 if new_value < 0: 

53 raise ValueError("new_value must be a non negative integer!") 

54 self.cur.execute(f"INSERT OR REPLACE INTO info (entity, count) VALUES ('{entity_name}', {new_value})") 

55 self.con.commit() 

56 

57 def read_counter(self, entity_name: str) -> int: 

58 """ 

59 It allows to read the counter value of provenance entities. 

60 

61 :param entity_name: The entity name 

62 :type entity_name: str 

63 :return: The requested counter value. 

64 """ 

65 entity_name = str(entity_name) 

66 result = self.cur.execute(f"SELECT count FROM info WHERE entity='{entity_name}'") 

67 rows = result.fetchall() 

68 if len(rows) == 1: 

69 return rows[0][0] 

70 elif len(rows) == 0: 

71 return 0 

72 else: 

73 raise(Exception("There is more than one counter for this entity. The databse id broken")) 

74 

75 def increment_counter(self, entity_name: str) -> int: 

76 """ 

77 It allows to increment the counter value of graph and provenance entities by one unit. 

78 

79 :param entity_name: The entity name 

80 :type entity_name: str 

81 :return: The newly-updated (already incremented) counter value. 

82 """ 

83 entity_name = str(entity_name) 

84 cur_count = self.read_counter(entity_name) 

85 count = cur_count + 1 

86 self.set_counter(count, entity_name) 

87 return count 

88 

89 def increment_metadata_counter(self): 

90 pass 

91 

92 def read_metadata_counter(self): 

93 pass 

94 

95 def set_metadata_counter(self): 

96 pass