public override List <IDictionary <string, object> > QueryDynamicTable(string tableName, DynamicTableFilter filter, ICollection <DynamicTableSort> sorts, out int totalCount, string tableAlias = null, DynamicQueryCallbackProvider queryCallbacks = null, int?hitsPerPage = null, int?page = null) { var desc = DescribeTable(tableName, true, out _); using (Facade.UseConnection(out DbCommand cmd)) { var colFx = new Func <List <TableColumnDefinition>, string, string, TableColumnResolveCallback, string>((cols, colName, alias, cb) => { var retVal = BrowseColumns(cols, colName, alias, cb, out var tmp); if (tmp is AliasQualifiedColumn ali) { retVal = ali.FullQualifiedName; } return(retVal); }); var rawQuery = filter != null?BuildWhereClause(desc, filter, cmd, 0, tableAlias, queryCallbacks) : null; var rawOrdering = (sorts != null && sorts.Count != 0) ? string.Join(", ", from t in sorts select $"{colFx(desc, t.ColumnName, tableAlias, queryCallbacks?.FQColumnQuery)} {t.SortOrder}") : null; var rawCols = string.Join(", ", from t in desc select SyntaxProvider.FullQualifyColumn(tableAlias, t.ColumnName)); var finalQuery = $@"select {rawCols}{(!string.IsNullOrEmpty(queryCallbacks?.CustomQuerySelection) ? $", {queryCallbacks?.CustomQuerySelection}" : "")}, [$$totalRecordCount$$] = count(*) over() from [{tableName}] {(!string.IsNullOrEmpty(tableAlias) ? $"[{tableAlias}]" : "")} {queryCallbacks?.CustomQueryTablePart} {(!string.IsNullOrEmpty(rawQuery) ? $"where {rawQuery}" : "")} {(!string.IsNullOrEmpty(rawOrdering) ? $"order by {rawOrdering}" : "")} {(hitsPerPage != null && page != null ? $@"offset {hitsPerPage * (page - 1)} rows fetch next {hitsPerPage} rows only" : "")}"; LogEnvironment.LogDebugEvent(null, finalQuery, (int)LogSeverity.Report, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); cmd.CommandText = finalQuery; var retVal = cmd.ExecuteReader().ToDictionaries(true).ToList(); totalCount = 0; if (retVal.Count != 0) { totalCount = Convert.ToInt32(retVal[0]["$$totalRecordCount$$"]); } return(retVal); } }
private void ReloadOperators() { List <string> operatorList = new List <string>(); SyntaxProvider?.GetComparisonOperators(operatorList); FillOperators(operatorList); }
private string BrowseColumns(ICollection <TableColumnDefinition> desc, string columnName, string tableAlias, TableColumnResolveCallback getCustomColumnDef, out TableColumnDefinition def) { def = desc.FirstOrDefault(n => n.ColumnName.Equals(columnName, StringComparison.OrdinalIgnoreCase)); if (def != null) { return(SyntaxProvider.FullQualifyColumn(tableAlias, def.ColumnName)); // $"{(tableAlias != null ? $"[{tableAlias}]." : "")}[{col.ColumnName}]"; } return(getCustomColumnDef?.Invoke(columnName, out def)); }
public void TokenDefinition_IsOperator2() { string[] input = { "{ 3 }" }; var syntaxRegex = RegexWrapper.DefaultWrap(SyntaxProvider.GetPattern()); var tokenDefinition = new TokenDefinition(TokenType.SyntaxOperator, syntaxRegex); var tokensGenerated = _tokenizer.Tokenize(input).ToList(); var operatorTokens = tokensGenerated.Where(t => t.TokenType == TokenType.SyntaxOperator).ToList(); Assert.IsTrue(operatorTokens.Any()); Assert.AreEqual(2, operatorTokens.Count()); Assert.IsNotNull(operatorTokens.FirstOrDefault(t => t.Value == "{")); Assert.IsNotNull(operatorTokens.FirstOrDefault(t => t.Value == "}")); }
private void ReportMissingMethod(SyntaxProvider syntaxProvider, Property property, string process) { syntaxProvider.Context.ReportDiagnostic(DiagnosticSeverity.Warning, $"{property} ({property.Type};{property.CollectionType}) has no {process} method associated with its type", property.DeclarationSyntax); }
private bool TryReadProperty(string streamName, string dataName, Property property, List <Property> properties, CodeBuilder builder, SyntaxProvider syntaxProvider, Method readMethod = null) { if (readMethod is null) { syntaxProvider.Methods.TryGetReadMethod(property, out readMethod); } var context = new MethodBuildingContext(streamName, dataName, property, properties, builder, readMethod, syntaxProvider.Methods, syntaxProvider.Context); if (property.Reading.Execute(context)) { return(true); } // Attributes behavior for (int i = 0; i < property.Attributes.Length; i++) { if (property.Attributes[i].ModifyDeserialization(context)) { property.Read.Execute(context); return(true); } } // Default behavior if (readMethod is null) { ReportMissingMethod(syntaxProvider, property, "deserialization"); return(false); } builder.Line($"{dataName} = {streamName}.{readMethod}();"); property.Read.Execute(context); return(true); }
private bool TryReadPropertyCollection(string streamName, string dataName, Property property, List <Property> properties, CodeBuilder builder, SyntaxProvider syntaxProvider) { // If there is a method for writing the whole collection, use it instead if (syntaxProvider.Methods.TryGetReadMethod(property, collection: true, out Method collectionReadMethod)) { return(TryReadProperty(streamName, dataName, property, properties, builder, syntaxProvider, collectionReadMethod)); } syntaxProvider.Methods.TryGetReadMethod(varInt, out Method readMethod); var context = new MethodBuildingContext(streamName, dataName, property, properties, builder, readMethod, syntaxProvider.Methods, syntaxProvider.Context); if (property.Reading.Execute(context)) { return(true); } // Attributes behavior for (int i = 0; i < property.Attributes.Length; i++) { if (property.Attributes[i].ModifyCollectionPrefixDeserialization(context)) { goto LOOP; } } // Default behavior if (readMethod is null) { ReportMissingMethod(syntaxProvider, property, "deserialization"); return(false); } string getLength = $"{streamName}.{readMethod}()"; builder.Line($"{dataName} = {property.NewCollection(getLength)};"); LOOP: builder.Statement($"for (int i = 0; i < {dataName}.{property.Length}; i++)"); context = new MethodBuildingContext(streamName, dataName + "[i]", property, properties, builder, readMethod, syntaxProvider.Methods, syntaxProvider.Context); // Attributes behavior for (int i = 0; i < property.Attributes.Length; i++) { if (property.Attributes[i].ModifyDeserialization(context)) { goto END_LOOP; } } // Default behavior if (readMethod is null) { ReportMissingMethod(syntaxProvider, property, "deserialization"); return(false); } builder.Line($"{dataName}[i] = {streamName}.{readMethod}();"); END_LOOP: builder.EndScope(); property.Read.Execute(context); return(true); }
private bool TryCreateReadingMethod(CodeBuilder builder, List <Property> properties, SyntaxProvider syntaxProvider) { string streamName = "stream"; foreach (Property property in properties) { if (property.IsCollection) { if (!TryReadPropertyCollection(streamName, property.Name, property, properties, builder, syntaxProvider)) { return(false); } } else { if (!TryReadProperty(streamName, property.Name, property, properties, builder, syntaxProvider)) { return(false); } } } return(true); }
private bool TryCreatePopulateMethod(CodeBuilder builder, List <Property> properties, SyntaxProvider syntaxProvider) { return(TryCreateReadingMethod(builder, properties, syntaxProvider)); }
private bool TrySerializeProperty(string streamName, Property property, List <Property> properties, CodeBuilder builder, SyntaxProvider syntaxProvider, Method writeMethod = null) { if (writeMethod is null) { syntaxProvider.Methods.TryGetWriteMethod(property, out writeMethod); } var context = new MethodBuildingContext(streamName, property.Name, property, properties, builder, writeMethod, syntaxProvider.Methods, syntaxProvider.Context); if (property.Writing.Execute(context)) { return(true); } // Attributes behavior for (int i = 0; i < property.Attributes.Length; i++) { if (property.Attributes[i].ModifySerialization(context)) { property.Written.Execute(context); return(true); } } // Default behavior if (writeMethod is null) { ReportMissingMethod(syntaxProvider, property, "serialization"); return(false); } builder.Line($"{streamName}.{writeMethod}({property});"); property.Written.Execute(context); return(true); }
private string ProcessClass(INamedTypeSymbol classSymbol, List <Property> fields, SyntaxProvider syntaxProvider) { fields.Sort((a, b) => a.Order.CompareTo(b.Order)); string @namespace = classSymbol.ContainingNamespace.ToDisplayString(); string className = classSymbol.IsGenericType ? $"{classSymbol.Name}<{string.Join(", ", classSymbol.TypeParameters.Select(parameter => parameter.Name))}>" : classSymbol.Name; var interfaces = classSymbol.AllInterfaces; bool clientbound = interfaces.Any(@interface => @interface.Name == Vocabulary.ClientboundInterface); bool serverbound = interfaces.Any(@interface => @interface.Name == Vocabulary.ServerboundInterface); var methods = classSymbol.GetMembers().OfType <IMethodSymbol>(); var source = new CodeBuilder(); var usings = new HashSet <string>(); foreach (SyntaxReference declaration in classSymbol.DeclaringSyntaxReferences) { SyntaxNode root = declaration.GetSyntax().GetRoot(); foreach (var usingDirective in root.DescendantNodes().OfType <UsingDirectiveSyntax>()) { usings.Add(usingDirective.Name.ToString()); } } usings.Add("Obsidian.Net"); usings.Add("Obsidian.Utilities"); usings.Add("System.Runtime.CompilerServices"); foreach (string @using in usings.OrderBy(s => s)) { source.Using(@using); } source.Line(); source.Namespace(@namespace); source.Type(classSymbol); var bodySource = CodeBuilder.WithIndentationOf(source.Indentation + 1); // Serialize(MinecraftStream stream) bool createSerializationMethod = clientbound && !methods.Any(m => m.Name == "Serialize" && m.Parameters.Length == 1 && m.Parameters[0].Type.Name == "MinecraftStream") && TryCreateSerializationMethod(bodySource, fields, syntaxProvider); if (createSerializationMethod) { source.XmlSummary("Serializes data from this packet into <see cref=\"MinecraftStream\"/>.\n<b>AUTOGENERATED</b>"); source.XmlParam("stream", "Target stream that this packet's data is written to."); source.Method("public void Serialize(MinecraftStream stream)"); source.Append(bodySource); source.EndScope(); } bodySource = CodeBuilder.WithIndentationOf(source.Indentation + 1); if (serverbound) { if (createSerializationMethod) { source.Line(); } // Deserialize(byte[] data) if (!methods.Any(m => m.Name == "Deserialize" && m.Parameters.Length == 1 && m.Parameters[0].Type.ToDisplayString() == "byte[]")) { source.XmlSummary($"Deserializes byte data into <see cref=\"{classSymbol.Name}\"/> packet.\n<b>AUTOGENERATED</b>"); source.XmlParam("data", "Data used to populate the packet."); source.XmlReturns("Deserialized packet."); source.Method($"public static {className} Deserialize(byte[] data)"); source.Line("using var stream = new MinecraftStream(data);"); source.Line("return Deserialize(stream);"); source.EndScope(); } // Deserialize(MinecraftStream stream) if (!methods.Any(m => m.Name == "Deserialize" && m.Parameters.Length == 1 && m.Parameters[0].Type.Name == "MinecraftStream")) { source.Line(); source.XmlSummary($"Deserializes data from a <see cref=\"MinecraftStream\"/> into <see cref=\"{classSymbol.Name}\"/> packet.\n<b>AUTOGENERATED</b>"); source.XmlParam("stream", "Stream that is read from to populate the packet."); source.XmlReturns("Deserialized packet."); source.Method($"public static {className} Deserialize(MinecraftStream stream)"); source.Line($"var packet = new {className}();"); source.Line("packet.Populate(stream);"); source.Line("return packet;"); source.EndScope(); } } bodySource = CodeBuilder.WithIndentationOf(source.Indentation + 1); if (serverbound && TryCreatePopulateMethod(bodySource, fields, syntaxProvider)) { // Populate(byte[] data) if (!methods.Any(m => m.Name == "Populate" && m.Parameters.Length == 1 && m.Parameters[0].Type.ToDisplayString() == "byte[]")) { source.Line(); source.XmlSummary($"Populates this packet with data from a <see cref=\"byte\"/>[] buffer."); source.XmlParam("data", "Data used to populate this packet."); source.Method("public void Populate(byte[] data)"); source.Line("using var stream = new MinecraftStream(data);"); source.Line("Populate(stream);"); source.EndScope(); } // Populate(MinecraftStream stream) if (!methods.Any(m => m.Name == "Populate" && m.Parameters.Length == 1 && m.Parameters[0].Type.Name == "MinecraftStream")) { source.Line(); source.XmlSummary("Populates this packet with data from a <see cref=\"MinecraftStream\"/>."); source.XmlParam("stream", "Stream used to populate this packet."); source.Method("public void Populate(MinecraftStream stream)"); source.Append(bodySource); source.EndScope(); } } bodySource.Clear(); source.EndScope(); // End of type source.EndScope(); // End of namespace return(source.ToString()); }
private bool TryCreateDeserializationMethod(CodeBuilder builder, string className, List <Field> fields, SyntaxProvider syntaxProvider) { builder.Line($"var packet = new {className}();"); foreach (var field in fields) { string elementType = field.TypeName, elementName = field.Name; if (field.IsArray) { elementName += "[i]"; string lengthProperty; if (field.TypeName.EndsWith("[]")) { lengthProperty = "Length"; elementType = field.TypeName.Substring(0, field.TypeName.Length - 2); } else { lengthProperty = "Count"; elementType = field.TypeName.Substring(5, field.TypeName.Length - 6); } if (field.IsVarLength) { elementType += "_Var"; } if (field.IsAbsolute) { elementType += "_Abs"; } string countValue; if (field.FixedLength >= 0) { countValue = field.FixedLength.ToString(); } else if (field.CountType is not null) { if (!syntaxProvider.ReadMethods.TryGetValue(field.CountType, out string readCountMethod)) { // CountType has no read method syntaxProvider.Context.ReportDiagnostic(DiagnosticDescriptors.Create(DiagnosticSeverity.Warning, $"{field.Name} ({field.TypeName})({elementType}) has no deserialization method associated with its count type", field.Declaration)); return(false); } countValue = $"stream.{readCountMethod}();"; } else { countValue = "stream.ReadVarInt()"; } builder.Line(field.TypeName.EndsWith("[]") ? $"packet.{field.Name} = new {elementType}[{countValue}];" : $"packet.{field.Name} = new {field.TypeName}({countValue});"); builder.Statement($"for (int i = 0; i < packet.{field.Name}.{lengthProperty}; i++)"); } if (TryGetMethod(elementType, syntaxProvider.ReadMethods, out string methodName)) { methodName = $"stream.{methodName}()"; if (field.OriginalType is not null) { if (field.IsGeneric) { string tempName = $"temp{field.Name}"; builder.Line($"var {tempName} = {methodName};"); methodName = $"System.Runtime.CompilerServices.Unsafe.As<{field.ActualType}, {field.OriginalType}>(ref {tempName})"; } else { methodName = $"({field.ActualType}){methodName}"; } } builder.Line($"packet.{elementName} = {methodName};"); } else { // Creating serialization method failed #if DEBUG syntaxProvider.Context.ReportDiagnostic(DiagnosticDescriptors.Create(DiagnosticSeverity.Warning, $"{field.Name} ({field.TypeName})({elementType}) has no deserialization method associated with it", field.Declaration)); #endif return(false); } if (field.IsArray) { // End the for loop builder.EndScope(); } } builder.Line("return packet;"); return(true); }
public override void AlterOrCreateTable(string tableName, TableColumnDefinition[] columns, bool forceDeleteColumn = false, bool useTransaction = true, bool whatIf = false) { var lenFx = new Func <TableColumnDefinition, string>(def => { var ln = def.DataLength ?? -1; return($"{(def.Type.LengthRequired ? $"({(ln != -1 ? ln.ToString() : "max")})" : "")}"); }); var pos = 1; foreach (var col in columns) { if (col.Type == null) { col.Type = SyntaxProvider.GetAppropriateType(col, true); } if (col.Position == 0) { col.Position = pos++; } } bool transactionCreated = false; if (useTransaction && (Facade.CurrentTransaction == null)) { if (!whatIf) { Facade.BeginTransaction(); } else { LogEnvironment.LogEvent("Table-Modification would start a new transaction!", LogSeverity.Report, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } transactionCreated = true; } try { List <string> dropIndices = new List <string>(); List <string> addIndices = new List <string>(); List <string> constraintChanges = new List <string>(); var cmd = ""; if (TableExists(tableName)) { var orig = DescribeTable(tableName, false, out var definitionEditable); var differ = DynamicTableHelper.CompareDefinitions(orig, columns); List <string> addCols = new List <string>(); List <string> dropCols = new List <string>(); List <string> alterCols = new List <string>(); foreach (var item in differ) { if (item.Table2Def == null && !forceDeleteColumn) { if (!whatIf) { throw new InvalidOperationException("Column removal must be explicitly forced!"); } else { LogEnvironment.LogEvent("Table-Modification would fail due to a column-removal with forceDeleteColumn=false!", LogSeverity.Error, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } if (item.Table2Def == null && !definitionEditable) { if (!whatIf) { throw new InvalidOperationException("Column removal is not supported on this table, because the index-configuration is not supported!"); } else { LogEnvironment.LogEvent("Table-Modification would fail due to a column-removal on a table with an unsupported index-configuration!", LogSeverity.Error, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } if (item.Table2Def == null) { dropCols.Add($"[{item.ColumnName}]"); } if (item.Table1Def != null && item.Table2Def != null) { if (!item.Table1Def.DataType.Equals(item.Table2Def.DataType, StringComparison.OrdinalIgnoreCase)) { if (!whatIf) { throw new InvalidOperationException("Changing the DataType is not supported!"); } else { LogEnvironment.LogEvent("Table-Modification would fail, because DataTypes must not be altered!", LogSeverity.Error, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } if (item.Table1Def.DataLength != item.Table2Def.DataLength || item.Table1Def.Nullable != item.Table2Def.Nullable) { alterCols.Add($"[{item.ColumnName}] {item.Table2Def.DataType}{lenFx(item.Table2Def)} {(item.Table2Def.Nullable ? "" : "NOT ")}NULL"); } if ((item.Table1Def.HasIndex != item.Table2Def.HasIndex || item.Table1Def.IsUniqueKey != item.Table2Def.IsUniqueKey) && item.Table1Def.IsForeignKey == item.Table2Def.IsForeignKey && !item.Table2Def.IsForeignKey) { if (item.Table1Def.IsPrimaryKey != item.Table2Def.IsPrimaryKey) { if (!whatIf) { throw new InvalidOperationException("Primary keys must not be altered!"); } else { LogEnvironment.LogEvent("Table-Modification would fail, because Primary-Key Columns may not be altered!", LogSeverity.Error, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } if (!definitionEditable) { if (!whatIf) { throw new InvalidOperationException("Index-Changes not supported on this table. Use Management studio to alter table."); } else { LogEnvironment.LogEvent("Table-Modification would fail, because index-configuration of the table is not supported!", LogSeverity.Error, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } if (!item.Table1Def.IsPrimaryKey) { if (item.Table1Def.IsUniqueKey) { dropIndices.Add($"UQ_{tableName}_{item.ColumnName}"); } else if (item.Table1Def.HasIndex) { dropIndices.Add($"CX_{tableName}_{item.ColumnName}"); } if (item.Table2Def.IsUniqueKey) { addIndices.Add($"Create UNIQUE INDEX [UQ_{tableName}_{item.ColumnName}] on [{tableName}] ([{item.ColumnName}] ASC)"); } else if (item.Table2Def.HasIndex) { addIndices.Add($"Create NONCLUSTERED INDEX [CX_{tableName}_{item.ColumnName}] on [{tableName}] ({item.ColumnName})"); } } } if (item.Table2Def.IsForeignKey != item.Table1Def.IsForeignKey) { if (!definitionEditable) { if (!whatIf) { throw new InvalidOperationException("Constraint-Changes not supported on this table. Use Management studio to alter table."); } else { LogEnvironment.LogEvent("Table-Modification would fail, because index-configuration of the table is not supported!", LogSeverity.Error, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } if (item.Table1Def.IsForeignKey) { constraintChanges.Add($"Alter Table [{tableName}] drop constraint [FK_{tableName}_{item.Table1Def.Position}_{item.Table1Def.RefTable}_{item.Table1Def.RefColumn}]"); } else { constraintChanges.Add($@"Alter Table [{tableName}] add constraint [FK_{tableName}_{item.Table2Def.Position}_{item.Table2Def.RefTable}_{item.Table2Def.RefColumn}] Foreign Key ({item.Table2Def.ColumnName}) references [{item.Table2Def.RefTable}] ([{item.Table2Def.RefColumn}])"); } } } else if (item.Table2Def != null) { addCols.Add($"[{item.ColumnName}] {item.Table2Def.DataType}{lenFx(item.Table2Def)} {(item.Table2Def.Nullable ? "" : "NOT ")}NULL"); if (!item.Table2Def.IsPrimaryKey && !item.Table2Def.IsForeignKey && (item.Table2Def.HasIndex || item.Table2Def.IsUniqueKey)) { if (item.Table2Def.IsUniqueKey) { addIndices.Add($"Create UNIQUE INDEX [UQ_{tableName}_{item.ColumnName}] on [{tableName}] ([{item.ColumnName}] ASC)"); } else if (item.Table2Def.HasIndex) { addIndices.Add($"Create NONCLUSTERED INDEX [CX_{tableName}_{item.ColumnName}] on [{tableName}] ({item.ColumnName})"); } } if (item.Table2Def.IsForeignKey) { constraintChanges.Add($@"Alter Table [{tableName}] add constraint [FK_{tableName}_{item.Table2Def.Position}_{item.Table2Def.RefTable}_{item.Table2Def.RefColumn}] Foreign Key ({item.Table2Def.ColumnName}) references [{item.Table2Def.RefTable}] ([{item.Table2Def.RefColumn}])"); } } } if (dropCols.Count != 0) { cmd = $"alter table [{tableName}] drop column {string.Join(", ", dropCols)}"; if (!whatIf) { Facade.ExecuteSqlRaw(cmd); } else { LogEnvironment.LogEvent($"Table-Modification would execute the following SQL-Command: {{{cmd}}}", LogSeverity.Report, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } if (alterCols.Count != 0) { foreach (var ac in alterCols) { cmd = $"alter table [{tableName}] alter column {ac}"; if (!whatIf) { Facade.ExecuteSqlRaw(cmd); } else { LogEnvironment.LogEvent($"Table-Modification would execute the following SQL-Command: {{{cmd}}}", LogSeverity.Report, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } } if (addCols.Count != 0) { cmd = $"alter table [{tableName}] add {string.Join(", ", addCols)}"; if (!whatIf) { Facade.ExecuteSqlRaw(cmd); } else { LogEnvironment.LogEvent($"Table-Modification would execute the following SQL-Command: {{{cmd}}}", LogSeverity.Report, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } } else { cmd = $"CREATE TABLE [{tableName}] ({string.Join(", ", from t in columns select $"[{t.ColumnName}] {t.DataType}{lenFx(t)} {(t.Nullable ? "" : "NOT")} NULL {(t.IsPrimaryKey ? "IDENTITY(1,1) PRIMARY KEY" : "")}")})"; if (!whatIf) { Facade.ExecuteSqlRaw(cmd); } else { LogEnvironment.LogEvent($"Table-Modification would execute the following SQL-Command: {{{cmd}}}", LogSeverity.Report, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } foreach (var item in columns) { if (!item.IsPrimaryKey && (item.HasIndex || item.IsUniqueKey)) { if (item.IsUniqueKey) { addIndices.Add($"Create UNIQUE INDEX [UQ_{tableName}_{item.ColumnName}] on [{tableName}] ([{item.ColumnName}] ASC)"); } else if (item.HasIndex) { addIndices.Add($"Create NONCLUSTERED INDEX [CX_{tableName}_{item.ColumnName}] on [{tableName}] ({item.ColumnName})"); } } if (item.IsForeignKey) { constraintChanges.Add($@"Alter Table [{tableName}] add constraint [FK_{tableName}_{item.Position}_{item.RefTable}_{item.RefColumn}] Foreign Key ({item.ColumnName}) references [{item.RefTable}] ([{item.RefColumn}])"); } } } if (dropIndices.Count != 0) { foreach (var di in dropIndices) { cmd = $"Drop INDEX IF EXISTS [{di}] on [{tableName}]"; if (!whatIf) { Facade.ExecuteSqlRaw(cmd); } else { LogEnvironment.LogEvent($"Table-Modification would execute the following SQL-Command: {{{cmd}}}", LogSeverity.Report, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } } if (addIndices.Count != 0) { foreach (var ai in addIndices) { cmd = ai; if (!whatIf) { Facade.ExecuteSqlRaw(cmd); } else { LogEnvironment.LogEvent($"Table-Modification would execute the following SQL-Command: {{{cmd}}}", LogSeverity.Report, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } } if (constraintChanges.Count != 0) { foreach (var cc in constraintChanges) { cmd = cc; if (!whatIf) { Facade.ExecuteSqlRaw(cmd); } else { LogEnvironment.LogEvent($"Table-Modification would execute the following SQL-Command: {{{cmd}}}", LogSeverity.Report, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } } if (transactionCreated) { if (!whatIf) { Facade.CommitTransaction(); } else { LogEnvironment.LogEvent($"Table-Modification would commit the started transaction.", LogSeverity.Report, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } } catch { if (transactionCreated) { if (!whatIf) { Facade.RollbackTransaction(); } else { LogEnvironment.LogEvent($"Table-Modification would rollback the started transaction.", LogSeverity.Report, "ITVComponents.EFRepo.SqlServer.SqlDynamicDataAdapter"); } } throw; } }
private bool CreateSerializationMethod(StringBuilder builder, List <Field> fields, SyntaxProvider syntaxProvider) { builder.AppendCode("using var packetStream = new MinecraftStream();"); foreach (var field in fields) { string elementType = field.TypeName, elementName = field.Name; if (field.IsArray) { elementName += "[i]"; string lengthProperty; if (field.TypeName.EndsWith("[]")) { lengthProperty = "Length"; elementType = field.TypeName.Substring(0, field.TypeName.Length - 2); } else { lengthProperty = "Count"; elementType = field.TypeName.Substring(5, field.TypeName.Length - 6); } if (field.IsVarLength) { elementType += "_Var"; } if (field.IsAbsolute) { elementType += "_Abs"; } if (field.FixedLength < 0) { builder.AppendCode($"packetStream.WriteVarInt({field.Name}.{lengthProperty});"); } builder.AppendCode($"for (int i = 0; i < {field.Name}.{lengthProperty}; i++)"); builder.AppendCode("{"); builder.Append('\t'); } if (field.OriginalType is not null) { if (field.IsGeneric) { elementName = $"({field.OriginalType})(object){elementName}"; } else { elementName = $"({field.OriginalType}){elementName}"; } } if (TryGetMethod(elementType, syntaxProvider.WriteMethods, out string methodName)) { builder.AppendCode($"packetStream.{methodName}({elementName});"); } else { // creating serialization method failed #if DEBUG syntaxProvider.Context.ReportDiagnostic(DiagnosticDescriptors.Create(DiagnosticSeverity.Warning, $"{field.Name} ({field.TypeName})({elementType}) has no serialization method associated with it", field.Declaration)); #endif return(false); } if (field.IsArray) { // end for loop builder.AppendCode("}"); } } builder.AppendCode("stream.Lock.Wait();"); builder.AppendCode("stream.WriteVarInt(Id.GetVarIntLength() + (int)packetStream.Length);"); builder.AppendCode("stream.WriteVarInt(Id);"); builder.AppendCode("packetStream.Position = 0;"); builder.AppendCode("packetStream.CopyTo(stream);"); builder.AppendCode("stream.Lock.Release();"); return(true); }
public override List <TableColumnDefinition> DescribeTable(string tableName, bool ignoreUnknownTypes, out bool definitionEditable) { var tmp = SqlQuery <TableColumnDefinition>(@"SELECT c.COLUMN_NAME ColumnName, c.DATA_TYPE DataType, c.CHARACTER_MAXIMUM_LENGTH DataLength, convert(bit,case c.IS_NULLABLE when 'Yes' then 1 else 0 end) Nullable, c.ordinal_position Position, convert(bit, case when ic.object_id is not null then 1 else 0 end) IsIdentity, convert(bit, case when rc.column_name is not null then 1 else 0 end) IsForeignKey, rc.table_name RefTable, rc.column_name RefColumn, convert(bit, case when k.column_name is not null then 1 else 0 end) HasIndex, convert(bit, case when pk.type='PK' then 1 else 0 end) IsPrimaryKey, convert(bit, case when pk.type='UQ' then 1 else 0 end) IsUniqueKey, convert(bit, case when count(cc.referenced_column_id) > 0 then 1 else 0 end) HasReferences FROM INFORMATION_SCHEMA.COLUMNS c left outer join information_schema.KEY_COLUMN_USAGE k on k.COLUMN_NAME = c.column_name and k.table_name = c.TABLE_NAME left outer join sys.identity_columns ic on object_Name(ic.object_id) = c.table_name and ic.name = c.COLUMN_NAME left outer join sys.foreign_key_columns fc on object_name(fc.parent_object_id) = c.table_name and fc.parent_column_id = c.ORDINAL_POSITION left outer join sys.key_constraints pk on object_name(pk.object_id) = k.CONSTRAINT_NAME and object_name(pk.parent_object_id) = c.table_name left outer join information_schema.COLUMNS rc on rc.table_name = object_name(fc.referenced_object_id) and rc.ORDINAL_POSITION = fc.referenced_column_id left outer join sys.foreign_key_columns cc on object_name(cc.referenced_object_id) = c.table_name and cc.referenced_column_id = c.ORDINAL_POSITION WHERE c.TABLE_NAME = @p0 group by c.COLUMN_NAME, c.DATA_TYPE, c.CHARACTER_MAXIMUM_LENGTH, convert(bit,case c.IS_NULLABLE when 'Yes' then 1 else 0 end) , c.ordinal_position, convert(bit, case when ic.object_id is not null then 1 else 0 end), convert(bit, case when rc.column_name is not null then 1 else 0 end), rc.table_name, rc.column_name, convert(bit,case when k.column_name is not null then 1 else 0 end), convert(bit, case when pk.type='PK' then 1 else 0 end), pk.type ORDER BY c.ORDINAL_POSITION", tableName); var tmp2 = (from t in tmp group t by new { t.ColumnName, t.DataLength, t.DataType, t.Nullable, t.Position, t.RefTable, t.RefColumn, t.HasReferences }) .ToList(); tmp.Clear(); definitionEditable = true; foreach (var t in tmp2) { tmp.Add(new TableColumnDefinition { ColumnName = t.Key.ColumnName, DataLength = t.Key.DataLength, DataType = t.Key.DataType, Nullable = t.Key.Nullable, Position = t.Key.Position, RefTable = t.Key.RefTable, RefColumn = t.Key.RefColumn, HasReferences = t.Key.HasReferences, HasIndex = t.All(n => n.HasIndex), IsForeignKey = t.All(n => n.IsForeignKey), IsIdentity = t.All(n => n.IsIdentity), IsPrimaryKey = t.All(n => n.IsPrimaryKey), IsUniqueKey = t.All(n => n.IsUniqueKey), Type = SyntaxProvider.GetAppropriateType(t.First(), !ignoreUnknownTypes) }); definitionEditable &= t.Count() == 1; } if (ignoreUnknownTypes) { tmp = tmp.Where(n => n.Type != null).ToList(); } return(tmp); }
private string ProcessClass(INamedTypeSymbol classSymbol, List <Field> fields, SyntaxProvider syntaxProvider) { fields.Sort((a, b) => a.Index.CompareTo(b.Index)); string @namespace = classSymbol.ContainingNamespace.ToDisplayString(); string className = classSymbol.IsGenericType ? $"{classSymbol.Name}<{string.Join(", ", classSymbol.TypeParameters.Select(parameter => parameter.Name))}>" : classSymbol.Name; var source = new StringBuilder(); foreach (SyntaxReference declaration in classSymbol.DeclaringSyntaxReferences) { SyntaxNode root = declaration.GetSyntax().GetRoot(); foreach (SyntaxNode usingDirective in root.DescendantNodes().Where(node => node is UsingDirectiveSyntax)) { source.Append(usingDirective.GetText().ToString()); } } var bodySource = new StringBuilder(); source.Append($@"using Obsidian.Net; using Obsidian.Util.Extensions; namespace {@namespace} {{ public "); if (classSymbol.IsAbstract) { source.Append("abstract "); } source.Append("partial "); source.Append(classSymbol.IsValueType ? "struct " : "class "); source.Append(className); source.Append(@" { "); string classOffset = "\t\t"; // Serialize(MinecraftStream stream) if (CreateSerializationMethod(bodySource, fields, syntaxProvider)) { source.AppendXML("summary", $"Serializes data from this packet into <see cref=\"MinecraftStream\"/>.\n<b>AUTOGENERATED</b>"); source.AppendXML("param", @"name=""stream""", "Target stream that this packet's data is written to.", true); source.Append($"{classOffset}public void Serialize(MinecraftStream stream)\n{classOffset}{{\n"); source.Append(bodySource.ToString()); source.Append($"{classOffset}}}\n\n"); } bodySource.Clear(); if (!classSymbol.IsAbstract && CreateDeserializationMethod(bodySource, className, fields, syntaxProvider)) { // Deserialize(byte[] data) source.AppendXML("summary", $"Deserializes byte data into <see cref=\"{classSymbol.Name}\"/> packet.\n<b>AUTOGENERATED</b>"); source.AppendXML("param", @"name=""data""", "Data used to populate the packet.", true); source.AppendXML("returns", "Deserialized packet.", true); source.Append($"{classOffset}public static {className} Deserialize(byte[] data)\n{classOffset}{{\n"); source.AppendCode("using var stream = new MinecraftStream(data);"); source.AppendCode("return Deserialize(stream);"); source.Append($"{classOffset}}}\n\n"); // Deserialize(MinecraftStream stream) source.AppendXML("summary", $"Deserializes data from <see cref=\"MinecraftStream\"/> into <see cref=\"{classSymbol.Name}\"/> packet.\n<b>AUTOGENERATED</b>"); source.AppendXML("param", @"name=""stream""", "Stream that is read from to populate the packet.", true); source.AppendXML("returns", "Deserialized packet.", true); source.Append($"{classOffset}public static {className} Deserialize(MinecraftStream stream)\n{classOffset}{{\n"); source.Append(bodySource.ToString()); source.Append($"{classOffset}}}"); } bodySource.Clear(); source.Append(@" } } "); return(source.ToString()); }
private bool CreateDeserializationMethod(StringBuilder builder, string className, List <Field> fields, SyntaxProvider syntaxProvider) { builder.AppendCode($"var packet = new {className}();"); foreach (var field in fields) { string elementType = field.TypeName, elementName = field.Name; if (field.IsArray) { elementName += "[i]"; string lengthProperty; if (field.TypeName.EndsWith("[]")) { lengthProperty = "Length"; elementType = field.TypeName.Substring(0, field.TypeName.Length - 2); } else { lengthProperty = "Count"; elementType = field.TypeName.Substring(5, field.TypeName.Length - 6); } if (field.IsVarLength) { elementType += "_Var"; } if (field.IsAbsolute) { elementType += "_Abs"; } string countValue = field.FixedLength >= 0 ? field.FixedLength.ToString() : "stream.ReadVarInt()"; builder.AppendCode(field.TypeName.EndsWith("[]") ? $"packet.{field.Name} = new {elementType}[{countValue}];" : $"packet.{field.Name} = new {field.TypeName}({countValue});"); builder.AppendCode($"for (int i = 0; i < packet.{field.Name}.{lengthProperty}; i++)"); builder.AppendCode("{"); builder.Append('\t'); } if (TryGetMethod(elementType, syntaxProvider.ReadMethods, out string methodName)) { methodName = "stream." + methodName; if (field.OriginalType is not null) { if (field.IsGeneric) { methodName = $"({field.ActualType})(object){methodName}"; } else { methodName = $"({field.ActualType}){methodName}"; } } builder.AppendCode($"packet.{elementName} = {methodName}();"); } else { // creating serialization method failed #if DEBUG syntaxProvider.Context.ReportDiagnostic(DiagnosticDescriptors.Create(DiagnosticSeverity.Warning, $"{field.Name} ({field.TypeName})({elementType}) has no deserialization method associated with it", field.Declaration)); #endif return(false); } if (field.IsArray) { // end for loop builder.AppendCode("}"); } } builder.AppendCode("return packet;"); return(true); }
private bool TryCreateSerializationMethod(CodeBuilder builder, List <Field> fields, SyntaxProvider syntaxProvider) { builder.Line("using var packetStream = new MinecraftStream();"); foreach (var field in fields) { string elementType = field.TypeName, elementName = field.Name; if (field.IsArray) { elementName += "[i]"; string lengthProperty; if (field.TypeName.EndsWith("[]")) { lengthProperty = "Length"; elementType = field.TypeName.Substring(0, field.TypeName.Length - 2); } else { lengthProperty = "Count"; elementType = field.TypeName.Substring(5, field.TypeName.Length - 6); } if (field.IsVarLength) { elementType += "_Var"; } if (field.IsAbsolute) { elementType += "_Abs"; } if (field.FixedLength < 0) { if (field.CountType is null) { builder.Line($"packetStream.WriteVarInt({field.Name}.{lengthProperty});"); } else { if (!syntaxProvider.WriteMethods.TryGetValue(field.CountType, out string writeCountMethod)) { // CountType has no write method syntaxProvider.Context.ReportDiagnostic(DiagnosticDescriptors.Create(DiagnosticSeverity.Warning, $"{field.Name} ({field.TypeName})({elementType}) has no serialization method associated with its count type", field.Declaration)); return(false); } builder.Line($"packetStream.{writeCountMethod}(({field.CountType}){field.Name}.{lengthProperty});"); } } builder.Statement($"for (int i = 0; i < {field.Name}.{lengthProperty}; i++)"); } if (field.OriginalType is not null) { if (field.IsGeneric) { string tempName = $"temp{field.Name}"; builder.Line($"var {tempName} = {elementName};"); elementName = $"System.Runtime.CompilerServices.Unsafe.As<{field.ActualType}, {field.OriginalType}>(ref {tempName})"; } else { elementName = $"({field.OriginalType}){elementName}"; } } if (TryGetMethod(elementType, syntaxProvider.WriteMethods, out string methodName)) { builder.Line($"packetStream.{methodName}({elementName});"); } else { // Creating serialization method failed #if DEBUG syntaxProvider.Context.ReportDiagnostic(DiagnosticDescriptors.Create(DiagnosticSeverity.Warning, $"{field.Name} ({field.TypeName})({elementType}) has no serialization method associated with it", field.Declaration)); #endif return(false); } if (field.IsArray) { // End the for loop builder.EndScope(); } } builder.Line("stream.Lock.Wait();"); builder.Line("stream.WriteVarInt(Id.GetVarIntLength() + (int)packetStream.Length);"); builder.Line("stream.WriteVarInt(Id);"); builder.Line("packetStream.Position = 0;"); builder.Line("packetStream.CopyTo(stream);"); builder.Line("stream.Lock.Release();"); return(true); }
private bool TryCreateSerializationMethod(CodeBuilder builder, List <Property> properties, SyntaxProvider syntaxProvider) { string streamName = "packetStream"; builder.Line($"using var {streamName} = new MinecraftStream();"); foreach (Property property in properties) { if (property.IsCollection) { if (!TrySerializePropertyCollection(streamName, property, properties, builder, syntaxProvider)) { return(false); } } else { if (!TrySerializeProperty(streamName, property, properties, builder, syntaxProvider)) { return(false); } } } builder.Line(); builder.Line("stream.Lock.Wait();"); builder.Line($"stream.WriteVarInt(Id.GetVarIntLength() + (int){streamName}.Length);"); builder.Line("stream.WriteVarInt(Id);"); builder.Line($"{streamName}.Position = 0;"); builder.Line($"{streamName}.CopyTo(stream);"); builder.Line("stream.Lock.Release();"); return(true); }
private string ProcessClass(INamedTypeSymbol classSymbol, List <Field> fields, SyntaxProvider syntaxProvider) { fields.Sort((a, b) => a.Index.CompareTo(b.Index)); string @namespace = classSymbol.ContainingNamespace.ToDisplayString(); string className = classSymbol.IsGenericType ? $"{classSymbol.Name}<{string.Join(", ", classSymbol.TypeParameters.Select(parameter => parameter.Name))}>" : classSymbol.Name; var attributes = classSymbol.GetAttributes(); bool isReadOnly = attributes.Any(attribute => attribute.AttributeClass.Name == serverOnly); bool isWriteOnly = attributes.Any(attribute => attribute.AttributeClass.Name == clientOnly); var source = new CodeBuilder(); foreach (SyntaxReference declaration in classSymbol.DeclaringSyntaxReferences) { SyntaxNode root = declaration.GetSyntax().GetRoot(); foreach (SyntaxNode usingDirective in root.DescendantNodes().Where(node => node is UsingDirectiveSyntax)) { source.Append(usingDirective.GetText().ToString()); } } source.Using("Obsidian.Net"); source.Using("Obsidian.Util.Extensions"); source.Using("System.Runtime.CompilerServices"); source.Line(); source.Namespace(@namespace); source.Type(classSymbol); var bodySource = CodeBuilder.WithIndentationOf(source.Indentation + 1); // Serialize(MinecraftStream stream) bool createSerializationMethod = !isReadOnly && TryCreateSerializationMethod(bodySource, fields, syntaxProvider); if (createSerializationMethod) { source.XmlSummary("Serializes data from this packet into <see cref=\"MinecraftStream\"/>.\n<b>AUTOGENERATED</b>"); source.XmlParam("stream", "Target stream that this packet's data is written to."); source.Method("public void Serialize(MinecraftStream stream)"); source.Append(bodySource); source.EndScope(); } bodySource = CodeBuilder.WithIndentationOf(source.Indentation + 1); if (!isWriteOnly && !classSymbol.IsAbstract && TryCreateDeserializationMethod(bodySource, className, fields, syntaxProvider)) { if (createSerializationMethod) { source.Line(); } // Deserialize(byte[] data) source.XmlSummary($"Deserializes byte data into <see cref=\"{classSymbol.Name}\"/> packet.\n<b>AUTOGENERATED</b>"); source.XmlParam("data", "Data used to populate the packet."); source.XmlReturns("Deserialized packet."); source.Method($"public static {className} Deserialize(byte[] data)"); source.Line("using var stream = new MinecraftStream(data);"); source.Line("return Deserialize(stream);"); source.EndScope(); source.Line(); // Deserialize(MinecraftStream stream) source.XmlSummary($"Deserializes data from <see cref=\"MinecraftStream\"/> into <see cref=\"{classSymbol.Name}\"/> packet.\n<b>AUTOGENERATED</b>"); source.XmlParam("stream", "Stream that is read from to populate the packet."); source.XmlReturns("Deserialized packet."); source.Method($"public static {className} Deserialize(MinecraftStream stream)"); source.Append(bodySource); source.EndScope(); } bodySource.Clear(); source.EndScope(); // EOF type source.EndScope(); // EOF namespace return(source.ToString()); }
private bool TrySerializePropertyCollection(string streamName, Property property, List <Property> properties, CodeBuilder builder, SyntaxProvider syntaxProvider) { // If there is a method for writing the whole collection, use it instead if (syntaxProvider.Methods.TryGetWriteMethod(property, collection: true, out Method collectionWriteMethod)) { return(TrySerializeProperty(streamName, property, properties, builder, syntaxProvider, collectionWriteMethod)); } syntaxProvider.Methods.TryGetWriteMethod(varInt, out Method writeMethod); var context = new MethodBuildingContext(streamName, property.Name, property, properties, builder, writeMethod, syntaxProvider.Methods, syntaxProvider.Context); if (property.Writing.Execute(context)) { return(true); } // Attributes behavior for (int i = 0; i < property.Attributes.Length; i++) { if (property.Attributes[i].ModifyCollectionPrefixSerialization(context)) { goto LOOP; } } // Default behavior if (writeMethod is null) { ReportMissingMethod(syntaxProvider, property, "serialization"); return(false); } builder.Line($"{streamName}.{writeMethod}({property}.{property.Length});"); LOOP: property.Written.Execute(context); // Begin the for loop builder.Statement($"for (int i = 0; i < {property}.{property.Length}; i++)"); syntaxProvider.Methods.TryGetWriteMethod(property, out writeMethod); context = new MethodBuildingContext(streamName, property.Name + "[i]", property, properties, builder, writeMethod, syntaxProvider.Methods, syntaxProvider.Context); // Attributes behavior for (int i = 0; i < property.Attributes.Length; i++) { if (property.Attributes[i].ModifySerialization(context)) { goto END_LOOP; } } // Default behavior if (writeMethod is null) { ReportMissingMethod(syntaxProvider, property, "serialization"); return(false); } builder.Line($"{streamName}.{writeMethod}({property}[i]);"); END_LOOP: builder.EndScope(); property.Written.Execute(context); return(true); }