/// <summary> /// Generate the expression to use in the SELECT clause. For regular columns this is just the column name. For left-joined /// columns, this is a sub-select statement. /// </summary> /// <param name="dbdef"></param> /// <param name="tabledef"></param> /// <param name="coldef"></param> /// <returns></returns> protected virtual string SqlColumnExpression(DataDictionary dbdef, TableDef tabledef, ColDef coldef) { //auto-left-joined col if (coldef.LeftJoin != null) { var fkCol = tabledef.FindCol(coldef.LeftJoin.ForeignKeyColumnName); if (fkCol == null) { throw new Exception($"Invalid foreign key column name in LeftJoin info on {coldef.Name}; it must be the name of a column in the same table"); } if (fkCol.ForeignKeyDatonTypeName == null) { throw new Exception($"Invalid use of foreign key column in LeftJoin; {fkCol.Name} must use a ForeignKey annotation to identify the foriegn table"); } var foreignTabledef = dbdef.FindDef(fkCol.ForeignKeyDatonTypeName).MainTableDef; string tableAlias = "_t_" + (++MaxtDynamicAliasUsed); return($"(select {coldef.LeftJoin.RemoteDisplayColumnName} from {foreignTabledef.SqlTableName} {tableAlias} where {tableAlias}.{foreignTabledef.PrimaryKeyColName}={tabledef.SqlTableName}.{fkCol.Name})"); } if (coldef.IsCustom || coldef.IsComputed) { throw new Exception("Cannot load custom or computed column from database"); } //regular col return(coldef.Name); }
/// <summary> /// Get where clause for viewon main table /// </summary> protected virtual SqlSelectBuilder.Where MainTableWhereClause(TableDef tabledef, ViewonKey key) { var w = new SqlSelectBuilder.Where(); foreach (var cri in key.Criteria) { var coldef = tabledef.FindCol(cri.Name); if (coldef != null) { var crihelper = new ViewonCriterion(coldef, cri.PackedValue); crihelper.ExportWhereClause(w, SqlFlavor); } } return(w); }
/// <summary> /// Get where clause for persiston main table, or null if this is a whole-table persiston /// </summary> protected virtual SqlSelectBuilder.Where MainTableWhereClause(TableDef tabledef, PersistonKey key) { if (key.WholeTable) { return(null); } var pkType = tabledef.FindCol(tabledef.PrimaryKeyColName).CSType; object pk = key.PrimaryKey; //always string here if (pkType != typeof(string)) { pk = Utils.ChangeType(pk, pkType); } var w = new SqlSelectBuilder.Where(); w.AddWhere($"{tabledef.PrimaryKeyColName}={w.NextParameterName()}", pk); return(w); }
/// <summary> /// Look for array nodes matching tableDef, such as Customer, Customer-new, Customer-deleted; and then /// construct target rows based on the values found in those arrays /// </summary> private static void ReadJsonDiffRowArray(JObject parent, TableDef tableDef, List <PersistonDiff.DiffRow> targetA) { void ParseArray(string arrayName, DiffKind kind, bool allowChildren, bool fillInMissingNegativeKey) { var rows = parent[arrayName]; if (rows == null) { return; } if (!(rows is JArray rowsA)) { throw new Exception($"Diff json nodes must be arrays"); } foreach (var childNode in rowsA) { if (!(childNode is JObject childObject)) { throw new Exception("Diff array members must be row objects, not values or arrays"); } var target = new PersistonDiff.DiffRow() { Kind = kind }; targetA.Add(target); ReadJsonDiffRow(childObject, target, tableDef, allowChildren); //if the client omits -1 primary key value on new rows, add it here; the save logic needs it but it is redundant from the client perspective if (fillInMissingNegativeKey && !target.Columns.ContainsKey(tableDef.PrimaryKeyColName)) { var newRowPK = Utils.ChangeType(-1, tableDef.FindCol(tableDef.PrimaryKeyColName).CSType); target.Columns[tableDef.PrimaryKeyColName] = newRowPK; } } } string name = CamelCasify(tableDef.Name); ParseArray(name, DiffKind.Other, true, false); ParseArray(name + "-new", DiffKind.NewRow, true, true); ParseArray(name + "-deleted", DiffKind.DeletedRow, false, false); }
/// <summary> /// Set value of colName in target from source /// </summary> /// <returns>true if it was a real change; false if same value</returns> private bool SetValue(TableDef tabledef, DiffRow source, string colName, Row target) { var coldef = tabledef.FindCol(colName); if (coldef != null) { var oldValue = target.GetValue(coldef); var newValue = source.Columns[colName]; bool isChange = ( (oldValue != null && !oldValue.Equals(newValue)) || (!(oldValue == null && newValue == null)) ); if (isChange) { target.SetValue(coldef, newValue); return(true); } } return(false); }