// This file is part of FeedReader.
//
// FeedReader is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// FeedReader is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FeedReader. If not, see .
public enum FeedReader.QueryType {
INSERT,
INSERT_OR_IGNORE,
INSERT_OR_REPLACE,
UPDATE,
SELECT,
DELETE
}
public class FeedReader.QueryBuilder : GLib.Object {
private QueryType m_type;
private string m_table;
private Gee.List m_fields = new Gee.ArrayList();
private Gee.List m_values = new Gee.ArrayList();
private Gee.List m_conditions = new Gee.ArrayList();
private string? m_order_by_column = null;
private bool m_order_descending = false;
private uint? m_limit = null;
private uint? m_offset = null;
public QueryBuilder(QueryType type, string table)
{
m_type = type;
m_table = table;
}
private void insert_value_pair(string field, string value)
requires (m_type == QueryType.INSERT
|| m_type == QueryType.INSERT_OR_IGNORE
|| m_type == QueryType.INSERT_OR_REPLACE)
{
m_fields.add(field);
m_values.add(value);
}
public void insert_param(string field, string value)
requires (value.has_prefix("$") && !value.contains("'"))
{
insert_value_pair(field, value);
}
public void insert_int(string field, int64 value)
{
insert_value_pair(field, value.to_string());
}
public void select_field(string field)
requires (m_type == QueryType.SELECT)
{
m_fields.add(field);
}
private void update(string field, string value)
requires (m_type == QueryType.UPDATE)
{
m_fields.add(field);
m_values.add(value);
}
public void update_param(string field, string value)
requires (value.has_prefix("$") && !value.contains("'"))
{
update(field, value);
}
public void update_string(string field, string value)
{
update(field, SQLite.quote_string(value));
}
public void update_int(string field, int64 value)
{
update(field, value.to_string());
}
private void where_equal(string field, string safe_value)
requires (m_type == QueryType.UPDATE
|| m_type == QueryType.SELECT
|| m_type == QueryType.DELETE)
{
m_conditions.add("%s = %s".printf(field, safe_value));
}
public void where_equal_param(string field, string value)
requires (value.has_prefix("$") && !value.contains("'"))
{
where_equal(field, value);
}
public void where_equal_int(string field, int64 value)
{
where_equal(field, value.to_string());
}
public void where_equal_string(string field, string value)
{
where_equal(field, SQLite.quote_string(value));
}
public void where(string condition)
requires (m_type == QueryType.UPDATE
|| m_type == QueryType.SELECT
|| m_type == QueryType.DELETE)
{
m_conditions.add(condition);
}
public void where_in_strings(string field, Gee.List values)
requires (m_type == QueryType.UPDATE
|| m_type == QueryType.SELECT
|| m_type == QueryType.DELETE)
{
if (values.size == 0)
{
m_conditions.add("1 <> 1");
}
else
{
var compound_values = new GLib.StringBuilder();
foreach(string value in values)
{
compound_values.append(SQLite.quote_string(value));
compound_values.append(", ");
}
compound_values.erase(compound_values.len - 2);
m_conditions.add("%s IN (%s)".printf(field, compound_values.str));
}
}
public void order_by(string field, bool desc)
requires (m_type == QueryType.SELECT)
{
m_order_by_column = field;
m_order_descending = desc;
}
public void limit(uint limit)
requires (m_type == QueryType.SELECT)
{
m_limit = limit;
}
public void offset(uint offset)
requires (m_type == QueryType.SELECT)
{
m_offset = offset;
}
public string to_string()
{
var query = new GLib.StringBuilder();
switch(m_type)
{
case QueryType.INSERT:
case QueryType.INSERT_OR_IGNORE:
case QueryType.INSERT_OR_REPLACE:
query.append("INSERT ");
if(m_type == QueryType.INSERT_OR_IGNORE)
{
query.append("OR IGNORE ");
}
else if(m_type == QueryType.INSERT_OR_REPLACE)
{
query.append("OR REPLACE ");
}
query.append_printf("INTO %s (", m_table);
StringUtils.stringbuilder_append_join(query, m_fields, ", ");
query.append(") VALUES (");
StringUtils.stringbuilder_append_join(query, m_values, ", ");
query.append_c(')');
break;
case QueryType.UPDATE:
query.append_printf("UPDATE %s SET ", m_table);
assert(m_fields.size > 0);
for(int i = 0; i < m_fields.size; i++)
{
if (i > 0)
{
query.append(", ");
}
query.append(m_fields.get(i));
query.append(" = ");
query.append(m_values.get(i));
}
append_conditions(query);
break;
case QueryType.DELETE:
query.append("DELETE FROM ");
query.append(m_table);
append_conditions(query);
break;
case QueryType.SELECT:
query.append("SELECT ");
StringUtils.stringbuilder_append_join(query, m_fields, ", ");
query.append_printf(" FROM %s", m_table);
append_conditions(query);
if (m_order_by_column != null)
{
query.append_printf(
" ORDER BY %s COLLATE NOCASE %s",
m_order_by_column,
m_order_descending ? "DESC" : "ASC");
}
if (m_limit != null)
{
query.append_printf(" LIMIT %u", m_limit);
}
if (m_offset != null)
{
query.append_printf(" OFFSET %u", m_offset);
}
break;
}
return query.str;
}
private void append_conditions(StringBuilder query)
{
if(m_conditions.size == 0)
{
return;
}
query.append(" WHERE ");
StringUtils.stringbuilder_append_join(query, m_conditions, " AND ");
}
public void print()
{
Logger.debug(to_string());
}
}