Radarr/src/Marr.Data/QGen/SelectQuery.cs

160 lines
4.7 KiB
C#

using System.Linq;
using System.Text;
using Marr.Data.Mapping;
using Marr.Data.QGen.Dialects;
namespace Marr.Data.QGen
{
/// <summary>
/// This class is responsible for creating a select query.
/// </summary>
public class SelectQuery : IQuery
{
public Dialect Dialect { get; set; }
public string WhereClause { get; set; }
public ISortQueryBuilder OrderBy { get; set; }
public TableCollection Tables { get; set; }
public bool UseAltName;
public SelectQuery(Dialect dialect, TableCollection tables, string whereClause, ISortQueryBuilder orderBy, bool useAltName)
{
Dialect = dialect;
Tables = tables;
WhereClause = whereClause;
OrderBy = orderBy;
UseAltName = useAltName;
}
public bool IsView
{
get
{
return Tables[0] is View;
}
}
public bool IsJoin
{
get
{
return Tables.Count > 1;
}
}
public virtual string Generate()
{
StringBuilder sql = new StringBuilder();
BuildSelectClause(sql);
BuildFromClause(sql);
BuildJoinClauses(sql);
BuildWhereClause(sql);
BuildOrderClause(sql);
return sql.ToString();
}
public void BuildSelectClause(StringBuilder sql)
{
sql.Append("SELECT ");
int startIndex = sql.Length;
// COLUMNS
foreach (Table join in Tables)
{
for (int i = 0; i < join.Columns.Count; i++)
{
var c = join.Columns[i];
if (sql.Length > startIndex)
sql.Append(",");
if (join is View)
{
string token = string.Concat(join.Alias, ".", NameOrAltName(c.ColumnInfo));
sql.Append(Dialect.CreateToken(token));
}
else
{
string token = string.Concat(join.Alias, ".", c.ColumnInfo.Name);
sql.Append(Dialect.CreateToken(token));
if (UseAltName && c.ColumnInfo.AltName != null && c.ColumnInfo.AltName != c.ColumnInfo.Name)
{
string altName = c.ColumnInfo.AltName;
sql.AppendFormat(" AS {0}", altName);
}
}
}
}
}
public string NameOrAltName(IColumnInfo columnInfo)
{
if (UseAltName && columnInfo.AltName != null && columnInfo.AltName != columnInfo.Name)
{
return columnInfo.AltName;
}
return columnInfo.Name;
}
public void BuildFromClause(StringBuilder sql)
{
// BASE TABLE
Table baseTable = Tables[0];
sql.AppendFormat(" FROM {0} {1} ", Dialect.CreateToken(baseTable.Name), Dialect.CreateToken(baseTable.Alias));
}
public void BuildJoinClauses(StringBuilder sql)
{
// JOINS
for (int i = 1; i < Tables.Count; i++)
{
if (Tables[i].JoinType != JoinType.None)
{
sql.AppendFormat("{0} {1} {2} {3} ",
TranslateJoin(Tables[i].JoinType),
Dialect.CreateToken(Tables[i].Name),
Dialect.CreateToken(Tables[i].Alias),
Tables[i].JoinClause);
}
}
}
public void BuildWhereClause(StringBuilder sql)
{
sql.Append(WhereClause);
}
public void BuildOrderClause(StringBuilder sql)
{
sql.Append(OrderBy.ToString());
}
public void BuildGroupBy(StringBuilder sql)
{
var baseTable = this.Tables.First();
var primaryKeyColumn = baseTable.Columns.Single(c => c.ColumnInfo.IsPrimaryKey);
string token = this.Dialect.CreateToken(string.Concat(baseTable.Alias, ".", primaryKeyColumn.ColumnInfo.Name));
sql.AppendFormat(" GROUP BY {0}", token);
}
private string TranslateJoin(JoinType join)
{
switch (join)
{
case JoinType.Inner:
return "INNER JOIN";
case JoinType.Left:
return "LEFT JOIN";
case JoinType.Right:
return "RIGHT JOIN";
default:
return string.Empty;
}
}
}
}