diff --git a/include/api.php b/include/api.php
index ffe193ab9e..892c036dcc 100644
--- a/include/api.php
+++ b/include/api.php
@@ -1763,13 +1763,10 @@ function api_statuses_home_timeline($type)
 		$idarray[] = intval($item["id"]);
 	}
 
-	$idlist = implode(",", $idarray);
-
-	if ($idlist != "") {
-		$unseen = q("SELECT `id` FROM `item` WHERE `unseen` AND `id` IN (%s)", $idlist);
-
+	if (!empty($idarray)) {
+		$unseen = dba::exists('item', ['unseen' => true, 'id' => $idarray]);
 		if ($unseen) {
-			q("UPDATE `item` SET `unseen` = 0 WHERE `unseen` AND `id` IN (%s)", $idlist);
+			Item::update(['unseen' => false], ['unseen' => true, 'id' => $idarray]);
 		}
 	}
 
diff --git a/mod/admin.php b/mod/admin.php
index 3090376bea..973cf39110 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -1106,9 +1106,7 @@ function admin_page_site_post(App $a)
 	Config::set('system', 'touch_icon', $touch_icon);
 
 	if ($banner == "") {
-		// don't know why, but del_config doesn't work...
-		q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1", dbesc("system"), dbesc("banner")
-		);
+		Config::delete('system', 'banner');
 	} else {
 		Config::set('system', 'banner', $banner);
 	}
diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php
index d5264aa056..94f355797d 100644
--- a/mod/dfrn_confirm.php
+++ b/mod/dfrn_confirm.php
@@ -283,12 +283,9 @@ function dfrn_confirm_post(App $a, $handsfree = null)
 				notice(L10n::t('Remote site reported: ') . $message . EOL);
 			}
 
-			if (($status == 0) && ($intro_id)) {
+			if (($status == 0) && $intro_id) {
 				// Success. Delete the notification.
-				q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d",
-					intval($intro_id),
-					intval($uid)
-				);
+				dba::delete('intro', ['id' => $intro_id]);
 			}
 
 			if ($status != 0) {
@@ -360,10 +357,7 @@ function dfrn_confirm_post(App $a, $handsfree = null)
 				}
 			}
 
