171 lines
6.3 KiB
C#
171 lines
6.3 KiB
C#
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Linq;
|
|
using AyaNova.Biz;
|
|
|
|
namespace AyaNova.PickList
|
|
{
|
|
|
|
internal static class PickListSqlBuilder
|
|
{
|
|
//Maximum number of results to return at any given time
|
|
//did a little research and may adjust this but it can be fairly girthy in this day and age
|
|
//and many people might not want or need to autocomplete type if we provide enough leeway.
|
|
//for example, if you're selecting a
|
|
const int MAXIMUM_RESULT_COUNT = 100;
|
|
|
|
//Build the query for a picklist request
|
|
internal static string Build(IAyaPickList pickList, List<string> templateColumnNames, string autoCompleteQuery, bool IncludeInactive)
|
|
{
|
|
|
|
|
|
//TODO: custom template routes and tests
|
|
//TODO: TESTS FOR ALL FORMS OF QUERY (tags, non text fields etc)
|
|
//TODO: Clean out unnneeded stuff in AyaPickListFieldDefinition (stuff from datalist copied over)
|
|
|
|
//determine this in advance as it will be used in a loop later
|
|
bool HasAutoCompleteQuery = !string.IsNullOrWhiteSpace(autoCompleteQuery);
|
|
|
|
//lists to collect the clauses so to avoid comma fuckery
|
|
List<string> lSelect = new List<string>();
|
|
string ActiveWhereFragment = string.Empty;
|
|
List<string> lWhere = new List<string>();
|
|
List<string> lOrderBy = new List<string>();
|
|
|
|
|
|
//Add rowid column as it's always required
|
|
AyaPickListFieldDefinition rowIdColumn = pickList.ColumnDefinitions.FirstOrDefault(x => x.IsRowId == true);
|
|
//this should only happen with a development error
|
|
if (rowIdColumn == null)
|
|
throw new System.ArgumentNullException($"DEV ERROR in PickListSqlBuilder.cs: picklist for {pickList.DefaultListObjectType.ToString()} has no rowId column specified in columnDefinitions list");
|
|
lSelect.Add(rowIdColumn.SqlIdColumnName + " AS rowid");
|
|
|
|
//add active only as default for all lists unless inactive is specified
|
|
if (!IncludeInactive)
|
|
{
|
|
AyaPickListFieldDefinition activeColumn = pickList.ColumnDefinitions.FirstOrDefault(x => x.IsActiveColumn == true);
|
|
//it's ok if there is no active column, it could happen so just roll with it
|
|
if (activeColumn != null)
|
|
{
|
|
lSelect.Add(activeColumn.SqlValueColumnName);
|
|
ActiveWhereFragment = activeColumn.SqlValueColumnName + " = true";
|
|
}
|
|
}
|
|
|
|
foreach (string ColumnName in templateColumnNames)
|
|
{
|
|
|
|
AyaPickListFieldDefinition o = pickList.ColumnDefinitions.FirstOrDefault(x => x.FieldKey == ColumnName);
|
|
#if (DEBUG)
|
|
if (o == null)
|
|
{
|
|
throw new System.ArgumentNullException($"DEV ERROR in PickListSqlBuilder.cs: field {ColumnName} specified in template was NOT found in columnDefinitions list");
|
|
}
|
|
#endif
|
|
if (o != null)
|
|
{//Ignore missing fields in production
|
|
|
|
var valueColumnName = o.GetSqlValueColumnName();
|
|
|
|
lSelect.Add(valueColumnName);
|
|
lOrderBy.Add(valueColumnName);
|
|
|
|
if (HasAutoCompleteQuery)
|
|
{
|
|
string sWhere = string.Empty;
|
|
|
|
//Tag?
|
|
if (o.ColumnDataType == UiFieldDataType.Tags)
|
|
{
|
|
//awidget.tags @> array['blah','blah3'::varchar(255)]
|
|
//or in real life: ((awidget.name like '%o34%') or (awidget.tags @> array['zone-0'::varchar(255)]) )
|
|
//but this means exact match only, not like comparison here
|
|
|
|
//This also works: ((awidget.name like '%o34%') or ('blue' like any(awidget.tags)) )
|
|
//but again, not a like query only exact match
|
|
|
|
//THIS is the one:
|
|
//(array_to_string(awidget.tags,',') like '%zo%')
|
|
sWhere = $"(array_to_string({valueColumnName},',') like '%{autoCompleteQuery}%')";
|
|
|
|
}
|
|
else if (o.ColumnDataType == UiFieldDataType.Text || o.ColumnDataType == UiFieldDataType.EmailAddress || o.ColumnDataType == UiFieldDataType.HTTP)
|
|
{
|
|
//regular text field
|
|
sWhere = $"({valueColumnName} LIKE '%{autoCompleteQuery}%')";
|
|
}
|
|
else
|
|
{
|
|
//needs to be cast to text
|
|
//(cast (awidget.serial as text) like '%some%')
|
|
sWhere = $"(cast ({valueColumnName} as text) LIKE '%{autoCompleteQuery}%')";
|
|
}
|
|
|
|
|
|
|
|
lWhere.Add(sWhere);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
//SELECT
|
|
sb.Append("select ");
|
|
foreach (string s in lSelect)
|
|
{
|
|
sb.Append(s);
|
|
sb.Append(",");
|
|
}
|
|
//clear trailing comma
|
|
sb.Length--;
|
|
|
|
//FROM
|
|
sb.Append(" ");
|
|
sb.Append(pickList.SQLFrom);
|
|
|
|
|
|
//WHERE
|
|
sb.Append(" where ");
|
|
if (!IncludeInactive)
|
|
{
|
|
sb.Append(ActiveWhereFragment);
|
|
sb.Append(" and (");
|
|
}
|
|
|
|
foreach (string s in lWhere)
|
|
{
|
|
sb.Append(s);
|
|
sb.Append(" or ");
|
|
}
|
|
//clear trailing or
|
|
sb.Length -= 4;
|
|
//enclosing parenthesis
|
|
if (!IncludeInactive)
|
|
{
|
|
sb.Append(")");
|
|
}
|
|
|
|
//ORDER BY
|
|
sb.Append(" order by ");
|
|
foreach (string s in lOrderBy)
|
|
{
|
|
sb.Append(s);
|
|
sb.Append(",");
|
|
}
|
|
//clear trailing comma
|
|
sb.Length--;
|
|
|
|
//LIMIT
|
|
sb.Append($" limit {MAXIMUM_RESULT_COUNT}");
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
|
|
|
|
|
|
|
}//eoc
|
|
}//ens
|