No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

query.py 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #-*- coding: utf-8 -*-
  2. import re
  3. from .leobject import LeObject, LeApiErrors, LeApiDataCheckError
  4. from lodel.plugin.hooks import LodelHook
  5. class LeQueryError(Exception):
  6. pass
  7. class LeQuery(object):
  8. ##@brief Hookname preffix
  9. _hook_prefix = None
  10. ##@brief arguments for the LeObject.check_data_value()
  11. _data_check_args = { 'complete': False, 'allow_internal': False }
  12. ##@brief Abstract constructor
  13. # @param target_class LeObject : class of object the query is about
  14. def __init__(self, target_class):
  15. if hook_prefix is None:
  16. raise NotImplementedError("Asbtract class")
  17. if not issubclass(target_class, LeObject):
  18. raise TypeError("target class has to be a child class of LeObject")
  19. self.__target_class = target_class
  20. ##@brief Execute a query and return the result
  21. # @param **datas
  22. # @return the query result
  23. # @see LeQuery.__query()
  24. #
  25. # @note maybe the datasource in not an argument but should be determined
  26. #elsewhere
  27. def execute(self, datasource, **datas):
  28. if len(datas) > 0:
  29. self.__target_class.check_datas_value(datas, **self._data_check_args)
  30. self.__target_class.prepare_datas() #not yet implemented
  31. if self._hook_prefix is None:
  32. raise NotImplementedError("Abstract method")
  33. LodelHook.call_hook( self._hook_prefix+'_pre',
  34. self.__target_class,
  35. datas)
  36. ret = self.__query(datasource, **datas)
  37. ret = LodelHook.call_hook( self._hook_prefix+'_post',
  38. self.__target_class,
  39. ret)
  40. return ret
  41. ##@brief Childs classes implements this method to execute the query
  42. # @param **datas
  43. # @return query result
  44. def __query(self, **datas):
  45. raise NotImplementedError("Asbtract method")
  46. class LeFilteredQuery(LeQuery):
  47. ##@brief The available operators used in query definitions
  48. query_operators = [
  49. '=',
  50. '<=',
  51. '>=',
  52. '!=',
  53. '<',
  54. '>',
  55. ' in ',
  56. ' not in ',
  57. ' like ',
  58. ' not like ']
  59. ##@brief Abtract constructor for queries with filter
  60. # @param target_class LeObject : class of object the query is about
  61. # @param query_filters list : list of string of query filters (or tuple
  62. #(FIELD, OPERATOR, VALUE) )
  63. def __init__(self, target_class, query_filter):
  64. super().__init__(target_class)
  65. ##@brief The query filter
  66. self.__query_filter = None
  67. self.set_qeury_filter(query_filter)
  68. ##@brief Set the query filter for a query
  69. def set_query_filter(self, query_filter):
  70. #
  71. # Query filter check & prepare should be done here
  72. #
  73. self.__query_filter = query_filter
  74. ##@brief A query for insert a new object
  75. class LeInsertQuery(LeQuery):
  76. _hook_prefix = 'leapi_insert_'
  77. _data_check_args = { 'complete': True, 'allow_internal': False }
  78. def __init__(self, target_class):
  79. super().__init__(target_class)
  80. ## @brief Implements an insert query operations
  81. # @param **datas : datas to be inserted
  82. def __query(self, datasource, **datas):
  83. pass
  84. ##@brief A query to update datas for a given object
  85. class LeUpdateQuery(LeFilteredQuery):
  86. _hook_prefix = 'leapi_update_'
  87. _data_check_args = { 'complete': True, 'allow_internal': False }
  88. def __init__(self, target_class, query_filter):
  89. super().__init__(target_class, query_filter)
  90. ##@brief Implements an update query
  91. # @param **datas : datas to update
  92. def __query(self, datasource, **datas):
  93. pass
  94. ##@brief A query to delete an object
  95. class LeDeleteQuery(LeFilteredQuery):
  96. _hook_prefix = 'leapi_delete_'
  97. def __init__(self, target_class, query_filter):
  98. super().__init__(target_class, query_filter)
  99. ## @brief Execute the delete query
  100. def execute(self, datasource):
  101. super().execute()
  102. ##@brief Implements delete query operations
  103. def __query(self, datasource):
  104. pass
  105. class LeGetQuery(LeFilteredQuery):
  106. _hook_prefix = 'leapi_get_'
  107. ##@brief Instanciate a new get query
  108. # @param target_class LeObject : class of object the query is about
  109. # @param query_filters list : list of string of query filters (or tuple
  110. #(FIELD, OPERATOR, VALUE) )
  111. # @param field_list list|None : list of string representing fields see @ref leobject_filters
  112. # @param order list : A list of field names or tuple (FIELDNAME, [ASC | DESC])
  113. # @param group list : A list of field names or tuple (FIELDNAME, [ASC | DESC])
  114. # @param limit int : The maximum number of returned results
  115. # @param offset int : offset
  116. def __init__(self, target_class, query_filter, **kwargs):
  117. super().__init__(target_class, query_filter)
  118. ##@brief The fields to get
  119. self.__field_list = None
  120. ##@brief An equivalent to the SQL ORDER BY
  121. self.__order = None
  122. ##@brief An equivalent to the SQL GROUP BY
  123. self.__group = None
  124. ##@brief An equivalent to the SQL LIMIT x
  125. self.__limit = None
  126. ##@brief An equivalent to the SQL LIMIT x, OFFSET
  127. self.__offset = 0
  128. # Checking kwargs and assigning default values if there is some
  129. for argname in kwargs:
  130. if argname not in ('order', 'group', 'limit', 'offset'):
  131. raise TypeError("Unexpected argument '%s'" % argname)
  132. if 'field_list' not in kwargs:
  133. #field_list = target_class.get_field_list
  134. pass
  135. else:
  136. #target_class.check_fields(kwargs['field_list'])
  137. field_list = kwargs['field_list']
  138. if 'order' in kwargs:
  139. #check kwargs['order']
  140. self.__order = kwargs['order']
  141. if 'group' in kwargs:
  142. #check kwargs['group']
  143. self.__group = kwargs['group']
  144. if 'limit' in kwargs:
  145. try:
  146. self.__limit = int(kwargs[limit])
  147. if self.__limit <= 0:
  148. raise ValueError()
  149. except ValueError:
  150. raise ValueError("limit argument expected to be an interger > 0")
  151. if 'offset' in kwargs:
  152. try:
  153. self.__offset = int(kwargs['offset'])
  154. if self.__offset < 0:
  155. raise ValueError()
  156. except ValueError:
  157. raise ValueError("offset argument expected to be an integer >= 0")
  158. ##@brief Execute the get query
  159. def execute(self, datasource):
  160. super().execute(datasource)