-			q("DELETE FROM `intro` WHERE `id` = %d AND `uid` = %d",
-				intval($intro_id),
-				intval($uid)
-			);
+			dba::delete('intro', ['id' => $intro_id]);
 
 			$r = q("UPDATE `contact` SET `name-date` = '%s',
 				`uri-date` = '%s',
diff --git a/mod/dfrn_poll.php b/mod/dfrn_poll.php
index 7d5418c364..5074c0dce9 100644
--- a/mod/dfrn_poll.php
+++ b/mod/dfrn_poll.php
@@ -140,7 +140,7 @@ function dfrn_poll_init(App $a)
 
 	if ($type === 'profile-check' && $dfrn_version < 2.2) {
 		if ((strlen($challenge)) && (strlen($sec))) {
-			q("DELETE FROM `profile_check` WHERE `expire` < " . intval(time()));
+			dba::delete('profile_check', ["`expire` < ?", time()]);
 			$r = q("SELECT * FROM `profile_check` WHERE `sec` = '%s' ORDER BY `expire` DESC LIMIT 1",
 				dbesc($sec)
 			);
@@ -205,7 +205,7 @@ function dfrn_poll_init(App $a)
 					break;
 			}
 
-			q("DELETE FROM `profile_check` WHERE `expire` < " . intval(time()));
+			dba::delete('profile_check', ["`expire` < ?", time()]);
 			$r = q("SELECT * FROM `profile_check` WHERE `dfrn_id` = '%s' ORDER BY `expire` DESC",
 				dbesc($dfrn_id));
 			if (DBM::is_result($r)) {
@@ -232,7 +232,7 @@ function dfrn_poll_post(App $a)
 		if (strlen($challenge) && strlen($sec)) {
 			logger('dfrn_poll: POST: profile-check');
 
-			q("DELETE FROM `profile_check` WHERE `expire` < " . intval(time()));
+			dba::delete('profile_check', ["`expire` < ?", time()]);
 			$r = q("SELECT * FROM `profile_check` WHERE `sec` = '%s' ORDER BY `expire` DESC LIMIT 1",
 				dbesc($sec)
 			);
@@ -305,11 +305,7 @@ function dfrn_poll_post(App $a)
 	$type = $r[0]['type'];
 	$last_update = $r[0]['last_update'];
 
-	$r = q("DELETE FROM `challenge` WHERE `dfrn-id` = '%s' AND `challenge` = '%s'",
-		dbesc($dfrn_id),
-		dbesc($challenge)
-	);
-
+	dba::delete('challenge', ['dfrn-id' => $dfrn_id, 'challenge' => $challenge]);
 
 	$sql_extra = '';
 	switch ($direction) {
@@ -414,7 +410,7 @@ function dfrn_poll_content(App $a)
 
 		$status = 0;
 
-		$r = q("DELETE FROM `challenge` WHERE `expire` < " . intval(time()));
+		dba::delete('challenge', ["`expire` < ?", time()]);
 
 		if ($type !== 'profile') {
 			$r = q("INSERT INTO `challenge` ( `challenge`, `dfrn-id`, `expire` , `type`, `last_update` )
diff --git a/mod/dfrn_request.php b/mod/dfrn_request.php
index e8bc509262..dae2d88524 100644
--- a/mod/dfrn_request.php
+++ b/mod/dfrn_request.php
@@ -263,13 +263,9 @@ function dfrn_request_post(App $a)
 		if (DBM::is_result($r)) {
 			foreach ($r as $rr) {
 				if (!$rr['rel']) {
-					q("DELETE FROM `contact` WHERE `id` = %d AND NOT `self`",
-						intval($rr['cid'])
-					);
+					dba::delete('contact', ['id' => $rr['cid'], 'self' => false]);
 				}
-				q("DELETE FROM `intro` WHERE `id` = %d",
-					intval($rr['iid'])
-				);
+				dba::delete('intro', ['id' => $rr['iid']]);
 			}
 		}
 
diff --git a/mod/message.php b/mod/message.php
index e9bfc076bb..822f5aadec 100644
--- a/mod/message.php
+++ b/mod/message.php
@@ -148,11 +148,7 @@ function message_content(App $a)
 
 		$cmd = $a->argv[1];
 		if ($cmd === 'drop') {
-			$r = q("DELETE FROM `mail` WHERE `id` = %d AND `uid` = %d LIMIT 1",
-				intval($a->argv[2]),
-				intval(local_user())
-			);
-			if ($r) {
+			if (dba::delete('mail', ['id' => $a->argv[2]])) {
 				info(L10n::t('Message deleted.') . EOL);
 			}
 			//goaway(System::baseUrl(true) . '/message' );
@@ -166,22 +162,7 @@ function message_content(App $a)
 				$parent = $r[0]['parent-uri'];
 				$convid = $r[0]['convid'];
 
-				$r = q("DELETE FROM `mail` WHERE `parent-uri` = '%s' AND `uid` = %d ",
-					dbesc($parent),
-					intval(local_user())
-				);
-
-				// remove diaspora conversation pointer
-				// Actually if we do this, we can never receive another reply to that conversation,
-				// as we will never again have the info we need to re-create it.
-				// We'll just have to orphan it.
-				//if ($convid) {
-				//	q("delete from conv where id = %d limit 1",
-				//		intval($convid)
-				//	);
-				//}
-
-				if ($r) {
+				if (dba::delete('mail', ['parent-uri' => $parent, 'uid' => local_user()])) {
 					info(L10n::t('Conversation removed.') . EOL);
 				}
 			}
diff --git a/mod/pubsubhubbub.php b/mod/pubsubhubbub.php
index 051ae2e842..7f06f9db77 100644
--- a/mod/pubsubhubbub.php
+++ b/mod/pubsubhubbub.php
@@ -135,8 +135,7 @@ function pubsubhubbub_init(App $a) {
 		  dbesc($hub_callback));
 
 		// delete old subscription if it exists
-		q("DELETE FROM `push_subscriber` WHERE `callback_url` = '%s'",
-		  dbesc($hub_callback));
+		dba::delete('push_subscriber', ['callback_url' => $hub_callback]);
 
 		if ($subscribe) {
 			$last_update = DateTimeFormat::utcNow();
diff --git a/mod/settings.php b/mod/settings.php
index 3102fef233..234731439f 100644
--- a/mod/settings.php
+++ b/mod/settings.php
@@ -149,9 +149,7 @@ function settings_post(App $a)
 		check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth');
 
 		$key = $_POST['remove'];
-		q("DELETE FROM tokens WHERE id='%s' AND uid=%d",
-			dbesc($key),
-			local_user());
+		dba::delete('tokens', ['id' => $key]);
 		goaway(System::baseUrl(true)."/settings/oauth/");
 		return;
 	}
@@ -714,9 +712,7 @@ function settings_content(App $a)
 		if (($a->argc > 3) && ($a->argv[2] === 'delete')) {
 			check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth', 't');
 
-			q("DELETE FROM clients WHERE client_id='%s' AND uid=%d",
-					dbesc($a->argv[3]),
-					local_user());
+			dba::delete('clients', ['client_id' => $a->argv[3], 'uid' => local_user()]);
 			goaway(System::baseUrl(true)."/settings/oauth/");
 			return;
 		}
diff --git a/src/Model/GContact.php b/src/Model/GContact.php
index 8f16c07fc1..7a12f1a697 100644
--- a/src/Model/GContact.php
+++ b/src/Model/GContact.php
@@ -239,10 +239,8 @@ class GContact
 
 			if ($alternate && ($gcontact['network'] == NETWORK_OSTATUS)) {
 				// Delete the old entry - if it exists
-				$r = q("SELECT `id` FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile)));
-				if (DBM::is_result($r)) {
-					q("DELETE FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile)));
-					q("DELETE FROM `glink` WHERE `gcid` = %d", intval($r[0]["id"]));
+				if (dba::exists('item', ['nurl' => normalise_link($orig_profile)])) {
+					dba::delete('gcontact', ['nurl' => normalise_link($orig_profile)]);
 				}
 			}
 		}
diff --git a/src/Model/Term.php b/src/Model/Term.php
index 03f19197a3..e5490fa7c6 100644
--- a/src/Model/Term.php
+++ b/src/Model/Term.php
@@ -29,8 +29,7 @@ class Term
 		}
 
 		// Clean up all tags
-		dba::e("DELETE FROM `term` WHERE `otype` = ? AND `oid` = ? AND `type` IN (?, ?)",
-			TERM_OBJ_POST, $itemid, TERM_HASHTAG, TERM_MENTION);
+		dba::delete('term', ['otype' => TERM_OBJ_POST, 'oid' => $itemid, 'type' => [TERM_HASHTAG, TERM_MENTION]]);
 
 		if ($message['deleted']) {
 			return;
@@ -135,11 +134,7 @@ class Term
 		}
 
 		// Clean up all tags
-		q("DELETE FROM `term` WHERE `otype` = %d AND `oid` = %d AND `type` IN (%d, %d)",
-			intval(TERM_OBJ_POST),
-			intval($itemid),
-			intval(TERM_FILE),
-			intval(TERM_CATEGORY));
+		dba::delete('term', ['otype' => TERM_OBJ_POST, 'oid' => $itemid, 'type' => [TERM_FILE, TERM_CATEGORY]]);
 
 		if ($message["deleted"]) {
 			return;
diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php
index 63bd2f83bc..f5e8f3a508 100644
--- a/src/Protocol/DFRN.php
+++ b/src/Protocol/DFRN.php
@@ -2078,94 +2078,30 @@ class DFRN
 		// Update the gcontact entry
 		$relocate["server_url"] = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$1$2", $relocate["url"]);
 
-		$x = q(
-			"UPDATE `gcontact` SET
-					`name` = '%s',
-					`photo` = '%s',
-					`url` = '%s',
-					`nurl` = '%s',
-					`addr` = '%s',
-					`connect` = '%s',
-					`notify` = '%s',
-					`server_url` = '%s'
-			WHERE `nurl` = '%s';",
-			dbesc($relocate["name"]),
-			dbesc($relocate["avatar"]),
-			dbesc($relocate["url"]),
-			dbesc(normalise_link($relocate["url"])),
-			dbesc($relocate["addr"]),
-			dbesc($relocate["addr"]),
-			dbesc($relocate["notify"]),
-			dbesc($relocate["server_url"]),
-			dbesc(normalise_link($old["url"]))
-		);
+		$fields = ['name' => $relocate["name"], 'photo' => $relocate["avatar"],
+			'url' => $relocate["url"], 'nurl' => normalise_link($relocate["url"]),
+			'addr' => $relocate["addr"], 'connect' => $relocate["addr"],
+			'notify' => $relocate["notify"], 'server_url' => $relocate["server_url"]];
+		dba::update('gcontact', $fields, ['nurl' => normalise_link($old["url"])]);
 
 		// Update the contact table. We try to find every entry.
-		$x = q(
-			"UPDATE `contact` SET
-					`name` = '%s',
-					`avatar` = '%s',
-					`url` = '%s',
-					`nurl` = '%s',
-					`addr` = '%s',
-					`request` = '%s',
-					`confirm` = '%s',
-					`notify` = '%s',
-					`poll` = '%s',
-					`site-pubkey` = '%s'
-			WHERE (`id` = %d AND `uid` = %d) OR (`nurl` = '%s');",
-			dbesc($relocate["name"]),
-			dbesc($relocate["avatar"]),
-			dbesc($relocate["url"]),
-			dbesc(normalise_link($relocate["url"])),
-			dbesc($relocate["addr"]),
-			dbesc($relocate["request"]),
-			dbesc($relocate["confirm"]),
-			dbesc($relocate["notify"]),
-			dbesc($relocate["poll"]),
-			dbesc($relocate["sitepubkey"]),
-			intval($importer["id"]),
-			intval($importer["importer_uid"]),
-			dbesc(normalise_link($old["url"]))
-		);
+		$fields = ['name' => $relocate["name"], 'avatar' => $relocate["avatar"],
+			'url' => $relocate["url"], 'nurl' => normalise_link($relocate["url"]),
+			'addr' => $relocate["addr"], 'request' => $relocate["request"],
+			'confirm' => $relocate["confirm"], 'notify' => $relocate["notify"],
+			'poll' => $relocate["poll"], 'site-pubkey' => $relocate["sitepubkey"]];
+		$condition = ["(`id` = ?) OR (`nurl` = ?)", $importer["id"], normalise_link($old["url"])];
 
 		Contact::updateAvatar($relocate["avatar"], $importer["importer_uid"], $importer["id"], true);
 
-		if ($x === false) {
-			return false;
-		}
+		logger('Contacts are updated.');
 
 		// update items
-		/// @todo This is an extreme performance killer
-		$fields = [
-			'owner-link' => [$old["url"], $relocate["url"]],
-			'author-link' => [$old["url"], $relocate["url"]],
-			//'owner-avatar' => array($old["photo"], $relocate["photo"]),
-			//'author-avatar' => array($old["photo"], $relocate["photo"]),
-		];
-		foreach ($fields as $n => $f) {
-			$r = q(
-				"SELECT `id` FROM `item` WHERE `%s` = '%s' AND `uid` = %d LIMIT 1",
-				$n,
-				dbesc($f[0]),
-				intval($importer["importer_uid"])
-			);
+		// This is an extreme performance killer
+		Item::update(['owner-link' => $relocate["url"]], ['owner-link' => $old["url"], 'uid' => $importer["importer_uid"]]);
+		Item::update(['author-link' => $relocate["url"]], ['author-link' => $old["url"], 'uid' => $importer["importer_uid"]]);
 
-			if (DBM::is_result($r)) {
-				$x = q(
-					"UPDATE `item` SET `%s` = '%s' WHERE `%s` = '%s' AND `uid` = %d",
-					$n,
-					dbesc($f[1]),
-					$n,
-					dbesc($f[0]),
-					intval($importer["importer_uid"])
-				);
-
-				if ($x === false) {
-					return false;
-				}
-			}
-		}
+		logger('Items are updated.');
 
 		/// @TODO
 		/// merge with current record, current contents have priority
diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php
index d8029858dd..7b3b843a15 100644
--- a/src/Protocol/Diaspora.php
+++ b/src/Protocol/Diaspora.php
@@ -1608,34 +1608,9 @@ class Diaspora
 		logger('Contacts are updated.');
 
 		// update items
-		/// @todo This is an extreme performance killer
-		$fields = [
-			'owner-link' => [$contact["url"], $data["url"]],
-			'author-link' => [$contact["url"], $data["url"]],
-		];
-		foreach ($fields as $n => $f) {
-			$r = q(
-				"SELECT `id` FROM `item` WHERE `%s` = '%s' AND `uid` = %d LIMIT 1",
-				$n,
-				dbesc($f[0]),
-				intval($importer["uid"])
-			);
-
-			if (DBM::is_result($r)) {
-				$x = q(
-					"UPDATE `item` SET `%s` = '%s' WHERE `%s` = '%s' AND `uid` = %d",
-					$n,
-					dbesc($f[1]),
-					$n,
-					dbesc($f[0]),
-					intval($importer["uid"])
-				);
-
-				if ($x === false) {
-					return false;
-				}
-			}
-		}
+		// This is an extreme performance killer
+		Item::update(['owner-link' => $data["url"]], ['owner-link' => $contact["url"], 'uid' => $importer["uid"]]);
+		Item::update(['author-link' => $data["url"]], ['author-link' => $contact["url"], 'uid' => $importer["uid"]]);
 
 		logger('Items are updated.');