Repository navigation
feat: 添加 SonnetDB 驱动适配与能力差距跟踪 - #101
Merged
Merged
Conversation
This was referenced Oct 8, 2026
nnhy
marked this pull request as ready for review
October 16, 2026 02:53
nnhy
marked this pull request as draft
October 16, 2026 13:31
nnhy
marked this pull request as ready for review
October 16, 2026 13:32
There was a problem hiding this comment.
🟡 Changes recommended
Numeric literal formatting permits SQL injection, and unresolved upsert, schema migration, and database-path issues affect correctness.
7 open findings
Numeric string inputs allow SQL injection in delete conditions · New Embedded source prefix breaks database existence checks · New Logical index properties are not resolved to physical columns · New Case-insensitive default comparison skips string default migrations · New Typed defaults bypass precision validation · New Unavailable string length metadata breaks automatic migrations · New Prefixed table names are duplicated during index removal · New
What changed in this PR
Adds draft SonnetDB support to XCode’s existing database infrastructure, with explicit capability limits.
Changes:
- Adds the provider, SQL dialect, metadata adapter, dependency package, and publishing integration.
- Adds embedded and remote integration tests and capability documentation.
- Fixes expression-based deletion conditions that previously referenced unpassed parameters.
| File | Description |
|---|---|
| XUnitTest.XCode/XUnitTest.XCode.csproj | References the driver package project. |
| XUnitTest.XCode/DataAccessLayer/SonnetDBTests.cs | Tests embedded operations and capability guards. |
| XUnitTest.XCode/DataAccessLayer/SonnetDBRemoteTests.cs | Tests remote operations and transactions. |
| XCode/Entity/Entity.cs | Formats executable deletion conditions. |
| XCode/DataAccessLayer/Database/SonnetDB.cs | Implements SonnetDB database integration. |
| XCode/DataAccessLayer/Common/DbFactory.cs | Registers the provider. |
| XCode/DataAccessLayer/Common/DatabaseType.cs | Adds the database identifier. |
| XCode.SonnetDB/XCode.SonnetDB.csproj | Packages driver dependencies. |
| Readme.MD | Links capability documentation. |
| NewLife.XCode.sln | Includes the package project. |
| Doc/SonnetDB.md | Documents setup, validation, and limitations. |
| ChangeLog.md | Records integration and deletion changes. |
| .github/workflows/publish.yml | Adds package publishing. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+110
to
+113
| if (value is Decimal number) return number.ToString(CultureInfo.InvariantCulture); | ||
| if (value is Double dbl) return dbl.ToString("R", CultureInfo.InvariantCulture); | ||
| if (value is Single single) return single.ToString("R", CultureInfo.InvariantCulture); | ||
| return Convert.ToString(value, CultureInfo.InvariantCulture)!; |
| var source = builder["Data Source"]; | ||
| var uriSource = source?.StartsWith("sonnetdb+", StringComparison.OrdinalIgnoreCase) == true ? source.Substring("sonnetdb+".Length) : source; | ||
| DatabaseName = Uri.TryCreate(uriSource, UriKind.Absolute, out var uri) && (uri.Scheme == "http" || uri.Scheme == "https") | ||
| ? Uri.UnescapeDataString(uri.AbsolutePath.Trim('/')) : source; |
Comment on lines
+329
to
+330
| var keys = table.Indexes.FirstOrDefault(index => index.Unique && index.Columns.Length > 0 && index.Columns.All(name => columns.Any(column => column.ColumnName.Equals(name, StringComparison.OrdinalIgnoreCase))))?.Columns | ||
| ?? table.PrimaryKeys.Select(column => column.ColumnName).ToArray(); |
| if (expectedDefault != null) expectedDefault = expectedDefault.Substring(" DEFAULT ".Length); | ||
| return entityColumn.Identity != dbColumn.Identity || entityColumn.PrimaryKey != dbColumn.PrimaryKey | ||
| || (entityColumn.Nullable && !entityColumn.PrimaryKey && !entityColumn.Identity) != dbColumn.Nullable | ||
| || !String.Equals(expectedDefault?.Trim(), dbColumn.DefaultValue?.Trim(), StringComparison.OrdinalIgnoreCase); |
| if ((field.DataType == typeof(DateTime) || field.DataType == typeof(DateTimeOffset) || field.DataType == typeof(TimeSpan)) | ||
| && !value.StartsWith("'") && value.IndexOf('(') < 0) | ||
| value = SonnetDB.Quote(value); | ||
| return " DEFAULT " + value; |
Comment on lines
+513
to
+514
| if (oldfield != null && field.DataType == typeof(String) && field.Length != oldfield.Length && field.Length > 0 && field.Length < Int32.MaxValue) | ||
| throw new NotSupportedException("SonnetDB STRING尚未支持长度约束变更。参见SonnetDB issue #240,尚需实现对应能力并正式发布。"); |
| public override String? CreateIndexSQL(IDataIndex index) => $"CREATE {(index.Unique ? "UNIQUE " : String.Empty)}INDEX {Database.FormatName(index.Name!)} ON {FormatName(index.Table)} ({String.Join(",", index.Table.GetColumns(index.Columns).Select(FormatName))})"; | ||
|
|
||
| /// <inheritdoc/> | ||
| public override String DropIndexSQL(IDataIndex index) => $"DROP INDEX {Database.FormatName(index.Name!)} ON {FormatName(index.Table)}"; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


SonnetDB 尚未被 XCode 的数据库工厂识别,也没有对应的驱动依赖包。此 PR 增加 SonnetDB 自己的 ADO.NET、SQL 方言和元数据适配,使关系表常用 CRUD、建模、分页、批量写入及事务可以接入现有 XCode 流程。Refs #100;这是 draft,能力差距 issue 保持开放,不宣称全部等价支持。
变更与已完成范围
数据库缺口:🛠️ 未完成 / 📦 发布依赖
图例:✅ 指对应实测通过,🛠️ 指尚需实现或修复,⛔ 指 4.0.0 不能完整提供,🧪 指验证待完成,📦 指正式发布待完成。只有源码已经合入而正式包不包含时,才写“等待 SonnetDB 发布”;不能用 main 或跳过测试冒充正式交付。
完整范围、接入示例、边界与后续状态见
Doc/SonnetDB.md。SonnetDB 的 RETURNING / UPSERT / 基础 DECIMAL / GetSchema 已随 4.0.0 发布,✅ 不重新列成等待开发或发版。嵌入式 DropDatabase 明确拒绝删除目录;备份/恢复未在本次验证中宣称已通过。验证
dotnet pack XCode.SonnetDB/XCode.SonnetDB.csproj -c Release,产物含 net10.0 的 NewLife.XCode / SonnetDB 依赖。依赖包不含编译程序集,沿用现有数据库包装模式。SQLiteTests.MetaTest在未初始化的Data/Membership.db中断言必须存在表;原始280b2a2f无 Sonnet 改动的隔离 worktree 同样复现。没有隐藏或修补该无关基线问题,也不宣称全套回归通过。未新增引擎依赖、虚拟业务主键或公共 ORM API,不修改 SonnetDB 服务端,不因数据库支持更多模型而扩建 XCode 特有接口。