paul@1078 | 1 | #!/usr/bin/env python |
paul@1078 | 2 | |
paul@1078 | 3 | """ |
paul@1078 | 4 | Database utilities. |
paul@1078 | 5 | |
paul@1078 | 6 | Copyright (C) 2016 Paul Boddie <paul@boddie.org.uk> |
paul@1078 | 7 | |
paul@1078 | 8 | This program is free software; you can redistribute it and/or modify it under |
paul@1078 | 9 | the terms of the GNU General Public License as published by the Free Software |
paul@1078 | 10 | Foundation; either version 3 of the License, or (at your option) any later |
paul@1078 | 11 | version. |
paul@1078 | 12 | |
paul@1078 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT |
paul@1078 | 14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
paul@1078 | 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
paul@1078 | 16 | details. |
paul@1078 | 17 | |
paul@1078 | 18 | You should have received a copy of the GNU General Public License along with |
paul@1078 | 19 | this program. If not, see <http://www.gnu.org/licenses/>. |
paul@1078 | 20 | """ |
paul@1078 | 21 | |
paul@1078 | 22 | import re |
paul@1078 | 23 | |
paul@1078 | 24 | class DatabaseOperations: |
paul@1078 | 25 | |
paul@1078 | 26 | "Special database-related operations." |
paul@1078 | 27 | |
paul@1078 | 28 | def __init__(self, column_names=None, filter_values=None): |
paul@1078 | 29 | self.column_names = column_names |
paul@1078 | 30 | self.filter_values = filter_values |
paul@1078 | 31 | |
paul@1078 | 32 | def get_query(self, query, columns=None, values=None): |
paul@1078 | 33 | |
paul@1078 | 34 | """ |
paul@1078 | 35 | Return 'query' parameterised with condition clauses indicated by |
paul@1078 | 36 | ":condition" in 'query' that are themselves populated using the given |
paul@1078 | 37 | 'columns' and 'values' together with any conditions provided when |
paul@1078 | 38 | initialising this class. |
paul@1078 | 39 | """ |
paul@1078 | 40 | |
paul@1078 | 41 | columns = self.merge_default_columns(columns) |
paul@1078 | 42 | values = self.merge_default_values(values) |
paul@1078 | 43 | |
paul@1078 | 44 | condition = self.get_condition(columns) |
paul@1078 | 45 | |
paul@1078 | 46 | # Replace ":condition", replicating the values the appropriate number of |
paul@1078 | 47 | # times. |
paul@1078 | 48 | |
paul@1078 | 49 | query, count = re.subn(":condition(?=[^a-zA-Z]|$)", condition, query) |
paul@1078 | 50 | all_values = values * count |
paul@1078 | 51 | |
paul@1078 | 52 | # Replace ":columns" and ":values", replicating the values again. |
paul@1078 | 53 | |
paul@1078 | 54 | columnlist = self.columnlist(columns) |
paul@1078 | 55 | placeholders = self.placeholders(values) |
paul@1078 | 56 | |
paul@1078 | 57 | query, _count = re.subn(":columns(?=[^a-zA-Z]|$)", columnlist, query) |
paul@1078 | 58 | query, count = re.subn(":values(?=[^a-zA-Z]|$)", placeholders, query) |
paul@1078 | 59 | all_values += values * count |
paul@1078 | 60 | |
paul@1078 | 61 | return query, all_values |
paul@1078 | 62 | |
paul@1078 | 63 | def get_condition(self, columns=None): |
paul@1078 | 64 | |
paul@1078 | 65 | "Return a condition clause featuring the given 'columns'." |
paul@1078 | 66 | |
paul@1078 | 67 | l = [] |
paul@1078 | 68 | for column in columns: |
paul@1078 | 69 | if " " in column: |
paul@1078 | 70 | l.append(column) |
paul@1078 | 71 | else: |
paul@1078 | 72 | l.append("%s = ?" % column) |
paul@1078 | 73 | |
paul@1078 | 74 | return "where %s" % " and ".join(l) |
paul@1078 | 75 | |
paul@1078 | 76 | def merge_default_columns(self, columns=None): |
paul@1078 | 77 | return list(self.column_names or []) + list(columns or []) |
paul@1078 | 78 | |
paul@1078 | 79 | def merge_default_values(self, values=None): |
paul@1078 | 80 | return list(self.filter_values or []) + list(values or []) |
paul@1078 | 81 | |
paul@1078 | 82 | def columnlist(self, columns=None): |
paul@1078 | 83 | return ", ".join(columns) |
paul@1078 | 84 | |
paul@1078 | 85 | def placeholders(self, values=None): |
paul@1078 | 86 | return ", ".join(["?"] * len(values)) |
paul@1078 | 87 | |
paul@1078 | 88 | # vim: tabstop=4 expandtab shiftwidth=4 |