- def __tuple2db_format_where(self, data):
- '''Compose the needed text for a SQL WHERE, parameter 'data' is a pair tuple (A,B),
- and it returns the text 'A="B"', where A is a field of a table and B is the value
- If B is None it returns the 'A is Null' text, without surrounding Null by quotes
- If B is not None it returns the text "A='B'" or 'A="B"' where B is surrounded by quotes,
- and it ensures internal quotes of B are escaped.
- '''
- if data[1]==None:
- return str(data[0]) + " is Null"
-
-# if type(data[1]) is tuple: #this can only happen in a WHERE_OR clause
-# text =[]
-# for d in data[1]:
-# if d==None:
-# text.append(str(data[0]) + " is Null")
-# continue
-# out=str(d)
-# if "'" not in out:
-# text.append( str(data[0]) + "='" + out + "'" )
-# elif '"' not in out:
-# text.append( str(data[0]) + '="' + out + '"' )
-# else:
-# text.append( str(data[0]) + '=' + json.dumps(out) )
-# return " OR ".join(text)
-
- out=str(data[1])
- return str(data[0]) + '=' + json.dumps(out)
-
- def __tuple2db_format_where_not(self, data):
- '''Compose the needed text for a SQL WHERE(not). parameter 'data' is a pair tuple (A,B),
- and it returns the text 'A<>"B"', where A is a field of a table and B is the value
- If B is None it returns the 'A is not Null' text, without surrounding Null by quotes
- If B is not None it returns the text "A<>'B'" or 'A<>"B"' where B is surrounded by quotes,
- and it ensures internal quotes of B are escaped.
- '''
- if data[1]==None:
- return str(data[0]) + " is not Null"
- out=str(data[1])
- return str(data[0]) + '<>' + json.dumps(out)
-
+ def __create_where(self, data, use_or=None):
+ """
+ Compose the needed text for a SQL WHERE, parameter 'data' can be a dict or a list of dict. By default lists are
+ concatenated with OR and dict with AND, unless parameter 'use_or' indicates other thing.
+ If a dict it will generate 'key1="value1" AND key2="value2" AND ...'.
+ If value is None, it will produce 'key is null'
+ If value is a list or tuple, it will produce 'key="value[0]" OR key="value[1]" OR ...'
+ keys can be suffixed by >,<,<>,>=,<=,' LIKE ' so that this is used to compare key and value instead of "="
+ The special keys "OR", "AND" with a dict value is used to create a nested WHERE
+ If a list, each item will be a dictionary that will be concatenated with OR by default
+ :param data: dict or list of dicts
+ :param use_or: Can be None (use default behaviour), True (use OR) or False (use AND)
+ :return: a string with the content to send to mysql
+ """
+ cmd = []
+ if isinstance(data, dict):
+ for k, v in data.items():
+ if k == "OR":
+ cmd.append("(" + self.__create_where(v, use_or=True) + ")")
+ continue
+ elif k == "AND":
+ cmd.append("(" + self.__create_where(v, use_or=False) + ")")
+ continue
+
+ if k.endswith(">") or k.endswith("<") or k.endswith("=") or k.endswith(" LIKE "):
+ pass
+ else:
+ k += "="
+
+ if v is None:
+ cmd.append(k.replace("=", " is").replace("<>", " is not") + " Null")
+ elif isinstance(v, (tuple, list)):
+ cmd2 = []
+ for v2 in v:
+ if v2 is None:
+ cmd2.append(k.replace("=", " is").replace("<>", " is not") + " Null")
+ else:
+ cmd2.append(k + json.dumps(str(v2)))
+ cmd.append("(" + " OR ".join(cmd2) + ")")
+ else:
+ cmd.append(k + json.dumps(str(v)))
+ elif isinstance(data, (tuple, list)):
+ if use_or is None:
+ use_or = True
+ for k in data:
+ cmd.append("(" + self.__create_where(k) + ")")
+ else:
+ raise db_base_Exception("invalid WHERE clause at '{}'".format(data))
+ if use_or:
+ return " OR ".join(cmd)
+ return " AND ".join(cmd)
+