using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using SyncEngine.Access; namespace SyncEngine.SqlServer { internal static class DataSyncPrimaryKeyHelper { public static IList GetPrimaryKeyColumns(AccessTableSchema table) { if (table?.PrimaryKeyColumns != null && table.PrimaryKeyColumns.Count > 0) { return table.PrimaryKeyColumns; } if (!string.IsNullOrWhiteSpace(table?.PrimaryKeyColumn)) { return new List { table.PrimaryKeyColumn }; } return new List(); } public static string BuildOrderBy(IList pkColumns) { return string.Join(", ", pkColumns.Select(c => "[" + c + "]")); } public static string BuildPkKey(IReadOnlyDictionary row, IList pkColumns) { return string.Join( "|", pkColumns.Select(c => { object value; if (row == null || !row.TryGetValue(c, out value) || value == null) { return string.Empty; } return Convert.ToString(value, CultureInfo.InvariantCulture); })); } /// Access/Jet lexicographic resume predicate: row > lastRow by PK column order. public static string BuildAccessResumeWhere(IList pkColumns, IReadOnlyDictionary lastRow) { if (lastRow == null || pkColumns == null || pkColumns.Count == 0) { return string.Empty; } var branches = new List(); for (var i = 0; i < pkColumns.Count; i++) { var equals = new List(); for (var j = 0; j < i; j++) { equals.Add(string.Format( "[{0}] = {1}", pkColumns[j], SqlLiteral(lastRow, pkColumns[j]))); } equals.Add(string.Format( "[{0}] > {1}", pkColumns[i], SqlLiteral(lastRow, pkColumns[i]))); branches.Add("(" + string.Join(" AND ", equals) + ")"); } return " WHERE (" + string.Join(" OR ", branches) + ")"; } public static string BuildSqlWhereClause(IList pkColumns, string parameterPrefix) { return string.Join( " AND ", pkColumns.Select((c, i) => string.Format("[{0}] = {1}{2}", c, parameterPrefix, i))); } public static void BindPrimaryKeyParameters( Microsoft.Data.SqlClient.SqlCommand cmd, IReadOnlyDictionary row, IList pkColumns, string parameterPrefix) { for (var i = 0; i < pkColumns.Count; i++) { object value; row.TryGetValue(pkColumns[i], out value); cmd.Parameters.AddWithValue(parameterPrefix + i, value ?? DBNull.Value); } } private static string SqlLiteral(IReadOnlyDictionary row, string column) { object value; if (row == null || !row.TryGetValue(column, out value)) { return "NULL"; } return AccessTypeMapper.SqlLiteral(value); } } }