diff --git a/orator/query/builder.py b/orator/query/builder.py index 6e8aaa6c..c4ea1579 100644 --- a/orator/query/builder.py +++ b/orator/query/builder.py @@ -1340,6 +1340,84 @@ def aggregate(self, func, *columns): if len(results) > 0: return dict((k.lower(), v) for k, v in results[0].items())["aggregate"] + def insert_ignore(self, _values=None, **values): + """ + Insert a new record into the database, use "INSERT IGNORE INTO", insert failure is only a warning, + if the batch insert other statements can be executed successfully + + :param _values: The new record values + :type _values: dict or list + + :param values: The new record values as keyword arguments + :type values: dict + + :return: The result + :rtype: bool + """ + if not values and not _values: + return True + + if not isinstance(_values, list): + if _values is not None: + values.update(_values) + + values = [values] + else: + values = _values + for i, value in enumerate(values): + values[i] = OrderedDict(sorted(value.items())) + + bindings = [] + + for record in values: + for value in record.values(): + bindings.append(value) + + sql = self._grammar.compile_insert(self, values, insert_type='INSERT_IGNORE') + + bindings = self._clean_bindings(bindings) + + return self._connection.insert(sql, bindings) + + def insert_replace(self, _values=None, **values): + """ + Insert a new record into the database, use "REPLACE INTO", if this data exists (primary key or unique index), + the old record is deleted and a new record is inserted to replace it + + :param _values: The new record values + :type _values: dict or list + + :param values: The new record values as keyword arguments + :type values: dict + + :return: The result + :rtype: bool + """ + if not values and not _values: + return True + + if not isinstance(_values, list): + if _values is not None: + values.update(_values) + + values = [values] + else: + values = _values + for i, value in enumerate(values): + values[i] = OrderedDict(sorted(value.items())) + + bindings = [] + + for record in values: + for value in record.values(): + bindings.append(value) + + sql = self._grammar.compile_insert(self, values, insert_type='REPLACE') + + bindings = self._clean_bindings(bindings) + + return self._connection.insert(sql, bindings) + def insert(self, _values=None, **values): """ Insert a new record into the database diff --git a/orator/query/grammars/grammar.py b/orator/query/grammars/grammar.py index ffd1d74d..84806d05 100644 --- a/orator/query/grammars/grammar.py +++ b/orator/query/grammars/grammar.py @@ -326,7 +326,7 @@ def _compile_union(self, union): return "%s%s" % (joiner, union["query"].to_sql()) - def compile_insert(self, query, values): + def compile_insert(self, query, values, insert_type='INSERT'): """ Compile an insert SQL statement @@ -336,6 +336,9 @@ def compile_insert(self, query, values): :param values: The values to insert :type values: dict or list + :param insert_type: Insert type: "INSERT"(default), "INSERT_IGNORE" or "REPLACE" + :type insert_type: str + :return: The compiled statement :rtype: str """ @@ -357,8 +360,12 @@ def compile_insert(self, query, values): value = ["(%s)" % parameters] * len(values) parameters = ", ".join(value) - - return "INSERT INTO %s (%s) VALUES %s" % (table, columns, parameters) + if insert_type == "INSERT_IGNORE": + return "INSERT INTO %s (%s) VALUES %s" % (table, columns, parameters) + elif insert_type == "REPLACE": + return "REPLACE INTO %s (%s) VALUES %s" % (table, columns, parameters) + else: + return "INSERT INTO %s (%s) VALUES %s" % (table, columns, parameters) def compile_insert_get_id(self, query, values, sequence): return self.compile_insert(query, values)