wip: doctor/cli/docs/api to vector db consolidation; api hardening for descriptions, tenant, and scopes; migrations and conversions of all DALs to EF v10
This commit is contained in:
@@ -10,7 +10,7 @@ BinaryIndex is a collection of libraries and services for binary analysis:
|
||||
- **BinaryIndex.Core** - Binary identity models, resolution logic, feature extractors
|
||||
- **BinaryIndex.Contracts** - API contracts and DTOs
|
||||
- **BinaryIndex.Cache** - Caching layer for binary analysis results
|
||||
- **BinaryIndex.Persistence** - PostgreSQL storage for signatures and identities
|
||||
- **BinaryIndex.Persistence** - PostgreSQL storage for signatures and identities (EF Core v10 + compiled models)
|
||||
|
||||
### Delta Signature Stack (Backport Detection)
|
||||
- **BinaryIndex.Disassembly.Abstractions** - Plugin interfaces for disassembly
|
||||
|
||||
@@ -17,15 +17,24 @@ Provide foundational data models, storage, and validation for Golden Set definit
|
||||
4. **Air-Gap Ready**: Validation supports offline mode without external lookups
|
||||
5. **Human-Readable**: YAML as primary format for git-friendliness
|
||||
|
||||
## DAL Technology
|
||||
- **Primary**: EF Core v10 DbContext (`EfCore/Context/GoldenSetDbContext.cs`) with 3 entities (definitions, targets, audit_log) in `golden_sets` schema.
|
||||
- **Compiled model**: `EfCore/CompiledModels/GoldenSetDbContextModel` generated for runtime performance.
|
||||
- **Legacy**: `PostgresGoldenSetStore` still uses NpgsqlDataSource directly (deferred from EF Core conversion). Mixed DAL acceptable per cutover strategy.
|
||||
- **SQL migrations remain authoritative**: EF models are scaffolded FROM the SQL schema, never the reverse.
|
||||
|
||||
## Dependencies
|
||||
- `BinaryIndex.Contracts` - Shared contracts and DTOs
|
||||
- `Npgsql` - PostgreSQL driver
|
||||
- `Npgsql.EntityFrameworkCore.PostgreSQL` - EF Core Npgsql provider
|
||||
- `Microsoft.EntityFrameworkCore` - EF Core v10
|
||||
- `YamlDotNet` - YAML serialization
|
||||
- `Microsoft.Extensions.*` - DI, Options, Logging, Caching
|
||||
|
||||
## Required Reading
|
||||
- `docs/modules/binary-index/golden-set-schema.md`
|
||||
- `docs-archived/implplan/SPRINT_20260110_012_001_BINDEX_golden_set_foundation.md`
|
||||
- `docs/db/EF_CORE_MODEL_GENERATION_STANDARDS.md`
|
||||
|
||||
## Test Strategy
|
||||
- Unit tests in `StellaOps.BinaryIndex.GoldenSet.Tests`
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.GoldenSet.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.GoldenSet.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class GoldenSetAuditLogEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.GoldenSet.EfCore.Models.GoldenSetAuditLogEntity",
|
||||
typeof(GoldenSetAuditLogEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 8,
|
||||
namedIndexCount: 2,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(GoldenSetAuditLogEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetAuditLogEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
id.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var goldenSetId = runtimeEntityType.AddProperty(
|
||||
"GoldenSetId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetAuditLogEntity).GetProperty("GoldenSetId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetAuditLogEntity).GetField("<GoldenSetId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
goldenSetId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
goldenSetId.AddAnnotation("Relational:ColumnName", "golden_set_id");
|
||||
|
||||
var action = runtimeEntityType.AddProperty(
|
||||
"Action",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetAuditLogEntity).GetProperty("Action", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetAuditLogEntity).GetField("<Action>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
action.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
action.AddAnnotation("Relational:ColumnName", "action");
|
||||
|
||||
var actorId = runtimeEntityType.AddProperty(
|
||||
"ActorId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetAuditLogEntity).GetProperty("ActorId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetAuditLogEntity).GetField("<ActorId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
actorId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
actorId.AddAnnotation("Relational:ColumnName", "actor_id");
|
||||
|
||||
var oldStatus = runtimeEntityType.AddProperty(
|
||||
"OldStatus",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetAuditLogEntity).GetProperty("OldStatus", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetAuditLogEntity).GetField("<OldStatus>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
oldStatus.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
oldStatus.AddAnnotation("Relational:ColumnName", "old_status");
|
||||
|
||||
var newStatus = runtimeEntityType.AddProperty(
|
||||
"NewStatus",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetAuditLogEntity).GetProperty("NewStatus", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetAuditLogEntity).GetField("<NewStatus>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
newStatus.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
newStatus.AddAnnotation("Relational:ColumnName", "new_status");
|
||||
|
||||
var details = runtimeEntityType.AddProperty(
|
||||
"Details",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetAuditLogEntity).GetProperty("Details", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetAuditLogEntity).GetField("<Details>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
details.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
details.AddAnnotation("Relational:ColumnName", "details");
|
||||
details.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
|
||||
var timestamp = runtimeEntityType.AddProperty(
|
||||
"Timestamp",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(GoldenSetAuditLogEntity).GetProperty("Timestamp", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetAuditLogEntity).GetField("<Timestamp>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
timestamp.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
timestamp.AddAnnotation("Relational:ColumnName", "timestamp");
|
||||
timestamp.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "audit_log_pkey");
|
||||
|
||||
var idx_audit_golden_set = runtimeEntityType.AddIndex(
|
||||
new[] { goldenSetId },
|
||||
name: "idx_audit_golden_set");
|
||||
|
||||
var idx_audit_timestamp = runtimeEntityType.AddIndex(
|
||||
new[] { timestamp },
|
||||
name: "idx_audit_timestamp");
|
||||
idx_audit_timestamp.AddAnnotation("Relational:IsDescending", new[] { true });
|
||||
|
||||
var idx_audit_actor = runtimeEntityType.AddIndex(
|
||||
new[] { actorId },
|
||||
name: "idx_audit_actor");
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "golden_sets");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "audit_log");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// <auto-generated />
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using StellaOps.BinaryIndex.GoldenSet.EfCore.CompiledModels;
|
||||
using StellaOps.BinaryIndex.GoldenSet.EfCore.Context;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
[assembly: DbContextModel(typeof(GoldenSetDbContext), typeof(GoldenSetDbContextModel))]
|
||||
@@ -0,0 +1,48 @@
|
||||
// <auto-generated />
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using StellaOps.BinaryIndex.GoldenSet.EfCore.Context;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.GoldenSet.EfCore.CompiledModels
|
||||
{
|
||||
[DbContext(typeof(GoldenSetDbContext))]
|
||||
public partial class GoldenSetDbContextModel : RuntimeModel
|
||||
{
|
||||
private static readonly bool _useOldBehavior31751 =
|
||||
System.AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue31751", out var enabled31751) && enabled31751;
|
||||
|
||||
static GoldenSetDbContextModel()
|
||||
{
|
||||
var model = new GoldenSetDbContextModel();
|
||||
|
||||
if (_useOldBehavior31751)
|
||||
{
|
||||
model.Initialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
var thread = new System.Threading.Thread(RunInitialization, 10 * 1024 * 1024);
|
||||
thread.Start();
|
||||
thread.Join();
|
||||
|
||||
void RunInitialization()
|
||||
{
|
||||
model.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
model.Customize();
|
||||
_instance = (GoldenSetDbContextModel)model.FinalizeModel();
|
||||
}
|
||||
|
||||
private static GoldenSetDbContextModel _instance;
|
||||
public static IModel Instance => _instance;
|
||||
|
||||
partial void Initialize();
|
||||
|
||||
partial void Customize();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.GoldenSet.EfCore.CompiledModels
|
||||
{
|
||||
public partial class GoldenSetDbContextModel
|
||||
{
|
||||
private GoldenSetDbContextModel()
|
||||
: base(skipDetectChanges: false, modelId: new Guid("b25d0a3e-8c4f-4e9b-a6d2-e7f1c3b82945"), entityTypeCount: 3)
|
||||
{
|
||||
}
|
||||
|
||||
partial void Initialize()
|
||||
{
|
||||
var definition = GoldenSetDefinitionEntityType.Create(this);
|
||||
var target = GoldenSetTargetEntityType.Create(this);
|
||||
var auditLog = GoldenSetAuditLogEntityType.Create(this);
|
||||
|
||||
GoldenSetDefinitionEntityType.CreateAnnotations(definition);
|
||||
GoldenSetTargetEntityType.CreateAnnotations(target);
|
||||
GoldenSetAuditLogEntityType.CreateAnnotations(auditLog);
|
||||
|
||||
AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
AddAnnotation("ProductVersion", "10.0.0");
|
||||
AddAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.GoldenSet.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.GoldenSet.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class GoldenSetDefinitionEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.GoldenSet.EfCore.Models.GoldenSetDefinitionEntity",
|
||||
typeof(GoldenSetDefinitionEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 15,
|
||||
namedIndexCount: 4,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
afterSaveBehavior: PropertySaveBehavior.Throw);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
|
||||
var component = runtimeEntityType.AddProperty(
|
||||
"Component",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("Component", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<Component>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
component.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
component.AddAnnotation("Relational:ColumnName", "component");
|
||||
|
||||
var contentDigest = runtimeEntityType.AddProperty(
|
||||
"ContentDigest",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("ContentDigest", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<ContentDigest>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
contentDigest.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
contentDigest.AddAnnotation("Relational:ColumnName", "content_digest");
|
||||
|
||||
var status = runtimeEntityType.AddProperty(
|
||||
"Status",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("Status", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<Status>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
status.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
status.AddAnnotation("Relational:ColumnName", "status");
|
||||
|
||||
var definitionYaml = runtimeEntityType.AddProperty(
|
||||
"DefinitionYaml",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("DefinitionYaml", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<DefinitionYaml>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
definitionYaml.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
definitionYaml.AddAnnotation("Relational:ColumnName", "definition_yaml");
|
||||
|
||||
var definitionJson = runtimeEntityType.AddProperty(
|
||||
"DefinitionJson",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("DefinitionJson", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<DefinitionJson>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
definitionJson.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
definitionJson.AddAnnotation("Relational:ColumnName", "definition_json");
|
||||
definitionJson.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
|
||||
var targetCount = runtimeEntityType.AddProperty(
|
||||
"TargetCount",
|
||||
typeof(int),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("TargetCount", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<TargetCount>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: 0);
|
||||
targetCount.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
targetCount.AddAnnotation("Relational:ColumnName", "target_count");
|
||||
|
||||
var authorId = runtimeEntityType.AddProperty(
|
||||
"AuthorId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("AuthorId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<AuthorId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
authorId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
authorId.AddAnnotation("Relational:ColumnName", "author_id");
|
||||
|
||||
var createdAt = runtimeEntityType.AddProperty(
|
||||
"CreatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("CreatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<CreatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
createdAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
createdAt.AddAnnotation("Relational:ColumnName", "created_at");
|
||||
createdAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var reviewedBy = runtimeEntityType.AddProperty(
|
||||
"ReviewedBy",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("ReviewedBy", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<ReviewedBy>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
reviewedBy.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
reviewedBy.AddAnnotation("Relational:ColumnName", "reviewed_by");
|
||||
|
||||
var reviewedAt = runtimeEntityType.AddProperty(
|
||||
"ReviewedAt",
|
||||
typeof(DateTime?),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("ReviewedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<ReviewedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
reviewedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
reviewedAt.AddAnnotation("Relational:ColumnName", "reviewed_at");
|
||||
|
||||
var sourceRef = runtimeEntityType.AddProperty(
|
||||
"SourceRef",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("SourceRef", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<SourceRef>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
sourceRef.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourceRef.AddAnnotation("Relational:ColumnName", "source_ref");
|
||||
|
||||
var tags = runtimeEntityType.AddProperty(
|
||||
"Tags",
|
||||
typeof(string[]),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("Tags", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<Tags>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
tags.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
tags.AddAnnotation("Relational:ColumnName", "tags");
|
||||
|
||||
var schemaVersion = runtimeEntityType.AddProperty(
|
||||
"SchemaVersion",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("SchemaVersion", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<SchemaVersion>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
schemaVersion.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
schemaVersion.AddAnnotation("Relational:ColumnName", "schema_version");
|
||||
|
||||
var updatedAt = runtimeEntityType.AddProperty(
|
||||
"UpdatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(GoldenSetDefinitionEntity).GetProperty("UpdatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetDefinitionEntity).GetField("<UpdatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
updatedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
updatedAt.AddAnnotation("Relational:ColumnName", "updated_at");
|
||||
updatedAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "definitions_pkey");
|
||||
|
||||
var idx_goldensets_component = runtimeEntityType.AddIndex(
|
||||
new[] { component },
|
||||
name: "idx_goldensets_component");
|
||||
|
||||
var idx_goldensets_status = runtimeEntityType.AddIndex(
|
||||
new[] { status },
|
||||
name: "idx_goldensets_status");
|
||||
|
||||
var idx_goldensets_digest = runtimeEntityType.AddIndex(
|
||||
new[] { contentDigest },
|
||||
name: "idx_goldensets_digest",
|
||||
unique: true);
|
||||
|
||||
var idx_goldensets_created = runtimeEntityType.AddIndex(
|
||||
new[] { createdAt },
|
||||
name: "idx_goldensets_created");
|
||||
idx_goldensets_created.AddAnnotation("Relational:IsDescending", new[] { true });
|
||||
|
||||
var idx_goldensets_component_status = runtimeEntityType.AddIndex(
|
||||
new[] { component, status },
|
||||
name: "idx_goldensets_component_status");
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "golden_sets");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "definitions");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.GoldenSet.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.GoldenSet.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class GoldenSetTargetEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.GoldenSet.EfCore.Models.GoldenSetTargetEntity",
|
||||
typeof(GoldenSetTargetEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 9,
|
||||
namedIndexCount: 1,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(GoldenSetTargetEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetTargetEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
id.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var goldenSetId = runtimeEntityType.AddProperty(
|
||||
"GoldenSetId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetTargetEntity).GetProperty("GoldenSetId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetTargetEntity).GetField("<GoldenSetId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
goldenSetId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
goldenSetId.AddAnnotation("Relational:ColumnName", "golden_set_id");
|
||||
|
||||
var functionName = runtimeEntityType.AddProperty(
|
||||
"FunctionName",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetTargetEntity).GetProperty("FunctionName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetTargetEntity).GetField("<FunctionName>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
functionName.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
functionName.AddAnnotation("Relational:ColumnName", "function_name");
|
||||
|
||||
var edges = runtimeEntityType.AddProperty(
|
||||
"Edges",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetTargetEntity).GetProperty("Edges", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetTargetEntity).GetField("<Edges>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd);
|
||||
edges.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
edges.AddAnnotation("Relational:ColumnName", "edges");
|
||||
edges.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
edges.AddAnnotation("Relational:DefaultValueSql", "'[]'::jsonb");
|
||||
|
||||
var sinks = runtimeEntityType.AddProperty(
|
||||
"Sinks",
|
||||
typeof(string[]),
|
||||
propertyInfo: typeof(GoldenSetTargetEntity).GetProperty("Sinks", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetTargetEntity).GetField("<Sinks>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
sinks.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sinks.AddAnnotation("Relational:ColumnName", "sinks");
|
||||
|
||||
var constants = runtimeEntityType.AddProperty(
|
||||
"Constants",
|
||||
typeof(string[]),
|
||||
propertyInfo: typeof(GoldenSetTargetEntity).GetProperty("Constants", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetTargetEntity).GetField("<Constants>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
constants.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
constants.AddAnnotation("Relational:ColumnName", "constants");
|
||||
|
||||
var taintInvariant = runtimeEntityType.AddProperty(
|
||||
"TaintInvariant",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetTargetEntity).GetProperty("TaintInvariant", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetTargetEntity).GetField("<TaintInvariant>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
taintInvariant.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
taintInvariant.AddAnnotation("Relational:ColumnName", "taint_invariant");
|
||||
|
||||
var sourceFile = runtimeEntityType.AddProperty(
|
||||
"SourceFile",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(GoldenSetTargetEntity).GetProperty("SourceFile", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetTargetEntity).GetField("<SourceFile>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
sourceFile.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourceFile.AddAnnotation("Relational:ColumnName", "source_file");
|
||||
|
||||
var sourceLine = runtimeEntityType.AddProperty(
|
||||
"SourceLine",
|
||||
typeof(int?),
|
||||
propertyInfo: typeof(GoldenSetTargetEntity).GetProperty("SourceLine", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(GoldenSetTargetEntity).GetField("<SourceLine>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
sourceLine.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourceLine.AddAnnotation("Relational:ColumnName", "source_line");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "targets_pkey");
|
||||
|
||||
var idx_targets_golden_set = runtimeEntityType.AddIndex(
|
||||
new[] { goldenSetId },
|
||||
name: "idx_targets_golden_set");
|
||||
|
||||
var idx_targets_function = runtimeEntityType.AddIndex(
|
||||
new[] { functionName },
|
||||
name: "idx_targets_function");
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "golden_sets");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "targets");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using StellaOps.BinaryIndex.GoldenSet.EfCore.Models;
|
||||
|
||||
namespace StellaOps.BinaryIndex.GoldenSet.EfCore.Context;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core DbContext for the GoldenSet module.
|
||||
/// Covers tables in the golden_sets schema.
|
||||
/// </summary>
|
||||
public partial class GoldenSetDbContext : DbContext
|
||||
{
|
||||
private readonly string _schemaName;
|
||||
|
||||
public GoldenSetDbContext(DbContextOptions<GoldenSetDbContext> options, string? schemaName = null)
|
||||
: base(options)
|
||||
{
|
||||
_schemaName = string.IsNullOrWhiteSpace(schemaName)
|
||||
? "golden_sets"
|
||||
: schemaName.Trim();
|
||||
}
|
||||
|
||||
public virtual DbSet<GoldenSetDefinitionEntity> Definitions { get; set; }
|
||||
public virtual DbSet<GoldenSetTargetEntity> Targets { get; set; }
|
||||
public virtual DbSet<GoldenSetAuditLogEntity> AuditLogs { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
var schemaName = _schemaName;
|
||||
|
||||
// =====================================================================
|
||||
// golden_sets.definitions
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<GoldenSetDefinitionEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("definitions_pkey");
|
||||
entity.ToTable("definitions", schemaName);
|
||||
|
||||
entity.HasIndex(e => e.Component, "idx_goldensets_component");
|
||||
entity.HasIndex(e => e.Status, "idx_goldensets_status");
|
||||
entity.HasIndex(e => e.ContentDigest, "idx_goldensets_digest").IsUnique();
|
||||
entity.HasIndex(e => e.CreatedAt, "idx_goldensets_created").IsDescending();
|
||||
entity.HasIndex(e => new { e.Component, e.Status }, "idx_goldensets_component_status");
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.Component).HasColumnName("component");
|
||||
entity.Property(e => e.ContentDigest).HasColumnName("content_digest");
|
||||
entity.Property(e => e.Status).HasColumnName("status");
|
||||
entity.Property(e => e.DefinitionYaml).HasColumnName("definition_yaml");
|
||||
entity.Property(e => e.DefinitionJson).HasColumnType("jsonb").HasColumnName("definition_json");
|
||||
entity.Property(e => e.TargetCount).HasColumnName("target_count");
|
||||
entity.Property(e => e.AuthorId).HasColumnName("author_id");
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("NOW()").HasColumnName("created_at");
|
||||
entity.Property(e => e.ReviewedBy).HasColumnName("reviewed_by");
|
||||
entity.Property(e => e.ReviewedAt).HasColumnName("reviewed_at");
|
||||
entity.Property(e => e.SourceRef).HasColumnName("source_ref");
|
||||
entity.Property(e => e.Tags).HasColumnName("tags");
|
||||
entity.Property(e => e.SchemaVersion).HasColumnName("schema_version");
|
||||
entity.Property(e => e.UpdatedAt).HasDefaultValueSql("NOW()").HasColumnName("updated_at");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// golden_sets.targets
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<GoldenSetTargetEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("targets_pkey");
|
||||
entity.ToTable("targets", schemaName);
|
||||
|
||||
entity.HasIndex(e => e.GoldenSetId, "idx_targets_golden_set");
|
||||
entity.HasIndex(e => e.FunctionName, "idx_targets_function");
|
||||
|
||||
entity.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()").HasColumnName("id");
|
||||
entity.Property(e => e.GoldenSetId).HasColumnName("golden_set_id");
|
||||
entity.Property(e => e.FunctionName).HasColumnName("function_name");
|
||||
entity.Property(e => e.Edges).HasColumnType("jsonb").HasDefaultValueSql("'[]'::jsonb").HasColumnName("edges");
|
||||
entity.Property(e => e.Sinks).HasColumnName("sinks");
|
||||
entity.Property(e => e.Constants).HasColumnName("constants");
|
||||
entity.Property(e => e.TaintInvariant).HasColumnName("taint_invariant");
|
||||
entity.Property(e => e.SourceFile).HasColumnName("source_file");
|
||||
entity.Property(e => e.SourceLine).HasColumnName("source_line");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// golden_sets.audit_log
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<GoldenSetAuditLogEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("audit_log_pkey");
|
||||
entity.ToTable("audit_log", schemaName);
|
||||
|
||||
entity.HasIndex(e => e.GoldenSetId, "idx_audit_golden_set");
|
||||
entity.HasIndex(e => e.Timestamp, "idx_audit_timestamp").IsDescending();
|
||||
entity.HasIndex(e => e.ActorId, "idx_audit_actor");
|
||||
|
||||
entity.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()").HasColumnName("id");
|
||||
entity.Property(e => e.GoldenSetId).HasColumnName("golden_set_id");
|
||||
entity.Property(e => e.Action).HasColumnName("action");
|
||||
entity.Property(e => e.ActorId).HasColumnName("actor_id");
|
||||
entity.Property(e => e.OldStatus).HasColumnName("old_status");
|
||||
entity.Property(e => e.NewStatus).HasColumnName("new_status");
|
||||
entity.Property(e => e.Details).HasColumnType("jsonb").HasColumnName("details");
|
||||
entity.Property(e => e.Timestamp).HasDefaultValueSql("NOW()").HasColumnName("timestamp");
|
||||
});
|
||||
|
||||
OnModelCreatingPartial(modelBuilder);
|
||||
}
|
||||
|
||||
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
|
||||
namespace StellaOps.BinaryIndex.GoldenSet.EfCore.Context;
|
||||
|
||||
/// <summary>
|
||||
/// Design-time factory for EF Core CLI tooling (scaffold, optimize).
|
||||
/// </summary>
|
||||
public sealed class GoldenSetDesignTimeDbContextFactory
|
||||
: IDesignTimeDbContextFactory<GoldenSetDbContext>
|
||||
{
|
||||
private const string DefaultConnectionString =
|
||||
"Host=localhost;Port=55433;Database=postgres;Username=postgres;Password=postgres;Search Path=golden_sets,public";
|
||||
private const string ConnectionStringEnvironmentVariable =
|
||||
"STELLAOPS_GOLDENSET_EF_CONNECTION";
|
||||
|
||||
public GoldenSetDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
var connectionString = ResolveConnectionString();
|
||||
var options = new DbContextOptionsBuilder<GoldenSetDbContext>()
|
||||
.UseNpgsql(connectionString)
|
||||
.Options;
|
||||
|
||||
return new GoldenSetDbContext(options);
|
||||
}
|
||||
|
||||
private static string ResolveConnectionString()
|
||||
{
|
||||
var fromEnvironment = Environment.GetEnvironmentVariable(ConnectionStringEnvironmentVariable);
|
||||
return string.IsNullOrWhiteSpace(fromEnvironment) ? DefaultConnectionString : fromEnvironment;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace StellaOps.BinaryIndex.GoldenSet.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for golden_sets.audit_log table.
|
||||
/// </summary>
|
||||
public partial class GoldenSetAuditLogEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string GoldenSetId { get; set; } = null!;
|
||||
public string Action { get; set; } = null!;
|
||||
public string ActorId { get; set; } = null!;
|
||||
public string? OldStatus { get; set; }
|
||||
public string? NewStatus { get; set; }
|
||||
public string? Details { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace StellaOps.BinaryIndex.GoldenSet.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for golden_sets.definitions table.
|
||||
/// </summary>
|
||||
public partial class GoldenSetDefinitionEntity
|
||||
{
|
||||
public string Id { get; set; } = null!;
|
||||
public string Component { get; set; } = null!;
|
||||
public string ContentDigest { get; set; } = null!;
|
||||
public string Status { get; set; } = null!;
|
||||
public string DefinitionYaml { get; set; } = null!;
|
||||
public string DefinitionJson { get; set; } = null!;
|
||||
public int TargetCount { get; set; }
|
||||
public string AuthorId { get; set; } = null!;
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public string? ReviewedBy { get; set; }
|
||||
public DateTime? ReviewedAt { get; set; }
|
||||
public string SourceRef { get; set; } = null!;
|
||||
public string[] Tags { get; set; } = null!;
|
||||
public string SchemaVersion { get; set; } = null!;
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace StellaOps.BinaryIndex.GoldenSet.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for golden_sets.targets table.
|
||||
/// </summary>
|
||||
public partial class GoldenSetTargetEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string GoldenSetId { get; set; } = null!;
|
||||
public string FunctionName { get; set; } = null!;
|
||||
public string Edges { get; set; } = null!;
|
||||
public string[] Sinks { get; set; } = null!;
|
||||
public string[] Constants { get; set; } = null!;
|
||||
public string? TaintInvariant { get; set; }
|
||||
public string? SourceFile { get; set; }
|
||||
public int? SourceLine { get; set; }
|
||||
}
|
||||
@@ -10,6 +10,17 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Migrations\**\*.sql" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Prevent automatic compiled-model binding so non-default schemas can build runtime models. -->
|
||||
<Compile Remove="EfCore\CompiledModels\GoldenSetDbContextAssemblyAttributes.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||
@@ -17,6 +28,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.DataAnnotations" />
|
||||
<PackageReference Include="Npgsql" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
|
||||
<PackageReference Include="YamlDotNet" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -7,3 +7,6 @@ Source of truth: `docs/implplan/SPRINT_20260130_002_Tools_csproj_remediation_sol
|
||||
| QA-BINARYINDEX-VERIFY-024 | BLOCKED | SPRINT_20260211_033 run-001: blocked because required module-local AGENTS is missing for `src/BinaryIndex/__Tests/StellaOps.BinaryIndex.GoldenSet.Tests` (repo AGENTS rule 5). |
|
||||
| REMED-05 | TODO | Remediation checklist: docs/implplan/audits/csproj-standards/remediation/checklists/src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.GoldenSet/StellaOps.BinaryIndex.GoldenSet.md. |
|
||||
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
|
||||
| BINARY-EF-02 | DONE | SPRINT_20260222_090: EF Core model baseline scaffolded (3 entities, golden_sets schema). |
|
||||
| BINARY-EF-04 | DONE | SPRINT_20260222_090: Compiled model (6 files) generated. |
|
||||
| BINARY-EF-05 | DONE | SPRINT_20260222_090: Build/tests validated (261 pass, 0 fail). Module docs updated. |
|
||||
|
||||
@@ -8,20 +8,33 @@ Own BinaryIndex persistence layer, migrations, and repositories. Keep data acces
|
||||
- Ensure RLS tenant context handling is safe and consistent.
|
||||
- Surface open work on `TASKS.md`; update statuses (TODO/DOING/DONE/BLOCKED/REVIEW).
|
||||
|
||||
## DAL Technology
|
||||
- **Primary**: EF Core v10 (as of Sprint 090 BinaryIndex DAL-to-EF-Core conversion).
|
||||
- **Legacy wrapper**: `BinaryIndexDbContext` provides NpgsqlConnection with tenant RLS; repositories create EF Core `BinaryIndexPersistenceDbContext` per operation.
|
||||
- **Compiled model**: `EfCore/CompiledModels/BinaryIndexPersistenceDbContextModel` used when schema names match defaults (`binaries` + `groundtruth`).
|
||||
- **Mixed DAL**: `FunctionCorpusRepository` (corpus schema) and `PostgresGoldenSetStore` (NpgsqlDataSource) remain Dapper/raw Npgsql. Mixed DAL is acceptable per cutover strategy for adapter-eligible modules.
|
||||
- **SQL migrations remain authoritative**: EF models are scaffolded FROM the SQL schema, never the reverse. No auto-migrations at runtime.
|
||||
|
||||
## Key Paths
|
||||
- `BinaryIndexDbContext.cs`
|
||||
- `BinaryIndexMigrationRunner.cs`
|
||||
- `Repositories/*.cs`
|
||||
- `BinaryIndexDbContext.cs` (legacy connection wrapper with tenant RLS)
|
||||
- `EfCore/Context/BinaryIndexPersistenceDbContext.cs` (EF Core DbContext, 15 entities across binaries + groundtruth schemas)
|
||||
- `EfCore/Models/*.cs` (EF Core entity models)
|
||||
- `EfCore/CompiledModels/*.cs` (compiled model for runtime performance)
|
||||
- `Postgres/BinaryIndexPersistenceDbContextFactory.cs` (runtime factory with UseModel conditional)
|
||||
- `Repositories/*.cs` (EF Core LINQ repositories)
|
||||
- `Services/BinaryVulnerabilityService.cs`
|
||||
- `Migrations/*.sql`
|
||||
- `Migrations/*.sql` (authoritative schema)
|
||||
|
||||
## Coordination
|
||||
- BinaryIndex core/corpus/fix index/fingerprint owners.
|
||||
- Infrastructure.Postgres team for migrations and testing.
|
||||
- Platform Database team for migration registry wiring (BinaryIndexMigrationModulePlugin).
|
||||
|
||||
## Required Reading
|
||||
- `docs/modules/binary-index/architecture.md`
|
||||
- `docs/modules/platform/architecture-overview.md`
|
||||
- `docs/db/EF_CORE_MODEL_GENERATION_STANDARDS.md`
|
||||
- `docs/db/EF_CORE_RUNTIME_CUTOVER_STRATEGY.md`
|
||||
|
||||
## Working Agreement
|
||||
- 1. Update task status to `DOING`/`DONE` in both corresponding sprint file `/docs/implplan/SPRINT_*.md` and the local `TASKS.md` when you start or finish work.
|
||||
@@ -29,4 +42,6 @@ Own BinaryIndex persistence layer, migrations, and repositories. Keep data acces
|
||||
- 3. Keep changes deterministic (stable ordering, timestamps, hashes) and align with offline/air-gap expectations.
|
||||
- 4. Coordinate doc updates, tests, and cross-guild communication whenever contracts or workflows change.
|
||||
- 5. Revert to `TODO` if you pause the task without shipping changes; leave notes in commit/PR descriptions for context.
|
||||
- 6. When modifying EF entity models, update the corresponding compiled model entity type file to stay in sync.
|
||||
- 7. When adding new database tables, update both the SQL migration AND the EF DbContext OnModelCreating.
|
||||
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class BinaryIdentityEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.BinaryIdentityEntity",
|
||||
typeof(BinaryIdentityEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 16,
|
||||
namedIndexCount: 5,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
id.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var tenantId = runtimeEntityType.AddProperty(
|
||||
"TenantId",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("TenantId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<TenantId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: Guid.Empty);
|
||||
tenantId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
tenantId.AddAnnotation("Relational:ColumnName", "tenant_id");
|
||||
|
||||
var binaryKey = runtimeEntityType.AddProperty(
|
||||
"BinaryKey",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("BinaryKey", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<BinaryKey>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
binaryKey.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binaryKey.AddAnnotation("Relational:ColumnName", "binary_key");
|
||||
|
||||
var buildId = runtimeEntityType.AddProperty(
|
||||
"BuildId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("BuildId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<BuildId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
buildId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
buildId.AddAnnotation("Relational:ColumnName", "build_id");
|
||||
|
||||
var buildIdType = runtimeEntityType.AddProperty(
|
||||
"BuildIdType",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("BuildIdType", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<BuildIdType>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
buildIdType.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
buildIdType.AddAnnotation("Relational:ColumnName", "build_id_type");
|
||||
|
||||
var fileSha256 = runtimeEntityType.AddProperty(
|
||||
"FileSha256",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("FileSha256", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<FileSha256>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
fileSha256.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
fileSha256.AddAnnotation("Relational:ColumnName", "file_sha256");
|
||||
|
||||
var textSha256 = runtimeEntityType.AddProperty(
|
||||
"TextSha256",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("TextSha256", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<TextSha256>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
textSha256.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
textSha256.AddAnnotation("Relational:ColumnName", "text_sha256");
|
||||
|
||||
var blake3Hash = runtimeEntityType.AddProperty(
|
||||
"Blake3Hash",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("Blake3Hash", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<Blake3Hash>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
blake3Hash.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
blake3Hash.AddAnnotation("Relational:ColumnName", "blake3_hash");
|
||||
|
||||
var format = runtimeEntityType.AddProperty(
|
||||
"Format",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("Format", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<Format>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
format.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
format.AddAnnotation("Relational:ColumnName", "format");
|
||||
|
||||
var architecture = runtimeEntityType.AddProperty(
|
||||
"Architecture",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("Architecture", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<Architecture>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
architecture.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
architecture.AddAnnotation("Relational:ColumnName", "architecture");
|
||||
|
||||
var osabi = runtimeEntityType.AddProperty(
|
||||
"Osabi",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("Osabi", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<Osabi>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
osabi.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
osabi.AddAnnotation("Relational:ColumnName", "osabi");
|
||||
|
||||
var binaryType = runtimeEntityType.AddProperty(
|
||||
"BinaryType",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("BinaryType", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<BinaryType>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
binaryType.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binaryType.AddAnnotation("Relational:ColumnName", "binary_type");
|
||||
|
||||
var isStripped = runtimeEntityType.AddProperty(
|
||||
"IsStripped",
|
||||
typeof(bool?),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("IsStripped", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<IsStripped>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
isStripped.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
isStripped.AddAnnotation("Relational:ColumnName", "is_stripped");
|
||||
|
||||
var firstSeenSnapshotId = runtimeEntityType.AddProperty(
|
||||
"FirstSeenSnapshotId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("FirstSeenSnapshotId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<FirstSeenSnapshotId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
firstSeenSnapshotId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
firstSeenSnapshotId.AddAnnotation("Relational:ColumnName", "first_seen_snapshot_id");
|
||||
|
||||
var lastSeenSnapshotId = runtimeEntityType.AddProperty(
|
||||
"LastSeenSnapshotId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("LastSeenSnapshotId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<LastSeenSnapshotId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
lastSeenSnapshotId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
lastSeenSnapshotId.AddAnnotation("Relational:ColumnName", "last_seen_snapshot_id");
|
||||
|
||||
var createdAt = runtimeEntityType.AddProperty(
|
||||
"CreatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("CreatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<CreatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
createdAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
createdAt.AddAnnotation("Relational:ColumnName", "created_at");
|
||||
createdAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var updatedAt = runtimeEntityType.AddProperty(
|
||||
"UpdatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(BinaryIdentityEntity).GetProperty("UpdatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryIdentityEntity).GetField("<UpdatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
updatedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
updatedAt.AddAnnotation("Relational:ColumnName", "updated_at");
|
||||
updatedAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "binary_identity_pkey");
|
||||
|
||||
var idx_binary_identity_tenant = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId },
|
||||
name: "idx_binary_identity_tenant");
|
||||
|
||||
var idx_binary_identity_buildid = runtimeEntityType.AddIndex(
|
||||
new[] { buildId },
|
||||
name: "idx_binary_identity_buildid");
|
||||
idx_binary_identity_buildid.AddAnnotation("Relational:Filter", "(build_id IS NOT NULL)");
|
||||
|
||||
var idx_binary_identity_sha256 = runtimeEntityType.AddIndex(
|
||||
new[] { fileSha256 },
|
||||
name: "idx_binary_identity_sha256");
|
||||
|
||||
var idx_binary_identity_key = runtimeEntityType.AddIndex(
|
||||
new[] { binaryKey },
|
||||
name: "idx_binary_identity_key");
|
||||
|
||||
var binary_identity_key_unique = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, binaryKey },
|
||||
name: "binary_identity_key_unique",
|
||||
unique: true);
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "binaries");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "binary_identity");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// <auto-generated />
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Context;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
[assembly: DbContextModel(typeof(BinaryIndexPersistenceDbContext), typeof(BinaryIndexPersistenceDbContextModel))]
|
||||
@@ -0,0 +1,48 @@
|
||||
// <auto-generated />
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Context;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[DbContext(typeof(BinaryIndexPersistenceDbContext))]
|
||||
public partial class BinaryIndexPersistenceDbContextModel : RuntimeModel
|
||||
{
|
||||
private static readonly bool _useOldBehavior31751 =
|
||||
System.AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue31751", out var enabled31751) && enabled31751;
|
||||
|
||||
static BinaryIndexPersistenceDbContextModel()
|
||||
{
|
||||
var model = new BinaryIndexPersistenceDbContextModel();
|
||||
|
||||
if (_useOldBehavior31751)
|
||||
{
|
||||
model.Initialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
var thread = new System.Threading.Thread(RunInitialization, 10 * 1024 * 1024);
|
||||
thread.Start();
|
||||
thread.Join();
|
||||
|
||||
void RunInitialization()
|
||||
{
|
||||
model.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
model.Customize();
|
||||
_instance = (BinaryIndexPersistenceDbContextModel)model.FinalizeModel();
|
||||
}
|
||||
|
||||
private static BinaryIndexPersistenceDbContextModel _instance;
|
||||
public static IModel Instance => _instance;
|
||||
|
||||
partial void Initialize();
|
||||
|
||||
partial void Customize();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
public partial class BinaryIndexPersistenceDbContextModel
|
||||
{
|
||||
private BinaryIndexPersistenceDbContextModel()
|
||||
: base(skipDetectChanges: false, modelId: new Guid("a14c9f2e-7b3d-4e8a-b5c1-d6f0e2a91834"), entityTypeCount: 15)
|
||||
{
|
||||
}
|
||||
|
||||
partial void Initialize()
|
||||
{
|
||||
// --- binaries schema ---
|
||||
var binaryIdentity = BinaryIdentityEntityType.Create(this);
|
||||
var corpusSnapshot = CorpusSnapshotEntityType.Create(this);
|
||||
var binaryVulnAssertion = BinaryVulnAssertionEntityType.Create(this);
|
||||
var deltaSignature = DeltaSignatureDbEntityType.Create(this);
|
||||
var deltaSigMatch = DeltaSigMatchDbEntityType.Create(this);
|
||||
var vulnerableFingerprint = VulnerableFingerprintEntityType.Create(this);
|
||||
var fingerprintMatch = FingerprintMatchEntityType.Create(this);
|
||||
var fingerprintCorpusMetadata = FingerprintCorpusMetadataEntityType.Create(this);
|
||||
var cveFixIndex = CveFixIndexEntityType.Create(this);
|
||||
var fixEvidence = FixEvidenceEntityType.Create(this);
|
||||
|
||||
// --- groundtruth schema ---
|
||||
var symbolSource = SymbolSourceEntityType.Create(this);
|
||||
var sourceState = SourceStateEntityType.Create(this);
|
||||
var rawDocument = RawDocumentEntityType.Create(this);
|
||||
var symbolObservation = SymbolObservationEntityType.Create(this);
|
||||
var securityPair = SecurityPairEntityType.Create(this);
|
||||
|
||||
// --- annotations ---
|
||||
BinaryIdentityEntityType.CreateAnnotations(binaryIdentity);
|
||||
CorpusSnapshotEntityType.CreateAnnotations(corpusSnapshot);
|
||||
BinaryVulnAssertionEntityType.CreateAnnotations(binaryVulnAssertion);
|
||||
DeltaSignatureDbEntityType.CreateAnnotations(deltaSignature);
|
||||
DeltaSigMatchDbEntityType.CreateAnnotations(deltaSigMatch);
|
||||
VulnerableFingerprintEntityType.CreateAnnotations(vulnerableFingerprint);
|
||||
FingerprintMatchEntityType.CreateAnnotations(fingerprintMatch);
|
||||
FingerprintCorpusMetadataEntityType.CreateAnnotations(fingerprintCorpusMetadata);
|
||||
CveFixIndexEntityType.CreateAnnotations(cveFixIndex);
|
||||
FixEvidenceEntityType.CreateAnnotations(fixEvidence);
|
||||
SymbolSourceEntityType.CreateAnnotations(symbolSource);
|
||||
SourceStateEntityType.CreateAnnotations(sourceState);
|
||||
RawDocumentEntityType.CreateAnnotations(rawDocument);
|
||||
SymbolObservationEntityType.CreateAnnotations(symbolObservation);
|
||||
SecurityPairEntityType.CreateAnnotations(securityPair);
|
||||
|
||||
AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
|
||||
AddAnnotation("ProductVersion", "10.0.0");
|
||||
AddAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class BinaryVulnAssertionEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.BinaryVulnAssertionEntity",
|
||||
typeof(BinaryVulnAssertionEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 12,
|
||||
namedIndexCount: 3,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
id.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var tenantId = runtimeEntityType.AddProperty(
|
||||
"TenantId",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("TenantId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<TenantId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: Guid.Empty);
|
||||
tenantId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
tenantId.AddAnnotation("Relational:ColumnName", "tenant_id");
|
||||
|
||||
var binaryKey = runtimeEntityType.AddProperty(
|
||||
"BinaryKey",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("BinaryKey", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<BinaryKey>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
binaryKey.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binaryKey.AddAnnotation("Relational:ColumnName", "binary_key");
|
||||
|
||||
var binaryIdentityId = runtimeEntityType.AddProperty(
|
||||
"BinaryIdentityId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("BinaryIdentityId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<BinaryIdentityId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
binaryIdentityId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binaryIdentityId.AddAnnotation("Relational:ColumnName", "binary_identity_id");
|
||||
|
||||
var cveId = runtimeEntityType.AddProperty(
|
||||
"CveId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("CveId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<CveId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
cveId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
cveId.AddAnnotation("Relational:ColumnName", "cve_id");
|
||||
|
||||
var advisoryId = runtimeEntityType.AddProperty(
|
||||
"AdvisoryId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("AdvisoryId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<AdvisoryId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
advisoryId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
advisoryId.AddAnnotation("Relational:ColumnName", "advisory_id");
|
||||
|
||||
var status = runtimeEntityType.AddProperty(
|
||||
"Status",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("Status", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<Status>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
status.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
status.AddAnnotation("Relational:ColumnName", "status");
|
||||
|
||||
var method = runtimeEntityType.AddProperty(
|
||||
"Method",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("Method", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<Method>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
method.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
method.AddAnnotation("Relational:ColumnName", "method");
|
||||
|
||||
var confidence = runtimeEntityType.AddProperty(
|
||||
"Confidence",
|
||||
typeof(decimal?),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("Confidence", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<Confidence>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
confidence.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
confidence.AddAnnotation("Relational:ColumnName", "confidence");
|
||||
|
||||
var evidenceRef = runtimeEntityType.AddProperty(
|
||||
"EvidenceRef",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("EvidenceRef", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<EvidenceRef>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
evidenceRef.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
evidenceRef.AddAnnotation("Relational:ColumnName", "evidence_ref");
|
||||
|
||||
var evidenceDigest = runtimeEntityType.AddProperty(
|
||||
"EvidenceDigest",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("EvidenceDigest", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<EvidenceDigest>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
evidenceDigest.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
evidenceDigest.AddAnnotation("Relational:ColumnName", "evidence_digest");
|
||||
|
||||
var evaluatedAt = runtimeEntityType.AddProperty(
|
||||
"EvaluatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("EvaluatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<EvaluatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
evaluatedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
evaluatedAt.AddAnnotation("Relational:ColumnName", "evaluated_at");
|
||||
evaluatedAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var createdAt = runtimeEntityType.AddProperty(
|
||||
"CreatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(BinaryVulnAssertionEntity).GetProperty("CreatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(BinaryVulnAssertionEntity).GetField("<CreatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
createdAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
createdAt.AddAnnotation("Relational:ColumnName", "created_at");
|
||||
createdAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "binary_vuln_assertion_pkey");
|
||||
|
||||
var idx_binary_vuln_assertion_tenant = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId },
|
||||
name: "idx_binary_vuln_assertion_tenant");
|
||||
|
||||
var idx_binary_vuln_assertion_binary = runtimeEntityType.AddIndex(
|
||||
new[] { binaryKey },
|
||||
name: "idx_binary_vuln_assertion_binary");
|
||||
|
||||
var idx_binary_vuln_assertion_cve = runtimeEntityType.AddIndex(
|
||||
new[] { cveId },
|
||||
name: "idx_binary_vuln_assertion_cve");
|
||||
|
||||
var binary_vuln_assertion_unique = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, binaryKey, cveId },
|
||||
name: "binary_vuln_assertion_unique",
|
||||
unique: true);
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "binaries");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "binary_vuln_assertion");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class CorpusSnapshotEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.CorpusSnapshotEntity",
|
||||
typeof(CorpusSnapshotEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 15,
|
||||
namedIndexCount: 2,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
id.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var tenantId = runtimeEntityType.AddProperty(
|
||||
"TenantId",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("TenantId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<TenantId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: Guid.Empty);
|
||||
tenantId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
tenantId.AddAnnotation("Relational:ColumnName", "tenant_id");
|
||||
|
||||
var distro = runtimeEntityType.AddProperty(
|
||||
"Distro",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("Distro", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<Distro>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
distro.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
distro.AddAnnotation("Relational:ColumnName", "distro");
|
||||
|
||||
var release = runtimeEntityType.AddProperty(
|
||||
"Release",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("Release", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<Release>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
release.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
release.AddAnnotation("Relational:ColumnName", "release");
|
||||
|
||||
var architecture = runtimeEntityType.AddProperty(
|
||||
"Architecture",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("Architecture", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<Architecture>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
architecture.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
architecture.AddAnnotation("Relational:ColumnName", "architecture");
|
||||
|
||||
var snapshotId = runtimeEntityType.AddProperty(
|
||||
"SnapshotId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("SnapshotId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<SnapshotId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
snapshotId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
snapshotId.AddAnnotation("Relational:ColumnName", "snapshot_id");
|
||||
|
||||
var packagesProcessed = runtimeEntityType.AddProperty(
|
||||
"PackagesProcessed",
|
||||
typeof(int),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("PackagesProcessed", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<PackagesProcessed>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: 0);
|
||||
packagesProcessed.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
packagesProcessed.AddAnnotation("Relational:ColumnName", "packages_processed");
|
||||
|
||||
var binariesIndexed = runtimeEntityType.AddProperty(
|
||||
"BinariesIndexed",
|
||||
typeof(int),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("BinariesIndexed", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<BinariesIndexed>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: 0);
|
||||
binariesIndexed.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binariesIndexed.AddAnnotation("Relational:ColumnName", "binaries_indexed");
|
||||
|
||||
var repoMetadataDigest = runtimeEntityType.AddProperty(
|
||||
"RepoMetadataDigest",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("RepoMetadataDigest", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<RepoMetadataDigest>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
repoMetadataDigest.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
repoMetadataDigest.AddAnnotation("Relational:ColumnName", "repo_metadata_digest");
|
||||
|
||||
var signingKeyId = runtimeEntityType.AddProperty(
|
||||
"SigningKeyId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("SigningKeyId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<SigningKeyId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
signingKeyId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
signingKeyId.AddAnnotation("Relational:ColumnName", "signing_key_id");
|
||||
|
||||
var dsseEnvelopeRef = runtimeEntityType.AddProperty(
|
||||
"DsseEnvelopeRef",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("DsseEnvelopeRef", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<DsseEnvelopeRef>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
dsseEnvelopeRef.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
dsseEnvelopeRef.AddAnnotation("Relational:ColumnName", "dsse_envelope_ref");
|
||||
|
||||
var status = runtimeEntityType.AddProperty(
|
||||
"Status",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("Status", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<Status>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
status.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
status.AddAnnotation("Relational:ColumnName", "status");
|
||||
|
||||
var error = runtimeEntityType.AddProperty(
|
||||
"Error",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("Error", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<Error>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
error.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
error.AddAnnotation("Relational:ColumnName", "error");
|
||||
|
||||
var startedAt = runtimeEntityType.AddProperty(
|
||||
"StartedAt",
|
||||
typeof(DateTime?),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("StartedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<StartedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
startedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
startedAt.AddAnnotation("Relational:ColumnName", "started_at");
|
||||
|
||||
var completedAt = runtimeEntityType.AddProperty(
|
||||
"CompletedAt",
|
||||
typeof(DateTime?),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("CompletedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<CompletedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
completedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
completedAt.AddAnnotation("Relational:ColumnName", "completed_at");
|
||||
|
||||
var createdAt = runtimeEntityType.AddProperty(
|
||||
"CreatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(CorpusSnapshotEntity).GetProperty("CreatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CorpusSnapshotEntity).GetField("<CreatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
createdAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
createdAt.AddAnnotation("Relational:ColumnName", "created_at");
|
||||
createdAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "corpus_snapshots_pkey");
|
||||
|
||||
var idx_corpus_snapshots_tenant = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId },
|
||||
name: "idx_corpus_snapshots_tenant");
|
||||
|
||||
var idx_corpus_snapshots_distro = runtimeEntityType.AddIndex(
|
||||
new[] { distro, release, architecture },
|
||||
name: "idx_corpus_snapshots_distro");
|
||||
|
||||
var corpus_snapshots_unique = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, distro, release, architecture, snapshotId },
|
||||
name: "corpus_snapshots_unique",
|
||||
unique: true);
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "binaries");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "corpus_snapshots");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class CveFixIndexEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.CveFixIndexEntity",
|
||||
typeof(CveFixIndexEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 14,
|
||||
namedIndexCount: 2,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
id.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var tenantId = runtimeEntityType.AddProperty(
|
||||
"TenantId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("TenantId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<TenantId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
tenantId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
tenantId.AddAnnotation("Relational:ColumnName", "tenant_id");
|
||||
|
||||
var distro = runtimeEntityType.AddProperty(
|
||||
"Distro",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("Distro", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<Distro>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
distro.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
distro.AddAnnotation("Relational:ColumnName", "distro");
|
||||
|
||||
var release = runtimeEntityType.AddProperty(
|
||||
"Release",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("Release", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<Release>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
release.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
release.AddAnnotation("Relational:ColumnName", "release");
|
||||
|
||||
var sourcePkg = runtimeEntityType.AddProperty(
|
||||
"SourcePkg",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("SourcePkg", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<SourcePkg>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
sourcePkg.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourcePkg.AddAnnotation("Relational:ColumnName", "source_pkg");
|
||||
|
||||
var cveId = runtimeEntityType.AddProperty(
|
||||
"CveId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("CveId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<CveId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
cveId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
cveId.AddAnnotation("Relational:ColumnName", "cve_id");
|
||||
|
||||
var architecture = runtimeEntityType.AddProperty(
|
||||
"Architecture",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("Architecture", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<Architecture>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
architecture.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
architecture.AddAnnotation("Relational:ColumnName", "architecture");
|
||||
|
||||
var state = runtimeEntityType.AddProperty(
|
||||
"State",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("State", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<State>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
state.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
state.AddAnnotation("Relational:ColumnName", "state");
|
||||
|
||||
var fixedVersion = runtimeEntityType.AddProperty(
|
||||
"FixedVersion",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("FixedVersion", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<FixedVersion>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
fixedVersion.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
fixedVersion.AddAnnotation("Relational:ColumnName", "fixed_version");
|
||||
|
||||
var method = runtimeEntityType.AddProperty(
|
||||
"Method",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("Method", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<Method>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
method.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
method.AddAnnotation("Relational:ColumnName", "method");
|
||||
|
||||
var confidence = runtimeEntityType.AddProperty(
|
||||
"Confidence",
|
||||
typeof(decimal),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("Confidence", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<Confidence>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: 0m);
|
||||
confidence.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
confidence.AddAnnotation("Relational:ColumnName", "confidence");
|
||||
|
||||
var evidenceId = runtimeEntityType.AddProperty(
|
||||
"EvidenceId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("EvidenceId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<EvidenceId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
evidenceId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
evidenceId.AddAnnotation("Relational:ColumnName", "evidence_id");
|
||||
|
||||
var snapshotId = runtimeEntityType.AddProperty(
|
||||
"SnapshotId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("SnapshotId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<SnapshotId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
snapshotId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
snapshotId.AddAnnotation("Relational:ColumnName", "snapshot_id");
|
||||
|
||||
var indexedAt = runtimeEntityType.AddProperty(
|
||||
"IndexedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("IndexedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<IndexedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
indexedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
indexedAt.AddAnnotation("Relational:ColumnName", "indexed_at");
|
||||
indexedAt.AddAnnotation("Relational:DefaultValueSql", "now()");
|
||||
|
||||
var updatedAt = runtimeEntityType.AddProperty(
|
||||
"UpdatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(CveFixIndexEntity).GetProperty("UpdatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(CveFixIndexEntity).GetField("<UpdatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
updatedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
updatedAt.AddAnnotation("Relational:ColumnName", "updated_at");
|
||||
updatedAt.AddAnnotation("Relational:DefaultValueSql", "now()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "cve_fix_index_pkey");
|
||||
|
||||
var idx_cve_fix_lookup = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, distro, release, sourcePkg, cveId },
|
||||
name: "idx_cve_fix_lookup");
|
||||
|
||||
var idx_cve_fix_by_cve = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, cveId, distro, release },
|
||||
name: "idx_cve_fix_by_cve");
|
||||
|
||||
var cve_fix_index_unique = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, distro, release, sourcePkg, cveId, architecture },
|
||||
name: "cve_fix_index_unique",
|
||||
unique: true);
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "binaries");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "cve_fix_index");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class DeltaSigMatchDbEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.DeltaSigMatchDbEntity",
|
||||
typeof(DeltaSigMatchDbEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 15,
|
||||
namedIndexCount: 4,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
id.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var tenantId = runtimeEntityType.AddProperty(
|
||||
"TenantId",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("TenantId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<TenantId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: Guid.Empty);
|
||||
tenantId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
tenantId.AddAnnotation("Relational:ColumnName", "tenant_id");
|
||||
|
||||
var binaryIdentityId = runtimeEntityType.AddProperty(
|
||||
"BinaryIdentityId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("BinaryIdentityId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<BinaryIdentityId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
binaryIdentityId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binaryIdentityId.AddAnnotation("Relational:ColumnName", "binary_identity_id");
|
||||
|
||||
var binaryKey = runtimeEntityType.AddProperty(
|
||||
"BinaryKey",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("BinaryKey", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<BinaryKey>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
binaryKey.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binaryKey.AddAnnotation("Relational:ColumnName", "binary_key");
|
||||
|
||||
var binarySha256 = runtimeEntityType.AddProperty(
|
||||
"BinarySha256",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("BinarySha256", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<BinarySha256>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true,
|
||||
maxLength: 64);
|
||||
binarySha256.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binarySha256.AddAnnotation("Relational:ColumnName", "binary_sha256");
|
||||
|
||||
var signatureId = runtimeEntityType.AddProperty(
|
||||
"SignatureId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("SignatureId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<SignatureId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
signatureId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
signatureId.AddAnnotation("Relational:ColumnName", "signature_id");
|
||||
|
||||
var cveId = runtimeEntityType.AddProperty(
|
||||
"CveId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("CveId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<CveId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 20);
|
||||
cveId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
cveId.AddAnnotation("Relational:ColumnName", "cve_id");
|
||||
|
||||
var symbolName = runtimeEntityType.AddProperty(
|
||||
"SymbolName",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("SymbolName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<SymbolName>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 255);
|
||||
symbolName.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
symbolName.AddAnnotation("Relational:ColumnName", "symbol_name");
|
||||
|
||||
var matchType = runtimeEntityType.AddProperty(
|
||||
"MatchType",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("MatchType", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<MatchType>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 20);
|
||||
matchType.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
matchType.AddAnnotation("Relational:ColumnName", "match_type");
|
||||
|
||||
var confidence = runtimeEntityType.AddProperty(
|
||||
"Confidence",
|
||||
typeof(decimal),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("Confidence", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<Confidence>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: 0m);
|
||||
confidence.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
confidence.AddAnnotation("Relational:ColumnName", "confidence");
|
||||
|
||||
var chunkMatchRatio = runtimeEntityType.AddProperty(
|
||||
"ChunkMatchRatio",
|
||||
typeof(decimal?),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("ChunkMatchRatio", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<ChunkMatchRatio>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
chunkMatchRatio.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
chunkMatchRatio.AddAnnotation("Relational:ColumnName", "chunk_match_ratio");
|
||||
|
||||
var matchedState = runtimeEntityType.AddProperty(
|
||||
"MatchedState",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("MatchedState", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<MatchedState>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 20);
|
||||
matchedState.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
matchedState.AddAnnotation("Relational:ColumnName", "matched_state");
|
||||
|
||||
var scanId = runtimeEntityType.AddProperty(
|
||||
"ScanId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("ScanId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<ScanId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
scanId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
scanId.AddAnnotation("Relational:ColumnName", "scan_id");
|
||||
|
||||
var scannedAt = runtimeEntityType.AddProperty(
|
||||
"ScannedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("ScannedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<ScannedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
scannedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
scannedAt.AddAnnotation("Relational:ColumnName", "scanned_at");
|
||||
scannedAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var explanation = runtimeEntityType.AddProperty(
|
||||
"Explanation",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("Explanation", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<Explanation>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
explanation.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
explanation.AddAnnotation("Relational:ColumnName", "explanation");
|
||||
|
||||
var metadata = runtimeEntityType.AddProperty(
|
||||
"Metadata",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSigMatchDbEntity).GetProperty("Metadata", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSigMatchDbEntity).GetField("<Metadata>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
metadata.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
metadata.AddAnnotation("Relational:ColumnName", "metadata");
|
||||
metadata.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "delta_sig_match_pkey");
|
||||
|
||||
var idx_delta_match_tenant = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId },
|
||||
name: "idx_delta_match_tenant");
|
||||
|
||||
var idx_delta_match_cve = runtimeEntityType.AddIndex(
|
||||
new[] { cveId },
|
||||
name: "idx_delta_match_cve");
|
||||
|
||||
var idx_delta_match_binary = runtimeEntityType.AddIndex(
|
||||
new[] { binaryKey },
|
||||
name: "idx_delta_match_binary");
|
||||
|
||||
var idx_delta_match_scan = runtimeEntityType.AddIndex(
|
||||
new[] { scanId },
|
||||
name: "idx_delta_match_scan");
|
||||
|
||||
var idx_delta_match_state = runtimeEntityType.AddIndex(
|
||||
new[] { matchedState },
|
||||
name: "idx_delta_match_state");
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "binaries");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "delta_sig_match");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class DeltaSignatureDbEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.DeltaSignatureDbEntity",
|
||||
typeof(DeltaSignatureDbEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 20,
|
||||
namedIndexCount: 5,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
id.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var tenantId = runtimeEntityType.AddProperty(
|
||||
"TenantId",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("TenantId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<TenantId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: Guid.Empty);
|
||||
tenantId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
tenantId.AddAnnotation("Relational:ColumnName", "tenant_id");
|
||||
|
||||
var cveId = runtimeEntityType.AddProperty(
|
||||
"CveId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("CveId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<CveId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 20);
|
||||
cveId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
cveId.AddAnnotation("Relational:ColumnName", "cve_id");
|
||||
|
||||
var packageName = runtimeEntityType.AddProperty(
|
||||
"PackageName",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("PackageName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<PackageName>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 255);
|
||||
packageName.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
packageName.AddAnnotation("Relational:ColumnName", "package_name");
|
||||
|
||||
var soname = runtimeEntityType.AddProperty(
|
||||
"Soname",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("Soname", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<Soname>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true,
|
||||
maxLength: 255);
|
||||
soname.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
soname.AddAnnotation("Relational:ColumnName", "soname");
|
||||
|
||||
var arch = runtimeEntityType.AddProperty(
|
||||
"Arch",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("Arch", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<Arch>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 20);
|
||||
arch.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
arch.AddAnnotation("Relational:ColumnName", "arch");
|
||||
|
||||
var abi = runtimeEntityType.AddProperty(
|
||||
"Abi",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("Abi", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<Abi>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 20);
|
||||
abi.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
abi.AddAnnotation("Relational:ColumnName", "abi");
|
||||
|
||||
var recipeId = runtimeEntityType.AddProperty(
|
||||
"RecipeId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("RecipeId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<RecipeId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 50);
|
||||
recipeId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
recipeId.AddAnnotation("Relational:ColumnName", "recipe_id");
|
||||
|
||||
var recipeVersion = runtimeEntityType.AddProperty(
|
||||
"RecipeVersion",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("RecipeVersion", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<RecipeVersion>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 10);
|
||||
recipeVersion.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
recipeVersion.AddAnnotation("Relational:ColumnName", "recipe_version");
|
||||
|
||||
var symbolName = runtimeEntityType.AddProperty(
|
||||
"SymbolName",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("SymbolName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<SymbolName>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 255);
|
||||
symbolName.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
symbolName.AddAnnotation("Relational:ColumnName", "symbol_name");
|
||||
|
||||
var scope = runtimeEntityType.AddProperty(
|
||||
"Scope",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("Scope", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<Scope>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 20);
|
||||
scope.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
scope.AddAnnotation("Relational:ColumnName", "scope");
|
||||
|
||||
var hashAlg = runtimeEntityType.AddProperty(
|
||||
"HashAlg",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("HashAlg", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<HashAlg>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 20);
|
||||
hashAlg.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
hashAlg.AddAnnotation("Relational:ColumnName", "hash_alg");
|
||||
|
||||
var hashHex = runtimeEntityType.AddProperty(
|
||||
"HashHex",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("HashHex", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<HashHex>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 128);
|
||||
hashHex.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
hashHex.AddAnnotation("Relational:ColumnName", "hash_hex");
|
||||
|
||||
var sizeBytes = runtimeEntityType.AddProperty(
|
||||
"SizeBytes",
|
||||
typeof(int),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("SizeBytes", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<SizeBytes>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: 0);
|
||||
sizeBytes.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sizeBytes.AddAnnotation("Relational:ColumnName", "size_bytes");
|
||||
|
||||
var cfgBbCount = runtimeEntityType.AddProperty(
|
||||
"CfgBbCount",
|
||||
typeof(int?),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("CfgBbCount", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<CfgBbCount>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
cfgBbCount.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
cfgBbCount.AddAnnotation("Relational:ColumnName", "cfg_bb_count");
|
||||
|
||||
var cfgEdgeHash = runtimeEntityType.AddProperty(
|
||||
"CfgEdgeHash",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("CfgEdgeHash", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<CfgEdgeHash>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true,
|
||||
maxLength: 128);
|
||||
cfgEdgeHash.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
cfgEdgeHash.AddAnnotation("Relational:ColumnName", "cfg_edge_hash");
|
||||
|
||||
var chunkHashes = runtimeEntityType.AddProperty(
|
||||
"ChunkHashes",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("ChunkHashes", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<ChunkHashes>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
chunkHashes.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
chunkHashes.AddAnnotation("Relational:ColumnName", "chunk_hashes");
|
||||
chunkHashes.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
|
||||
var signatureState = runtimeEntityType.AddProperty(
|
||||
"SignatureState",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("SignatureState", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<SignatureState>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
maxLength: 20);
|
||||
signatureState.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
signatureState.AddAnnotation("Relational:ColumnName", "signature_state");
|
||||
|
||||
var createdAt = runtimeEntityType.AddProperty(
|
||||
"CreatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("CreatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<CreatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
createdAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
createdAt.AddAnnotation("Relational:ColumnName", "created_at");
|
||||
createdAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var updatedAt = runtimeEntityType.AddProperty(
|
||||
"UpdatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("UpdatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<UpdatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
updatedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
updatedAt.AddAnnotation("Relational:ColumnName", "updated_at");
|
||||
updatedAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var attestationDsse = runtimeEntityType.AddProperty(
|
||||
"AttestationDsse",
|
||||
typeof(byte[]),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("AttestationDsse", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<AttestationDsse>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
attestationDsse.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
attestationDsse.AddAnnotation("Relational:ColumnName", "attestation_dsse");
|
||||
|
||||
var metadata = runtimeEntityType.AddProperty(
|
||||
"Metadata",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(DeltaSignatureDbEntity).GetProperty("Metadata", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(DeltaSignatureDbEntity).GetField("<Metadata>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
metadata.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
metadata.AddAnnotation("Relational:ColumnName", "metadata");
|
||||
metadata.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "delta_signature_pkey");
|
||||
|
||||
var idx_delta_sig_tenant = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId },
|
||||
name: "idx_delta_sig_tenant");
|
||||
|
||||
var idx_delta_sig_cve = runtimeEntityType.AddIndex(
|
||||
new[] { cveId },
|
||||
name: "idx_delta_sig_cve");
|
||||
|
||||
var idx_delta_sig_pkg = runtimeEntityType.AddIndex(
|
||||
new[] { packageName, soname },
|
||||
name: "idx_delta_sig_pkg");
|
||||
|
||||
var idx_delta_sig_hash = runtimeEntityType.AddIndex(
|
||||
new[] { hashHex },
|
||||
name: "idx_delta_sig_hash");
|
||||
|
||||
var idx_delta_sig_state = runtimeEntityType.AddIndex(
|
||||
new[] { signatureState },
|
||||
name: "idx_delta_sig_state");
|
||||
|
||||
var idx_delta_sig_arch = runtimeEntityType.AddIndex(
|
||||
new[] { arch, abi },
|
||||
name: "idx_delta_sig_arch");
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "binaries");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "delta_signature");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class FingerprintCorpusMetadataEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.FingerprintCorpusMetadataEntity",
|
||||
typeof(FingerprintCorpusMetadataEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 10,
|
||||
namedIndexCount: 2,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(FingerprintCorpusMetadataEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintCorpusMetadataEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
id.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var tenantId = runtimeEntityType.AddProperty(
|
||||
"TenantId",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(FingerprintCorpusMetadataEntity).GetProperty("TenantId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintCorpusMetadataEntity).GetField("<TenantId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: Guid.Empty);
|
||||
tenantId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
tenantId.AddAnnotation("Relational:ColumnName", "tenant_id");
|
||||
|
||||
var purl = runtimeEntityType.AddProperty(
|
||||
"Purl",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintCorpusMetadataEntity).GetProperty("Purl", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintCorpusMetadataEntity).GetField("<Purl>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
purl.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
purl.AddAnnotation("Relational:ColumnName", "purl");
|
||||
|
||||
var version = runtimeEntityType.AddProperty(
|
||||
"Version",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintCorpusMetadataEntity).GetProperty("Version", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintCorpusMetadataEntity).GetField("<Version>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
version.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
version.AddAnnotation("Relational:ColumnName", "version");
|
||||
|
||||
var algorithm = runtimeEntityType.AddProperty(
|
||||
"Algorithm",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintCorpusMetadataEntity).GetProperty("Algorithm", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintCorpusMetadataEntity).GetField("<Algorithm>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
algorithm.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
algorithm.AddAnnotation("Relational:ColumnName", "algorithm");
|
||||
|
||||
var binaryDigest = runtimeEntityType.AddProperty(
|
||||
"BinaryDigest",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintCorpusMetadataEntity).GetProperty("BinaryDigest", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintCorpusMetadataEntity).GetField("<BinaryDigest>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
binaryDigest.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binaryDigest.AddAnnotation("Relational:ColumnName", "binary_digest");
|
||||
|
||||
var functionCount = runtimeEntityType.AddProperty(
|
||||
"FunctionCount",
|
||||
typeof(int),
|
||||
propertyInfo: typeof(FingerprintCorpusMetadataEntity).GetProperty("FunctionCount", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintCorpusMetadataEntity).GetField("<FunctionCount>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: 0);
|
||||
functionCount.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
functionCount.AddAnnotation("Relational:ColumnName", "function_count");
|
||||
|
||||
var fingerprintsIndexed = runtimeEntityType.AddProperty(
|
||||
"FingerprintsIndexed",
|
||||
typeof(int),
|
||||
propertyInfo: typeof(FingerprintCorpusMetadataEntity).GetProperty("FingerprintsIndexed", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintCorpusMetadataEntity).GetField("<FingerprintsIndexed>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: 0);
|
||||
fingerprintsIndexed.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
fingerprintsIndexed.AddAnnotation("Relational:ColumnName", "fingerprints_indexed");
|
||||
|
||||
var indexedBy = runtimeEntityType.AddProperty(
|
||||
"IndexedBy",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintCorpusMetadataEntity).GetProperty("IndexedBy", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintCorpusMetadataEntity).GetField("<IndexedBy>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
indexedBy.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
indexedBy.AddAnnotation("Relational:ColumnName", "indexed_by");
|
||||
|
||||
var indexedAt = runtimeEntityType.AddProperty(
|
||||
"IndexedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(FingerprintCorpusMetadataEntity).GetProperty("IndexedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintCorpusMetadataEntity).GetField("<IndexedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
indexedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
indexedAt.AddAnnotation("Relational:ColumnName", "indexed_at");
|
||||
indexedAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var createdAt = runtimeEntityType.AddProperty(
|
||||
"CreatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(FingerprintCorpusMetadataEntity).GetProperty("CreatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintCorpusMetadataEntity).GetField("<CreatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
createdAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
createdAt.AddAnnotation("Relational:ColumnName", "created_at");
|
||||
createdAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "fingerprint_corpus_metadata_pkey");
|
||||
|
||||
var idx_fingerprint_corpus_tenant = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId },
|
||||
name: "idx_fingerprint_corpus_tenant");
|
||||
|
||||
var idx_fingerprint_corpus_purl = runtimeEntityType.AddIndex(
|
||||
new[] { purl, version },
|
||||
name: "idx_fingerprint_corpus_purl");
|
||||
|
||||
var fingerprint_corpus_metadata_unique = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, purl, version, algorithm },
|
||||
name: "fingerprint_corpus_metadata_unique",
|
||||
unique: true);
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "binaries");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "fingerprint_corpus_metadata");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class FingerprintMatchEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.FingerprintMatchEntity",
|
||||
typeof(FingerprintMatchEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 16,
|
||||
namedIndexCount: 2,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
id.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var tenantId = runtimeEntityType.AddProperty(
|
||||
"TenantId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("TenantId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<TenantId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
tenantId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
tenantId.AddAnnotation("Relational:ColumnName", "tenant_id");
|
||||
|
||||
var scanId = runtimeEntityType.AddProperty(
|
||||
"ScanId",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("ScanId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<ScanId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: Guid.Empty);
|
||||
scanId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
scanId.AddAnnotation("Relational:ColumnName", "scan_id");
|
||||
|
||||
var matchType = runtimeEntityType.AddProperty(
|
||||
"MatchType",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("MatchType", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<MatchType>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
matchType.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
matchType.AddAnnotation("Relational:ColumnName", "match_type");
|
||||
|
||||
var binaryKey = runtimeEntityType.AddProperty(
|
||||
"BinaryKey",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("BinaryKey", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<BinaryKey>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
binaryKey.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binaryKey.AddAnnotation("Relational:ColumnName", "binary_key");
|
||||
|
||||
var binaryIdentityId = runtimeEntityType.AddProperty(
|
||||
"BinaryIdentityId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("BinaryIdentityId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<BinaryIdentityId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
binaryIdentityId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binaryIdentityId.AddAnnotation("Relational:ColumnName", "binary_identity_id");
|
||||
|
||||
var vulnerablePurl = runtimeEntityType.AddProperty(
|
||||
"VulnerablePurl",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("VulnerablePurl", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<VulnerablePurl>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
vulnerablePurl.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
vulnerablePurl.AddAnnotation("Relational:ColumnName", "vulnerable_purl");
|
||||
|
||||
var vulnerableVersion = runtimeEntityType.AddProperty(
|
||||
"VulnerableVersion",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("VulnerableVersion", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<VulnerableVersion>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
vulnerableVersion.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
vulnerableVersion.AddAnnotation("Relational:ColumnName", "vulnerable_version");
|
||||
|
||||
var matchedFingerprintId = runtimeEntityType.AddProperty(
|
||||
"MatchedFingerprintId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("MatchedFingerprintId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<MatchedFingerprintId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
matchedFingerprintId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
matchedFingerprintId.AddAnnotation("Relational:ColumnName", "matched_fingerprint_id");
|
||||
|
||||
var matchedFunction = runtimeEntityType.AddProperty(
|
||||
"MatchedFunction",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("MatchedFunction", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<MatchedFunction>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
matchedFunction.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
matchedFunction.AddAnnotation("Relational:ColumnName", "matched_function");
|
||||
|
||||
var similarity = runtimeEntityType.AddProperty(
|
||||
"Similarity",
|
||||
typeof(decimal?),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("Similarity", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<Similarity>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
similarity.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
similarity.AddAnnotation("Relational:ColumnName", "similarity");
|
||||
|
||||
var advisoryIds = runtimeEntityType.AddProperty(
|
||||
"AdvisoryIds",
|
||||
typeof(string[]),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("AdvisoryIds", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<AdvisoryIds>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
advisoryIds.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
advisoryIds.AddAnnotation("Relational:ColumnName", "advisory_ids");
|
||||
|
||||
var reachabilityStatus = runtimeEntityType.AddProperty(
|
||||
"ReachabilityStatus",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("ReachabilityStatus", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<ReachabilityStatus>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
reachabilityStatus.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
reachabilityStatus.AddAnnotation("Relational:ColumnName", "reachability_status");
|
||||
|
||||
var evidence = runtimeEntityType.AddProperty(
|
||||
"Evidence",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("Evidence", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<Evidence>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
evidence.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
evidence.AddAnnotation("Relational:ColumnName", "evidence");
|
||||
evidence.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
|
||||
var matchedAt = runtimeEntityType.AddProperty(
|
||||
"MatchedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("MatchedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<MatchedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
matchedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
matchedAt.AddAnnotation("Relational:ColumnName", "matched_at");
|
||||
matchedAt.AddAnnotation("Relational:DefaultValueSql", "now()");
|
||||
|
||||
var createdAt = runtimeEntityType.AddProperty(
|
||||
"CreatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(FingerprintMatchEntity).GetProperty("CreatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FingerprintMatchEntity).GetField("<CreatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
createdAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
createdAt.AddAnnotation("Relational:ColumnName", "created_at");
|
||||
createdAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "fingerprint_matches_pkey");
|
||||
|
||||
var idx_match_scan = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, scanId },
|
||||
name: "idx_match_scan");
|
||||
|
||||
var idx_match_fingerprint = runtimeEntityType.AddIndex(
|
||||
new[] { matchedFingerprintId },
|
||||
name: "idx_match_fingerprint");
|
||||
|
||||
var idx_match_binary = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, binaryKey },
|
||||
name: "idx_match_binary");
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "binaries");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "fingerprint_matches");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class FixEvidenceEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.FixEvidenceEntity",
|
||||
typeof(FixEvidenceEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 8,
|
||||
namedIndexCount: 1,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(FixEvidenceEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FixEvidenceEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
id.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var tenantId = runtimeEntityType.AddProperty(
|
||||
"TenantId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FixEvidenceEntity).GetProperty("TenantId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FixEvidenceEntity).GetField("<TenantId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
tenantId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
tenantId.AddAnnotation("Relational:ColumnName", "tenant_id");
|
||||
|
||||
var evidenceType = runtimeEntityType.AddProperty(
|
||||
"EvidenceType",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FixEvidenceEntity).GetProperty("EvidenceType", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FixEvidenceEntity).GetField("<EvidenceType>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
evidenceType.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
evidenceType.AddAnnotation("Relational:ColumnName", "evidence_type");
|
||||
|
||||
var sourceFile = runtimeEntityType.AddProperty(
|
||||
"SourceFile",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FixEvidenceEntity).GetProperty("SourceFile", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FixEvidenceEntity).GetField("<SourceFile>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
sourceFile.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourceFile.AddAnnotation("Relational:ColumnName", "source_file");
|
||||
|
||||
var sourceSha256 = runtimeEntityType.AddProperty(
|
||||
"SourceSha256",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FixEvidenceEntity).GetProperty("SourceSha256", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FixEvidenceEntity).GetField("<SourceSha256>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
sourceSha256.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourceSha256.AddAnnotation("Relational:ColumnName", "source_sha256");
|
||||
|
||||
var excerpt = runtimeEntityType.AddProperty(
|
||||
"Excerpt",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FixEvidenceEntity).GetProperty("Excerpt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FixEvidenceEntity).GetField("<Excerpt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
excerpt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
excerpt.AddAnnotation("Relational:ColumnName", "excerpt");
|
||||
|
||||
var metadata = runtimeEntityType.AddProperty(
|
||||
"Metadata",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(FixEvidenceEntity).GetProperty("Metadata", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FixEvidenceEntity).GetField("<Metadata>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd);
|
||||
metadata.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
metadata.AddAnnotation("Relational:ColumnName", "metadata");
|
||||
metadata.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
metadata.AddAnnotation("Relational:DefaultValueSql", "'{}'::jsonb");
|
||||
|
||||
var snapshotId = runtimeEntityType.AddProperty(
|
||||
"SnapshotId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(FixEvidenceEntity).GetProperty("SnapshotId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FixEvidenceEntity).GetField("<SnapshotId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
snapshotId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
snapshotId.AddAnnotation("Relational:ColumnName", "snapshot_id");
|
||||
|
||||
var createdAt = runtimeEntityType.AddProperty(
|
||||
"CreatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(FixEvidenceEntity).GetProperty("CreatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(FixEvidenceEntity).GetField("<CreatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
createdAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
createdAt.AddAnnotation("Relational:ColumnName", "created_at");
|
||||
createdAt.AddAnnotation("Relational:DefaultValueSql", "now()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "fix_evidence_pkey");
|
||||
|
||||
var idx_fix_evidence_snapshot = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, snapshotId },
|
||||
name: "idx_fix_evidence_snapshot");
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "binaries");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "fix_evidence");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class RawDocumentEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.RawDocumentEntity",
|
||||
typeof(RawDocumentEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 11,
|
||||
namedIndexCount: 3,
|
||||
keyCount: 1);
|
||||
|
||||
var digest = runtimeEntityType.AddProperty(
|
||||
"Digest",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(RawDocumentEntity).GetProperty("Digest", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(RawDocumentEntity).GetField("<Digest>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
afterSaveBehavior: PropertySaveBehavior.Throw);
|
||||
digest.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
digest.AddAnnotation("Relational:ColumnName", "digest");
|
||||
|
||||
var sourceId = runtimeEntityType.AddProperty(
|
||||
"SourceId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(RawDocumentEntity).GetProperty("SourceId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(RawDocumentEntity).GetField("<SourceId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
sourceId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourceId.AddAnnotation("Relational:ColumnName", "source_id");
|
||||
|
||||
var documentUri = runtimeEntityType.AddProperty(
|
||||
"DocumentUri",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(RawDocumentEntity).GetProperty("DocumentUri", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(RawDocumentEntity).GetField("<DocumentUri>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
documentUri.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
documentUri.AddAnnotation("Relational:ColumnName", "document_uri");
|
||||
|
||||
var contentType = runtimeEntityType.AddProperty(
|
||||
"ContentType",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(RawDocumentEntity).GetProperty("ContentType", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(RawDocumentEntity).GetField("<ContentType>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
contentType.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
contentType.AddAnnotation("Relational:ColumnName", "content_type");
|
||||
|
||||
var contentSize = runtimeEntityType.AddProperty(
|
||||
"ContentSize",
|
||||
typeof(long),
|
||||
propertyInfo: typeof(RawDocumentEntity).GetProperty("ContentSize", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(RawDocumentEntity).GetField("<ContentSize>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: 0L);
|
||||
contentSize.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
contentSize.AddAnnotation("Relational:ColumnName", "content_size");
|
||||
|
||||
var etag = runtimeEntityType.AddProperty(
|
||||
"Etag",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(RawDocumentEntity).GetProperty("Etag", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(RawDocumentEntity).GetField("<Etag>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
etag.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
etag.AddAnnotation("Relational:ColumnName", "etag");
|
||||
|
||||
var fetchedAt = runtimeEntityType.AddProperty(
|
||||
"FetchedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(RawDocumentEntity).GetProperty("FetchedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(RawDocumentEntity).GetField("<FetchedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
fetchedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
fetchedAt.AddAnnotation("Relational:ColumnName", "fetched_at");
|
||||
|
||||
var recordedAt = runtimeEntityType.AddProperty(
|
||||
"RecordedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(RawDocumentEntity).GetProperty("RecordedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(RawDocumentEntity).GetField("<RecordedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
recordedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
recordedAt.AddAnnotation("Relational:ColumnName", "recorded_at");
|
||||
recordedAt.AddAnnotation("Relational:DefaultValueSql", "now()");
|
||||
|
||||
var status = runtimeEntityType.AddProperty(
|
||||
"Status",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(RawDocumentEntity).GetProperty("Status", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(RawDocumentEntity).GetField("<Status>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
status.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
status.AddAnnotation("Relational:ColumnName", "status");
|
||||
|
||||
var payloadId = runtimeEntityType.AddProperty(
|
||||
"PayloadId",
|
||||
typeof(Guid?),
|
||||
propertyInfo: typeof(RawDocumentEntity).GetProperty("PayloadId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(RawDocumentEntity).GetField("<PayloadId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
payloadId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
payloadId.AddAnnotation("Relational:ColumnName", "payload_id");
|
||||
|
||||
var metadata = runtimeEntityType.AddProperty(
|
||||
"Metadata",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(RawDocumentEntity).GetProperty("Metadata", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(RawDocumentEntity).GetField("<Metadata>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd);
|
||||
metadata.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
metadata.AddAnnotation("Relational:ColumnName", "metadata");
|
||||
metadata.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
metadata.AddAnnotation("Relational:DefaultValueSql", "'{}'::jsonb");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { digest });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "raw_documents_pkey");
|
||||
|
||||
var idx_raw_documents_source_id = runtimeEntityType.AddIndex(
|
||||
new[] { sourceId },
|
||||
name: "idx_raw_documents_source_id");
|
||||
|
||||
var idx_raw_documents_status = runtimeEntityType.AddIndex(
|
||||
new[] { status },
|
||||
name: "idx_raw_documents_status");
|
||||
|
||||
var idx_raw_documents_fetched_at = runtimeEntityType.AddIndex(
|
||||
new[] { fetchedAt },
|
||||
name: "idx_raw_documents_fetched_at");
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "groundtruth");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "raw_documents");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class SecurityPairEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.SecurityPairEntity",
|
||||
typeof(SecurityPairEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 16,
|
||||
namedIndexCount: 3,
|
||||
keyCount: 1);
|
||||
|
||||
var pairId = runtimeEntityType.AddProperty(
|
||||
"PairId",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("PairId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<PairId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
pairId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
pairId.AddAnnotation("Relational:ColumnName", "pair_id");
|
||||
pairId.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var cveId = runtimeEntityType.AddProperty(
|
||||
"CveId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("CveId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<CveId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
cveId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
cveId.AddAnnotation("Relational:ColumnName", "cve_id");
|
||||
|
||||
var packageName = runtimeEntityType.AddProperty(
|
||||
"PackageName",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("PackageName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<PackageName>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
packageName.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
packageName.AddAnnotation("Relational:ColumnName", "package_name");
|
||||
|
||||
var distro = runtimeEntityType.AddProperty(
|
||||
"Distro",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("Distro", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<Distro>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
distro.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
distro.AddAnnotation("Relational:ColumnName", "distro");
|
||||
|
||||
var distroVersion = runtimeEntityType.AddProperty(
|
||||
"DistroVersion",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("DistroVersion", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<DistroVersion>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
distroVersion.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
distroVersion.AddAnnotation("Relational:ColumnName", "distro_version");
|
||||
|
||||
var vulnerableVersion = runtimeEntityType.AddProperty(
|
||||
"VulnerableVersion",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("VulnerableVersion", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<VulnerableVersion>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
vulnerableVersion.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
vulnerableVersion.AddAnnotation("Relational:ColumnName", "vulnerable_version");
|
||||
|
||||
var vulnerableDebugId = runtimeEntityType.AddProperty(
|
||||
"VulnerableDebugId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("VulnerableDebugId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<VulnerableDebugId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
vulnerableDebugId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
vulnerableDebugId.AddAnnotation("Relational:ColumnName", "vulnerable_debug_id");
|
||||
|
||||
var vulnerableObservationId = runtimeEntityType.AddProperty(
|
||||
"VulnerableObservationId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("VulnerableObservationId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<VulnerableObservationId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
vulnerableObservationId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
vulnerableObservationId.AddAnnotation("Relational:ColumnName", "vulnerable_observation_id");
|
||||
|
||||
var fixedVersion = runtimeEntityType.AddProperty(
|
||||
"FixedVersion",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("FixedVersion", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<FixedVersion>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
fixedVersion.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
fixedVersion.AddAnnotation("Relational:ColumnName", "fixed_version");
|
||||
|
||||
var fixedDebugId = runtimeEntityType.AddProperty(
|
||||
"FixedDebugId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("FixedDebugId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<FixedDebugId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
fixedDebugId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
fixedDebugId.AddAnnotation("Relational:ColumnName", "fixed_debug_id");
|
||||
|
||||
var fixedObservationId = runtimeEntityType.AddProperty(
|
||||
"FixedObservationId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("FixedObservationId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<FixedObservationId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
fixedObservationId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
fixedObservationId.AddAnnotation("Relational:ColumnName", "fixed_observation_id");
|
||||
|
||||
var upstreamDiffUrl = runtimeEntityType.AddProperty(
|
||||
"UpstreamDiffUrl",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("UpstreamDiffUrl", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<UpstreamDiffUrl>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
upstreamDiffUrl.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
upstreamDiffUrl.AddAnnotation("Relational:ColumnName", "upstream_diff_url");
|
||||
|
||||
var patchFunctions = runtimeEntityType.AddProperty(
|
||||
"PatchFunctions",
|
||||
typeof(string[]),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("PatchFunctions", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<PatchFunctions>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
patchFunctions.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
patchFunctions.AddAnnotation("Relational:ColumnName", "patch_functions");
|
||||
|
||||
var verificationStatus = runtimeEntityType.AddProperty(
|
||||
"VerificationStatus",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("VerificationStatus", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<VerificationStatus>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
verificationStatus.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
verificationStatus.AddAnnotation("Relational:ColumnName", "verification_status");
|
||||
|
||||
var metadata = runtimeEntityType.AddProperty(
|
||||
"Metadata",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("Metadata", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<Metadata>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd);
|
||||
metadata.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
metadata.AddAnnotation("Relational:ColumnName", "metadata");
|
||||
metadata.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
metadata.AddAnnotation("Relational:DefaultValueSql", "'{}'::jsonb");
|
||||
|
||||
var createdAt = runtimeEntityType.AddProperty(
|
||||
"CreatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("CreatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<CreatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
createdAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
createdAt.AddAnnotation("Relational:ColumnName", "created_at");
|
||||
createdAt.AddAnnotation("Relational:DefaultValueSql", "now()");
|
||||
|
||||
var updatedAt = runtimeEntityType.AddProperty(
|
||||
"UpdatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(SecurityPairEntity).GetProperty("UpdatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SecurityPairEntity).GetField("<UpdatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
updatedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
updatedAt.AddAnnotation("Relational:ColumnName", "updated_at");
|
||||
updatedAt.AddAnnotation("Relational:DefaultValueSql", "now()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { pairId });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "security_pairs_pkey");
|
||||
|
||||
var idx_security_pairs_cve_id = runtimeEntityType.AddIndex(
|
||||
new[] { cveId },
|
||||
name: "idx_security_pairs_cve_id");
|
||||
|
||||
var idx_security_pairs_package = runtimeEntityType.AddIndex(
|
||||
new[] { packageName, distro },
|
||||
name: "idx_security_pairs_package");
|
||||
|
||||
var idx_security_pairs_status = runtimeEntityType.AddIndex(
|
||||
new[] { verificationStatus },
|
||||
name: "idx_security_pairs_status");
|
||||
|
||||
var uq_security_pair = runtimeEntityType.AddIndex(
|
||||
new[] { cveId, packageName, distro, vulnerableVersion, fixedVersion },
|
||||
name: "uq_security_pair",
|
||||
unique: true);
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "groundtruth");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "security_pairs");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class SourceStateEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.SourceStateEntity",
|
||||
typeof(SourceStateEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 8,
|
||||
namedIndexCount: 0,
|
||||
keyCount: 1);
|
||||
|
||||
var sourceId = runtimeEntityType.AddProperty(
|
||||
"SourceId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SourceStateEntity).GetProperty("SourceId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SourceStateEntity).GetField("<SourceId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
afterSaveBehavior: PropertySaveBehavior.Throw);
|
||||
sourceId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourceId.AddAnnotation("Relational:ColumnName", "source_id");
|
||||
|
||||
var lastSyncAt = runtimeEntityType.AddProperty(
|
||||
"LastSyncAt",
|
||||
typeof(DateTime?),
|
||||
propertyInfo: typeof(SourceStateEntity).GetProperty("LastSyncAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SourceStateEntity).GetField("<LastSyncAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
lastSyncAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
lastSyncAt.AddAnnotation("Relational:ColumnName", "last_sync_at");
|
||||
|
||||
var cursorPosition = runtimeEntityType.AddProperty(
|
||||
"CursorPosition",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SourceStateEntity).GetProperty("CursorPosition", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SourceStateEntity).GetField("<CursorPosition>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
cursorPosition.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
cursorPosition.AddAnnotation("Relational:ColumnName", "cursor_position");
|
||||
|
||||
var cursorMetadata = runtimeEntityType.AddProperty(
|
||||
"CursorMetadata",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SourceStateEntity).GetProperty("CursorMetadata", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SourceStateEntity).GetField("<CursorMetadata>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
cursorMetadata.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
cursorMetadata.AddAnnotation("Relational:ColumnName", "cursor_metadata");
|
||||
cursorMetadata.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
|
||||
var syncStatus = runtimeEntityType.AddProperty(
|
||||
"SyncStatus",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SourceStateEntity).GetProperty("SyncStatus", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SourceStateEntity).GetField("<SyncStatus>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
syncStatus.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
syncStatus.AddAnnotation("Relational:ColumnName", "sync_status");
|
||||
|
||||
var lastError = runtimeEntityType.AddProperty(
|
||||
"LastError",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SourceStateEntity).GetProperty("LastError", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SourceStateEntity).GetField("<LastError>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
lastError.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
lastError.AddAnnotation("Relational:ColumnName", "last_error");
|
||||
|
||||
var documentCount = runtimeEntityType.AddProperty(
|
||||
"DocumentCount",
|
||||
typeof(long),
|
||||
propertyInfo: typeof(SourceStateEntity).GetProperty("DocumentCount", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SourceStateEntity).GetField("<DocumentCount>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: 0L);
|
||||
documentCount.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
documentCount.AddAnnotation("Relational:ColumnName", "document_count");
|
||||
|
||||
var observationCount = runtimeEntityType.AddProperty(
|
||||
"ObservationCount",
|
||||
typeof(long),
|
||||
propertyInfo: typeof(SourceStateEntity).GetProperty("ObservationCount", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SourceStateEntity).GetField("<ObservationCount>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: 0L);
|
||||
observationCount.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
observationCount.AddAnnotation("Relational:ColumnName", "observation_count");
|
||||
|
||||
var updatedAt = runtimeEntityType.AddProperty(
|
||||
"UpdatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(SourceStateEntity).GetProperty("UpdatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SourceStateEntity).GetField("<UpdatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
updatedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
updatedAt.AddAnnotation("Relational:ColumnName", "updated_at");
|
||||
updatedAt.AddAnnotation("Relational:DefaultValueSql", "now()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { sourceId });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "source_state_pkey");
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "groundtruth");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "source_state");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class SymbolObservationEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.SymbolObservationEntity",
|
||||
typeof(SymbolObservationEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 18,
|
||||
namedIndexCount: 6,
|
||||
keyCount: 1);
|
||||
|
||||
var observationId = runtimeEntityType.AddProperty(
|
||||
"ObservationId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("ObservationId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<ObservationId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
afterSaveBehavior: PropertySaveBehavior.Throw);
|
||||
observationId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
observationId.AddAnnotation("Relational:ColumnName", "observation_id");
|
||||
|
||||
var sourceId = runtimeEntityType.AddProperty(
|
||||
"SourceId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("SourceId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<SourceId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
sourceId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourceId.AddAnnotation("Relational:ColumnName", "source_id");
|
||||
|
||||
var debugId = runtimeEntityType.AddProperty(
|
||||
"DebugId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("DebugId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<DebugId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
debugId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
debugId.AddAnnotation("Relational:ColumnName", "debug_id");
|
||||
|
||||
var codeId = runtimeEntityType.AddProperty(
|
||||
"CodeId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("CodeId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<CodeId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
codeId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
codeId.AddAnnotation("Relational:ColumnName", "code_id");
|
||||
|
||||
var binaryName = runtimeEntityType.AddProperty(
|
||||
"BinaryName",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("BinaryName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<BinaryName>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
binaryName.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binaryName.AddAnnotation("Relational:ColumnName", "binary_name");
|
||||
|
||||
var binaryPath = runtimeEntityType.AddProperty(
|
||||
"BinaryPath",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("BinaryPath", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<BinaryPath>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
binaryPath.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
binaryPath.AddAnnotation("Relational:ColumnName", "binary_path");
|
||||
|
||||
var architecture = runtimeEntityType.AddProperty(
|
||||
"Architecture",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("Architecture", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<Architecture>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
architecture.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
architecture.AddAnnotation("Relational:ColumnName", "architecture");
|
||||
|
||||
var distro = runtimeEntityType.AddProperty(
|
||||
"Distro",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("Distro", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<Distro>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
distro.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
distro.AddAnnotation("Relational:ColumnName", "distro");
|
||||
|
||||
var distroVersion = runtimeEntityType.AddProperty(
|
||||
"DistroVersion",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("DistroVersion", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<DistroVersion>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
distroVersion.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
distroVersion.AddAnnotation("Relational:ColumnName", "distro_version");
|
||||
|
||||
var packageName = runtimeEntityType.AddProperty(
|
||||
"PackageName",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("PackageName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<PackageName>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
packageName.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
packageName.AddAnnotation("Relational:ColumnName", "package_name");
|
||||
|
||||
var packageVersion = runtimeEntityType.AddProperty(
|
||||
"PackageVersion",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("PackageVersion", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<PackageVersion>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
packageVersion.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
packageVersion.AddAnnotation("Relational:ColumnName", "package_version");
|
||||
|
||||
var symbolCount = runtimeEntityType.AddProperty(
|
||||
"SymbolCount",
|
||||
typeof(int),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("SymbolCount", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<SymbolCount>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: 0);
|
||||
symbolCount.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
symbolCount.AddAnnotation("Relational:ColumnName", "symbol_count");
|
||||
|
||||
var symbols = runtimeEntityType.AddProperty(
|
||||
"Symbols",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("Symbols", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<Symbols>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
symbols.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
symbols.AddAnnotation("Relational:ColumnName", "symbols");
|
||||
symbols.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
|
||||
var buildMetadata = runtimeEntityType.AddProperty(
|
||||
"BuildMetadata",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("BuildMetadata", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<BuildMetadata>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
buildMetadata.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
buildMetadata.AddAnnotation("Relational:ColumnName", "build_metadata");
|
||||
buildMetadata.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
|
||||
var provenance = runtimeEntityType.AddProperty(
|
||||
"Provenance",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("Provenance", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<Provenance>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
provenance.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
provenance.AddAnnotation("Relational:ColumnName", "provenance");
|
||||
provenance.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
|
||||
var contentHash = runtimeEntityType.AddProperty(
|
||||
"ContentHash",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("ContentHash", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<ContentHash>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
contentHash.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
contentHash.AddAnnotation("Relational:ColumnName", "content_hash");
|
||||
|
||||
var supersedesId = runtimeEntityType.AddProperty(
|
||||
"SupersedesId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("SupersedesId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<SupersedesId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
supersedesId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
supersedesId.AddAnnotation("Relational:ColumnName", "supersedes_id");
|
||||
|
||||
var createdAt = runtimeEntityType.AddProperty(
|
||||
"CreatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(SymbolObservationEntity).GetProperty("CreatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolObservationEntity).GetField("<CreatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
createdAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
createdAt.AddAnnotation("Relational:ColumnName", "created_at");
|
||||
createdAt.AddAnnotation("Relational:DefaultValueSql", "now()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { observationId });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "symbol_observations_pkey");
|
||||
|
||||
var idx_symbol_observations_debug_id = runtimeEntityType.AddIndex(
|
||||
new[] { debugId },
|
||||
name: "idx_symbol_observations_debug_id");
|
||||
|
||||
var idx_symbol_observations_source_id = runtimeEntityType.AddIndex(
|
||||
new[] { sourceId },
|
||||
name: "idx_symbol_observations_source_id");
|
||||
|
||||
var idx_symbol_observations_binary_name = runtimeEntityType.AddIndex(
|
||||
new[] { binaryName },
|
||||
name: "idx_symbol_observations_binary_name");
|
||||
|
||||
var idx_symbol_observations_package = runtimeEntityType.AddIndex(
|
||||
new[] { packageName, packageVersion },
|
||||
name: "idx_symbol_observations_package");
|
||||
|
||||
var idx_symbol_observations_distro = runtimeEntityType.AddIndex(
|
||||
new[] { distro, distroVersion },
|
||||
name: "idx_symbol_observations_distro");
|
||||
|
||||
var idx_symbol_observations_created_at = runtimeEntityType.AddIndex(
|
||||
new[] { createdAt },
|
||||
name: "idx_symbol_observations_created_at");
|
||||
|
||||
var uq_content_hash = runtimeEntityType.AddIndex(
|
||||
new[] { contentHash },
|
||||
name: "uq_content_hash",
|
||||
unique: true);
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "groundtruth");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "symbol_observations");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class SymbolSourceEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.SymbolSourceEntity",
|
||||
typeof(SymbolSourceEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 9,
|
||||
namedIndexCount: 0,
|
||||
keyCount: 1);
|
||||
|
||||
var sourceId = runtimeEntityType.AddProperty(
|
||||
"SourceId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolSourceEntity).GetProperty("SourceId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolSourceEntity).GetField("<SourceId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
afterSaveBehavior: PropertySaveBehavior.Throw);
|
||||
sourceId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourceId.AddAnnotation("Relational:ColumnName", "source_id");
|
||||
|
||||
var displayName = runtimeEntityType.AddProperty(
|
||||
"DisplayName",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolSourceEntity).GetProperty("DisplayName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolSourceEntity).GetField("<DisplayName>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
displayName.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
displayName.AddAnnotation("Relational:ColumnName", "display_name");
|
||||
|
||||
var sourceType = runtimeEntityType.AddProperty(
|
||||
"SourceType",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolSourceEntity).GetProperty("SourceType", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolSourceEntity).GetField("<SourceType>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
sourceType.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourceType.AddAnnotation("Relational:ColumnName", "source_type");
|
||||
|
||||
var baseUrl = runtimeEntityType.AddProperty(
|
||||
"BaseUrl",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolSourceEntity).GetProperty("BaseUrl", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolSourceEntity).GetField("<BaseUrl>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
baseUrl.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
baseUrl.AddAnnotation("Relational:ColumnName", "base_url");
|
||||
|
||||
var supportedDistros = runtimeEntityType.AddProperty(
|
||||
"SupportedDistros",
|
||||
typeof(string[]),
|
||||
propertyInfo: typeof(SymbolSourceEntity).GetProperty("SupportedDistros", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolSourceEntity).GetField("<SupportedDistros>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
supportedDistros.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
supportedDistros.AddAnnotation("Relational:ColumnName", "supported_distros");
|
||||
|
||||
var isEnabled = runtimeEntityType.AddProperty(
|
||||
"IsEnabled",
|
||||
typeof(bool),
|
||||
propertyInfo: typeof(SymbolSourceEntity).GetProperty("IsEnabled", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolSourceEntity).GetField("<IsEnabled>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
sentinel: false);
|
||||
isEnabled.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
isEnabled.AddAnnotation("Relational:ColumnName", "is_enabled");
|
||||
|
||||
var configJson = runtimeEntityType.AddProperty(
|
||||
"ConfigJson",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(SymbolSourceEntity).GetProperty("ConfigJson", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolSourceEntity).GetField("<ConfigJson>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
configJson.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
configJson.AddAnnotation("Relational:ColumnName", "config_json");
|
||||
configJson.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
|
||||
var createdAt = runtimeEntityType.AddProperty(
|
||||
"CreatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(SymbolSourceEntity).GetProperty("CreatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolSourceEntity).GetField("<CreatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
createdAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
createdAt.AddAnnotation("Relational:ColumnName", "created_at");
|
||||
createdAt.AddAnnotation("Relational:DefaultValueSql", "now()");
|
||||
|
||||
var updatedAt = runtimeEntityType.AddProperty(
|
||||
"UpdatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(SymbolSourceEntity).GetProperty("UpdatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(SymbolSourceEntity).GetField("<UpdatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
updatedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
updatedAt.AddAnnotation("Relational:ColumnName", "updated_at");
|
||||
updatedAt.AddAnnotation("Relational:DefaultValueSql", "now()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { sourceId });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "symbol_sources_pkey");
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "groundtruth");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "symbol_sources");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
#pragma warning disable 219, 612, 618
|
||||
#nullable disable
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels
|
||||
{
|
||||
[EntityFrameworkInternal]
|
||||
public partial class VulnerableFingerprintEntityType
|
||||
{
|
||||
public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType baseEntityType = null)
|
||||
{
|
||||
var runtimeEntityType = model.AddEntityType(
|
||||
"StellaOps.BinaryIndex.Persistence.EfCore.Models.VulnerableFingerprintEntity",
|
||||
typeof(VulnerableFingerprintEntity),
|
||||
baseEntityType,
|
||||
propertyCount: 21,
|
||||
namedIndexCount: 3,
|
||||
keyCount: 1);
|
||||
|
||||
var id = runtimeEntityType.AddProperty(
|
||||
"Id",
|
||||
typeof(Guid),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<Id>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: Guid.Empty);
|
||||
id.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
id.AddAnnotation("Relational:ColumnName", "id");
|
||||
id.AddAnnotation("Relational:DefaultValueSql", "gen_random_uuid()");
|
||||
|
||||
var tenantId = runtimeEntityType.AddProperty(
|
||||
"TenantId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("TenantId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<TenantId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
tenantId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
tenantId.AddAnnotation("Relational:ColumnName", "tenant_id");
|
||||
|
||||
var cveId = runtimeEntityType.AddProperty(
|
||||
"CveId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("CveId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<CveId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
cveId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
cveId.AddAnnotation("Relational:ColumnName", "cve_id");
|
||||
|
||||
var component = runtimeEntityType.AddProperty(
|
||||
"Component",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("Component", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<Component>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
component.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
component.AddAnnotation("Relational:ColumnName", "component");
|
||||
|
||||
var purl = runtimeEntityType.AddProperty(
|
||||
"Purl",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("Purl", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<Purl>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
purl.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
purl.AddAnnotation("Relational:ColumnName", "purl");
|
||||
|
||||
var algorithm = runtimeEntityType.AddProperty(
|
||||
"Algorithm",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("Algorithm", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<Algorithm>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
algorithm.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
algorithm.AddAnnotation("Relational:ColumnName", "algorithm");
|
||||
|
||||
var fingerprintId = runtimeEntityType.AddProperty(
|
||||
"FingerprintId",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("FingerprintId", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<FingerprintId>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
fingerprintId.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
fingerprintId.AddAnnotation("Relational:ColumnName", "fingerprint_id");
|
||||
|
||||
var fingerprintHash = runtimeEntityType.AddProperty(
|
||||
"FingerprintHash",
|
||||
typeof(byte[]),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("FingerprintHash", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<FingerprintHash>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
fingerprintHash.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
fingerprintHash.AddAnnotation("Relational:ColumnName", "fingerprint_hash");
|
||||
|
||||
var architecture = runtimeEntityType.AddProperty(
|
||||
"Architecture",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("Architecture", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<Architecture>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
|
||||
architecture.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
architecture.AddAnnotation("Relational:ColumnName", "architecture");
|
||||
|
||||
var functionName = runtimeEntityType.AddProperty(
|
||||
"FunctionName",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("FunctionName", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<FunctionName>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
functionName.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
functionName.AddAnnotation("Relational:ColumnName", "function_name");
|
||||
|
||||
var sourceFile = runtimeEntityType.AddProperty(
|
||||
"SourceFile",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("SourceFile", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<SourceFile>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
sourceFile.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourceFile.AddAnnotation("Relational:ColumnName", "source_file");
|
||||
|
||||
var sourceLine = runtimeEntityType.AddProperty(
|
||||
"SourceLine",
|
||||
typeof(int?),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("SourceLine", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<SourceLine>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
sourceLine.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
sourceLine.AddAnnotation("Relational:ColumnName", "source_line");
|
||||
|
||||
var similarityThreshold = runtimeEntityType.AddProperty(
|
||||
"SimilarityThreshold",
|
||||
typeof(decimal?),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("SimilarityThreshold", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<SimilarityThreshold>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
similarityThreshold.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
similarityThreshold.AddAnnotation("Relational:ColumnName", "similarity_threshold");
|
||||
|
||||
var confidence = runtimeEntityType.AddProperty(
|
||||
"Confidence",
|
||||
typeof(decimal?),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("Confidence", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<Confidence>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
confidence.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
confidence.AddAnnotation("Relational:ColumnName", "confidence");
|
||||
|
||||
var validated = runtimeEntityType.AddProperty(
|
||||
"Validated",
|
||||
typeof(bool?),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("Validated", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<Validated>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
validated.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
validated.AddAnnotation("Relational:ColumnName", "validated");
|
||||
|
||||
var validationStats = runtimeEntityType.AddProperty(
|
||||
"ValidationStats",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("ValidationStats", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<ValidationStats>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
validationStats.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
validationStats.AddAnnotation("Relational:ColumnName", "validation_stats");
|
||||
validationStats.AddAnnotation("Relational:ColumnType", "jsonb");
|
||||
|
||||
var vulnBuildRef = runtimeEntityType.AddProperty(
|
||||
"VulnBuildRef",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("VulnBuildRef", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<VulnBuildRef>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
vulnBuildRef.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
vulnBuildRef.AddAnnotation("Relational:ColumnName", "vuln_build_ref");
|
||||
|
||||
var fixedBuildRef = runtimeEntityType.AddProperty(
|
||||
"FixedBuildRef",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("FixedBuildRef", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<FixedBuildRef>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
fixedBuildRef.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
fixedBuildRef.AddAnnotation("Relational:ColumnName", "fixed_build_ref");
|
||||
|
||||
var notes = runtimeEntityType.AddProperty(
|
||||
"Notes",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("Notes", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<Notes>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
notes.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
notes.AddAnnotation("Relational:ColumnName", "notes");
|
||||
|
||||
var evidenceRef = runtimeEntityType.AddProperty(
|
||||
"EvidenceRef",
|
||||
typeof(string),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("EvidenceRef", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<EvidenceRef>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
nullable: true);
|
||||
evidenceRef.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
evidenceRef.AddAnnotation("Relational:ColumnName", "evidence_ref");
|
||||
|
||||
var indexedAt = runtimeEntityType.AddProperty(
|
||||
"IndexedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("IndexedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<IndexedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
indexedAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
indexedAt.AddAnnotation("Relational:ColumnName", "indexed_at");
|
||||
indexedAt.AddAnnotation("Relational:DefaultValueSql", "now()");
|
||||
|
||||
var createdAt = runtimeEntityType.AddProperty(
|
||||
"CreatedAt",
|
||||
typeof(DateTime),
|
||||
propertyInfo: typeof(VulnerableFingerprintEntity).GetProperty("CreatedAt", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
fieldInfo: typeof(VulnerableFingerprintEntity).GetField("<CreatedAt>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly),
|
||||
valueGenerated: ValueGenerated.OnAdd,
|
||||
sentinel: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
createdAt.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None);
|
||||
createdAt.AddAnnotation("Relational:ColumnName", "created_at");
|
||||
createdAt.AddAnnotation("Relational:DefaultValueSql", "NOW()");
|
||||
|
||||
var key = runtimeEntityType.AddKey(
|
||||
new[] { id });
|
||||
runtimeEntityType.SetPrimaryKey(key);
|
||||
key.AddAnnotation("Relational:Name", "vulnerable_fingerprints_pkey");
|
||||
|
||||
var idx_fingerprint_cve = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, cveId },
|
||||
name: "idx_fingerprint_cve");
|
||||
|
||||
var idx_fingerprint_component = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, component },
|
||||
name: "idx_fingerprint_component");
|
||||
|
||||
var idx_fingerprint_algorithm = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, algorithm, architecture },
|
||||
name: "idx_fingerprint_algorithm");
|
||||
|
||||
var vulnerable_fingerprints_unique = runtimeEntityType.AddIndex(
|
||||
new[] { tenantId, fingerprintId },
|
||||
name: "vulnerable_fingerprints_unique",
|
||||
unique: true);
|
||||
|
||||
return runtimeEntityType;
|
||||
}
|
||||
|
||||
public static void CreateAnnotations(RuntimeEntityType runtimeEntityType)
|
||||
{
|
||||
runtimeEntityType.AddAnnotation("Relational:FunctionName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:Schema", "binaries");
|
||||
runtimeEntityType.AddAnnotation("Relational:SqlQuery", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:TableName", "vulnerable_fingerprints");
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewName", null);
|
||||
runtimeEntityType.AddAnnotation("Relational:ViewSchema", null);
|
||||
|
||||
Customize(runtimeEntityType);
|
||||
}
|
||||
|
||||
static partial void Customize(RuntimeEntityType runtimeEntityType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,489 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Context;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core DbContext for the BinaryIndex Persistence module.
|
||||
/// Covers tables in the binaries and groundtruth schemas.
|
||||
/// </summary>
|
||||
public partial class BinaryIndexPersistenceDbContext : DbContext
|
||||
{
|
||||
private readonly string _binariesSchema;
|
||||
private readonly string _groundtruthSchema;
|
||||
|
||||
public BinaryIndexPersistenceDbContext(
|
||||
DbContextOptions<BinaryIndexPersistenceDbContext> options,
|
||||
string? binariesSchema = null,
|
||||
string? groundtruthSchema = null)
|
||||
: base(options)
|
||||
{
|
||||
_binariesSchema = string.IsNullOrWhiteSpace(binariesSchema) ? "binaries" : binariesSchema.Trim();
|
||||
_groundtruthSchema = string.IsNullOrWhiteSpace(groundtruthSchema) ? "groundtruth" : groundtruthSchema.Trim();
|
||||
}
|
||||
|
||||
// --- binaries schema ---
|
||||
public virtual DbSet<BinaryIdentityEntity> BinaryIdentities { get; set; }
|
||||
public virtual DbSet<CorpusSnapshotEntity> CorpusSnapshots { get; set; }
|
||||
public virtual DbSet<BinaryVulnAssertionEntity> BinaryVulnAssertions { get; set; }
|
||||
public virtual DbSet<DeltaSignatureDbEntity> DeltaSignatures { get; set; }
|
||||
public virtual DbSet<DeltaSigMatchDbEntity> DeltaSigMatches { get; set; }
|
||||
public virtual DbSet<VulnerableFingerprintEntity> VulnerableFingerprints { get; set; }
|
||||
public virtual DbSet<FingerprintMatchEntity> FingerprintMatches { get; set; }
|
||||
public virtual DbSet<FingerprintCorpusMetadataEntity> FingerprintCorpusMetadata { get; set; }
|
||||
public virtual DbSet<CveFixIndexEntity> CveFixIndexes { get; set; }
|
||||
public virtual DbSet<FixEvidenceEntity> FixEvidences { get; set; }
|
||||
|
||||
// --- groundtruth schema ---
|
||||
public virtual DbSet<SymbolSourceEntity> SymbolSources { get; set; }
|
||||
public virtual DbSet<SourceStateEntity> SourceStates { get; set; }
|
||||
public virtual DbSet<RawDocumentEntity> RawDocuments { get; set; }
|
||||
public virtual DbSet<SymbolObservationEntity> SymbolObservations { get; set; }
|
||||
public virtual DbSet<SecurityPairEntity> SecurityPairs { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
var binaries = _binariesSchema;
|
||||
var groundtruth = _groundtruthSchema;
|
||||
|
||||
// =====================================================================
|
||||
// binaries.binary_identity
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<BinaryIdentityEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("binary_identity_pkey");
|
||||
entity.ToTable("binary_identity", binaries);
|
||||
|
||||
entity.HasIndex(e => e.TenantId, "idx_binary_identity_tenant");
|
||||
entity.HasIndex(e => e.BuildId, "idx_binary_identity_buildid")
|
||||
.HasFilter("(build_id IS NOT NULL)");
|
||||
entity.HasIndex(e => e.FileSha256, "idx_binary_identity_sha256");
|
||||
entity.HasIndex(e => e.BinaryKey, "idx_binary_identity_key");
|
||||
entity.HasIndex(e => new { e.TenantId, e.BinaryKey }, "binary_identity_key_unique").IsUnique();
|
||||
|
||||
entity.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()").HasColumnName("id");
|
||||
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
|
||||
entity.Property(e => e.BinaryKey).HasColumnName("binary_key");
|
||||
entity.Property(e => e.BuildId).HasColumnName("build_id");
|
||||
entity.Property(e => e.BuildIdType).HasColumnName("build_id_type");
|
||||
entity.Property(e => e.FileSha256).HasColumnName("file_sha256");
|
||||
entity.Property(e => e.TextSha256).HasColumnName("text_sha256");
|
||||
entity.Property(e => e.Blake3Hash).HasColumnName("blake3_hash");
|
||||
entity.Property(e => e.Format).HasColumnName("format");
|
||||
entity.Property(e => e.Architecture).HasColumnName("architecture");
|
||||
entity.Property(e => e.Osabi).HasColumnName("osabi");
|
||||
entity.Property(e => e.BinaryType).HasColumnName("binary_type");
|
||||
entity.Property(e => e.IsStripped).HasColumnName("is_stripped");
|
||||
entity.Property(e => e.FirstSeenSnapshotId).HasColumnName("first_seen_snapshot_id");
|
||||
entity.Property(e => e.LastSeenSnapshotId).HasColumnName("last_seen_snapshot_id");
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("NOW()").HasColumnName("created_at");
|
||||
entity.Property(e => e.UpdatedAt).HasDefaultValueSql("NOW()").HasColumnName("updated_at");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// binaries.corpus_snapshots
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<CorpusSnapshotEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("corpus_snapshots_pkey");
|
||||
entity.ToTable("corpus_snapshots", binaries);
|
||||
|
||||
entity.HasIndex(e => e.TenantId, "idx_corpus_snapshots_tenant");
|
||||
entity.HasIndex(e => new { e.Distro, e.Release, e.Architecture }, "idx_corpus_snapshots_distro");
|
||||
entity.HasIndex(e => new { e.TenantId, e.Distro, e.Release, e.Architecture, e.SnapshotId }, "corpus_snapshots_unique").IsUnique();
|
||||
|
||||
entity.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()").HasColumnName("id");
|
||||
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
|
||||
entity.Property(e => e.Distro).HasColumnName("distro");
|
||||
entity.Property(e => e.Release).HasColumnName("release");
|
||||
entity.Property(e => e.Architecture).HasColumnName("architecture");
|
||||
entity.Property(e => e.SnapshotId).HasColumnName("snapshot_id");
|
||||
entity.Property(e => e.PackagesProcessed).HasColumnName("packages_processed");
|
||||
entity.Property(e => e.BinariesIndexed).HasColumnName("binaries_indexed");
|
||||
entity.Property(e => e.RepoMetadataDigest).HasColumnName("repo_metadata_digest");
|
||||
entity.Property(e => e.SigningKeyId).HasColumnName("signing_key_id");
|
||||
entity.Property(e => e.DsseEnvelopeRef).HasColumnName("dsse_envelope_ref");
|
||||
entity.Property(e => e.Status).HasColumnName("status");
|
||||
entity.Property(e => e.Error).HasColumnName("error");
|
||||
entity.Property(e => e.StartedAt).HasColumnName("started_at");
|
||||
entity.Property(e => e.CompletedAt).HasColumnName("completed_at");
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("NOW()").HasColumnName("created_at");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// binaries.binary_vuln_assertion
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<BinaryVulnAssertionEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("binary_vuln_assertion_pkey");
|
||||
entity.ToTable("binary_vuln_assertion", binaries);
|
||||
|
||||
entity.HasIndex(e => e.TenantId, "idx_binary_vuln_assertion_tenant");
|
||||
entity.HasIndex(e => e.BinaryKey, "idx_binary_vuln_assertion_binary");
|
||||
entity.HasIndex(e => e.CveId, "idx_binary_vuln_assertion_cve");
|
||||
entity.HasIndex(e => new { e.TenantId, e.BinaryKey, e.CveId }, "binary_vuln_assertion_unique").IsUnique();
|
||||
|
||||
entity.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()").HasColumnName("id");
|
||||
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
|
||||
entity.Property(e => e.BinaryKey).HasColumnName("binary_key");
|
||||
entity.Property(e => e.BinaryIdentityId).HasColumnName("binary_identity_id");
|
||||
entity.Property(e => e.CveId).HasColumnName("cve_id");
|
||||
entity.Property(e => e.AdvisoryId).HasColumnName("advisory_id");
|
||||
entity.Property(e => e.Status).HasColumnName("status");
|
||||
entity.Property(e => e.Method).HasColumnName("method");
|
||||
entity.Property(e => e.Confidence).HasColumnName("confidence");
|
||||
entity.Property(e => e.EvidenceRef).HasColumnName("evidence_ref");
|
||||
entity.Property(e => e.EvidenceDigest).HasColumnName("evidence_digest");
|
||||
entity.Property(e => e.EvaluatedAt).HasDefaultValueSql("NOW()").HasColumnName("evaluated_at");
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("NOW()").HasColumnName("created_at");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// binaries.delta_signature
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<DeltaSignatureDbEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("delta_signature_pkey");
|
||||
entity.ToTable("delta_signature", binaries);
|
||||
|
||||
entity.HasIndex(e => e.TenantId, "idx_delta_sig_tenant");
|
||||
entity.HasIndex(e => e.CveId, "idx_delta_sig_cve");
|
||||
entity.HasIndex(e => new { e.PackageName, e.Soname }, "idx_delta_sig_pkg");
|
||||
entity.HasIndex(e => e.HashHex, "idx_delta_sig_hash");
|
||||
entity.HasIndex(e => e.SignatureState, "idx_delta_sig_state");
|
||||
entity.HasIndex(e => new { e.Arch, e.Abi }, "idx_delta_sig_arch");
|
||||
|
||||
entity.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()").HasColumnName("id");
|
||||
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
|
||||
entity.Property(e => e.CveId).HasMaxLength(20).HasColumnName("cve_id");
|
||||
entity.Property(e => e.PackageName).HasMaxLength(255).HasColumnName("package_name");
|
||||
entity.Property(e => e.Soname).HasMaxLength(255).HasColumnName("soname");
|
||||
entity.Property(e => e.Arch).HasMaxLength(20).HasColumnName("arch");
|
||||
entity.Property(e => e.Abi).HasMaxLength(20).HasColumnName("abi");
|
||||
entity.Property(e => e.RecipeId).HasMaxLength(50).HasColumnName("recipe_id");
|
||||
entity.Property(e => e.RecipeVersion).HasMaxLength(10).HasColumnName("recipe_version");
|
||||
entity.Property(e => e.SymbolName).HasMaxLength(255).HasColumnName("symbol_name");
|
||||
entity.Property(e => e.Scope).HasMaxLength(20).HasColumnName("scope");
|
||||
entity.Property(e => e.HashAlg).HasMaxLength(20).HasColumnName("hash_alg");
|
||||
entity.Property(e => e.HashHex).HasMaxLength(128).HasColumnName("hash_hex");
|
||||
entity.Property(e => e.SizeBytes).HasColumnName("size_bytes");
|
||||
entity.Property(e => e.CfgBbCount).HasColumnName("cfg_bb_count");
|
||||
entity.Property(e => e.CfgEdgeHash).HasMaxLength(128).HasColumnName("cfg_edge_hash");
|
||||
entity.Property(e => e.ChunkHashes).HasColumnType("jsonb").HasColumnName("chunk_hashes");
|
||||
entity.Property(e => e.SignatureState).HasMaxLength(20).HasColumnName("signature_state");
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("NOW()").HasColumnName("created_at");
|
||||
entity.Property(e => e.UpdatedAt).HasDefaultValueSql("NOW()").HasColumnName("updated_at");
|
||||
entity.Property(e => e.AttestationDsse).HasColumnName("attestation_dsse");
|
||||
entity.Property(e => e.Metadata).HasColumnType("jsonb").HasColumnName("metadata");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// binaries.delta_sig_match
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<DeltaSigMatchDbEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("delta_sig_match_pkey");
|
||||
entity.ToTable("delta_sig_match", binaries);
|
||||
|
||||
entity.HasIndex(e => e.TenantId, "idx_delta_match_tenant");
|
||||
entity.HasIndex(e => e.CveId, "idx_delta_match_cve");
|
||||
entity.HasIndex(e => e.BinaryKey, "idx_delta_match_binary");
|
||||
entity.HasIndex(e => e.ScanId, "idx_delta_match_scan");
|
||||
entity.HasIndex(e => e.MatchedState, "idx_delta_match_state");
|
||||
|
||||
entity.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()").HasColumnName("id");
|
||||
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
|
||||
entity.Property(e => e.BinaryIdentityId).HasColumnName("binary_identity_id");
|
||||
entity.Property(e => e.BinaryKey).HasColumnName("binary_key");
|
||||
entity.Property(e => e.BinarySha256).HasMaxLength(64).HasColumnName("binary_sha256");
|
||||
entity.Property(e => e.SignatureId).HasColumnName("signature_id");
|
||||
entity.Property(e => e.CveId).HasMaxLength(20).HasColumnName("cve_id");
|
||||
entity.Property(e => e.SymbolName).HasMaxLength(255).HasColumnName("symbol_name");
|
||||
entity.Property(e => e.MatchType).HasMaxLength(20).HasColumnName("match_type");
|
||||
entity.Property(e => e.Confidence).HasColumnName("confidence");
|
||||
entity.Property(e => e.ChunkMatchRatio).HasColumnName("chunk_match_ratio");
|
||||
entity.Property(e => e.MatchedState).HasMaxLength(20).HasColumnName("matched_state");
|
||||
entity.Property(e => e.ScanId).HasColumnName("scan_id");
|
||||
entity.Property(e => e.ScannedAt).HasDefaultValueSql("NOW()").HasColumnName("scanned_at");
|
||||
entity.Property(e => e.Explanation).HasColumnName("explanation");
|
||||
entity.Property(e => e.Metadata).HasColumnType("jsonb").HasColumnName("metadata");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// binaries.vulnerable_fingerprints
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<VulnerableFingerprintEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("vulnerable_fingerprints_pkey");
|
||||
entity.ToTable("vulnerable_fingerprints", binaries);
|
||||
|
||||
entity.HasIndex(e => new { e.TenantId, e.CveId }, "idx_fingerprint_cve");
|
||||
entity.HasIndex(e => new { e.TenantId, e.Component }, "idx_fingerprint_component");
|
||||
entity.HasIndex(e => new { e.TenantId, e.Algorithm, e.Architecture }, "idx_fingerprint_algorithm");
|
||||
entity.HasIndex(e => new { e.TenantId, e.FingerprintId }, "vulnerable_fingerprints_unique").IsUnique();
|
||||
|
||||
entity.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()").HasColumnName("id");
|
||||
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
|
||||
entity.Property(e => e.CveId).HasColumnName("cve_id");
|
||||
entity.Property(e => e.Component).HasColumnName("component");
|
||||
entity.Property(e => e.Purl).HasColumnName("purl");
|
||||
entity.Property(e => e.Algorithm).HasColumnName("algorithm");
|
||||
entity.Property(e => e.FingerprintId).HasColumnName("fingerprint_id");
|
||||
entity.Property(e => e.FingerprintHash).HasColumnName("fingerprint_hash");
|
||||
entity.Property(e => e.Architecture).HasColumnName("architecture");
|
||||
entity.Property(e => e.FunctionName).HasColumnName("function_name");
|
||||
entity.Property(e => e.SourceFile).HasColumnName("source_file");
|
||||
entity.Property(e => e.SourceLine).HasColumnName("source_line");
|
||||
entity.Property(e => e.SimilarityThreshold).HasColumnName("similarity_threshold");
|
||||
entity.Property(e => e.Confidence).HasColumnName("confidence");
|
||||
entity.Property(e => e.Validated).HasColumnName("validated");
|
||||
entity.Property(e => e.ValidationStats).HasColumnType("jsonb").HasColumnName("validation_stats");
|
||||
entity.Property(e => e.VulnBuildRef).HasColumnName("vuln_build_ref");
|
||||
entity.Property(e => e.FixedBuildRef).HasColumnName("fixed_build_ref");
|
||||
entity.Property(e => e.Notes).HasColumnName("notes");
|
||||
entity.Property(e => e.EvidenceRef).HasColumnName("evidence_ref");
|
||||
entity.Property(e => e.IndexedAt).HasDefaultValueSql("now()").HasColumnName("indexed_at");
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("NOW()").HasColumnName("created_at");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// binaries.fingerprint_matches
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<FingerprintMatchEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("fingerprint_matches_pkey");
|
||||
entity.ToTable("fingerprint_matches", binaries);
|
||||
|
||||
entity.HasIndex(e => new { e.TenantId, e.ScanId }, "idx_match_scan");
|
||||
entity.HasIndex(e => e.MatchedFingerprintId, "idx_match_fingerprint");
|
||||
entity.HasIndex(e => new { e.TenantId, e.BinaryKey }, "idx_match_binary");
|
||||
|
||||
entity.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()").HasColumnName("id");
|
||||
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
|
||||
entity.Property(e => e.ScanId).HasColumnName("scan_id");
|
||||
entity.Property(e => e.MatchType).HasColumnName("match_type");
|
||||
entity.Property(e => e.BinaryKey).HasColumnName("binary_key");
|
||||
entity.Property(e => e.BinaryIdentityId).HasColumnName("binary_identity_id");
|
||||
entity.Property(e => e.VulnerablePurl).HasColumnName("vulnerable_purl");
|
||||
entity.Property(e => e.VulnerableVersion).HasColumnName("vulnerable_version");
|
||||
entity.Property(e => e.MatchedFingerprintId).HasColumnName("matched_fingerprint_id");
|
||||
entity.Property(e => e.MatchedFunction).HasColumnName("matched_function");
|
||||
entity.Property(e => e.Similarity).HasColumnName("similarity");
|
||||
entity.Property(e => e.AdvisoryIds).HasColumnName("advisory_ids");
|
||||
entity.Property(e => e.ReachabilityStatus).HasColumnName("reachability_status");
|
||||
entity.Property(e => e.Evidence).HasColumnType("jsonb").HasColumnName("evidence");
|
||||
entity.Property(e => e.MatchedAt).HasDefaultValueSql("now()").HasColumnName("matched_at");
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("NOW()").HasColumnName("created_at");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// binaries.fingerprint_corpus_metadata
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<FingerprintCorpusMetadataEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("fingerprint_corpus_metadata_pkey");
|
||||
entity.ToTable("fingerprint_corpus_metadata", binaries);
|
||||
|
||||
entity.HasIndex(e => e.TenantId, "idx_fingerprint_corpus_tenant");
|
||||
entity.HasIndex(e => new { e.Purl, e.Version }, "idx_fingerprint_corpus_purl");
|
||||
entity.HasIndex(e => new { e.TenantId, e.Purl, e.Version, e.Algorithm }, "fingerprint_corpus_metadata_unique").IsUnique();
|
||||
|
||||
entity.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()").HasColumnName("id");
|
||||
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
|
||||
entity.Property(e => e.Purl).HasColumnName("purl");
|
||||
entity.Property(e => e.Version).HasColumnName("version");
|
||||
entity.Property(e => e.Algorithm).HasColumnName("algorithm");
|
||||
entity.Property(e => e.BinaryDigest).HasColumnName("binary_digest");
|
||||
entity.Property(e => e.FunctionCount).HasColumnName("function_count");
|
||||
entity.Property(e => e.FingerprintsIndexed).HasColumnName("fingerprints_indexed");
|
||||
entity.Property(e => e.IndexedBy).HasColumnName("indexed_by");
|
||||
entity.Property(e => e.IndexedAt).HasDefaultValueSql("NOW()").HasColumnName("indexed_at");
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("NOW()").HasColumnName("created_at");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// binaries.cve_fix_index
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<CveFixIndexEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("cve_fix_index_pkey");
|
||||
entity.ToTable("cve_fix_index", binaries);
|
||||
|
||||
entity.HasIndex(e => new { e.TenantId, e.Distro, e.Release, e.SourcePkg, e.CveId }, "idx_cve_fix_lookup");
|
||||
entity.HasIndex(e => new { e.TenantId, e.CveId, e.Distro, e.Release }, "idx_cve_fix_by_cve");
|
||||
entity.HasIndex(e => new { e.TenantId, e.Distro, e.Release, e.SourcePkg, e.CveId, e.Architecture }, "cve_fix_index_unique").IsUnique();
|
||||
|
||||
entity.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()").HasColumnName("id");
|
||||
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
|
||||
entity.Property(e => e.Distro).HasColumnName("distro");
|
||||
entity.Property(e => e.Release).HasColumnName("release");
|
||||
entity.Property(e => e.SourcePkg).HasColumnName("source_pkg");
|
||||
entity.Property(e => e.CveId).HasColumnName("cve_id");
|
||||
entity.Property(e => e.Architecture).HasColumnName("architecture");
|
||||
entity.Property(e => e.State).HasColumnName("state");
|
||||
entity.Property(e => e.FixedVersion).HasColumnName("fixed_version");
|
||||
entity.Property(e => e.Method).HasColumnName("method");
|
||||
entity.Property(e => e.Confidence).HasColumnName("confidence");
|
||||
entity.Property(e => e.EvidenceId).HasColumnName("evidence_id");
|
||||
entity.Property(e => e.SnapshotId).HasColumnName("snapshot_id");
|
||||
entity.Property(e => e.IndexedAt).HasDefaultValueSql("now()").HasColumnName("indexed_at");
|
||||
entity.Property(e => e.UpdatedAt).HasDefaultValueSql("now()").HasColumnName("updated_at");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// binaries.fix_evidence
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<FixEvidenceEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("fix_evidence_pkey");
|
||||
entity.ToTable("fix_evidence", binaries);
|
||||
|
||||
entity.HasIndex(e => new { e.TenantId, e.SnapshotId }, "idx_fix_evidence_snapshot");
|
||||
|
||||
entity.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()").HasColumnName("id");
|
||||
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
|
||||
entity.Property(e => e.EvidenceType).HasColumnName("evidence_type");
|
||||
entity.Property(e => e.SourceFile).HasColumnName("source_file");
|
||||
entity.Property(e => e.SourceSha256).HasColumnName("source_sha256");
|
||||
entity.Property(e => e.Excerpt).HasColumnName("excerpt");
|
||||
entity.Property(e => e.Metadata).HasColumnType("jsonb").HasDefaultValueSql("'{}'::jsonb").HasColumnName("metadata");
|
||||
entity.Property(e => e.SnapshotId).HasColumnName("snapshot_id");
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("now()").HasColumnName("created_at");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// groundtruth.symbol_sources
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<SymbolSourceEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.SourceId).HasName("symbol_sources_pkey");
|
||||
entity.ToTable("symbol_sources", groundtruth);
|
||||
|
||||
entity.Property(e => e.SourceId).HasColumnName("source_id");
|
||||
entity.Property(e => e.DisplayName).HasColumnName("display_name");
|
||||
entity.Property(e => e.SourceType).HasColumnName("source_type");
|
||||
entity.Property(e => e.BaseUrl).HasColumnName("base_url");
|
||||
entity.Property(e => e.SupportedDistros).HasColumnName("supported_distros");
|
||||
entity.Property(e => e.IsEnabled).HasColumnName("is_enabled");
|
||||
entity.Property(e => e.ConfigJson).HasColumnType("jsonb").HasColumnName("config_json");
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("now()").HasColumnName("created_at");
|
||||
entity.Property(e => e.UpdatedAt).HasDefaultValueSql("now()").HasColumnName("updated_at");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// groundtruth.source_state
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<SourceStateEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.SourceId).HasName("source_state_pkey");
|
||||
entity.ToTable("source_state", groundtruth);
|
||||
|
||||
entity.Property(e => e.SourceId).HasColumnName("source_id");
|
||||
entity.Property(e => e.LastSyncAt).HasColumnName("last_sync_at");
|
||||
entity.Property(e => e.CursorPosition).HasColumnName("cursor_position");
|
||||
entity.Property(e => e.CursorMetadata).HasColumnType("jsonb").HasColumnName("cursor_metadata");
|
||||
entity.Property(e => e.SyncStatus).HasColumnName("sync_status");
|
||||
entity.Property(e => e.LastError).HasColumnName("last_error");
|
||||
entity.Property(e => e.DocumentCount).HasColumnName("document_count");
|
||||
entity.Property(e => e.ObservationCount).HasColumnName("observation_count");
|
||||
entity.Property(e => e.UpdatedAt).HasDefaultValueSql("now()").HasColumnName("updated_at");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// groundtruth.raw_documents
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<RawDocumentEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Digest).HasName("raw_documents_pkey");
|
||||
entity.ToTable("raw_documents", groundtruth);
|
||||
|
||||
entity.HasIndex(e => e.SourceId, "idx_raw_documents_source_id");
|
||||
entity.HasIndex(e => e.Status, "idx_raw_documents_status");
|
||||
entity.HasIndex(e => e.FetchedAt, "idx_raw_documents_fetched_at");
|
||||
|
||||
entity.Property(e => e.Digest).HasColumnName("digest");
|
||||
entity.Property(e => e.SourceId).HasColumnName("source_id");
|
||||
entity.Property(e => e.DocumentUri).HasColumnName("document_uri");
|
||||
entity.Property(e => e.ContentType).HasColumnName("content_type");
|
||||
entity.Property(e => e.ContentSize).HasColumnName("content_size");
|
||||
entity.Property(e => e.Etag).HasColumnName("etag");
|
||||
entity.Property(e => e.FetchedAt).HasColumnName("fetched_at");
|
||||
entity.Property(e => e.RecordedAt).HasDefaultValueSql("now()").HasColumnName("recorded_at");
|
||||
entity.Property(e => e.Status).HasColumnName("status");
|
||||
entity.Property(e => e.PayloadId).HasColumnName("payload_id");
|
||||
entity.Property(e => e.Metadata).HasColumnType("jsonb").HasDefaultValueSql("'{}'::jsonb").HasColumnName("metadata");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// groundtruth.symbol_observations
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<SymbolObservationEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.ObservationId).HasName("symbol_observations_pkey");
|
||||
entity.ToTable("symbol_observations", groundtruth);
|
||||
|
||||
entity.HasIndex(e => e.DebugId, "idx_symbol_observations_debug_id");
|
||||
entity.HasIndex(e => e.SourceId, "idx_symbol_observations_source_id");
|
||||
entity.HasIndex(e => e.BinaryName, "idx_symbol_observations_binary_name");
|
||||
entity.HasIndex(e => new { e.PackageName, e.PackageVersion }, "idx_symbol_observations_package");
|
||||
entity.HasIndex(e => new { e.Distro, e.DistroVersion }, "idx_symbol_observations_distro");
|
||||
entity.HasIndex(e => e.CreatedAt, "idx_symbol_observations_created_at");
|
||||
entity.HasIndex(e => e.ContentHash, "uq_content_hash").IsUnique();
|
||||
|
||||
entity.Property(e => e.ObservationId).HasColumnName("observation_id");
|
||||
entity.Property(e => e.SourceId).HasColumnName("source_id");
|
||||
entity.Property(e => e.DebugId).HasColumnName("debug_id");
|
||||
entity.Property(e => e.CodeId).HasColumnName("code_id");
|
||||
entity.Property(e => e.BinaryName).HasColumnName("binary_name");
|
||||
entity.Property(e => e.BinaryPath).HasColumnName("binary_path");
|
||||
entity.Property(e => e.Architecture).HasColumnName("architecture");
|
||||
entity.Property(e => e.Distro).HasColumnName("distro");
|
||||
entity.Property(e => e.DistroVersion).HasColumnName("distro_version");
|
||||
entity.Property(e => e.PackageName).HasColumnName("package_name");
|
||||
entity.Property(e => e.PackageVersion).HasColumnName("package_version");
|
||||
entity.Property(e => e.SymbolCount).HasColumnName("symbol_count");
|
||||
entity.Property(e => e.Symbols).HasColumnType("jsonb").HasColumnName("symbols");
|
||||
entity.Property(e => e.BuildMetadata).HasColumnType("jsonb").HasColumnName("build_metadata");
|
||||
entity.Property(e => e.Provenance).HasColumnType("jsonb").HasColumnName("provenance");
|
||||
entity.Property(e => e.ContentHash).HasColumnName("content_hash");
|
||||
entity.Property(e => e.SupersedesId).HasColumnName("supersedes_id");
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("now()").HasColumnName("created_at");
|
||||
});
|
||||
|
||||
// =====================================================================
|
||||
// groundtruth.security_pairs
|
||||
// =====================================================================
|
||||
modelBuilder.Entity<SecurityPairEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.PairId).HasName("security_pairs_pkey");
|
||||
entity.ToTable("security_pairs", groundtruth);
|
||||
|
||||
entity.HasIndex(e => e.CveId, "idx_security_pairs_cve_id");
|
||||
entity.HasIndex(e => new { e.PackageName, e.Distro }, "idx_security_pairs_package");
|
||||
entity.HasIndex(e => e.VerificationStatus, "idx_security_pairs_status");
|
||||
entity.HasIndex(e => new { e.CveId, e.PackageName, e.Distro, e.VulnerableVersion, e.FixedVersion }, "uq_security_pair").IsUnique();
|
||||
|
||||
entity.Property(e => e.PairId).HasDefaultValueSql("gen_random_uuid()").HasColumnName("pair_id");
|
||||
entity.Property(e => e.CveId).HasColumnName("cve_id");
|
||||
entity.Property(e => e.PackageName).HasColumnName("package_name");
|
||||
entity.Property(e => e.Distro).HasColumnName("distro");
|
||||
entity.Property(e => e.DistroVersion).HasColumnName("distro_version");
|
||||
entity.Property(e => e.VulnerableVersion).HasColumnName("vulnerable_version");
|
||||
entity.Property(e => e.VulnerableDebugId).HasColumnName("vulnerable_debug_id");
|
||||
entity.Property(e => e.VulnerableObservationId).HasColumnName("vulnerable_observation_id");
|
||||
entity.Property(e => e.FixedVersion).HasColumnName("fixed_version");
|
||||
entity.Property(e => e.FixedDebugId).HasColumnName("fixed_debug_id");
|
||||
entity.Property(e => e.FixedObservationId).HasColumnName("fixed_observation_id");
|
||||
entity.Property(e => e.UpstreamDiffUrl).HasColumnName("upstream_diff_url");
|
||||
entity.Property(e => e.PatchFunctions).HasColumnName("patch_functions");
|
||||
entity.Property(e => e.VerificationStatus).HasColumnName("verification_status");
|
||||
entity.Property(e => e.Metadata).HasColumnType("jsonb").HasDefaultValueSql("'{}'::jsonb").HasColumnName("metadata");
|
||||
entity.Property(e => e.CreatedAt).HasDefaultValueSql("now()").HasColumnName("created_at");
|
||||
entity.Property(e => e.UpdatedAt).HasDefaultValueSql("now()").HasColumnName("updated_at");
|
||||
});
|
||||
|
||||
OnModelCreatingPartial(modelBuilder);
|
||||
}
|
||||
|
||||
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Context;
|
||||
|
||||
/// <summary>
|
||||
/// Design-time factory for EF Core CLI tooling (scaffold, optimize).
|
||||
/// </summary>
|
||||
public sealed class BinaryIndexPersistenceDesignTimeDbContextFactory
|
||||
: IDesignTimeDbContextFactory<BinaryIndexPersistenceDbContext>
|
||||
{
|
||||
private const string DefaultConnectionString =
|
||||
"Host=localhost;Port=55433;Database=postgres;Username=postgres;Password=postgres;Search Path=binaries,groundtruth,public";
|
||||
private const string ConnectionStringEnvironmentVariable =
|
||||
"STELLAOPS_BINARYINDEX_EF_CONNECTION";
|
||||
|
||||
public BinaryIndexPersistenceDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
var connectionString = ResolveConnectionString();
|
||||
var options = new DbContextOptionsBuilder<BinaryIndexPersistenceDbContext>()
|
||||
.UseNpgsql(connectionString)
|
||||
.Options;
|
||||
|
||||
return new BinaryIndexPersistenceDbContext(options);
|
||||
}
|
||||
|
||||
private static string ResolveConnectionString()
|
||||
{
|
||||
var fromEnvironment = Environment.GetEnvironmentVariable(ConnectionStringEnvironmentVariable);
|
||||
return string.IsNullOrWhiteSpace(fromEnvironment) ? DefaultConnectionString : fromEnvironment;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for binaries.binary_identity table.
|
||||
/// </summary>
|
||||
public partial class BinaryIdentityEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TenantId { get; set; }
|
||||
public string BinaryKey { get; set; } = null!;
|
||||
public string? BuildId { get; set; }
|
||||
public string? BuildIdType { get; set; }
|
||||
public string FileSha256 { get; set; } = null!;
|
||||
public string? TextSha256 { get; set; }
|
||||
public string? Blake3Hash { get; set; }
|
||||
public string Format { get; set; } = null!;
|
||||
public string Architecture { get; set; } = null!;
|
||||
public string? Osabi { get; set; }
|
||||
public string? BinaryType { get; set; }
|
||||
public bool? IsStripped { get; set; }
|
||||
public Guid? FirstSeenSnapshotId { get; set; }
|
||||
public Guid? LastSeenSnapshotId { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for binaries.binary_vuln_assertion table.
|
||||
/// </summary>
|
||||
public partial class BinaryVulnAssertionEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TenantId { get; set; }
|
||||
public string BinaryKey { get; set; } = null!;
|
||||
public Guid? BinaryIdentityId { get; set; }
|
||||
public string CveId { get; set; } = null!;
|
||||
public Guid? AdvisoryId { get; set; }
|
||||
public string Status { get; set; } = null!;
|
||||
public string Method { get; set; } = null!;
|
||||
public decimal? Confidence { get; set; }
|
||||
public string? EvidenceRef { get; set; }
|
||||
public string? EvidenceDigest { get; set; }
|
||||
public DateTime EvaluatedAt { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for binaries.corpus_snapshots table.
|
||||
/// </summary>
|
||||
public partial class CorpusSnapshotEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TenantId { get; set; }
|
||||
public string Distro { get; set; } = null!;
|
||||
public string Release { get; set; } = null!;
|
||||
public string Architecture { get; set; } = null!;
|
||||
public string SnapshotId { get; set; } = null!;
|
||||
public int PackagesProcessed { get; set; }
|
||||
public int BinariesIndexed { get; set; }
|
||||
public string? RepoMetadataDigest { get; set; }
|
||||
public string? SigningKeyId { get; set; }
|
||||
public string? DsseEnvelopeRef { get; set; }
|
||||
public string Status { get; set; } = null!;
|
||||
public string? Error { get; set; }
|
||||
public DateTime? StartedAt { get; set; }
|
||||
public DateTime? CompletedAt { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for binaries.cve_fix_index table.
|
||||
/// </summary>
|
||||
public partial class CveFixIndexEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string TenantId { get; set; } = null!;
|
||||
public string Distro { get; set; } = null!;
|
||||
public string Release { get; set; } = null!;
|
||||
public string SourcePkg { get; set; } = null!;
|
||||
public string CveId { get; set; } = null!;
|
||||
public string? Architecture { get; set; }
|
||||
public string State { get; set; } = null!;
|
||||
public string? FixedVersion { get; set; }
|
||||
public string Method { get; set; } = null!;
|
||||
public decimal Confidence { get; set; }
|
||||
public Guid? EvidenceId { get; set; }
|
||||
public Guid? SnapshotId { get; set; }
|
||||
public DateTime IndexedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for binaries.delta_sig_match table.
|
||||
/// </summary>
|
||||
public partial class DeltaSigMatchDbEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TenantId { get; set; }
|
||||
public Guid? BinaryIdentityId { get; set; }
|
||||
public string BinaryKey { get; set; } = null!;
|
||||
public string? BinarySha256 { get; set; }
|
||||
public Guid? SignatureId { get; set; }
|
||||
public string CveId { get; set; } = null!;
|
||||
public string SymbolName { get; set; } = null!;
|
||||
public string MatchType { get; set; } = null!;
|
||||
public decimal Confidence { get; set; }
|
||||
public decimal? ChunkMatchRatio { get; set; }
|
||||
public string MatchedState { get; set; } = null!;
|
||||
public Guid? ScanId { get; set; }
|
||||
public DateTime ScannedAt { get; set; }
|
||||
public string? Explanation { get; set; }
|
||||
public string? Metadata { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for binaries.delta_signature table.
|
||||
/// </summary>
|
||||
public partial class DeltaSignatureDbEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TenantId { get; set; }
|
||||
public string CveId { get; set; } = null!;
|
||||
public string PackageName { get; set; } = null!;
|
||||
public string? Soname { get; set; }
|
||||
public string Arch { get; set; } = null!;
|
||||
public string Abi { get; set; } = null!;
|
||||
public string RecipeId { get; set; } = null!;
|
||||
public string RecipeVersion { get; set; } = null!;
|
||||
public string SymbolName { get; set; } = null!;
|
||||
public string Scope { get; set; } = null!;
|
||||
public string HashAlg { get; set; } = null!;
|
||||
public string HashHex { get; set; } = null!;
|
||||
public int SizeBytes { get; set; }
|
||||
public int? CfgBbCount { get; set; }
|
||||
public string? CfgEdgeHash { get; set; }
|
||||
public string? ChunkHashes { get; set; }
|
||||
public string SignatureState { get; set; } = null!;
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
public byte[]? AttestationDsse { get; set; }
|
||||
public string? Metadata { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for binaries.fingerprint_corpus_metadata table.
|
||||
/// </summary>
|
||||
public partial class FingerprintCorpusMetadataEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TenantId { get; set; }
|
||||
public string Purl { get; set; } = null!;
|
||||
public string Version { get; set; } = null!;
|
||||
public string Algorithm { get; set; } = null!;
|
||||
public string? BinaryDigest { get; set; }
|
||||
public int FunctionCount { get; set; }
|
||||
public int FingerprintsIndexed { get; set; }
|
||||
public string? IndexedBy { get; set; }
|
||||
public DateTime IndexedAt { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for binaries.fingerprint_matches table.
|
||||
/// </summary>
|
||||
public partial class FingerprintMatchEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string TenantId { get; set; } = null!;
|
||||
public Guid ScanId { get; set; }
|
||||
public string MatchType { get; set; } = null!;
|
||||
public string BinaryKey { get; set; } = null!;
|
||||
public Guid? BinaryIdentityId { get; set; }
|
||||
public string VulnerablePurl { get; set; } = null!;
|
||||
public string VulnerableVersion { get; set; } = null!;
|
||||
public Guid? MatchedFingerprintId { get; set; }
|
||||
public string? MatchedFunction { get; set; }
|
||||
public decimal? Similarity { get; set; }
|
||||
public string[]? AdvisoryIds { get; set; }
|
||||
public string? ReachabilityStatus { get; set; }
|
||||
public string? Evidence { get; set; }
|
||||
public DateTime MatchedAt { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for binaries.fix_evidence table.
|
||||
/// </summary>
|
||||
public partial class FixEvidenceEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string TenantId { get; set; } = null!;
|
||||
public string EvidenceType { get; set; } = null!;
|
||||
public string? SourceFile { get; set; }
|
||||
public string? SourceSha256 { get; set; }
|
||||
public string? Excerpt { get; set; }
|
||||
public string Metadata { get; set; } = null!;
|
||||
public Guid? SnapshotId { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for groundtruth.raw_documents table.
|
||||
/// </summary>
|
||||
public partial class RawDocumentEntity
|
||||
{
|
||||
public string Digest { get; set; } = null!;
|
||||
public string SourceId { get; set; } = null!;
|
||||
public string DocumentUri { get; set; } = null!;
|
||||
public string ContentType { get; set; } = null!;
|
||||
public long ContentSize { get; set; }
|
||||
public string? Etag { get; set; }
|
||||
public DateTime FetchedAt { get; set; }
|
||||
public DateTime RecordedAt { get; set; }
|
||||
public string Status { get; set; } = null!;
|
||||
public Guid? PayloadId { get; set; }
|
||||
public string Metadata { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for groundtruth.security_pairs table.
|
||||
/// </summary>
|
||||
public partial class SecurityPairEntity
|
||||
{
|
||||
public Guid PairId { get; set; }
|
||||
public string CveId { get; set; } = null!;
|
||||
public string PackageName { get; set; } = null!;
|
||||
public string Distro { get; set; } = null!;
|
||||
public string? DistroVersion { get; set; }
|
||||
public string VulnerableVersion { get; set; } = null!;
|
||||
public string? VulnerableDebugId { get; set; }
|
||||
public string? VulnerableObservationId { get; set; }
|
||||
public string FixedVersion { get; set; } = null!;
|
||||
public string? FixedDebugId { get; set; }
|
||||
public string? FixedObservationId { get; set; }
|
||||
public string? UpstreamDiffUrl { get; set; }
|
||||
public string[]? PatchFunctions { get; set; }
|
||||
public string VerificationStatus { get; set; } = null!;
|
||||
public string Metadata { get; set; } = null!;
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for groundtruth.source_state table.
|
||||
/// </summary>
|
||||
public partial class SourceStateEntity
|
||||
{
|
||||
public string SourceId { get; set; } = null!;
|
||||
public DateTime? LastSyncAt { get; set; }
|
||||
public string? CursorPosition { get; set; }
|
||||
public string? CursorMetadata { get; set; }
|
||||
public string SyncStatus { get; set; } = null!;
|
||||
public string? LastError { get; set; }
|
||||
public long DocumentCount { get; set; }
|
||||
public long ObservationCount { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for groundtruth.symbol_observations table.
|
||||
/// </summary>
|
||||
public partial class SymbolObservationEntity
|
||||
{
|
||||
public string ObservationId { get; set; } = null!;
|
||||
public string SourceId { get; set; } = null!;
|
||||
public string DebugId { get; set; } = null!;
|
||||
public string? CodeId { get; set; }
|
||||
public string BinaryName { get; set; } = null!;
|
||||
public string? BinaryPath { get; set; }
|
||||
public string Architecture { get; set; } = null!;
|
||||
public string? Distro { get; set; }
|
||||
public string? DistroVersion { get; set; }
|
||||
public string? PackageName { get; set; }
|
||||
public string? PackageVersion { get; set; }
|
||||
public int SymbolCount { get; set; }
|
||||
public string Symbols { get; set; } = null!;
|
||||
public string? BuildMetadata { get; set; }
|
||||
public string Provenance { get; set; } = null!;
|
||||
public string ContentHash { get; set; } = null!;
|
||||
public string? SupersedesId { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for groundtruth.symbol_sources table.
|
||||
/// </summary>
|
||||
public partial class SymbolSourceEntity
|
||||
{
|
||||
public string SourceId { get; set; } = null!;
|
||||
public string DisplayName { get; set; } = null!;
|
||||
public string SourceType { get; set; } = null!;
|
||||
public string BaseUrl { get; set; } = null!;
|
||||
public string[] SupportedDistros { get; set; } = null!;
|
||||
public bool IsEnabled { get; set; }
|
||||
public string? ConfigJson { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
/// <summary>
|
||||
/// EF Core entity for binaries.vulnerable_fingerprints table.
|
||||
/// </summary>
|
||||
public partial class VulnerableFingerprintEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string TenantId { get; set; } = null!;
|
||||
public string CveId { get; set; } = null!;
|
||||
public string Component { get; set; } = null!;
|
||||
public string? Purl { get; set; }
|
||||
public string Algorithm { get; set; } = null!;
|
||||
public string FingerprintId { get; set; } = null!;
|
||||
public byte[] FingerprintHash { get; set; } = null!;
|
||||
public string Architecture { get; set; } = null!;
|
||||
public string? FunctionName { get; set; }
|
||||
public string? SourceFile { get; set; }
|
||||
public int? SourceLine { get; set; }
|
||||
public decimal? SimilarityThreshold { get; set; }
|
||||
public decimal? Confidence { get; set; }
|
||||
public bool? Validated { get; set; }
|
||||
public string? ValidationStats { get; set; }
|
||||
public string? VulnBuildRef { get; set; }
|
||||
public string? FixedBuildRef { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
public string? EvidenceRef { get; set; }
|
||||
public DateTime IndexedAt { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Npgsql;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.CompiledModels;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Context;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.Postgres;
|
||||
|
||||
/// <summary>
|
||||
/// Runtime factory for BinaryIndex EF Core DbContext.
|
||||
/// Uses compiled model for the default schema path.
|
||||
/// </summary>
|
||||
internal static class BinaryIndexPersistenceDbContextFactory
|
||||
{
|
||||
public const string DefaultBinariesSchema = "binaries";
|
||||
public const string DefaultGroundtruthSchema = "groundtruth";
|
||||
|
||||
public static BinaryIndexPersistenceDbContext Create(
|
||||
NpgsqlConnection connection,
|
||||
int commandTimeoutSeconds,
|
||||
string? binariesSchema = null,
|
||||
string? groundtruthSchema = null)
|
||||
{
|
||||
var normalizedBinaries = string.IsNullOrWhiteSpace(binariesSchema)
|
||||
? DefaultBinariesSchema
|
||||
: binariesSchema.Trim();
|
||||
|
||||
var normalizedGroundtruth = string.IsNullOrWhiteSpace(groundtruthSchema)
|
||||
? DefaultGroundtruthSchema
|
||||
: groundtruthSchema.Trim();
|
||||
|
||||
var optionsBuilder = new DbContextOptionsBuilder<BinaryIndexPersistenceDbContext>()
|
||||
.UseNpgsql(connection, npgsql => npgsql.CommandTimeout(commandTimeoutSeconds));
|
||||
|
||||
if (string.Equals(normalizedBinaries, DefaultBinariesSchema, StringComparison.Ordinal)
|
||||
&& string.Equals(normalizedGroundtruth, DefaultGroundtruthSchema, StringComparison.Ordinal))
|
||||
{
|
||||
// Use the static compiled model when schema mapping matches the defaults.
|
||||
optionsBuilder.UseModel(BinaryIndexPersistenceDbContextModel.Instance);
|
||||
}
|
||||
|
||||
return new BinaryIndexPersistenceDbContext(
|
||||
optionsBuilder.Options, normalizedBinaries, normalizedGroundtruth);
|
||||
}
|
||||
}
|
||||
@@ -1,265 +1,135 @@
|
||||
|
||||
using Dapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using StellaOps.BinaryIndex.Core.Models;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Context;
|
||||
using StellaOps.BinaryIndex.Persistence.Postgres;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Repository implementation for binary identity operations.
|
||||
/// EF Core repository implementation for binary identity operations.
|
||||
/// </summary>
|
||||
public sealed class BinaryIdentityRepository : IBinaryIdentityRepository
|
||||
{
|
||||
private readonly BinaryIndexDbContext _dbContext;
|
||||
private readonly BinaryIndexDbContext _connectionContext;
|
||||
private const int CommandTimeoutSeconds = 30;
|
||||
|
||||
public BinaryIdentityRepository(BinaryIndexDbContext dbContext)
|
||||
public BinaryIdentityRepository(BinaryIndexDbContext connectionContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_connectionContext = connectionContext;
|
||||
}
|
||||
|
||||
public async Task<BinaryIdentity?> GetByBuildIdAsync(string buildId, string buildIdType, CancellationToken ct)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var conn = await _connectionContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id AS "Id",
|
||||
tenant_id AS "TenantId",
|
||||
binary_key AS "BinaryKey",
|
||||
build_id AS "BuildId",
|
||||
build_id_type AS "BuildIdType",
|
||||
file_sha256 AS "FileSha256",
|
||||
text_sha256 AS "TextSha256",
|
||||
blake3_hash AS "Blake3Hash",
|
||||
format AS "Format",
|
||||
architecture AS "Architecture",
|
||||
osabi AS "OsAbi",
|
||||
binary_type AS "BinaryType",
|
||||
is_stripped AS "IsStripped",
|
||||
first_seen_snapshot_id AS "FirstSeenSnapshotId",
|
||||
last_seen_snapshot_id AS "LastSeenSnapshotId",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM binaries.binary_identity
|
||||
WHERE build_id = @BuildId AND build_id_type = @BuildIdType
|
||||
LIMIT 1
|
||||
""";
|
||||
var entity = await dbContext.BinaryIdentities
|
||||
.AsNoTracking()
|
||||
.Where(e => e.BuildId == buildId && e.BuildIdType == buildIdType)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { BuildId = buildId, BuildIdType = buildIdType },
|
||||
cancellationToken: ct);
|
||||
var row = await conn.QuerySingleOrDefaultAsync<BinaryIdentityRow>(command);
|
||||
return row?.ToModel();
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
public async Task<BinaryIdentity?> GetByKeyAsync(string binaryKey, CancellationToken ct)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var conn = await _connectionContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id AS "Id",
|
||||
tenant_id AS "TenantId",
|
||||
binary_key AS "BinaryKey",
|
||||
build_id AS "BuildId",
|
||||
build_id_type AS "BuildIdType",
|
||||
file_sha256 AS "FileSha256",
|
||||
text_sha256 AS "TextSha256",
|
||||
blake3_hash AS "Blake3Hash",
|
||||
format AS "Format",
|
||||
architecture AS "Architecture",
|
||||
osabi AS "OsAbi",
|
||||
binary_type AS "BinaryType",
|
||||
is_stripped AS "IsStripped",
|
||||
first_seen_snapshot_id AS "FirstSeenSnapshotId",
|
||||
last_seen_snapshot_id AS "LastSeenSnapshotId",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM binaries.binary_identity
|
||||
WHERE binary_key = @BinaryKey
|
||||
LIMIT 1
|
||||
""";
|
||||
var entity = await dbContext.BinaryIdentities
|
||||
.AsNoTracking()
|
||||
.Where(e => e.BinaryKey == binaryKey)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { BinaryKey = binaryKey },
|
||||
cancellationToken: ct);
|
||||
var row = await conn.QuerySingleOrDefaultAsync<BinaryIdentityRow>(command);
|
||||
return row?.ToModel();
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
public async Task<BinaryIdentity?> GetByFileSha256Async(string fileSha256, CancellationToken ct)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var conn = await _connectionContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id AS "Id",
|
||||
tenant_id AS "TenantId",
|
||||
binary_key AS "BinaryKey",
|
||||
build_id AS "BuildId",
|
||||
build_id_type AS "BuildIdType",
|
||||
file_sha256 AS "FileSha256",
|
||||
text_sha256 AS "TextSha256",
|
||||
blake3_hash AS "Blake3Hash",
|
||||
format AS "Format",
|
||||
architecture AS "Architecture",
|
||||
osabi AS "OsAbi",
|
||||
binary_type AS "BinaryType",
|
||||
is_stripped AS "IsStripped",
|
||||
first_seen_snapshot_id AS "FirstSeenSnapshotId",
|
||||
last_seen_snapshot_id AS "LastSeenSnapshotId",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM binaries.binary_identity
|
||||
WHERE file_sha256 = @FileSha256
|
||||
ORDER BY updated_at DESC
|
||||
LIMIT 1
|
||||
""";
|
||||
var entity = await dbContext.BinaryIdentities
|
||||
.AsNoTracking()
|
||||
.Where(e => e.FileSha256 == fileSha256)
|
||||
.OrderByDescending(e => e.UpdatedAt)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { FileSha256 = fileSha256 },
|
||||
cancellationToken: ct);
|
||||
var row = await conn.QuerySingleOrDefaultAsync<BinaryIdentityRow>(command);
|
||||
return row?.ToModel();
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
public async Task<BinaryIdentity> UpsertAsync(BinaryIdentity identity, CancellationToken ct)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
// Complex UPSERT with ON CONFLICT requires raw SQL through EF Core
|
||||
await using var conn = await _connectionContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
INSERT INTO binaries.binary_identity (
|
||||
tenant_id, binary_key, build_id, build_id_type, file_sha256, text_sha256, blake3_hash,
|
||||
format, architecture, osabi, binary_type, is_stripped, first_seen_snapshot_id,
|
||||
last_seen_snapshot_id, created_at, updated_at
|
||||
) VALUES (
|
||||
current_setting('app.tenant_id')::uuid, @BinaryKey, @BuildId, @BuildIdType, @FileSha256,
|
||||
@TextSha256, @Blake3Hash, @Format, @Architecture, @OsAbi, @BinaryType, @IsStripped,
|
||||
@FirstSeenSnapshotId, @LastSeenSnapshotId, @CreatedAt, @UpdatedAt
|
||||
)
|
||||
ON CONFLICT (tenant_id, binary_key) DO UPDATE SET
|
||||
updated_at = EXCLUDED.updated_at,
|
||||
last_seen_snapshot_id = EXCLUDED.last_seen_snapshot_id
|
||||
RETURNING id AS "Id",
|
||||
tenant_id AS "TenantId",
|
||||
binary_key AS "BinaryKey",
|
||||
build_id AS "BuildId",
|
||||
build_id_type AS "BuildIdType",
|
||||
file_sha256 AS "FileSha256",
|
||||
text_sha256 AS "TextSha256",
|
||||
blake3_hash AS "Blake3Hash",
|
||||
format AS "Format",
|
||||
architecture AS "Architecture",
|
||||
osabi AS "OsAbi",
|
||||
binary_type AS "BinaryType",
|
||||
is_stripped AS "IsStripped",
|
||||
first_seen_snapshot_id AS "FirstSeenSnapshotId",
|
||||
last_seen_snapshot_id AS "LastSeenSnapshotId",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
""";
|
||||
var results = await dbContext.BinaryIdentities
|
||||
.FromSqlInterpolated($"""
|
||||
INSERT INTO binaries.binary_identity (
|
||||
tenant_id, binary_key, build_id, build_id_type, file_sha256, text_sha256, blake3_hash,
|
||||
format, architecture, osabi, binary_type, is_stripped, first_seen_snapshot_id,
|
||||
last_seen_snapshot_id, created_at, updated_at
|
||||
) VALUES (
|
||||
current_setting('app.tenant_id')::uuid, {identity.BinaryKey}, {identity.BuildId}, {identity.BuildIdType}, {identity.FileSha256},
|
||||
{identity.TextSha256}, {identity.Blake3Hash}, {identity.Format.ToString().ToLowerInvariant()}, {identity.Architecture}, {identity.OsAbi}, {ToDbBinaryType(identity.Type)}, {identity.IsStripped},
|
||||
{identity.FirstSeenSnapshotId}, {identity.LastSeenSnapshotId}, {identity.CreatedAt}, {identity.UpdatedAt}
|
||||
)
|
||||
ON CONFLICT (tenant_id, binary_key) DO UPDATE SET
|
||||
updated_at = EXCLUDED.updated_at,
|
||||
last_seen_snapshot_id = EXCLUDED.last_seen_snapshot_id
|
||||
RETURNING id, tenant_id, binary_key, build_id, build_id_type, file_sha256, text_sha256,
|
||||
blake3_hash, format, architecture, osabi, binary_type, is_stripped,
|
||||
first_seen_snapshot_id, last_seen_snapshot_id, created_at, updated_at
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
identity.BinaryKey,
|
||||
identity.BuildId,
|
||||
identity.BuildIdType,
|
||||
identity.FileSha256,
|
||||
identity.TextSha256,
|
||||
identity.Blake3Hash,
|
||||
Format = identity.Format.ToString().ToLowerInvariant(),
|
||||
identity.Architecture,
|
||||
identity.OsAbi,
|
||||
BinaryType = ToDbBinaryType(identity.Type),
|
||||
identity.IsStripped,
|
||||
identity.FirstSeenSnapshotId,
|
||||
identity.LastSeenSnapshotId,
|
||||
identity.CreatedAt,
|
||||
identity.UpdatedAt
|
||||
},
|
||||
cancellationToken: ct);
|
||||
var row = await conn.QuerySingleAsync<BinaryIdentityRow>(command);
|
||||
|
||||
return row.ToModel();
|
||||
var row = results.First();
|
||||
return ToModel(row);
|
||||
}
|
||||
|
||||
public async Task<ImmutableArray<BinaryIdentity>> GetBatchAsync(IEnumerable<string> binaryKeys, CancellationToken ct)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
|
||||
const string sql = """
|
||||
SELECT id AS "Id",
|
||||
tenant_id AS "TenantId",
|
||||
binary_key AS "BinaryKey",
|
||||
build_id AS "BuildId",
|
||||
build_id_type AS "BuildIdType",
|
||||
file_sha256 AS "FileSha256",
|
||||
text_sha256 AS "TextSha256",
|
||||
blake3_hash AS "Blake3Hash",
|
||||
format AS "Format",
|
||||
architecture AS "Architecture",
|
||||
osabi AS "OsAbi",
|
||||
binary_type AS "BinaryType",
|
||||
is_stripped AS "IsStripped",
|
||||
first_seen_snapshot_id AS "FirstSeenSnapshotId",
|
||||
last_seen_snapshot_id AS "LastSeenSnapshotId",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM binaries.binary_identity
|
||||
WHERE binary_key = ANY(@BinaryKeys)
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { BinaryKeys = binaryKeys.ToArray() },
|
||||
cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<BinaryIdentityRow>(command);
|
||||
return rows.Select(r => r.ToModel()).ToImmutableArray();
|
||||
}
|
||||
|
||||
private sealed class BinaryIdentityRow
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid TenantId { get; set; }
|
||||
public string BinaryKey { get; set; } = string.Empty;
|
||||
public string? BuildId { get; set; }
|
||||
public string? BuildIdType { get; set; }
|
||||
public string FileSha256 { get; set; } = string.Empty;
|
||||
public string? TextSha256 { get; set; }
|
||||
public string? Blake3Hash { get; set; }
|
||||
public string Format { get; set; } = string.Empty;
|
||||
public string Architecture { get; set; } = string.Empty;
|
||||
public string? OsAbi { get; set; }
|
||||
public string? BinaryType { get; set; }
|
||||
public bool IsStripped { get; set; }
|
||||
public Guid? FirstSeenSnapshotId { get; set; }
|
||||
public Guid? LastSeenSnapshotId { get; set; }
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
public DateTimeOffset UpdatedAt { get; set; }
|
||||
|
||||
public BinaryIdentity ToModel() => new()
|
||||
var keys = binaryKeys.ToArray();
|
||||
if (keys.Length == 0)
|
||||
{
|
||||
Id = Id,
|
||||
BinaryKey = BinaryKey,
|
||||
BuildId = BuildId,
|
||||
BuildIdType = BuildIdType,
|
||||
FileSha256 = FileSha256,
|
||||
TextSha256 = TextSha256,
|
||||
Blake3Hash = Blake3Hash,
|
||||
Format = Enum.Parse<BinaryFormat>(Format, ignoreCase: true),
|
||||
Architecture = Architecture,
|
||||
OsAbi = OsAbi,
|
||||
Type = FromDbBinaryType(BinaryType),
|
||||
IsStripped = IsStripped,
|
||||
FirstSeenSnapshotId = FirstSeenSnapshotId,
|
||||
LastSeenSnapshotId = LastSeenSnapshotId,
|
||||
CreatedAt = CreatedAt,
|
||||
UpdatedAt = UpdatedAt
|
||||
};
|
||||
return [];
|
||||
}
|
||||
|
||||
await using var conn = await _connectionContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
var entities = await dbContext.BinaryIdentities
|
||||
.AsNoTracking()
|
||||
.Where(e => keys.Contains(e.BinaryKey))
|
||||
.ToListAsync(ct);
|
||||
|
||||
return entities.Select(ToModel).ToImmutableArray();
|
||||
}
|
||||
|
||||
private static BinaryIdentity ToModel(EfCore.Models.BinaryIdentityEntity entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
BinaryKey = entity.BinaryKey,
|
||||
BuildId = entity.BuildId,
|
||||
BuildIdType = entity.BuildIdType,
|
||||
FileSha256 = entity.FileSha256,
|
||||
TextSha256 = entity.TextSha256,
|
||||
Blake3Hash = entity.Blake3Hash,
|
||||
Format = Enum.Parse<BinaryFormat>(entity.Format, ignoreCase: true),
|
||||
Architecture = entity.Architecture,
|
||||
OsAbi = entity.Osabi,
|
||||
Type = FromDbBinaryType(entity.BinaryType),
|
||||
IsStripped = entity.IsStripped ?? false,
|
||||
FirstSeenSnapshotId = entity.FirstSeenSnapshotId,
|
||||
LastSeenSnapshotId = entity.LastSeenSnapshotId,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
UpdatedAt = entity.UpdatedAt
|
||||
};
|
||||
|
||||
private static string? ToDbBinaryType(BinaryType? type)
|
||||
{
|
||||
return type switch
|
||||
|
||||
@@ -1,36 +1,39 @@
|
||||
|
||||
using Dapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using StellaOps.BinaryIndex.Core.Services;
|
||||
using StellaOps.BinaryIndex.Persistence.Postgres;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.Repositories;
|
||||
|
||||
public sealed class BinaryVulnAssertionRepository : IBinaryVulnAssertionRepository
|
||||
{
|
||||
private readonly BinaryIndexDbContext _dbContext;
|
||||
private readonly BinaryIndexDbContext _connectionContext;
|
||||
private const int CommandTimeoutSeconds = 30;
|
||||
|
||||
public BinaryVulnAssertionRepository(BinaryIndexDbContext dbContext)
|
||||
public BinaryVulnAssertionRepository(BinaryIndexDbContext connectionContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_connectionContext = connectionContext;
|
||||
}
|
||||
|
||||
public async Task<ImmutableArray<BinaryVulnAssertion>> GetByBinaryKeyAsync(string binaryKey, CancellationToken ct)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var conn = await _connectionContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id AS "Id",
|
||||
binary_key AS "BinaryKey",
|
||||
cve_id AS "CveId",
|
||||
status AS "Status",
|
||||
method AS "Method",
|
||||
confidence AS "Confidence"
|
||||
FROM binaries.binary_vuln_assertion
|
||||
WHERE binary_key = @BinaryKey
|
||||
""";
|
||||
var entities = await dbContext.BinaryVulnAssertions
|
||||
.AsNoTracking()
|
||||
.Where(e => e.BinaryKey == binaryKey)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { BinaryKey = binaryKey }, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<BinaryVulnAssertion>(command);
|
||||
return rows.ToImmutableArray();
|
||||
return entities.Select(e => new BinaryVulnAssertion
|
||||
{
|
||||
Id = e.Id,
|
||||
BinaryKey = e.BinaryKey,
|
||||
CveId = e.CveId,
|
||||
Status = e.Status,
|
||||
Method = e.Method,
|
||||
Confidence = e.Confidence
|
||||
}).ToImmutableArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,77 +1,63 @@
|
||||
using Dapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.BinaryIndex.Corpus;
|
||||
using StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
using StellaOps.BinaryIndex.Persistence.Postgres;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Repository for corpus snapshots.
|
||||
/// EF Core repository for corpus snapshots.
|
||||
/// </summary>
|
||||
public sealed class CorpusSnapshotRepository : ICorpusSnapshotRepository
|
||||
{
|
||||
private readonly BinaryIndexDbContext _dbContext;
|
||||
private readonly BinaryIndexDbContext _connectionContext;
|
||||
private readonly ILogger<CorpusSnapshotRepository> _logger;
|
||||
private const int CommandTimeoutSeconds = 30;
|
||||
|
||||
public CorpusSnapshotRepository(
|
||||
BinaryIndexDbContext dbContext,
|
||||
BinaryIndexDbContext connectionContext,
|
||||
ILogger<CorpusSnapshotRepository> logger)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_connectionContext = connectionContext;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<CorpusSnapshot> CreateAsync(CorpusSnapshot snapshot, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var conn = await _connectionContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
INSERT INTO binaries.corpus_snapshots (
|
||||
id,
|
||||
tenant_id,
|
||||
distro,
|
||||
release,
|
||||
architecture,
|
||||
snapshot_id,
|
||||
repo_metadata_digest,
|
||||
created_at
|
||||
)
|
||||
VALUES (
|
||||
@Id,
|
||||
binaries_app.require_current_tenant()::uuid,
|
||||
@Distro,
|
||||
@Release,
|
||||
@Architecture,
|
||||
@SnapshotId,
|
||||
@MetadataDigest,
|
||||
NOW()
|
||||
)
|
||||
RETURNING id AS "Id",
|
||||
distro AS "Distro",
|
||||
release AS "Release",
|
||||
architecture AS "Architecture",
|
||||
repo_metadata_digest AS "MetadataDigest",
|
||||
created_at AS "CapturedAt"
|
||||
""";
|
||||
var snapshotIdValue = $"{snapshot.Distro}_{snapshot.Release}_{snapshot.Architecture}_{snapshot.CapturedAt:yyyyMMddHHmmss}";
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
snapshot.Id,
|
||||
snapshot.Distro,
|
||||
snapshot.Release,
|
||||
snapshot.Architecture,
|
||||
SnapshotId = $"{snapshot.Distro}_{snapshot.Release}_{snapshot.Architecture}_{snapshot.CapturedAt:yyyyMMddHHmmss}",
|
||||
snapshot.MetadataDigest
|
||||
},
|
||||
cancellationToken: ct);
|
||||
var row = await conn.QuerySingleAsync<CorpusSnapshotRow>(command);
|
||||
// Use raw SQL for INSERT ... RETURNING with tenant function
|
||||
var results = await dbContext.CorpusSnapshots
|
||||
.FromSqlInterpolated($"""
|
||||
INSERT INTO binaries.corpus_snapshots (
|
||||
id, tenant_id, distro, release, architecture,
|
||||
snapshot_id, repo_metadata_digest, created_at
|
||||
)
|
||||
VALUES (
|
||||
{snapshot.Id},
|
||||
binaries_app.require_current_tenant()::uuid,
|
||||
{snapshot.Distro}, {snapshot.Release}, {snapshot.Architecture},
|
||||
{snapshotIdValue}, {snapshot.MetadataDigest}, NOW()
|
||||
)
|
||||
RETURNING id, tenant_id, distro, release, architecture, snapshot_id,
|
||||
packages_processed, binaries_indexed, repo_metadata_digest,
|
||||
signing_key_id, dsse_envelope_ref, status, error,
|
||||
started_at, completed_at, created_at
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(ct);
|
||||
|
||||
var entity = results.First();
|
||||
|
||||
_logger.LogInformation(
|
||||
"Created corpus snapshot {Id} for {Distro} {Release}/{Architecture}",
|
||||
row.Id, row.Distro, row.Release, row.Architecture);
|
||||
entity.Id, entity.Distro, entity.Release, entity.Architecture);
|
||||
|
||||
return row.ToModel();
|
||||
return ToModel(entity);
|
||||
}
|
||||
|
||||
public async Task<CorpusSnapshot?> FindByKeyAsync(
|
||||
@@ -80,75 +66,38 @@ public sealed class CorpusSnapshotRepository : ICorpusSnapshotRepository
|
||||
string architecture,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var conn = await _connectionContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id AS "Id",
|
||||
distro AS "Distro",
|
||||
release AS "Release",
|
||||
architecture AS "Architecture",
|
||||
repo_metadata_digest AS "MetadataDigest",
|
||||
created_at AS "CapturedAt"
|
||||
FROM binaries.corpus_snapshots
|
||||
WHERE distro = @Distro
|
||||
AND release = @Release
|
||||
AND architecture = @Architecture
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1
|
||||
""";
|
||||
var entity = await dbContext.CorpusSnapshots
|
||||
.AsNoTracking()
|
||||
.Where(e => e.Distro == distro && e.Release == release && e.Architecture == architecture)
|
||||
.OrderByDescending(e => e.CreatedAt)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
Distro = distro,
|
||||
Release = release,
|
||||
Architecture = architecture
|
||||
},
|
||||
cancellationToken: ct);
|
||||
var row = await conn.QuerySingleOrDefaultAsync<CorpusSnapshotRow>(command);
|
||||
|
||||
return row?.ToModel();
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
public async Task<CorpusSnapshot?> GetByIdAsync(Guid id, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var conn = await _connectionContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id AS "Id",
|
||||
distro AS "Distro",
|
||||
release AS "Release",
|
||||
architecture AS "Architecture",
|
||||
repo_metadata_digest AS "MetadataDigest",
|
||||
created_at AS "CapturedAt"
|
||||
FROM binaries.corpus_snapshots
|
||||
WHERE id = @Id
|
||||
""";
|
||||
var entity = await dbContext.CorpusSnapshots
|
||||
.AsNoTracking()
|
||||
.Where(e => e.Id == id)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { Id = id }, cancellationToken: ct);
|
||||
var row = await conn.QuerySingleOrDefaultAsync<CorpusSnapshotRow>(command);
|
||||
|
||||
return row?.ToModel();
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
private sealed class CorpusSnapshotRow
|
||||
private static CorpusSnapshot ToModel(CorpusSnapshotEntity entity) => new()
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Distro { get; set; } = string.Empty;
|
||||
public string Release { get; set; } = string.Empty;
|
||||
public string Architecture { get; set; } = string.Empty;
|
||||
public string MetadataDigest { get; set; } = string.Empty;
|
||||
public DateTimeOffset CapturedAt { get; set; }
|
||||
|
||||
public CorpusSnapshot ToModel() => new()
|
||||
{
|
||||
Id = Id,
|
||||
Distro = Distro,
|
||||
Release = Release,
|
||||
Architecture = Architecture,
|
||||
MetadataDigest = MetadataDigest,
|
||||
CapturedAt = CapturedAt
|
||||
};
|
||||
}
|
||||
Id = entity.Id,
|
||||
Distro = entity.Distro,
|
||||
Release = entity.Release,
|
||||
Architecture = entity.Architecture,
|
||||
MetadataDigest = entity.RepoMetadataDigest ?? string.Empty,
|
||||
CapturedAt = entity.CreatedAt
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
// Copyright (c) StellaOps. All rights reserved.
|
||||
// Licensed under BUSL-1.1. See LICENSE in the project root.
|
||||
|
||||
|
||||
using Dapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.BinaryIndex.DeltaSig;
|
||||
using StellaOps.BinaryIndex.Persistence.Postgres;
|
||||
using StellaOps.Determinism;
|
||||
using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// PostgreSQL repository implementation for delta signatures.
|
||||
/// EF Core repository implementation for delta signatures.
|
||||
/// </summary>
|
||||
public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
{
|
||||
@@ -21,6 +20,7 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
private readonly ILogger<DeltaSignatureRepository> _logger;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private readonly IGuidProvider _guidProvider;
|
||||
private const int CommandTimeoutSeconds = 30;
|
||||
|
||||
private static readonly JsonSerializerOptions s_jsonOptions = new()
|
||||
{
|
||||
@@ -46,73 +46,51 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
|
||||
const string sql = """
|
||||
INSERT INTO binaries.delta_signature (
|
||||
id, tenant_id, cve_id, package_name, soname, arch, abi,
|
||||
recipe_id, recipe_version, symbol_name, scope,
|
||||
hash_alg, hash_hex, size_bytes,
|
||||
cfg_bb_count, cfg_edge_hash, chunk_hashes,
|
||||
signature_state, created_at, updated_at,
|
||||
attestation_dsse, metadata
|
||||
)
|
||||
VALUES (
|
||||
@Id, binaries_app.require_current_tenant()::uuid, @CveId, @PackageName, @Soname, @Arch, @Abi,
|
||||
@RecipeId, @RecipeVersion, @SymbolName, @Scope,
|
||||
@HashAlg, @HashHex, @SizeBytes,
|
||||
@CfgBbCount, @CfgEdgeHash, @ChunkHashes::jsonb,
|
||||
@SignatureState, @CreatedAt, @UpdatedAt,
|
||||
@AttestationDsse, @Metadata::jsonb
|
||||
)
|
||||
RETURNING id, created_at, updated_at
|
||||
""";
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
var now = _timeProvider.GetUtcNow();
|
||||
var id = entity.Id != Guid.Empty ? entity.Id : _guidProvider.NewGuid();
|
||||
var chunkHashesJson = entity.ChunkHashes.HasValue
|
||||
? JsonSerializer.Serialize(entity.ChunkHashes.Value, s_jsonOptions)
|
||||
: (string?)null;
|
||||
var metadataJson = entity.Metadata != null
|
||||
? JsonSerializer.Serialize(entity.Metadata, s_jsonOptions)
|
||||
: (string?)null;
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
Id = id,
|
||||
entity.CveId,
|
||||
entity.PackageName,
|
||||
entity.Soname,
|
||||
entity.Arch,
|
||||
entity.Abi,
|
||||
entity.RecipeId,
|
||||
entity.RecipeVersion,
|
||||
entity.SymbolName,
|
||||
entity.Scope,
|
||||
entity.HashAlg,
|
||||
entity.HashHex,
|
||||
entity.SizeBytes,
|
||||
entity.CfgBbCount,
|
||||
entity.CfgEdgeHash,
|
||||
ChunkHashes = entity.ChunkHashes.HasValue
|
||||
? JsonSerializer.Serialize(entity.ChunkHashes.Value, s_jsonOptions)
|
||||
: null,
|
||||
entity.SignatureState,
|
||||
CreatedAt = now,
|
||||
UpdatedAt = now,
|
||||
entity.AttestationDsse,
|
||||
Metadata = entity.Metadata != null
|
||||
? JsonSerializer.Serialize(entity.Metadata, s_jsonOptions)
|
||||
: null
|
||||
},
|
||||
cancellationToken: ct);
|
||||
var result = await conn.QuerySingleAsync<(Guid Id, DateTimeOffset CreatedAt, DateTimeOffset UpdatedAt)>(command);
|
||||
var results = await efContext.DeltaSignatures
|
||||
.FromSqlInterpolated($"""
|
||||
INSERT INTO binaries.delta_signature (
|
||||
id, tenant_id, cve_id, package_name, soname, arch, abi,
|
||||
recipe_id, recipe_version, symbol_name, scope,
|
||||
hash_alg, hash_hex, size_bytes,
|
||||
cfg_bb_count, cfg_edge_hash, chunk_hashes,
|
||||
signature_state, created_at, updated_at,
|
||||
attestation_dsse, metadata
|
||||
)
|
||||
VALUES (
|
||||
{id}, binaries_app.require_current_tenant()::uuid, {entity.CveId}, {entity.PackageName}, {entity.Soname}, {entity.Arch}, {entity.Abi},
|
||||
{entity.RecipeId}, {entity.RecipeVersion}, {entity.SymbolName}, {entity.Scope},
|
||||
{entity.HashAlg}, {entity.HashHex}, {entity.SizeBytes},
|
||||
{entity.CfgBbCount}, {entity.CfgEdgeHash}, {chunkHashesJson}::jsonb,
|
||||
{entity.SignatureState}, {now}, {now},
|
||||
{entity.AttestationDsse}, {metadataJson}::jsonb
|
||||
)
|
||||
RETURNING id, tenant_id, cve_id, package_name, soname, arch, abi,
|
||||
recipe_id, recipe_version, symbol_name, scope,
|
||||
hash_alg, hash_hex, size_bytes,
|
||||
cfg_bb_count, cfg_edge_hash, chunk_hashes,
|
||||
signature_state, created_at, updated_at,
|
||||
attestation_dsse, metadata
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(ct);
|
||||
|
||||
var row = results.First();
|
||||
_logger.LogDebug(
|
||||
"Created delta signature {Id} for {CveId}/{SymbolName} ({State})",
|
||||
result.Id, entity.CveId, entity.SymbolName, entity.SignatureState);
|
||||
row.Id, row.CveId, row.SymbolName, row.SignatureState);
|
||||
|
||||
return entity with
|
||||
{
|
||||
Id = result.Id,
|
||||
CreatedAt = result.CreatedAt,
|
||||
UpdatedAt = result.UpdatedAt
|
||||
};
|
||||
return ToModel(row);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -138,22 +116,14 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id, cve_id as CveId, package_name as PackageName, soname as Soname,
|
||||
arch as Arch, abi as Abi, recipe_id as RecipeId, recipe_version as RecipeVersion,
|
||||
symbol_name as SymbolName, scope as Scope, hash_alg as HashAlg, hash_hex as HashHex,
|
||||
size_bytes as SizeBytes, cfg_bb_count as CfgBbCount, cfg_edge_hash as CfgEdgeHash,
|
||||
chunk_hashes as ChunkHashesJson, signature_state as SignatureState,
|
||||
created_at as CreatedAt, updated_at as UpdatedAt,
|
||||
attestation_dsse as AttestationDsse, metadata as MetadataJson
|
||||
FROM binaries.delta_signature
|
||||
WHERE id = @Id
|
||||
""";
|
||||
var entity = await efContext.DeltaSignatures
|
||||
.AsNoTracking()
|
||||
.Where(e => e.Id == id)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { Id = id }, cancellationToken: ct);
|
||||
var row = await conn.QuerySingleOrDefaultAsync<DeltaSignatureRow>(command);
|
||||
return row?.ToEntity();
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -162,23 +132,15 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id, cve_id as CveId, package_name as PackageName, soname as Soname,
|
||||
arch as Arch, abi as Abi, recipe_id as RecipeId, recipe_version as RecipeVersion,
|
||||
symbol_name as SymbolName, scope as Scope, hash_alg as HashAlg, hash_hex as HashHex,
|
||||
size_bytes as SizeBytes, cfg_bb_count as CfgBbCount, cfg_edge_hash as CfgEdgeHash,
|
||||
chunk_hashes as ChunkHashesJson, signature_state as SignatureState,
|
||||
created_at as CreatedAt, updated_at as UpdatedAt,
|
||||
attestation_dsse as AttestationDsse, metadata as MetadataJson
|
||||
FROM binaries.delta_signature
|
||||
WHERE cve_id = @CveId
|
||||
ORDER BY package_name, symbol_name, signature_state
|
||||
""";
|
||||
var entities = await efContext.DeltaSignatures
|
||||
.AsNoTracking()
|
||||
.Where(e => e.CveId == cveId)
|
||||
.OrderBy(e => e.PackageName).ThenBy(e => e.SymbolName).ThenBy(e => e.SignatureState)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { CveId = cveId }, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<DeltaSignatureRow>(command);
|
||||
return rows.Select(r => r.ToEntity()).ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -188,33 +150,22 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
var sql = """
|
||||
SELECT id, cve_id as CveId, package_name as PackageName, soname as Soname,
|
||||
arch as Arch, abi as Abi, recipe_id as RecipeId, recipe_version as RecipeVersion,
|
||||
symbol_name as SymbolName, scope as Scope, hash_alg as HashAlg, hash_hex as HashHex,
|
||||
size_bytes as SizeBytes, cfg_bb_count as CfgBbCount, cfg_edge_hash as CfgEdgeHash,
|
||||
chunk_hashes as ChunkHashesJson, signature_state as SignatureState,
|
||||
created_at as CreatedAt, updated_at as UpdatedAt,
|
||||
attestation_dsse as AttestationDsse, metadata as MetadataJson
|
||||
FROM binaries.delta_signature
|
||||
WHERE package_name = @PackageName
|
||||
""";
|
||||
var query = efContext.DeltaSignatures
|
||||
.AsNoTracking()
|
||||
.Where(e => e.PackageName == packageName);
|
||||
|
||||
if (soname != null)
|
||||
{
|
||||
sql += " AND soname = @Soname";
|
||||
query = query.Where(e => e.Soname == soname);
|
||||
}
|
||||
|
||||
sql += " ORDER BY cve_id, symbol_name, signature_state";
|
||||
var entities = await query
|
||||
.OrderBy(e => e.CveId).ThenBy(e => e.SymbolName).ThenBy(e => e.SignatureState)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { PackageName = packageName, Soname = soname },
|
||||
cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<DeltaSignatureRow>(command);
|
||||
|
||||
return rows.Select(r => r.ToEntity()).ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -223,26 +174,15 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id, cve_id as CveId, package_name as PackageName, soname as Soname,
|
||||
arch as Arch, abi as Abi, recipe_id as RecipeId, recipe_version as RecipeVersion,
|
||||
symbol_name as SymbolName, scope as Scope, hash_alg as HashAlg, hash_hex as HashHex,
|
||||
size_bytes as SizeBytes, cfg_bb_count as CfgBbCount, cfg_edge_hash as CfgEdgeHash,
|
||||
chunk_hashes as ChunkHashesJson, signature_state as SignatureState,
|
||||
created_at as CreatedAt, updated_at as UpdatedAt,
|
||||
attestation_dsse as AttestationDsse, metadata as MetadataJson
|
||||
FROM binaries.delta_signature
|
||||
WHERE hash_hex = @HashHex
|
||||
""";
|
||||
var normalizedHash = hashHex.ToLowerInvariant();
|
||||
var entities = await efContext.DeltaSignatures
|
||||
.AsNoTracking()
|
||||
.Where(e => e.HashHex == normalizedHash)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { HashHex = hashHex.ToLowerInvariant() },
|
||||
cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<DeltaSignatureRow>(command);
|
||||
|
||||
return rows.Select(r => r.ToEntity()).ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -252,36 +192,22 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
IEnumerable<string> symbolNames,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var symbolList = symbolNames.ToList();
|
||||
if (symbolList.Count == 0)
|
||||
var symbolList = symbolNames.ToArray();
|
||||
if (symbolList.Length == 0)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id, cve_id as CveId, package_name as PackageName, soname as Soname,
|
||||
arch as Arch, abi as Abi, recipe_id as RecipeId, recipe_version as RecipeVersion,
|
||||
symbol_name as SymbolName, scope as Scope, hash_alg as HashAlg, hash_hex as HashHex,
|
||||
size_bytes as SizeBytes, cfg_bb_count as CfgBbCount, cfg_edge_hash as CfgEdgeHash,
|
||||
chunk_hashes as ChunkHashesJson, signature_state as SignatureState,
|
||||
created_at as CreatedAt, updated_at as UpdatedAt,
|
||||
attestation_dsse as AttestationDsse, metadata as MetadataJson
|
||||
FROM binaries.delta_signature
|
||||
WHERE arch = @Arch
|
||||
AND abi = @Abi
|
||||
AND symbol_name = ANY(@SymbolNames)
|
||||
ORDER BY cve_id, symbol_name, signature_state
|
||||
""";
|
||||
var entities = await efContext.DeltaSignatures
|
||||
.AsNoTracking()
|
||||
.Where(e => e.Arch == arch && e.Abi == abi && symbolList.Contains(e.SymbolName))
|
||||
.OrderBy(e => e.CveId).ThenBy(e => e.SymbolName).ThenBy(e => e.SignatureState)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { Arch = arch, Abi = abi, SymbolNames = symbolList.ToArray() },
|
||||
cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<DeltaSignatureRow>(command);
|
||||
|
||||
return rows.Select(r => r.ToEntity()).ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -292,50 +218,31 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
var conditions = new List<string>();
|
||||
var parameters = new DynamicParameters();
|
||||
IQueryable<EfCore.Models.DeltaSignatureDbEntity> query = efContext.DeltaSignatures.AsNoTracking();
|
||||
|
||||
if (cveFilter is { Count: > 0 })
|
||||
{
|
||||
conditions.Add("cve_id = ANY(@CveIds)");
|
||||
parameters.Add("CveIds", cveFilter.ToArray());
|
||||
query = query.Where(e => cveFilter.Contains(e.CveId));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(packageFilter))
|
||||
{
|
||||
conditions.Add("package_name = @PackageName");
|
||||
parameters.Add("PackageName", packageFilter);
|
||||
query = query.Where(e => e.PackageName == packageFilter);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(archFilter))
|
||||
{
|
||||
conditions.Add("arch = @Arch");
|
||||
parameters.Add("Arch", archFilter);
|
||||
query = query.Where(e => e.Arch == archFilter);
|
||||
}
|
||||
|
||||
var whereClause = conditions.Count > 0
|
||||
? "WHERE " + string.Join(" AND ", conditions)
|
||||
: string.Empty;
|
||||
var entities = await query
|
||||
.OrderBy(e => e.CveId).ThenBy(e => e.SymbolName).ThenBy(e => e.SignatureState)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var sql = $"""
|
||||
SELECT id, cve_id as CveId, package_name as PackageName, soname as Soname,
|
||||
arch as Arch, abi as Abi, recipe_id as RecipeId, recipe_version as RecipeVersion,
|
||||
symbol_name as SymbolName, scope as Scope, hash_alg as HashAlg, hash_hex as HashHex,
|
||||
size_bytes as SizeBytes, cfg_bb_count as CfgBbCount, cfg_edge_hash as CfgEdgeHash,
|
||||
chunk_hashes as ChunkHashesJson, signature_state as SignatureState,
|
||||
created_at as CreatedAt, updated_at as UpdatedAt,
|
||||
attestation_dsse as AttestationDsse, metadata as MetadataJson
|
||||
FROM binaries.delta_signature
|
||||
{whereClause}
|
||||
ORDER BY cve_id, symbol_name, signature_state
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(sql, parameters, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<DeltaSignatureRow>(command);
|
||||
|
||||
_logger.LogDebug("GetAllMatchingAsync returned {Count} signatures", rows.Count());
|
||||
return rows.Select(r => r.ToEntity()).ToList();
|
||||
_logger.LogDebug("GetAllMatchingAsync returned {Count} signatures", entities.Count);
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -344,68 +251,51 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
|
||||
const string sql = """
|
||||
UPDATE binaries.delta_signature
|
||||
SET cve_id = @CveId,
|
||||
package_name = @PackageName,
|
||||
soname = @Soname,
|
||||
arch = @Arch,
|
||||
abi = @Abi,
|
||||
recipe_id = @RecipeId,
|
||||
recipe_version = @RecipeVersion,
|
||||
symbol_name = @SymbolName,
|
||||
scope = @Scope,
|
||||
hash_alg = @HashAlg,
|
||||
hash_hex = @HashHex,
|
||||
size_bytes = @SizeBytes,
|
||||
cfg_bb_count = @CfgBbCount,
|
||||
cfg_edge_hash = @CfgEdgeHash,
|
||||
chunk_hashes = @ChunkHashes::jsonb,
|
||||
signature_state = @SignatureState,
|
||||
updated_at = @UpdatedAt,
|
||||
attestation_dsse = @AttestationDsse,
|
||||
metadata = @Metadata::jsonb
|
||||
WHERE id = @Id
|
||||
RETURNING updated_at
|
||||
""";
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
var now = _timeProvider.GetUtcNow();
|
||||
var chunkHashesJson = entity.ChunkHashes.HasValue
|
||||
? JsonSerializer.Serialize(entity.ChunkHashes.Value, s_jsonOptions)
|
||||
: (string?)null;
|
||||
var metadataJson = entity.Metadata != null
|
||||
? JsonSerializer.Serialize(entity.Metadata, s_jsonOptions)
|
||||
: (string?)null;
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
entity.Id,
|
||||
entity.CveId,
|
||||
entity.PackageName,
|
||||
entity.Soname,
|
||||
entity.Arch,
|
||||
entity.Abi,
|
||||
entity.RecipeId,
|
||||
entity.RecipeVersion,
|
||||
entity.SymbolName,
|
||||
entity.Scope,
|
||||
entity.HashAlg,
|
||||
entity.HashHex,
|
||||
entity.SizeBytes,
|
||||
entity.CfgBbCount,
|
||||
entity.CfgEdgeHash,
|
||||
ChunkHashes = entity.ChunkHashes.HasValue
|
||||
? JsonSerializer.Serialize(entity.ChunkHashes.Value, s_jsonOptions)
|
||||
: null,
|
||||
entity.SignatureState,
|
||||
UpdatedAt = now,
|
||||
entity.AttestationDsse,
|
||||
Metadata = entity.Metadata != null
|
||||
? JsonSerializer.Serialize(entity.Metadata, s_jsonOptions)
|
||||
: null
|
||||
},
|
||||
cancellationToken: ct);
|
||||
var updatedAt = await conn.ExecuteScalarAsync<DateTimeOffset>(command);
|
||||
var results = await efContext.DeltaSignatures
|
||||
.FromSqlInterpolated($"""
|
||||
UPDATE binaries.delta_signature
|
||||
SET cve_id = {entity.CveId},
|
||||
package_name = {entity.PackageName},
|
||||
soname = {entity.Soname},
|
||||
arch = {entity.Arch},
|
||||
abi = {entity.Abi},
|
||||
recipe_id = {entity.RecipeId},
|
||||
recipe_version = {entity.RecipeVersion},
|
||||
symbol_name = {entity.SymbolName},
|
||||
scope = {entity.Scope},
|
||||
hash_alg = {entity.HashAlg},
|
||||
hash_hex = {entity.HashHex},
|
||||
size_bytes = {entity.SizeBytes},
|
||||
cfg_bb_count = {entity.CfgBbCount},
|
||||
cfg_edge_hash = {entity.CfgEdgeHash},
|
||||
chunk_hashes = {chunkHashesJson}::jsonb,
|
||||
signature_state = {entity.SignatureState},
|
||||
updated_at = {now},
|
||||
attestation_dsse = {entity.AttestationDsse},
|
||||
metadata = {metadataJson}::jsonb
|
||||
WHERE id = {entity.Id}
|
||||
RETURNING id, tenant_id, cve_id, package_name, soname, arch, abi,
|
||||
recipe_id, recipe_version, symbol_name, scope,
|
||||
hash_alg, hash_hex, size_bytes,
|
||||
cfg_bb_count, cfg_edge_hash, chunk_hashes,
|
||||
signature_state, created_at, updated_at,
|
||||
attestation_dsse, metadata
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(ct);
|
||||
|
||||
_logger.LogDebug("Updated delta signature {Id}", entity.Id);
|
||||
return entity with { UpdatedAt = updatedAt };
|
||||
return ToModel(results.First());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -414,10 +304,10 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = "DELETE FROM binaries.delta_signature WHERE id = @Id";
|
||||
var command = new CommandDefinition(sql, new { Id = id }, cancellationToken: ct);
|
||||
var rows = await conn.ExecuteAsync(command);
|
||||
var rows = await efContext.Database.ExecuteSqlInterpolatedAsync(
|
||||
$"DELETE FROM binaries.delta_signature WHERE id = {id}", ct);
|
||||
|
||||
if (rows > 0)
|
||||
{
|
||||
@@ -432,16 +322,15 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT signature_state as State, COUNT(*) as Count
|
||||
FROM binaries.delta_signature
|
||||
GROUP BY signature_state
|
||||
""";
|
||||
var groups = await efContext.DeltaSignatures
|
||||
.AsNoTracking()
|
||||
.GroupBy(e => e.SignatureState)
|
||||
.Select(g => new { State = g.Key, Count = g.Count() })
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<(string State, int Count)>(command);
|
||||
return rows.ToDictionary(r => r.State, r => r.Count);
|
||||
return groups.ToDictionary(g => g.State, g => g.Count);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -457,37 +346,59 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
var conditions = new List<string>();
|
||||
var parameters = new DynamicParameters();
|
||||
// Build LINQ query for filtering
|
||||
IQueryable<EfCore.Models.DeltaSignatureDbEntity> baseQuery = efContext.DeltaSignatures.AsNoTracking();
|
||||
|
||||
if (cveFilter is { Count: > 0 })
|
||||
{
|
||||
conditions.Add("ds.cve_id = ANY(@CveIds)");
|
||||
parameters.Add("CveIds", cveFilter.ToArray());
|
||||
baseQuery = baseQuery.Where(e => cveFilter.Contains(e.CveId));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(packageFilter))
|
||||
{
|
||||
conditions.Add("ds.package_name = @PackageName");
|
||||
parameters.Add("PackageName", packageFilter);
|
||||
baseQuery = baseQuery.Where(e => e.PackageName == packageFilter);
|
||||
}
|
||||
|
||||
// Count total CVEs matching filter
|
||||
var totalCount = await baseQuery
|
||||
.Select(e => e.CveId)
|
||||
.Distinct()
|
||||
.CountAsync(ct);
|
||||
|
||||
// Get aggregated coverage by CVE -- use raw SQL for the CTE with FILTER aggregation
|
||||
// which EF Core cannot translate directly
|
||||
var cveIds = cveFilter is { Count: > 0 } ? cveFilter.ToArray() : (string[]?)null;
|
||||
|
||||
// Build WHERE conditions dynamically based on filters
|
||||
var conditions = new List<string>();
|
||||
var parameters = new List<object>();
|
||||
var paramIndex = 0;
|
||||
|
||||
if (cveIds is not null)
|
||||
{
|
||||
conditions.Add($"ds.cve_id = ANY(@p{paramIndex})");
|
||||
parameters.Add(cveIds);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(packageFilter))
|
||||
{
|
||||
conditions.Add($"ds.package_name = @p{paramIndex}");
|
||||
parameters.Add(packageFilter);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
var whereClause = conditions.Count > 0
|
||||
? "WHERE " + string.Join(" AND ", conditions)
|
||||
: string.Empty;
|
||||
|
||||
// Count total CVEs matching filter
|
||||
var countSql = $"""
|
||||
SELECT COUNT(DISTINCT ds.cve_id)
|
||||
FROM binaries.delta_signature ds
|
||||
{whereClause}
|
||||
""";
|
||||
var limitParamIdx = paramIndex;
|
||||
var offsetParamIdx = paramIndex + 1;
|
||||
parameters.Add(limit);
|
||||
parameters.Add(offset);
|
||||
|
||||
var countCommand = new CommandDefinition(countSql, parameters, cancellationToken: ct);
|
||||
var totalCount = await conn.ExecuteScalarAsync<int>(countCommand);
|
||||
|
||||
// Get aggregated coverage by CVE
|
||||
var sql = $"""
|
||||
WITH cve_stats AS (
|
||||
SELECT
|
||||
@@ -503,35 +414,35 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
GROUP BY ds.cve_id, ds.package_name
|
||||
)
|
||||
SELECT
|
||||
cve_id as CveId,
|
||||
package_name as PackageName,
|
||||
vulnerable_count as VulnerableCount,
|
||||
patched_count as PatchedCount,
|
||||
unknown_count as UnknownCount,
|
||||
symbol_count as SymbolCount,
|
||||
cve_id as "CveId",
|
||||
package_name as "PackageName",
|
||||
vulnerable_count as "VulnerableCount",
|
||||
patched_count as "PatchedCount",
|
||||
unknown_count as "UnknownCount",
|
||||
symbol_count as "SymbolCount",
|
||||
CASE WHEN (vulnerable_count + patched_count + unknown_count) > 0
|
||||
THEN (patched_count * 100.0 / (vulnerable_count + patched_count + unknown_count))
|
||||
ELSE 0
|
||||
END as CoveragePercent,
|
||||
last_updated_at as LastUpdatedAt
|
||||
END as "CoveragePercent",
|
||||
last_updated_at as "LastUpdatedAt"
|
||||
FROM cve_stats
|
||||
ORDER BY cve_id
|
||||
LIMIT @Limit OFFSET @Offset
|
||||
LIMIT @p{limitParamIdx} OFFSET @p{offsetParamIdx}
|
||||
""";
|
||||
|
||||
parameters.Add("Limit", limit);
|
||||
parameters.Add("Offset", offset);
|
||||
|
||||
var command = new CommandDefinition(sql, parameters, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<PatchCoverageEntry>(command);
|
||||
#pragma warning disable EF1002 // SQL built dynamically from safe parameters
|
||||
var entries = await efContext.Database
|
||||
.SqlQueryRaw<PatchCoverageEntry>(sql, parameters.ToArray())
|
||||
.ToListAsync(ct);
|
||||
#pragma warning restore EF1002
|
||||
|
||||
_logger.LogDebug(
|
||||
"GetPatchCoverageAsync returned {Count} entries (total: {Total})",
|
||||
rows.Count(), totalCount);
|
||||
entries.Count, totalCount);
|
||||
|
||||
return new PatchCoverageResult
|
||||
{
|
||||
Entries = rows.ToList(),
|
||||
Entries = entries,
|
||||
TotalCount = totalCount,
|
||||
Offset = offset,
|
||||
Limit = limit
|
||||
@@ -544,28 +455,25 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
// Get function-level breakdown
|
||||
const string functionSql = """
|
||||
SELECT
|
||||
ds.symbol_name as SymbolName,
|
||||
ds.soname as Soname,
|
||||
COUNT(*) FILTER (WHERE ds.signature_state = 'vulnerable') as VulnerableCount,
|
||||
COUNT(*) FILTER (WHERE ds.signature_state = 'patched') as PatchedCount,
|
||||
COUNT(*) FILTER (WHERE ds.signature_state NOT IN ('vulnerable', 'patched')) as UnknownCount,
|
||||
(COUNT(*) FILTER (WHERE ds.signature_state = 'vulnerable') > 0
|
||||
AND COUNT(*) FILTER (WHERE ds.signature_state = 'patched') > 0) as HasDelta
|
||||
FROM binaries.delta_signature ds
|
||||
WHERE ds.cve_id = @CveId
|
||||
GROUP BY ds.symbol_name, ds.soname
|
||||
ORDER BY ds.symbol_name
|
||||
""";
|
||||
|
||||
var functionCommand = new CommandDefinition(
|
||||
functionSql,
|
||||
new { CveId = cveId },
|
||||
cancellationToken: ct);
|
||||
var functions = (await conn.QueryAsync<FunctionCoverageEntry>(functionCommand)).ToList();
|
||||
// Get function-level breakdown -- requires FILTER aggregation (raw SQL)
|
||||
var functions = await efContext.Database
|
||||
.SqlQueryRaw<FunctionCoverageEntry>("""
|
||||
SELECT
|
||||
ds.symbol_name as "SymbolName",
|
||||
ds.soname as "Soname",
|
||||
COUNT(*) FILTER (WHERE ds.signature_state = 'vulnerable') as "VulnerableCount",
|
||||
COUNT(*) FILTER (WHERE ds.signature_state = 'patched') as "PatchedCount",
|
||||
COUNT(*) FILTER (WHERE ds.signature_state NOT IN ('vulnerable', 'patched')) as "UnknownCount",
|
||||
(COUNT(*) FILTER (WHERE ds.signature_state = 'vulnerable') > 0
|
||||
AND COUNT(*) FILTER (WHERE ds.signature_state = 'patched') > 0) as "HasDelta"
|
||||
FROM binaries.delta_signature ds
|
||||
WHERE ds.cve_id = @p0
|
||||
GROUP BY ds.symbol_name, ds.soname
|
||||
ORDER BY ds.symbol_name
|
||||
""", cveId)
|
||||
.ToListAsync(ct);
|
||||
|
||||
if (functions.Count == 0)
|
||||
{
|
||||
@@ -573,14 +481,11 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
}
|
||||
|
||||
// Get package name
|
||||
const string packageSql = """
|
||||
SELECT DISTINCT package_name
|
||||
FROM binaries.delta_signature
|
||||
WHERE cve_id = @CveId
|
||||
LIMIT 1
|
||||
""";
|
||||
var packageName = await conn.ExecuteScalarAsync<string>(
|
||||
new CommandDefinition(packageSql, new { CveId = cveId }, cancellationToken: ct)) ?? "unknown";
|
||||
var packageName = await efContext.DeltaSignatures
|
||||
.AsNoTracking()
|
||||
.Where(e => e.CveId == cveId)
|
||||
.Select(e => e.PackageName)
|
||||
.FirstOrDefaultAsync(ct) ?? "unknown";
|
||||
|
||||
// Compute summary
|
||||
var totalVulnerable = functions.Sum(f => f.VulnerableCount);
|
||||
@@ -625,144 +530,96 @@ public sealed class DeltaSignatureRepository : IDeltaSignatureRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
var conditions = new List<string> { "m.cve_id = @CveId" };
|
||||
var parameters = new DynamicParameters();
|
||||
parameters.Add("CveId", cveId);
|
||||
// Build filter query for delta_sig_match
|
||||
IQueryable<EfCore.Models.DeltaSigMatchDbEntity> query = efContext.DeltaSigMatches
|
||||
.AsNoTracking()
|
||||
.Where(e => e.CveId == cveId);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(symbolName))
|
||||
{
|
||||
conditions.Add("m.symbol_name = @SymbolName");
|
||||
parameters.Add("SymbolName", symbolName);
|
||||
query = query.Where(e => e.SymbolName == symbolName);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(matchState))
|
||||
{
|
||||
conditions.Add("m.matched_state = @MatchState");
|
||||
parameters.Add("MatchState", matchState);
|
||||
query = query.Where(e => e.MatchedState == matchState);
|
||||
}
|
||||
|
||||
var whereClause = "WHERE " + string.Join(" AND ", conditions);
|
||||
var totalCount = await query.CountAsync(ct);
|
||||
|
||||
// Count total matches
|
||||
var countSql = $"""
|
||||
SELECT COUNT(*)
|
||||
FROM binaries.delta_sig_match m
|
||||
{whereClause}
|
||||
""";
|
||||
var countCommand = new CommandDefinition(countSql, parameters, cancellationToken: ct);
|
||||
var totalCount = await conn.ExecuteScalarAsync<int>(countCommand);
|
||||
|
||||
// Get paginated matches
|
||||
var sql = $"""
|
||||
SELECT
|
||||
m.id as MatchId,
|
||||
m.binary_key as BinaryKey,
|
||||
m.binary_sha256 as BinarySha256,
|
||||
m.symbol_name as SymbolName,
|
||||
m.matched_state as MatchState,
|
||||
m.confidence as Confidence,
|
||||
m.scan_id as ScanId,
|
||||
m.scanned_at as ScannedAt
|
||||
FROM binaries.delta_sig_match m
|
||||
{whereClause}
|
||||
ORDER BY m.scanned_at DESC
|
||||
LIMIT @Limit OFFSET @Offset
|
||||
""";
|
||||
|
||||
parameters.Add("Limit", limit);
|
||||
parameters.Add("Offset", offset);
|
||||
|
||||
var command = new CommandDefinition(sql, parameters, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<PatchMatchEntry>(command);
|
||||
var matches = await query
|
||||
.OrderByDescending(e => e.ScannedAt)
|
||||
.Skip(offset)
|
||||
.Take(limit)
|
||||
.Select(m => new PatchMatchEntry
|
||||
{
|
||||
MatchId = m.Id,
|
||||
BinaryKey = m.BinaryKey,
|
||||
BinarySha256 = m.BinarySha256,
|
||||
SymbolName = m.SymbolName,
|
||||
MatchState = m.MatchedState,
|
||||
Confidence = m.Confidence,
|
||||
ScanId = m.ScanId,
|
||||
ScannedAt = m.ScannedAt
|
||||
})
|
||||
.ToListAsync(ct);
|
||||
|
||||
_logger.LogDebug(
|
||||
"GetMatchingImagesAsync for {CveId}: {Count} matches (total: {Total})",
|
||||
cveId, rows.Count(), totalCount);
|
||||
cveId, matches.Count, totalCount);
|
||||
|
||||
return new PatchMatchPage
|
||||
{
|
||||
Matches = rows.ToList(),
|
||||
Matches = matches,
|
||||
TotalCount = totalCount,
|
||||
Offset = offset,
|
||||
Limit = limit
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal row type for Dapper mapping.
|
||||
/// </summary>
|
||||
private sealed class DeltaSignatureRow
|
||||
private static DeltaSignatureEntity ToModel(EfCore.Models.DeltaSignatureDbEntity entity)
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string CveId { get; set; } = "";
|
||||
public string PackageName { get; set; } = "";
|
||||
public string? Soname { get; set; }
|
||||
public string Arch { get; set; } = "";
|
||||
public string Abi { get; set; } = "gnu";
|
||||
public string RecipeId { get; set; } = "";
|
||||
public string RecipeVersion { get; set; } = "";
|
||||
public string SymbolName { get; set; } = "";
|
||||
public string Scope { get; set; } = ".text";
|
||||
public string HashAlg { get; set; } = "sha256";
|
||||
public string HashHex { get; set; } = "";
|
||||
public int SizeBytes { get; set; }
|
||||
public int? CfgBbCount { get; set; }
|
||||
public string? CfgEdgeHash { get; set; }
|
||||
public string? ChunkHashesJson { get; set; }
|
||||
public string SignatureState { get; set; } = "";
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
public DateTimeOffset UpdatedAt { get; set; }
|
||||
public byte[]? AttestationDsse { get; set; }
|
||||
public string? MetadataJson { get; set; }
|
||||
|
||||
public DeltaSignatureEntity ToEntity()
|
||||
ImmutableArray<ChunkHash>? chunks = null;
|
||||
if (!string.IsNullOrEmpty(entity.ChunkHashes))
|
||||
{
|
||||
ImmutableArray<ChunkHash>? chunks = null;
|
||||
if (!string.IsNullOrEmpty(ChunkHashesJson))
|
||||
var chunkList = JsonSerializer.Deserialize<List<ChunkHash>>(entity.ChunkHashes, s_jsonOptions);
|
||||
if (chunkList != null)
|
||||
{
|
||||
var chunkList = JsonSerializer.Deserialize<List<ChunkHash>>(ChunkHashesJson, s_jsonOptions);
|
||||
if (chunkList != null)
|
||||
{
|
||||
chunks = [.. chunkList];
|
||||
}
|
||||
chunks = [.. chunkList];
|
||||
}
|
||||
|
||||
Dictionary<string, object>? metadata = null;
|
||||
if (!string.IsNullOrEmpty(MetadataJson))
|
||||
{
|
||||
metadata = JsonSerializer.Deserialize<Dictionary<string, object>>(MetadataJson, s_jsonOptions);
|
||||
}
|
||||
|
||||
return new DeltaSignatureEntity
|
||||
{
|
||||
Id = Id,
|
||||
CveId = CveId,
|
||||
PackageName = PackageName,
|
||||
Soname = Soname,
|
||||
Arch = Arch,
|
||||
Abi = Abi,
|
||||
RecipeId = RecipeId,
|
||||
RecipeVersion = RecipeVersion,
|
||||
SymbolName = SymbolName,
|
||||
Scope = Scope,
|
||||
HashAlg = HashAlg,
|
||||
HashHex = HashHex,
|
||||
SizeBytes = SizeBytes,
|
||||
CfgBbCount = CfgBbCount,
|
||||
CfgEdgeHash = CfgEdgeHash,
|
||||
ChunkHashes = chunks,
|
||||
SignatureState = SignatureState,
|
||||
CreatedAt = CreatedAt,
|
||||
UpdatedAt = UpdatedAt,
|
||||
AttestationDsse = AttestationDsse,
|
||||
Metadata = metadata
|
||||
};
|
||||
}
|
||||
|
||||
private static readonly JsonSerializerOptions s_jsonOptions = new()
|
||||
Dictionary<string, object>? metadata = null;
|
||||
if (!string.IsNullOrEmpty(entity.Metadata))
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
metadata = JsonSerializer.Deserialize<Dictionary<string, object>>(entity.Metadata, s_jsonOptions);
|
||||
}
|
||||
|
||||
return new DeltaSignatureEntity
|
||||
{
|
||||
Id = entity.Id,
|
||||
CveId = entity.CveId,
|
||||
PackageName = entity.PackageName,
|
||||
Soname = entity.Soname,
|
||||
Arch = entity.Arch,
|
||||
Abi = entity.Abi,
|
||||
RecipeId = entity.RecipeId,
|
||||
RecipeVersion = entity.RecipeVersion,
|
||||
SymbolName = entity.SymbolName,
|
||||
Scope = entity.Scope,
|
||||
HashAlg = entity.HashAlg,
|
||||
HashHex = entity.HashHex,
|
||||
SizeBytes = entity.SizeBytes,
|
||||
CfgBbCount = entity.CfgBbCount,
|
||||
CfgEdgeHash = entity.CfgEdgeHash,
|
||||
ChunkHashes = chunks,
|
||||
SignatureState = entity.SignatureState,
|
||||
CreatedAt = new DateTimeOffset(entity.CreatedAt, TimeSpan.Zero),
|
||||
UpdatedAt = new DateTimeOffset(entity.UpdatedAt, TimeSpan.Zero),
|
||||
AttestationDsse = entity.AttestationDsse,
|
||||
Metadata = metadata
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
|
||||
using Dapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using IGuidProvider = StellaOps.Determinism.IGuidProvider;
|
||||
using StellaOps.BinaryIndex.Fingerprints;
|
||||
using StellaOps.BinaryIndex.Fingerprints.Models;
|
||||
using StellaOps.BinaryIndex.Persistence.Postgres;
|
||||
using System.Collections.Immutable;
|
||||
using System.Text.Json;
|
||||
using SystemGuidProvider = StellaOps.Determinism.SystemGuidProvider;
|
||||
@@ -10,12 +11,13 @@ using SystemGuidProvider = StellaOps.Determinism.SystemGuidProvider;
|
||||
namespace StellaOps.BinaryIndex.Persistence.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Repository implementation for vulnerable fingerprints.
|
||||
/// EF Core repository implementation for vulnerable fingerprints.
|
||||
/// </summary>
|
||||
public sealed class FingerprintRepository : IFingerprintRepository
|
||||
{
|
||||
private readonly BinaryIndexDbContext _dbContext;
|
||||
private readonly IGuidProvider _guidProvider;
|
||||
private const int CommandTimeoutSeconds = 30;
|
||||
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);
|
||||
|
||||
public FingerprintRepository(BinaryIndexDbContext dbContext, IGuidProvider? guidProvider = null)
|
||||
@@ -27,92 +29,63 @@ public sealed class FingerprintRepository : IFingerprintRepository
|
||||
public async Task<VulnFingerprint> CreateAsync(VulnFingerprint fingerprint, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
INSERT INTO binaries.vulnerable_fingerprints (
|
||||
id, tenant_id, cve_id, component, purl, algorithm, fingerprint_id, fingerprint_hash,
|
||||
architecture, function_name, source_file, source_line, similarity_threshold,
|
||||
confidence, validated, validation_stats, vuln_build_ref, fixed_build_ref, indexed_at
|
||||
)
|
||||
VALUES (
|
||||
@Id, binaries_app.require_current_tenant()::uuid, @CveId, @Component, @Purl, @Algorithm,
|
||||
@FingerprintId, @FingerprintHash, @Architecture, @FunctionName, @SourceFile,
|
||||
@SourceLine, @SimilarityThreshold, @Confidence, @Validated, @ValidationStats::jsonb,
|
||||
@VulnBuildRef, @FixedBuildRef, @IndexedAt
|
||||
)
|
||||
RETURNING id
|
||||
""";
|
||||
var id = fingerprint.Id != Guid.Empty ? fingerprint.Id : _guidProvider.NewGuid();
|
||||
var algorithm = ToDbAlgorithm(fingerprint.Algorithm);
|
||||
var validationStats = fingerprint.ValidationStats != null
|
||||
? JsonSerializer.Serialize(fingerprint.ValidationStats, JsonOptions)
|
||||
: "{}";
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
Id = fingerprint.Id != Guid.Empty ? fingerprint.Id : _guidProvider.NewGuid(),
|
||||
fingerprint.CveId,
|
||||
fingerprint.Component,
|
||||
fingerprint.Purl,
|
||||
Algorithm = ToDbAlgorithm(fingerprint.Algorithm),
|
||||
fingerprint.FingerprintId,
|
||||
fingerprint.FingerprintHash,
|
||||
fingerprint.Architecture,
|
||||
fingerprint.FunctionName,
|
||||
fingerprint.SourceFile,
|
||||
fingerprint.SourceLine,
|
||||
fingerprint.SimilarityThreshold,
|
||||
fingerprint.Confidence,
|
||||
fingerprint.Validated,
|
||||
ValidationStats = fingerprint.ValidationStats != null
|
||||
? JsonSerializer.Serialize(fingerprint.ValidationStats, JsonOptions)
|
||||
: "{}",
|
||||
fingerprint.VulnBuildRef,
|
||||
fingerprint.FixedBuildRef,
|
||||
fingerprint.IndexedAt
|
||||
},
|
||||
cancellationToken: ct);
|
||||
var id = await conn.ExecuteScalarAsync<Guid>(command);
|
||||
var results = await efContext.VulnerableFingerprints
|
||||
.FromSqlInterpolated($"""
|
||||
INSERT INTO binaries.vulnerable_fingerprints (
|
||||
id, tenant_id, cve_id, component, purl, algorithm, fingerprint_id, fingerprint_hash,
|
||||
architecture, function_name, source_file, source_line, similarity_threshold,
|
||||
confidence, validated, validation_stats, vuln_build_ref, fixed_build_ref, indexed_at
|
||||
)
|
||||
VALUES (
|
||||
{id}, binaries_app.require_current_tenant()::uuid, {fingerprint.CveId}, {fingerprint.Component}, {fingerprint.Purl}, {algorithm},
|
||||
{fingerprint.FingerprintId}, {fingerprint.FingerprintHash}, {fingerprint.Architecture}, {fingerprint.FunctionName}, {fingerprint.SourceFile},
|
||||
{fingerprint.SourceLine}, {fingerprint.SimilarityThreshold}, {fingerprint.Confidence}, {fingerprint.Validated}, {validationStats}::jsonb,
|
||||
{fingerprint.VulnBuildRef}, {fingerprint.FixedBuildRef}, {fingerprint.IndexedAt}
|
||||
)
|
||||
RETURNING id, tenant_id, cve_id, component, purl, algorithm, fingerprint_id, fingerprint_hash,
|
||||
architecture, function_name, source_file, source_line, similarity_threshold,
|
||||
confidence, validated, validation_stats, vuln_build_ref, fixed_build_ref,
|
||||
notes, evidence_ref, indexed_at, created_at
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(ct);
|
||||
|
||||
return fingerprint with { Id = id };
|
||||
return ToModel(results.First());
|
||||
}
|
||||
|
||||
public async Task<VulnFingerprint?> GetByIdAsync(Guid id, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id, cve_id as CveId, component, purl, algorithm, fingerprint_id as FingerprintId,
|
||||
fingerprint_hash as FingerprintHash, architecture, function_name as FunctionName,
|
||||
source_file as SourceFile, source_line as SourceLine,
|
||||
similarity_threshold as SimilarityThreshold, confidence, validated,
|
||||
validation_stats as ValidationStats, vuln_build_ref as VulnBuildRef,
|
||||
fixed_build_ref as FixedBuildRef, indexed_at as IndexedAt
|
||||
FROM binaries.vulnerable_fingerprints
|
||||
WHERE id = @Id
|
||||
""";
|
||||
var entity = await efContext.VulnerableFingerprints
|
||||
.AsNoTracking()
|
||||
.Where(e => e.Id == id)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { Id = id }, cancellationToken: ct);
|
||||
var row = await conn.QuerySingleOrDefaultAsync<VulnFingerprintRow>(command);
|
||||
return row?.ToModel();
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
public async Task<ImmutableArray<VulnFingerprint>> GetByCveAsync(string cveId, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id, cve_id as CveId, component, purl, algorithm, fingerprint_id as FingerprintId,
|
||||
fingerprint_hash as FingerprintHash, architecture, function_name as FunctionName,
|
||||
source_file as SourceFile, source_line as SourceLine,
|
||||
similarity_threshold as SimilarityThreshold, confidence, validated,
|
||||
validation_stats as ValidationStats, vuln_build_ref as VulnBuildRef,
|
||||
fixed_build_ref as FixedBuildRef, indexed_at as IndexedAt
|
||||
FROM binaries.vulnerable_fingerprints
|
||||
WHERE cve_id = @CveId
|
||||
ORDER BY component, fingerprint_id
|
||||
""";
|
||||
var entities = await efContext.VulnerableFingerprints
|
||||
.AsNoTracking()
|
||||
.Where(e => e.CveId == cveId)
|
||||
.OrderBy(e => e.Component).ThenBy(e => e.FingerprintId)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { CveId = cveId }, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<VulnFingerprintRow>(command);
|
||||
return rows.Select(r => r.ToModel()).ToImmutableArray();
|
||||
return entities.Select(ToModel).ToImmutableArray();
|
||||
}
|
||||
|
||||
public async Task<ImmutableArray<VulnFingerprint>> SearchByHashAsync(
|
||||
@@ -122,32 +95,21 @@ public sealed class FingerprintRepository : IFingerprintRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT id, cve_id as CveId, component, purl, algorithm, fingerprint_id as FingerprintId,
|
||||
fingerprint_hash as FingerprintHash, architecture, function_name as FunctionName,
|
||||
source_file as SourceFile, source_line as SourceLine,
|
||||
similarity_threshold as SimilarityThreshold, confidence, validated,
|
||||
validation_stats as ValidationStats, vuln_build_ref as VulnBuildRef,
|
||||
fixed_build_ref as FixedBuildRef, indexed_at as IndexedAt
|
||||
FROM binaries.vulnerable_fingerprints
|
||||
WHERE fingerprint_hash = @Hash
|
||||
AND algorithm = @Algorithm
|
||||
AND (@Architecture IS NULL OR architecture = @Architecture)
|
||||
""";
|
||||
var dbAlgorithm = ToDbAlgorithm(algorithm);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
Hash = hash,
|
||||
Algorithm = ToDbAlgorithm(algorithm),
|
||||
Architecture = architecture
|
||||
},
|
||||
cancellationToken: ct);
|
||||
var query = efContext.VulnerableFingerprints
|
||||
.AsNoTracking()
|
||||
.Where(e => e.FingerprintHash == hash && e.Algorithm == dbAlgorithm);
|
||||
|
||||
var rows = await conn.QueryAsync<VulnFingerprintRow>(command);
|
||||
return rows.Select(r => r.ToModel()).ToImmutableArray();
|
||||
if (architecture is not null)
|
||||
{
|
||||
query = query.Where(e => e.Architecture == architecture);
|
||||
}
|
||||
|
||||
var entities = await query.ToListAsync(ct);
|
||||
return entities.Select(ToModel).ToImmutableArray();
|
||||
}
|
||||
|
||||
public async Task UpdateValidationStatsAsync(
|
||||
@@ -156,24 +118,15 @@ public sealed class FingerprintRepository : IFingerprintRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
var statsJson = JsonSerializer.Serialize(stats, JsonOptions);
|
||||
await efContext.Database.ExecuteSqlInterpolatedAsync($"""
|
||||
UPDATE binaries.vulnerable_fingerprints
|
||||
SET validation_stats = @Stats::jsonb,
|
||||
SET validation_stats = {statsJson}::jsonb,
|
||||
validated = TRUE
|
||||
WHERE id = @Id
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
Id = id,
|
||||
Stats = JsonSerializer.Serialize(stats, JsonOptions)
|
||||
},
|
||||
cancellationToken: ct);
|
||||
|
||||
await conn.ExecuteAsync(command);
|
||||
WHERE id = {id}
|
||||
""", ct);
|
||||
}
|
||||
|
||||
private static string ToDbAlgorithm(FingerprintAlgorithm algorithm)
|
||||
@@ -201,67 +154,46 @@ public sealed class FingerprintRepository : IFingerprintRepository
|
||||
};
|
||||
}
|
||||
|
||||
private sealed class VulnFingerprintRow
|
||||
private static VulnFingerprint ToModel(EfCore.Models.VulnerableFingerprintEntity entity)
|
||||
{
|
||||
public Guid Id { get; init; }
|
||||
public string CveId { get; init; } = string.Empty;
|
||||
public string Component { get; init; } = string.Empty;
|
||||
public string? Purl { get; init; }
|
||||
public string Algorithm { get; init; } = string.Empty;
|
||||
public string FingerprintId { get; init; } = string.Empty;
|
||||
public byte[] FingerprintHash { get; init; } = Array.Empty<byte>();
|
||||
public string Architecture { get; init; } = string.Empty;
|
||||
public string? FunctionName { get; init; }
|
||||
public string? SourceFile { get; init; }
|
||||
public int? SourceLine { get; init; }
|
||||
public decimal SimilarityThreshold { get; init; }
|
||||
public decimal? Confidence { get; init; }
|
||||
public bool Validated { get; init; }
|
||||
public string? ValidationStats { get; init; }
|
||||
public string? VulnBuildRef { get; init; }
|
||||
public string? FixedBuildRef { get; init; }
|
||||
public DateTimeOffset IndexedAt { get; init; }
|
||||
|
||||
public VulnFingerprint ToModel()
|
||||
FingerprintValidationStats? stats = null;
|
||||
if (!string.IsNullOrWhiteSpace(entity.ValidationStats))
|
||||
{
|
||||
FingerprintValidationStats? stats = null;
|
||||
if (!string.IsNullOrWhiteSpace(ValidationStats))
|
||||
{
|
||||
stats = JsonSerializer.Deserialize<FingerprintValidationStats>(ValidationStats, JsonOptions);
|
||||
}
|
||||
|
||||
return new VulnFingerprint
|
||||
{
|
||||
Id = Id,
|
||||
CveId = CveId,
|
||||
Component = Component,
|
||||
Purl = Purl,
|
||||
Algorithm = ParseAlgorithm(Algorithm),
|
||||
FingerprintId = FingerprintId,
|
||||
FingerprintHash = FingerprintHash,
|
||||
Architecture = Architecture,
|
||||
FunctionName = FunctionName,
|
||||
SourceFile = SourceFile,
|
||||
SourceLine = SourceLine,
|
||||
SimilarityThreshold = SimilarityThreshold,
|
||||
Confidence = Confidence,
|
||||
Validated = Validated,
|
||||
ValidationStats = stats,
|
||||
VulnBuildRef = VulnBuildRef,
|
||||
FixedBuildRef = FixedBuildRef,
|
||||
IndexedAt = IndexedAt
|
||||
};
|
||||
stats = JsonSerializer.Deserialize<FingerprintValidationStats>(entity.ValidationStats, JsonOptions);
|
||||
}
|
||||
|
||||
return new VulnFingerprint
|
||||
{
|
||||
Id = entity.Id,
|
||||
CveId = entity.CveId,
|
||||
Component = entity.Component,
|
||||
Purl = entity.Purl,
|
||||
Algorithm = ParseAlgorithm(entity.Algorithm),
|
||||
FingerprintId = entity.FingerprintId,
|
||||
FingerprintHash = entity.FingerprintHash,
|
||||
Architecture = entity.Architecture,
|
||||
FunctionName = entity.FunctionName,
|
||||
SourceFile = entity.SourceFile,
|
||||
SourceLine = entity.SourceLine,
|
||||
SimilarityThreshold = entity.SimilarityThreshold ?? 0m,
|
||||
Confidence = entity.Confidence,
|
||||
Validated = entity.Validated ?? false,
|
||||
ValidationStats = stats,
|
||||
VulnBuildRef = entity.VulnBuildRef,
|
||||
FixedBuildRef = entity.FixedBuildRef,
|
||||
IndexedAt = new DateTimeOffset(entity.IndexedAt, TimeSpan.Zero)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Repository implementation for fingerprint matches.
|
||||
/// EF Core repository implementation for fingerprint matches.
|
||||
/// </summary>
|
||||
public sealed class FingerprintMatchRepository : IFingerprintMatchRepository
|
||||
{
|
||||
private readonly BinaryIndexDbContext _dbContext;
|
||||
private readonly IGuidProvider _guidProvider;
|
||||
private const int CommandTimeoutSeconds = 30;
|
||||
|
||||
public FingerprintMatchRepository(BinaryIndexDbContext dbContext, IGuidProvider? guidProvider = null)
|
||||
{
|
||||
@@ -272,43 +204,34 @@ public sealed class FingerprintMatchRepository : IFingerprintMatchRepository
|
||||
public async Task<FingerprintMatch> CreateAsync(FingerprintMatch match, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
INSERT INTO binaries.fingerprint_matches (
|
||||
id, tenant_id, scan_id, match_type, binary_key, binary_identity_id,
|
||||
vulnerable_purl, vulnerable_version, matched_fingerprint_id, matched_function,
|
||||
similarity, advisory_ids, reachability_status, matched_at
|
||||
)
|
||||
VALUES (
|
||||
@Id, binaries_app.require_current_tenant()::uuid, @ScanId, @MatchType, @BinaryKey,
|
||||
@BinaryIdentityId, @VulnerablePurl, @VulnerableVersion, @MatchedFingerprintId,
|
||||
@MatchedFunction, @Similarity, @AdvisoryIds, @ReachabilityStatus, @MatchedAt
|
||||
)
|
||||
RETURNING id
|
||||
""";
|
||||
var id = match.Id != Guid.Empty ? match.Id : _guidProvider.NewGuid();
|
||||
var matchType = match.Type.ToString().ToLowerInvariant();
|
||||
var advisoryIds = match.AdvisoryIds.IsDefaultOrEmpty ? null : match.AdvisoryIds.ToArray();
|
||||
var reachabilityStatus = match.ReachabilityStatus?.ToString().ToLowerInvariant();
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
Id = match.Id != Guid.Empty ? match.Id : _guidProvider.NewGuid(),
|
||||
match.ScanId,
|
||||
MatchType = match.Type.ToString().ToLowerInvariant(),
|
||||
match.BinaryKey,
|
||||
BinaryIdentityId = (Guid?)null,
|
||||
match.VulnerablePurl,
|
||||
match.VulnerableVersion,
|
||||
match.MatchedFingerprintId,
|
||||
match.MatchedFunction,
|
||||
match.Similarity,
|
||||
AdvisoryIds = match.AdvisoryIds.IsDefaultOrEmpty ? null : match.AdvisoryIds.ToArray(),
|
||||
ReachabilityStatus = match.ReachabilityStatus?.ToString().ToLowerInvariant(),
|
||||
match.MatchedAt
|
||||
},
|
||||
cancellationToken: ct);
|
||||
var id = await conn.ExecuteScalarAsync<Guid>(command);
|
||||
var results = await efContext.FingerprintMatches
|
||||
.FromSqlInterpolated($"""
|
||||
INSERT INTO binaries.fingerprint_matches (
|
||||
id, tenant_id, scan_id, match_type, binary_key, binary_identity_id,
|
||||
vulnerable_purl, vulnerable_version, matched_fingerprint_id, matched_function,
|
||||
similarity, advisory_ids, reachability_status, matched_at
|
||||
)
|
||||
VALUES (
|
||||
{id}, binaries_app.require_current_tenant()::uuid, {match.ScanId}, {matchType}, {match.BinaryKey},
|
||||
{(Guid?)null}, {match.VulnerablePurl}, {match.VulnerableVersion}, {match.MatchedFingerprintId},
|
||||
{match.MatchedFunction}, {match.Similarity}, {advisoryIds}, {reachabilityStatus}, {match.MatchedAt}
|
||||
)
|
||||
RETURNING id, tenant_id, scan_id, match_type, binary_key, binary_identity_id,
|
||||
vulnerable_purl, vulnerable_version, matched_fingerprint_id, matched_function,
|
||||
similarity, advisory_ids, reachability_status, evidence, matched_at, created_at
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(ct);
|
||||
|
||||
return match with { Id = id };
|
||||
var row = results.First();
|
||||
return match with { Id = row.Id };
|
||||
}
|
||||
|
||||
public async Task<ImmutableArray<FingerprintMatch>> GetByScanAsync(Guid scanId, CancellationToken ct = default)
|
||||
@@ -320,21 +243,13 @@ public sealed class FingerprintMatchRepository : IFingerprintMatchRepository
|
||||
public async Task UpdateReachabilityAsync(Guid id, ReachabilityStatus status, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
var statusStr = status.ToString().ToLowerInvariant();
|
||||
await efContext.Database.ExecuteSqlInterpolatedAsync($"""
|
||||
UPDATE binaries.fingerprint_matches
|
||||
SET reachability_status = @Status
|
||||
WHERE id = @Id
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
Id = id,
|
||||
Status = status.ToString().ToLowerInvariant()
|
||||
},
|
||||
cancellationToken: ct);
|
||||
await conn.ExecuteAsync(command);
|
||||
SET reachability_status = {statusStr}
|
||||
WHERE id = {id}
|
||||
""", ct);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
|
||||
using Npgsql;
|
||||
using NpgsqlTypes;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using StellaOps.BinaryIndex.Core.Models;
|
||||
using StellaOps.BinaryIndex.FixIndex.Models;
|
||||
using StellaOps.BinaryIndex.FixIndex.Repositories;
|
||||
using StellaOps.BinaryIndex.Persistence.Postgres;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// PostgreSQL implementation of <see cref="IFixIndexRepository"/>.
|
||||
/// EF Core implementation of <see cref="IFixIndexRepository"/>.
|
||||
/// </summary>
|
||||
public sealed class FixIndexRepository : IFixIndexRepository
|
||||
{
|
||||
private readonly BinaryIndexDbContext _dbContext;
|
||||
private const int CommandTimeoutSeconds = 30;
|
||||
|
||||
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web)
|
||||
{
|
||||
@@ -33,28 +34,16 @@ public sealed class FixIndexRepository : IFixIndexRepository
|
||||
string cveId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
const string sql = """
|
||||
SELECT id, distro, release, source_pkg, cve_id, state, fixed_version,
|
||||
method, confidence, evidence_id, snapshot_id, indexed_at, updated_at
|
||||
FROM binaries.cve_fix_index
|
||||
WHERE distro = @distro AND release = @release
|
||||
AND source_pkg = @sourcePkg AND cve_id = @cveId
|
||||
""";
|
||||
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(cancellationToken);
|
||||
await using var cmd = new NpgsqlCommand(sql, conn);
|
||||
cmd.Parameters.AddWithValue("distro", distro);
|
||||
cmd.Parameters.AddWithValue("release", release);
|
||||
cmd.Parameters.AddWithValue("sourcePkg", sourcePkg);
|
||||
cmd.Parameters.AddWithValue("cveId", cveId);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
await using var reader = await cmd.ExecuteReaderAsync(cancellationToken);
|
||||
if (await reader.ReadAsync(cancellationToken))
|
||||
{
|
||||
return MapToFixIndexEntry(reader);
|
||||
}
|
||||
var entity = await efContext.CveFixIndexes
|
||||
.AsNoTracking()
|
||||
.Where(e => e.Distro == distro && e.Release == release
|
||||
&& e.SourcePkg == sourcePkg && e.CveId == cveId)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
return null;
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -64,28 +53,16 @@ public sealed class FixIndexRepository : IFixIndexRepository
|
||||
string sourcePkg,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
const string sql = """
|
||||
SELECT id, distro, release, source_pkg, cve_id, state, fixed_version,
|
||||
method, confidence, evidence_id, snapshot_id, indexed_at, updated_at
|
||||
FROM binaries.cve_fix_index
|
||||
WHERE distro = @distro AND release = @release AND source_pkg = @sourcePkg
|
||||
ORDER BY cve_id
|
||||
""";
|
||||
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(cancellationToken);
|
||||
await using var cmd = new NpgsqlCommand(sql, conn);
|
||||
cmd.Parameters.AddWithValue("distro", distro);
|
||||
cmd.Parameters.AddWithValue("release", release);
|
||||
cmd.Parameters.AddWithValue("sourcePkg", sourcePkg);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
var results = new List<FixIndexEntry>();
|
||||
await using var reader = await cmd.ExecuteReaderAsync(cancellationToken);
|
||||
while (await reader.ReadAsync(cancellationToken))
|
||||
{
|
||||
results.Add(MapToFixIndexEntry(reader));
|
||||
}
|
||||
var entities = await efContext.CveFixIndexes
|
||||
.AsNoTracking()
|
||||
.Where(e => e.Distro == distro && e.Release == release && e.SourcePkg == sourcePkg)
|
||||
.OrderBy(e => e.CveId)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return results;
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -93,26 +70,16 @@ public sealed class FixIndexRepository : IFixIndexRepository
|
||||
string cveId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
const string sql = """
|
||||
SELECT id, distro, release, source_pkg, cve_id, state, fixed_version,
|
||||
method, confidence, evidence_id, snapshot_id, indexed_at, updated_at
|
||||
FROM binaries.cve_fix_index
|
||||
WHERE cve_id = @cveId
|
||||
ORDER BY distro, release, source_pkg
|
||||
""";
|
||||
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(cancellationToken);
|
||||
await using var cmd = new NpgsqlCommand(sql, conn);
|
||||
cmd.Parameters.AddWithValue("cveId", cveId);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
var results = new List<FixIndexEntry>();
|
||||
await using var reader = await cmd.ExecuteReaderAsync(cancellationToken);
|
||||
while (await reader.ReadAsync(cancellationToken))
|
||||
{
|
||||
results.Add(MapToFixIndexEntry(reader));
|
||||
}
|
||||
var entities = await efContext.CveFixIndexes
|
||||
.AsNoTracking()
|
||||
.Where(e => e.CveId == cveId)
|
||||
.OrderBy(e => e.Distro).ThenBy(e => e.Release).ThenBy(e => e.SourcePkg)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return results;
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -123,47 +90,40 @@ public sealed class FixIndexRepository : IFixIndexRepository
|
||||
// First store evidence
|
||||
var evidenceId = await StoreEvidenceAsync(evidence, cancellationToken);
|
||||
|
||||
const string sql = """
|
||||
INSERT INTO binaries.cve_fix_index
|
||||
(distro, release, source_pkg, cve_id, architecture, state, fixed_version, method, confidence, evidence_id, snapshot_id)
|
||||
VALUES
|
||||
(@distro, @release, @sourcePkg, @cveId, @architecture, @state, @fixedVersion, @method, @confidence, @evidenceId, @snapshotId)
|
||||
ON CONFLICT (tenant_id, distro, release, source_pkg, cve_id, architecture)
|
||||
DO UPDATE SET
|
||||
state = EXCLUDED.state,
|
||||
fixed_version = EXCLUDED.fixed_version,
|
||||
method = CASE
|
||||
WHEN binaries.cve_fix_index.confidence < EXCLUDED.confidence THEN EXCLUDED.method
|
||||
ELSE binaries.cve_fix_index.method
|
||||
END,
|
||||
confidence = GREATEST(binaries.cve_fix_index.confidence, EXCLUDED.confidence),
|
||||
evidence_id = CASE
|
||||
WHEN binaries.cve_fix_index.confidence < EXCLUDED.confidence THEN EXCLUDED.evidence_id
|
||||
ELSE binaries.cve_fix_index.evidence_id
|
||||
END,
|
||||
snapshot_id = EXCLUDED.snapshot_id,
|
||||
updated_at = now()
|
||||
RETURNING id, distro, release, source_pkg, cve_id, state, fixed_version,
|
||||
method, confidence, evidence_id, snapshot_id, indexed_at, updated_at
|
||||
""";
|
||||
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(cancellationToken);
|
||||
await using var cmd = new NpgsqlCommand(sql, conn);
|
||||
cmd.Parameters.AddWithValue("distro", evidence.Distro);
|
||||
cmd.Parameters.AddWithValue("release", evidence.Release);
|
||||
cmd.Parameters.AddWithValue("sourcePkg", evidence.SourcePkg);
|
||||
cmd.Parameters.AddWithValue("cveId", evidence.CveId);
|
||||
cmd.Parameters.AddWithValue("architecture", DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("state", evidence.State.ToString().ToLowerInvariant());
|
||||
cmd.Parameters.AddWithValue("fixedVersion", (object?)evidence.FixedVersion ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("method", ToDbFixMethod(evidence.Method));
|
||||
cmd.Parameters.AddWithValue("confidence", evidence.Confidence);
|
||||
cmd.Parameters.AddWithValue("evidenceId", evidenceId);
|
||||
cmd.Parameters.AddWithValue("snapshotId", (object?)evidence.SnapshotId ?? DBNull.Value);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
await using var reader = await cmd.ExecuteReaderAsync(cancellationToken);
|
||||
await reader.ReadAsync(cancellationToken);
|
||||
return MapToFixIndexEntry(reader);
|
||||
var state = evidence.State.ToString().ToLowerInvariant();
|
||||
var method = ToDbFixMethod(evidence.Method);
|
||||
|
||||
var results = await efContext.CveFixIndexes
|
||||
.FromSqlInterpolated($"""
|
||||
INSERT INTO binaries.cve_fix_index
|
||||
(distro, release, source_pkg, cve_id, architecture, state, fixed_version, method, confidence, evidence_id, snapshot_id)
|
||||
VALUES
|
||||
({evidence.Distro}, {evidence.Release}, {evidence.SourcePkg}, {evidence.CveId}, {(string?)null}, {state}, {evidence.FixedVersion}, {method}, {evidence.Confidence}, {evidenceId}, {evidence.SnapshotId})
|
||||
ON CONFLICT (tenant_id, distro, release, source_pkg, cve_id, architecture)
|
||||
DO UPDATE SET
|
||||
state = EXCLUDED.state,
|
||||
fixed_version = EXCLUDED.fixed_version,
|
||||
method = CASE
|
||||
WHEN binaries.cve_fix_index.confidence < EXCLUDED.confidence THEN EXCLUDED.method
|
||||
ELSE binaries.cve_fix_index.method
|
||||
END,
|
||||
confidence = GREATEST(binaries.cve_fix_index.confidence, EXCLUDED.confidence),
|
||||
evidence_id = CASE
|
||||
WHEN binaries.cve_fix_index.confidence < EXCLUDED.confidence THEN EXCLUDED.evidence_id
|
||||
ELSE binaries.cve_fix_index.evidence_id
|
||||
END,
|
||||
snapshot_id = EXCLUDED.snapshot_id,
|
||||
updated_at = now()
|
||||
RETURNING id, tenant_id, distro, release, source_pkg, cve_id, architecture,
|
||||
state, fixed_version, method, confidence, evidence_id, snapshot_id, indexed_at, updated_at
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return ToModel(results.First());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -187,24 +147,22 @@ public sealed class FixIndexRepository : IFixIndexRepository
|
||||
{
|
||||
var (evidenceType, sourceFile, excerpt, metadata) = MapEvidencePayload(evidence.Evidence);
|
||||
|
||||
const string sql = """
|
||||
INSERT INTO binaries.fix_evidence
|
||||
(evidence_type, source_file, excerpt, metadata, snapshot_id)
|
||||
VALUES
|
||||
(@evidenceType, @sourceFile, @excerpt, @metadata::jsonb, @snapshotId)
|
||||
RETURNING id
|
||||
""";
|
||||
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(cancellationToken);
|
||||
await using var cmd = new NpgsqlCommand(sql, conn);
|
||||
cmd.Parameters.AddWithValue("evidenceType", evidenceType);
|
||||
cmd.Parameters.AddWithValue("sourceFile", (object?)sourceFile ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("excerpt", (object?)excerpt ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("metadata", NpgsqlDbType.Jsonb, metadata);
|
||||
cmd.Parameters.AddWithValue("snapshotId", (object?)evidence.SnapshotId ?? DBNull.Value);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
var result = await cmd.ExecuteScalarAsync(cancellationToken);
|
||||
return (Guid)result!;
|
||||
var results = await efContext.FixEvidences
|
||||
.FromSqlInterpolated($"""
|
||||
INSERT INTO binaries.fix_evidence
|
||||
(evidence_type, source_file, excerpt, metadata, snapshot_id)
|
||||
VALUES
|
||||
({evidenceType}, {sourceFile}, {excerpt}, {metadata}::jsonb, {evidence.SnapshotId})
|
||||
RETURNING id, tenant_id, evidence_type, source_file, source_sha256, excerpt,
|
||||
metadata, snapshot_id, created_at
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return results.First().Id;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -212,33 +170,30 @@ public sealed class FixIndexRepository : IFixIndexRepository
|
||||
Guid evidenceId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
const string sql = """
|
||||
SELECT id, evidence_type, source_file, source_sha256, excerpt, metadata::text, snapshot_id, created_at
|
||||
FROM binaries.fix_evidence
|
||||
WHERE id = @id
|
||||
""";
|
||||
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(cancellationToken);
|
||||
await using var cmd = new NpgsqlCommand(sql, conn);
|
||||
cmd.Parameters.AddWithValue("id", evidenceId);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
await using var reader = await cmd.ExecuteReaderAsync(cancellationToken);
|
||||
if (await reader.ReadAsync(cancellationToken))
|
||||
var entity = await efContext.FixEvidences
|
||||
.AsNoTracking()
|
||||
.Where(e => e.Id == evidenceId)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
if (entity is null)
|
||||
{
|
||||
return new FixEvidenceRecord
|
||||
{
|
||||
Id = reader.GetGuid(0),
|
||||
EvidenceType = reader.GetString(1),
|
||||
SourceFile = reader.IsDBNull(2) ? null : reader.GetString(2),
|
||||
SourceSha256 = reader.IsDBNull(3) ? null : reader.GetString(3),
|
||||
Excerpt = reader.IsDBNull(4) ? null : reader.GetString(4),
|
||||
MetadataJson = reader.GetString(5),
|
||||
SnapshotId = reader.IsDBNull(6) ? null : reader.GetGuid(6),
|
||||
CreatedAt = reader.GetFieldValue<DateTimeOffset>(7)
|
||||
};
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
return new FixEvidenceRecord
|
||||
{
|
||||
Id = entity.Id,
|
||||
EvidenceType = entity.EvidenceType,
|
||||
SourceFile = entity.SourceFile,
|
||||
SourceSha256 = entity.SourceSha256,
|
||||
Excerpt = entity.Excerpt,
|
||||
MetadataJson = entity.Metadata,
|
||||
SnapshotId = entity.SnapshotId,
|
||||
CreatedAt = new DateTimeOffset(entity.CreatedAt, TimeSpan.Zero)
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -246,41 +201,41 @@ public sealed class FixIndexRepository : IFixIndexRepository
|
||||
Guid snapshotId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
const string sql = """
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(cancellationToken);
|
||||
await using var efContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
// Use raw SQL for the CTE-based multi-table delete
|
||||
var result = await efContext.Database.SqlQueryRaw<int>("""
|
||||
WITH deleted_index AS (
|
||||
DELETE FROM binaries.cve_fix_index WHERE snapshot_id = @snapshotId RETURNING 1
|
||||
DELETE FROM binaries.cve_fix_index WHERE snapshot_id = @p0 RETURNING 1
|
||||
),
|
||||
deleted_evidence AS (
|
||||
DELETE FROM binaries.fix_evidence WHERE snapshot_id = @snapshotId RETURNING 1
|
||||
DELETE FROM binaries.fix_evidence WHERE snapshot_id = @p0 RETURNING 1
|
||||
)
|
||||
SELECT (SELECT COUNT(*) FROM deleted_index) + (SELECT COUNT(*) FROM deleted_evidence)
|
||||
""";
|
||||
SELECT CAST((SELECT COUNT(*) FROM deleted_index) + (SELECT COUNT(*) FROM deleted_evidence) AS integer) AS "Value"
|
||||
""", snapshotId)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(cancellationToken);
|
||||
await using var cmd = new NpgsqlCommand(sql, conn);
|
||||
cmd.Parameters.AddWithValue("snapshotId", snapshotId);
|
||||
|
||||
var result = await cmd.ExecuteScalarAsync(cancellationToken);
|
||||
return Convert.ToInt32(result);
|
||||
return result.FirstOrDefault();
|
||||
}
|
||||
|
||||
private static FixIndexEntry MapToFixIndexEntry(NpgsqlDataReader reader)
|
||||
private static FixIndexEntry ToModel(EfCore.Models.CveFixIndexEntity entity)
|
||||
{
|
||||
return new FixIndexEntry
|
||||
{
|
||||
Id = reader.GetGuid(0),
|
||||
Distro = reader.GetString(1),
|
||||
Release = reader.GetString(2),
|
||||
SourcePkg = reader.GetString(3),
|
||||
CveId = reader.GetString(4),
|
||||
State = Enum.Parse<FixState>(reader.GetString(5), ignoreCase: true),
|
||||
FixedVersion = reader.IsDBNull(6) ? null : reader.GetString(6),
|
||||
Method = ParseFixMethod(reader.GetString(7)),
|
||||
Confidence = reader.GetDecimal(8),
|
||||
EvidenceId = reader.IsDBNull(9) ? null : reader.GetGuid(9),
|
||||
SnapshotId = reader.IsDBNull(10) ? null : reader.GetGuid(10),
|
||||
IndexedAt = reader.GetFieldValue<DateTimeOffset>(11),
|
||||
UpdatedAt = reader.GetFieldValue<DateTimeOffset>(12)
|
||||
Id = entity.Id,
|
||||
Distro = entity.Distro,
|
||||
Release = entity.Release,
|
||||
SourcePkg = entity.SourcePkg,
|
||||
CveId = entity.CveId,
|
||||
State = Enum.Parse<FixState>(entity.State, ignoreCase: true),
|
||||
FixedVersion = entity.FixedVersion,
|
||||
Method = ParseFixMethod(entity.Method),
|
||||
Confidence = entity.Confidence,
|
||||
EvidenceId = entity.EvidenceId,
|
||||
SnapshotId = entity.SnapshotId,
|
||||
IndexedAt = new DateTimeOffset(entity.IndexedAt, TimeSpan.Zero),
|
||||
UpdatedAt = new DateTimeOffset(entity.UpdatedAt, TimeSpan.Zero)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
using Dapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using StellaOps.BinaryIndex.Persistence.Postgres;
|
||||
using EfModels = StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.Repositories.GroundTruth;
|
||||
|
||||
/// <summary>
|
||||
/// Repository implementation for raw document storage (immutable, append-only).
|
||||
/// EF Core repository implementation for raw document storage (immutable, append-only).
|
||||
/// </summary>
|
||||
public sealed class RawDocumentRepository : IRawDocumentRepository
|
||||
{
|
||||
private readonly BinaryIndexDbContext _dbContext;
|
||||
private const int CommandTimeoutSeconds = 30;
|
||||
|
||||
public RawDocumentRepository(BinaryIndexDbContext dbContext)
|
||||
{
|
||||
@@ -18,38 +21,25 @@ public sealed class RawDocumentRepository : IRawDocumentRepository
|
||||
public async Task<RawDocumentEntity?> GetByDigestAsync(string digest, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT digest AS "Digest",
|
||||
source_id AS "SourceId",
|
||||
document_uri AS "DocumentUri",
|
||||
content_type AS "ContentType",
|
||||
content_size AS "ContentSize",
|
||||
etag AS "ETag",
|
||||
fetched_at AS "FetchedAt",
|
||||
recorded_at AS "RecordedAt",
|
||||
status AS "Status",
|
||||
payload_id AS "PayloadId",
|
||||
metadata::text AS "MetadataJson"
|
||||
FROM groundtruth.raw_documents
|
||||
WHERE digest = @Digest
|
||||
""";
|
||||
var entity = await dbContext.RawDocuments
|
||||
.AsNoTracking()
|
||||
.Where(e => e.Digest == digest)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { Digest = digest }, cancellationToken: ct);
|
||||
return await conn.QuerySingleOrDefaultAsync<RawDocumentEntity>(command);
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<bool> ExistsAsync(string digest, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT EXISTS(SELECT 1 FROM groundtruth.raw_documents WHERE digest = @Digest)
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(sql, new { Digest = digest }, cancellationToken: ct);
|
||||
return await conn.QuerySingleAsync<bool>(command);
|
||||
return await dbContext.RawDocuments
|
||||
.AsNoTracking()
|
||||
.AnyAsync(e => e.Digest == digest, ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -59,28 +49,16 @@ public sealed class RawDocumentRepository : IRawDocumentRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT digest AS "Digest",
|
||||
source_id AS "SourceId",
|
||||
document_uri AS "DocumentUri",
|
||||
content_type AS "ContentType",
|
||||
content_size AS "ContentSize",
|
||||
etag AS "ETag",
|
||||
fetched_at AS "FetchedAt",
|
||||
recorded_at AS "RecordedAt",
|
||||
status AS "Status",
|
||||
payload_id AS "PayloadId",
|
||||
metadata::text AS "MetadataJson"
|
||||
FROM groundtruth.raw_documents
|
||||
WHERE source_id = @SourceId AND status = 'pending_parse'
|
||||
ORDER BY fetched_at ASC
|
||||
LIMIT @Limit
|
||||
""";
|
||||
var entities = await dbContext.RawDocuments
|
||||
.AsNoTracking()
|
||||
.Where(e => e.SourceId == sourceId && e.Status == "pending_parse")
|
||||
.OrderBy(e => e.FetchedAt)
|
||||
.Take(limit)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { SourceId = sourceId, Limit = limit }, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<RawDocumentEntity>(command);
|
||||
return rows.ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -90,65 +68,36 @@ public sealed class RawDocumentRepository : IRawDocumentRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT digest AS "Digest",
|
||||
source_id AS "SourceId",
|
||||
document_uri AS "DocumentUri",
|
||||
content_type AS "ContentType",
|
||||
content_size AS "ContentSize",
|
||||
etag AS "ETag",
|
||||
fetched_at AS "FetchedAt",
|
||||
recorded_at AS "RecordedAt",
|
||||
status AS "Status",
|
||||
payload_id AS "PayloadId",
|
||||
metadata::text AS "MetadataJson"
|
||||
FROM groundtruth.raw_documents
|
||||
WHERE source_id = @SourceId AND status = 'pending_map'
|
||||
ORDER BY fetched_at ASC
|
||||
LIMIT @Limit
|
||||
""";
|
||||
var entities = await dbContext.RawDocuments
|
||||
.AsNoTracking()
|
||||
.Where(e => e.SourceId == sourceId && e.Status == "pending_map")
|
||||
.OrderBy(e => e.FetchedAt)
|
||||
.Take(limit)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { SourceId = sourceId, Limit = limit }, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<RawDocumentEntity>(command);
|
||||
return rows.ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<bool> InsertAsync(RawDocumentEntity document, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var affected = await dbContext.Database.ExecuteSqlInterpolatedAsync($"""
|
||||
INSERT INTO groundtruth.raw_documents (
|
||||
digest, source_id, document_uri, content_type, content_size,
|
||||
etag, fetched_at, recorded_at, status, payload_id, metadata
|
||||
) VALUES (
|
||||
@Digest, @SourceId, @DocumentUri, @ContentType, @ContentSize,
|
||||
@ETag, @FetchedAt, @Now, @Status, @PayloadId, @MetadataJson::jsonb
|
||||
{document.Digest}, {document.SourceId}, {document.DocumentUri}, {document.ContentType}, {document.ContentSize},
|
||||
{document.ETag}, {document.FetchedAt}, {now}, {document.Status}, {document.PayloadId}, {document.MetadataJson}::jsonb
|
||||
)
|
||||
ON CONFLICT (digest) DO NOTHING
|
||||
""";
|
||||
""", ct);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
document.Digest,
|
||||
document.SourceId,
|
||||
document.DocumentUri,
|
||||
document.ContentType,
|
||||
document.ContentSize,
|
||||
document.ETag,
|
||||
document.FetchedAt,
|
||||
Now = DateTimeOffset.UtcNow,
|
||||
document.Status,
|
||||
document.PayloadId,
|
||||
document.MetadataJson
|
||||
},
|
||||
cancellationToken: ct);
|
||||
|
||||
var affected = await conn.ExecuteAsync(command);
|
||||
return affected > 0;
|
||||
}
|
||||
|
||||
@@ -156,15 +105,13 @@ public sealed class RawDocumentRepository : IRawDocumentRepository
|
||||
public async Task UpdateStatusAsync(string digest, string status, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
await dbContext.Database.ExecuteSqlInterpolatedAsync($"""
|
||||
UPDATE groundtruth.raw_documents
|
||||
SET status = @Status
|
||||
WHERE digest = @Digest
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(sql, new { Digest = digest, Status = status }, cancellationToken: ct);
|
||||
await conn.ExecuteAsync(command);
|
||||
SET status = {status}
|
||||
WHERE digest = {digest}
|
||||
""", ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -173,16 +120,30 @@ public sealed class RawDocumentRepository : IRawDocumentRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT status AS "Status", COUNT(*) AS "Count"
|
||||
FROM groundtruth.raw_documents
|
||||
WHERE source_id = @SourceId
|
||||
GROUP BY status
|
||||
""";
|
||||
var groups = await dbContext.RawDocuments
|
||||
.AsNoTracking()
|
||||
.Where(e => e.SourceId == sourceId)
|
||||
.GroupBy(e => e.Status)
|
||||
.Select(g => new { Status = g.Key, Count = (long)g.Count() })
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { SourceId = sourceId }, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<(string Status, long Count)>(command);
|
||||
return rows.ToDictionary(r => r.Status, r => r.Count);
|
||||
return groups.ToDictionary(g => g.Status, g => g.Count);
|
||||
}
|
||||
|
||||
private static RawDocumentEntity ToModel(EfModels.RawDocumentEntity entity) => new()
|
||||
{
|
||||
Digest = entity.Digest,
|
||||
SourceId = entity.SourceId,
|
||||
DocumentUri = entity.DocumentUri,
|
||||
ContentType = entity.ContentType,
|
||||
ContentSize = entity.ContentSize,
|
||||
ETag = entity.Etag,
|
||||
FetchedAt = new DateTimeOffset(entity.FetchedAt, TimeSpan.Zero),
|
||||
RecordedAt = new DateTimeOffset(entity.RecordedAt, TimeSpan.Zero),
|
||||
Status = entity.Status,
|
||||
PayloadId = entity.PayloadId,
|
||||
MetadataJson = entity.Metadata
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
using Dapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using StellaOps.BinaryIndex.Persistence.Postgres;
|
||||
using EfModels = StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.Repositories.GroundTruth;
|
||||
|
||||
/// <summary>
|
||||
/// Repository implementation for security pair (pre/post CVE binary) management.
|
||||
/// EF Core repository implementation for security pair (pre/post CVE binary) management.
|
||||
/// </summary>
|
||||
public sealed class SecurityPairRepository : ISecurityPairRepository
|
||||
{
|
||||
private readonly BinaryIndexDbContext _dbContext;
|
||||
private const int CommandTimeoutSeconds = 30;
|
||||
|
||||
public SecurityPairRepository(BinaryIndexDbContext dbContext)
|
||||
{
|
||||
@@ -18,65 +21,29 @@ public sealed class SecurityPairRepository : ISecurityPairRepository
|
||||
public async Task<SecurityPairEntity?> GetByIdAsync(Guid pairId, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT pair_id AS "PairId",
|
||||
cve_id AS "CveId",
|
||||
package_name AS "PackageName",
|
||||
distro AS "Distro",
|
||||
distro_version AS "DistroVersion",
|
||||
vulnerable_version AS "VulnerableVersion",
|
||||
vulnerable_debug_id AS "VulnerableDebugId",
|
||||
vulnerable_observation_id AS "VulnerableObservationId",
|
||||
fixed_version AS "FixedVersion",
|
||||
fixed_debug_id AS "FixedDebugId",
|
||||
fixed_observation_id AS "FixedObservationId",
|
||||
upstream_diff_url AS "UpstreamDiffUrl",
|
||||
patch_functions AS "PatchFunctions",
|
||||
verification_status AS "VerificationStatus",
|
||||
metadata::text AS "MetadataJson",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM groundtruth.security_pairs
|
||||
WHERE pair_id = @PairId
|
||||
""";
|
||||
var entity = await dbContext.SecurityPairs
|
||||
.AsNoTracking()
|
||||
.Where(e => e.PairId == pairId)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { PairId = pairId }, cancellationToken: ct);
|
||||
var row = await conn.QuerySingleOrDefaultAsync<SecurityPairRow>(command);
|
||||
return row?.ToEntity();
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IReadOnlyList<SecurityPairEntity>> GetByCveAsync(string cveId, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT pair_id AS "PairId",
|
||||
cve_id AS "CveId",
|
||||
package_name AS "PackageName",
|
||||
distro AS "Distro",
|
||||
distro_version AS "DistroVersion",
|
||||
vulnerable_version AS "VulnerableVersion",
|
||||
vulnerable_debug_id AS "VulnerableDebugId",
|
||||
vulnerable_observation_id AS "VulnerableObservationId",
|
||||
fixed_version AS "FixedVersion",
|
||||
fixed_debug_id AS "FixedDebugId",
|
||||
fixed_observation_id AS "FixedObservationId",
|
||||
upstream_diff_url AS "UpstreamDiffUrl",
|
||||
patch_functions AS "PatchFunctions",
|
||||
verification_status AS "VerificationStatus",
|
||||
metadata::text AS "MetadataJson",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM groundtruth.security_pairs
|
||||
WHERE cve_id = @CveId
|
||||
ORDER BY package_name, distro
|
||||
""";
|
||||
var entities = await dbContext.SecurityPairs
|
||||
.AsNoTracking()
|
||||
.Where(e => e.CveId == cveId)
|
||||
.OrderBy(e => e.PackageName).ThenBy(e => e.Distro)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { CveId = cveId }, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<SecurityPairRow>(command);
|
||||
return rows.Select(r => r.ToEntity()).ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -86,37 +53,22 @@ public sealed class SecurityPairRepository : ISecurityPairRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT pair_id AS "PairId",
|
||||
cve_id AS "CveId",
|
||||
package_name AS "PackageName",
|
||||
distro AS "Distro",
|
||||
distro_version AS "DistroVersion",
|
||||
vulnerable_version AS "VulnerableVersion",
|
||||
vulnerable_debug_id AS "VulnerableDebugId",
|
||||
vulnerable_observation_id AS "VulnerableObservationId",
|
||||
fixed_version AS "FixedVersion",
|
||||
fixed_debug_id AS "FixedDebugId",
|
||||
fixed_observation_id AS "FixedObservationId",
|
||||
upstream_diff_url AS "UpstreamDiffUrl",
|
||||
patch_functions AS "PatchFunctions",
|
||||
verification_status AS "VerificationStatus",
|
||||
metadata::text AS "MetadataJson",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM groundtruth.security_pairs
|
||||
WHERE package_name = @PackageName
|
||||
AND (@Distro IS NULL OR distro = @Distro)
|
||||
ORDER BY cve_id, distro
|
||||
""";
|
||||
var query = dbContext.SecurityPairs
|
||||
.AsNoTracking()
|
||||
.Where(e => e.PackageName == packageName);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { PackageName = packageName, Distro = distro },
|
||||
cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<SecurityPairRow>(command);
|
||||
return rows.Select(r => r.ToEntity()).ToList();
|
||||
if (distro is not null)
|
||||
{
|
||||
query = query.Where(e => e.Distro == distro);
|
||||
}
|
||||
|
||||
var entities = await query
|
||||
.OrderBy(e => e.CveId).ThenBy(e => e.Distro)
|
||||
.ToListAsync(ct);
|
||||
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -125,108 +77,62 @@ public sealed class SecurityPairRepository : ISecurityPairRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT pair_id AS "PairId",
|
||||
cve_id AS "CveId",
|
||||
package_name AS "PackageName",
|
||||
distro AS "Distro",
|
||||
distro_version AS "DistroVersion",
|
||||
vulnerable_version AS "VulnerableVersion",
|
||||
vulnerable_debug_id AS "VulnerableDebugId",
|
||||
vulnerable_observation_id AS "VulnerableObservationId",
|
||||
fixed_version AS "FixedVersion",
|
||||
fixed_debug_id AS "FixedDebugId",
|
||||
fixed_observation_id AS "FixedObservationId",
|
||||
upstream_diff_url AS "UpstreamDiffUrl",
|
||||
patch_functions AS "PatchFunctions",
|
||||
verification_status AS "VerificationStatus",
|
||||
metadata::text AS "MetadataJson",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM groundtruth.security_pairs
|
||||
WHERE verification_status = 'pending'
|
||||
ORDER BY created_at ASC
|
||||
LIMIT @Limit
|
||||
""";
|
||||
var entities = await dbContext.SecurityPairs
|
||||
.AsNoTracking()
|
||||
.Where(e => e.VerificationStatus == "pending")
|
||||
.OrderBy(e => e.CreatedAt)
|
||||
.Take(limit)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { Limit = limit }, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<SecurityPairRow>(command);
|
||||
return rows.Select(r => r.ToEntity()).ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<SecurityPairEntity> UpsertAsync(SecurityPairEntity pair, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
INSERT INTO groundtruth.security_pairs (
|
||||
cve_id, package_name, distro, distro_version,
|
||||
vulnerable_version, vulnerable_debug_id, vulnerable_observation_id,
|
||||
fixed_version, fixed_debug_id, fixed_observation_id,
|
||||
upstream_diff_url, patch_functions, verification_status, metadata,
|
||||
created_at, updated_at
|
||||
) VALUES (
|
||||
@CveId, @PackageName, @Distro, @DistroVersion,
|
||||
@VulnerableVersion, @VulnerableDebugId, @VulnerableObservationId,
|
||||
@FixedVersion, @FixedDebugId, @FixedObservationId,
|
||||
@UpstreamDiffUrl, @PatchFunctions, @VerificationStatus, @MetadataJson::jsonb,
|
||||
@Now, @Now
|
||||
)
|
||||
ON CONFLICT (cve_id, package_name, distro, vulnerable_version, fixed_version) DO UPDATE SET
|
||||
distro_version = EXCLUDED.distro_version,
|
||||
vulnerable_debug_id = COALESCE(EXCLUDED.vulnerable_debug_id, groundtruth.security_pairs.vulnerable_debug_id),
|
||||
vulnerable_observation_id = COALESCE(EXCLUDED.vulnerable_observation_id, groundtruth.security_pairs.vulnerable_observation_id),
|
||||
fixed_debug_id = COALESCE(EXCLUDED.fixed_debug_id, groundtruth.security_pairs.fixed_debug_id),
|
||||
fixed_observation_id = COALESCE(EXCLUDED.fixed_observation_id, groundtruth.security_pairs.fixed_observation_id),
|
||||
upstream_diff_url = COALESCE(EXCLUDED.upstream_diff_url, groundtruth.security_pairs.upstream_diff_url),
|
||||
patch_functions = COALESCE(EXCLUDED.patch_functions, groundtruth.security_pairs.patch_functions),
|
||||
metadata = COALESCE(EXCLUDED.metadata, groundtruth.security_pairs.metadata),
|
||||
updated_at = EXCLUDED.updated_at
|
||||
RETURNING pair_id AS "PairId",
|
||||
cve_id AS "CveId",
|
||||
package_name AS "PackageName",
|
||||
distro AS "Distro",
|
||||
distro_version AS "DistroVersion",
|
||||
vulnerable_version AS "VulnerableVersion",
|
||||
vulnerable_debug_id AS "VulnerableDebugId",
|
||||
vulnerable_observation_id AS "VulnerableObservationId",
|
||||
fixed_version AS "FixedVersion",
|
||||
fixed_debug_id AS "FixedDebugId",
|
||||
fixed_observation_id AS "FixedObservationId",
|
||||
upstream_diff_url AS "UpstreamDiffUrl",
|
||||
patch_functions AS "PatchFunctions",
|
||||
verification_status AS "VerificationStatus",
|
||||
metadata::text AS "MetadataJson",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
""";
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var patchFunctions = pair.PatchFunctions?.ToArray();
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
pair.CveId,
|
||||
pair.PackageName,
|
||||
pair.Distro,
|
||||
pair.DistroVersion,
|
||||
pair.VulnerableVersion,
|
||||
pair.VulnerableDebugId,
|
||||
pair.VulnerableObservationId,
|
||||
pair.FixedVersion,
|
||||
pair.FixedDebugId,
|
||||
pair.FixedObservationId,
|
||||
pair.UpstreamDiffUrl,
|
||||
PatchFunctions = pair.PatchFunctions?.ToArray(),
|
||||
pair.VerificationStatus,
|
||||
pair.MetadataJson,
|
||||
Now = DateTimeOffset.UtcNow
|
||||
},
|
||||
cancellationToken: ct);
|
||||
var results = await dbContext.SecurityPairs
|
||||
.FromSqlInterpolated($"""
|
||||
INSERT INTO groundtruth.security_pairs (
|
||||
cve_id, package_name, distro, distro_version,
|
||||
vulnerable_version, vulnerable_debug_id, vulnerable_observation_id,
|
||||
fixed_version, fixed_debug_id, fixed_observation_id,
|
||||
upstream_diff_url, patch_functions, verification_status, metadata,
|
||||
created_at, updated_at
|
||||
) VALUES (
|
||||
{pair.CveId}, {pair.PackageName}, {pair.Distro}, {pair.DistroVersion},
|
||||
{pair.VulnerableVersion}, {pair.VulnerableDebugId}, {pair.VulnerableObservationId},
|
||||
{pair.FixedVersion}, {pair.FixedDebugId}, {pair.FixedObservationId},
|
||||
{pair.UpstreamDiffUrl}, {patchFunctions}, {pair.VerificationStatus}, {pair.MetadataJson}::jsonb,
|
||||
{now}, {now}
|
||||
)
|
||||
ON CONFLICT (cve_id, package_name, distro, vulnerable_version, fixed_version) DO UPDATE SET
|
||||
distro_version = EXCLUDED.distro_version,
|
||||
vulnerable_debug_id = COALESCE(EXCLUDED.vulnerable_debug_id, groundtruth.security_pairs.vulnerable_debug_id),
|
||||
vulnerable_observation_id = COALESCE(EXCLUDED.vulnerable_observation_id, groundtruth.security_pairs.vulnerable_observation_id),
|
||||
fixed_debug_id = COALESCE(EXCLUDED.fixed_debug_id, groundtruth.security_pairs.fixed_debug_id),
|
||||
fixed_observation_id = COALESCE(EXCLUDED.fixed_observation_id, groundtruth.security_pairs.fixed_observation_id),
|
||||
upstream_diff_url = COALESCE(EXCLUDED.upstream_diff_url, groundtruth.security_pairs.upstream_diff_url),
|
||||
patch_functions = COALESCE(EXCLUDED.patch_functions, groundtruth.security_pairs.patch_functions),
|
||||
metadata = COALESCE(EXCLUDED.metadata, groundtruth.security_pairs.metadata),
|
||||
updated_at = EXCLUDED.updated_at
|
||||
RETURNING pair_id, cve_id, package_name, distro, distro_version,
|
||||
vulnerable_version, vulnerable_debug_id, vulnerable_observation_id,
|
||||
fixed_version, fixed_debug_id, fixed_observation_id,
|
||||
upstream_diff_url, patch_functions, verification_status,
|
||||
metadata, created_at, updated_at
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(ct);
|
||||
|
||||
var row = await conn.QuerySingleAsync<SecurityPairRow>(command);
|
||||
return row.ToEntity();
|
||||
return ToModel(results.First());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -236,19 +142,14 @@ public sealed class SecurityPairRepository : ISecurityPairRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
await dbContext.Database.ExecuteSqlInterpolatedAsync($"""
|
||||
UPDATE groundtruth.security_pairs
|
||||
SET verification_status = @Status, updated_at = @Now
|
||||
WHERE pair_id = @PairId
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { PairId = pairId, Status = status, Now = DateTimeOffset.UtcNow },
|
||||
cancellationToken: ct);
|
||||
|
||||
await conn.ExecuteAsync(command);
|
||||
SET verification_status = {status}, updated_at = {now}
|
||||
WHERE pair_id = {pairId}
|
||||
""", ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -259,27 +160,16 @@ public sealed class SecurityPairRepository : ISecurityPairRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
await dbContext.Database.ExecuteSqlInterpolatedAsync($"""
|
||||
UPDATE groundtruth.security_pairs
|
||||
SET vulnerable_observation_id = COALESCE(@VulnerableObservationId, vulnerable_observation_id),
|
||||
fixed_observation_id = COALESCE(@FixedObservationId, fixed_observation_id),
|
||||
updated_at = @Now
|
||||
WHERE pair_id = @PairId
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
PairId = pairId,
|
||||
VulnerableObservationId = vulnerableObservationId,
|
||||
FixedObservationId = fixedObservationId,
|
||||
Now = DateTimeOffset.UtcNow
|
||||
},
|
||||
cancellationToken: ct);
|
||||
|
||||
await conn.ExecuteAsync(command);
|
||||
SET vulnerable_observation_id = COALESCE({vulnerableObservationId}, vulnerable_observation_id),
|
||||
fixed_observation_id = COALESCE({fixedObservationId}, fixed_observation_id),
|
||||
updated_at = {now}
|
||||
WHERE pair_id = {pairId}
|
||||
""", ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -288,76 +178,36 @@ public sealed class SecurityPairRepository : ISecurityPairRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT pair_id AS "PairId",
|
||||
cve_id AS "CveId",
|
||||
package_name AS "PackageName",
|
||||
distro AS "Distro",
|
||||
distro_version AS "DistroVersion",
|
||||
vulnerable_version AS "VulnerableVersion",
|
||||
vulnerable_debug_id AS "VulnerableDebugId",
|
||||
vulnerable_observation_id AS "VulnerableObservationId",
|
||||
fixed_version AS "FixedVersion",
|
||||
fixed_debug_id AS "FixedDebugId",
|
||||
fixed_observation_id AS "FixedObservationId",
|
||||
upstream_diff_url AS "UpstreamDiffUrl",
|
||||
patch_functions AS "PatchFunctions",
|
||||
verification_status AS "VerificationStatus",
|
||||
metadata::text AS "MetadataJson",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM groundtruth.security_pairs
|
||||
WHERE vulnerable_observation_id IS NOT NULL
|
||||
AND fixed_observation_id IS NOT NULL
|
||||
ORDER BY updated_at DESC
|
||||
LIMIT @Limit
|
||||
""";
|
||||
var entities = await dbContext.SecurityPairs
|
||||
.AsNoTracking()
|
||||
.Where(e => e.VulnerableObservationId != null && e.FixedObservationId != null)
|
||||
.OrderByDescending(e => e.UpdatedAt)
|
||||
.Take(limit)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { Limit = limit }, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<SecurityPairRow>(command);
|
||||
return rows.Select(r => r.ToEntity()).ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
private sealed class SecurityPairRow
|
||||
private static SecurityPairEntity ToModel(EfModels.SecurityPairEntity entity) => new()
|
||||
{
|
||||
public Guid PairId { get; set; }
|
||||
public string CveId { get; set; } = string.Empty;
|
||||
public string PackageName { get; set; } = string.Empty;
|
||||
public string Distro { get; set; } = string.Empty;
|
||||
public string? DistroVersion { get; set; }
|
||||
public string VulnerableVersion { get; set; } = string.Empty;
|
||||
public string? VulnerableDebugId { get; set; }
|
||||
public string? VulnerableObservationId { get; set; }
|
||||
public string FixedVersion { get; set; } = string.Empty;
|
||||
public string? FixedDebugId { get; set; }
|
||||
public string? FixedObservationId { get; set; }
|
||||
public string? UpstreamDiffUrl { get; set; }
|
||||
public string[]? PatchFunctions { get; set; }
|
||||
public string VerificationStatus { get; set; } = string.Empty;
|
||||
public string? MetadataJson { get; set; }
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
public DateTimeOffset UpdatedAt { get; set; }
|
||||
|
||||
public SecurityPairEntity ToEntity() => new()
|
||||
{
|
||||
PairId = PairId,
|
||||
CveId = CveId,
|
||||
PackageName = PackageName,
|
||||
Distro = Distro,
|
||||
DistroVersion = DistroVersion,
|
||||
VulnerableVersion = VulnerableVersion,
|
||||
VulnerableDebugId = VulnerableDebugId,
|
||||
VulnerableObservationId = VulnerableObservationId,
|
||||
FixedVersion = FixedVersion,
|
||||
FixedDebugId = FixedDebugId,
|
||||
FixedObservationId = FixedObservationId,
|
||||
UpstreamDiffUrl = UpstreamDiffUrl,
|
||||
PatchFunctions = PatchFunctions,
|
||||
VerificationStatus = VerificationStatus,
|
||||
MetadataJson = MetadataJson,
|
||||
CreatedAt = CreatedAt,
|
||||
UpdatedAt = UpdatedAt
|
||||
};
|
||||
}
|
||||
PairId = entity.PairId,
|
||||
CveId = entity.CveId,
|
||||
PackageName = entity.PackageName,
|
||||
Distro = entity.Distro,
|
||||
DistroVersion = entity.DistroVersion,
|
||||
VulnerableVersion = entity.VulnerableVersion,
|
||||
VulnerableDebugId = entity.VulnerableDebugId,
|
||||
VulnerableObservationId = entity.VulnerableObservationId,
|
||||
FixedVersion = entity.FixedVersion,
|
||||
FixedDebugId = entity.FixedDebugId,
|
||||
FixedObservationId = entity.FixedObservationId,
|
||||
UpstreamDiffUrl = entity.UpstreamDiffUrl,
|
||||
PatchFunctions = entity.PatchFunctions,
|
||||
VerificationStatus = entity.VerificationStatus,
|
||||
MetadataJson = entity.Metadata,
|
||||
CreatedAt = new DateTimeOffset(entity.CreatedAt, TimeSpan.Zero),
|
||||
UpdatedAt = new DateTimeOffset(entity.UpdatedAt, TimeSpan.Zero)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
using Dapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using StellaOps.BinaryIndex.Persistence.Postgres;
|
||||
using EfModels = StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.Repositories.GroundTruth;
|
||||
|
||||
/// <summary>
|
||||
/// Repository implementation for source sync state and cursor management.
|
||||
/// EF Core repository implementation for source sync state and cursor management.
|
||||
/// </summary>
|
||||
public sealed class SourceStateRepository : ISourceStateRepository
|
||||
{
|
||||
private readonly BinaryIndexDbContext _dbContext;
|
||||
private const int CommandTimeoutSeconds = 30;
|
||||
|
||||
public SourceStateRepository(BinaryIndexDbContext dbContext)
|
||||
{
|
||||
@@ -18,104 +21,65 @@ public sealed class SourceStateRepository : ISourceStateRepository
|
||||
public async Task<SourceStateEntity?> GetAsync(string sourceId, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT source_id AS "SourceId",
|
||||
last_sync_at AS "LastSyncAt",
|
||||
cursor_position AS "CursorPosition",
|
||||
cursor_metadata::text AS "CursorMetadataJson",
|
||||
sync_status AS "SyncStatus",
|
||||
last_error AS "LastError",
|
||||
document_count AS "DocumentCount",
|
||||
observation_count AS "ObservationCount",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM groundtruth.source_state
|
||||
WHERE source_id = @SourceId
|
||||
""";
|
||||
var entity = await dbContext.SourceStates
|
||||
.AsNoTracking()
|
||||
.Where(e => e.SourceId == sourceId)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { SourceId = sourceId }, cancellationToken: ct);
|
||||
return await conn.QuerySingleOrDefaultAsync<SourceStateEntity>(command);
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IReadOnlyList<SourceStateEntity>> GetAllAsync(CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT source_id AS "SourceId",
|
||||
last_sync_at AS "LastSyncAt",
|
||||
cursor_position AS "CursorPosition",
|
||||
cursor_metadata::text AS "CursorMetadataJson",
|
||||
sync_status AS "SyncStatus",
|
||||
last_error AS "LastError",
|
||||
document_count AS "DocumentCount",
|
||||
observation_count AS "ObservationCount",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM groundtruth.source_state
|
||||
ORDER BY source_id
|
||||
""";
|
||||
var entities = await dbContext.SourceStates
|
||||
.AsNoTracking()
|
||||
.OrderBy(e => e.SourceId)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<SourceStateEntity>(command);
|
||||
return rows.ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task UpdateAsync(SourceStateEntity state, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
await dbContext.Database.ExecuteSqlInterpolatedAsync($"""
|
||||
UPDATE groundtruth.source_state
|
||||
SET last_sync_at = @LastSyncAt,
|
||||
cursor_position = @CursorPosition,
|
||||
cursor_metadata = @CursorMetadataJson::jsonb,
|
||||
sync_status = @SyncStatus,
|
||||
last_error = @LastError,
|
||||
document_count = @DocumentCount,
|
||||
observation_count = @ObservationCount,
|
||||
updated_at = @Now
|
||||
WHERE source_id = @SourceId
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
state.SourceId,
|
||||
state.LastSyncAt,
|
||||
state.CursorPosition,
|
||||
state.CursorMetadataJson,
|
||||
state.SyncStatus,
|
||||
state.LastError,
|
||||
state.DocumentCount,
|
||||
state.ObservationCount,
|
||||
Now = DateTimeOffset.UtcNow
|
||||
},
|
||||
cancellationToken: ct);
|
||||
|
||||
await conn.ExecuteAsync(command);
|
||||
SET last_sync_at = {state.LastSyncAt},
|
||||
cursor_position = {state.CursorPosition},
|
||||
cursor_metadata = {state.CursorMetadataJson}::jsonb,
|
||||
sync_status = {state.SyncStatus},
|
||||
last_error = {state.LastError},
|
||||
document_count = {state.DocumentCount},
|
||||
observation_count = {state.ObservationCount},
|
||||
updated_at = {now}
|
||||
WHERE source_id = {state.SourceId}
|
||||
""", ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<bool> TrySetSyncingAsync(string sourceId, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
// Only set to syncing if currently idle (optimistic locking)
|
||||
const string sql = """
|
||||
var affected = await dbContext.Database.ExecuteSqlInterpolatedAsync($"""
|
||||
UPDATE groundtruth.source_state
|
||||
SET sync_status = 'syncing', updated_at = @Now
|
||||
WHERE source_id = @SourceId AND sync_status = 'idle'
|
||||
""";
|
||||
SET sync_status = 'syncing', updated_at = {now}
|
||||
WHERE source_id = {sourceId} AND sync_status = 'idle'
|
||||
""", ct);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { SourceId = sourceId, Now = DateTimeOffset.UtcNow },
|
||||
cancellationToken: ct);
|
||||
|
||||
var affected = await conn.ExecuteAsync(command);
|
||||
return affected > 0;
|
||||
}
|
||||
|
||||
@@ -123,42 +87,45 @@ public sealed class SourceStateRepository : ISourceStateRepository
|
||||
public async Task ClearSyncingAsync(string sourceId, string? error = null, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
await dbContext.Database.ExecuteSqlInterpolatedAsync($"""
|
||||
UPDATE groundtruth.source_state
|
||||
SET sync_status = CASE WHEN @Error IS NULL THEN 'idle' ELSE 'error' END,
|
||||
last_error = @Error,
|
||||
last_sync_at = CASE WHEN @Error IS NULL THEN @Now ELSE last_sync_at END,
|
||||
updated_at = @Now
|
||||
WHERE source_id = @SourceId
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { SourceId = sourceId, Error = error, Now = DateTimeOffset.UtcNow },
|
||||
cancellationToken: ct);
|
||||
|
||||
await conn.ExecuteAsync(command);
|
||||
SET sync_status = CASE WHEN {error} IS NULL THEN 'idle' ELSE 'error' END,
|
||||
last_error = {error},
|
||||
last_sync_at = CASE WHEN {error} IS NULL THEN {now} ELSE last_sync_at END,
|
||||
updated_at = {now}
|
||||
WHERE source_id = {sourceId}
|
||||
""", ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task IncrementCountsAsync(string sourceId, int documents, int observations, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
await dbContext.Database.ExecuteSqlInterpolatedAsync($"""
|
||||
UPDATE groundtruth.source_state
|
||||
SET document_count = document_count + @Documents,
|
||||
observation_count = observation_count + @Observations,
|
||||
updated_at = @Now
|
||||
WHERE source_id = @SourceId
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { SourceId = sourceId, Documents = documents, Observations = observations, Now = DateTimeOffset.UtcNow },
|
||||
cancellationToken: ct);
|
||||
|
||||
await conn.ExecuteAsync(command);
|
||||
SET document_count = document_count + {documents},
|
||||
observation_count = observation_count + {observations},
|
||||
updated_at = {now}
|
||||
WHERE source_id = {sourceId}
|
||||
""", ct);
|
||||
}
|
||||
|
||||
private static SourceStateEntity ToModel(EfModels.SourceStateEntity entity) => new()
|
||||
{
|
||||
SourceId = entity.SourceId,
|
||||
LastSyncAt = entity.LastSyncAt.HasValue ? new DateTimeOffset(entity.LastSyncAt.Value, TimeSpan.Zero) : null,
|
||||
CursorPosition = entity.CursorPosition,
|
||||
CursorMetadataJson = entity.CursorMetadata,
|
||||
SyncStatus = entity.SyncStatus,
|
||||
LastError = entity.LastError,
|
||||
DocumentCount = entity.DocumentCount,
|
||||
ObservationCount = entity.ObservationCount,
|
||||
UpdatedAt = new DateTimeOffset(entity.UpdatedAt, TimeSpan.Zero)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
using Dapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using StellaOps.BinaryIndex.Persistence.Postgres;
|
||||
using EfModels = StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.Repositories.GroundTruth;
|
||||
|
||||
/// <summary>
|
||||
/// Repository implementation for symbol observation persistence.
|
||||
/// EF Core repository implementation for symbol observation persistence.
|
||||
/// Follows immutable, append-only pattern with supersession.
|
||||
/// </summary>
|
||||
public sealed class SymbolObservationRepository : ISymbolObservationRepository
|
||||
{
|
||||
private readonly BinaryIndexDbContext _dbContext;
|
||||
private const int CommandTimeoutSeconds = 30;
|
||||
|
||||
public SymbolObservationRepository(BinaryIndexDbContext dbContext)
|
||||
{
|
||||
@@ -19,105 +22,58 @@ public sealed class SymbolObservationRepository : ISymbolObservationRepository
|
||||
public async Task<SymbolObservationEntity?> GetByIdAsync(string observationId, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT observation_id AS "ObservationId",
|
||||
source_id AS "SourceId",
|
||||
debug_id AS "DebugId",
|
||||
code_id AS "CodeId",
|
||||
binary_name AS "BinaryName",
|
||||
binary_path AS "BinaryPath",
|
||||
architecture AS "Architecture",
|
||||
distro AS "Distro",
|
||||
distro_version AS "DistroVersion",
|
||||
package_name AS "PackageName",
|
||||
package_version AS "PackageVersion",
|
||||
symbol_count AS "SymbolCount",
|
||||
symbols::text AS "SymbolsJson",
|
||||
build_metadata::text AS "BuildMetadataJson",
|
||||
provenance::text AS "ProvenanceJson",
|
||||
content_hash AS "ContentHash",
|
||||
supersedes_id AS "SupersedesId",
|
||||
created_at AS "CreatedAt"
|
||||
FROM groundtruth.symbol_observations
|
||||
WHERE observation_id = @ObservationId
|
||||
""";
|
||||
var entity = await dbContext.SymbolObservations
|
||||
.AsNoTracking()
|
||||
.Where(e => e.ObservationId == observationId)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { ObservationId = observationId }, cancellationToken: ct);
|
||||
return await conn.QuerySingleOrDefaultAsync<SymbolObservationEntity>(command);
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IReadOnlyList<SymbolObservationEntity>> GetByDebugIdAsync(string debugId, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT observation_id AS "ObservationId",
|
||||
source_id AS "SourceId",
|
||||
debug_id AS "DebugId",
|
||||
code_id AS "CodeId",
|
||||
binary_name AS "BinaryName",
|
||||
binary_path AS "BinaryPath",
|
||||
architecture AS "Architecture",
|
||||
distro AS "Distro",
|
||||
distro_version AS "DistroVersion",
|
||||
package_name AS "PackageName",
|
||||
package_version AS "PackageVersion",
|
||||
symbol_count AS "SymbolCount",
|
||||
symbols::text AS "SymbolsJson",
|
||||
build_metadata::text AS "BuildMetadataJson",
|
||||
provenance::text AS "ProvenanceJson",
|
||||
content_hash AS "ContentHash",
|
||||
supersedes_id AS "SupersedesId",
|
||||
created_at AS "CreatedAt"
|
||||
FROM groundtruth.symbol_observations
|
||||
WHERE debug_id = @DebugId
|
||||
ORDER BY created_at DESC
|
||||
""";
|
||||
var entities = await dbContext.SymbolObservations
|
||||
.AsNoTracking()
|
||||
.Where(e => e.DebugId == debugId)
|
||||
.OrderByDescending(e => e.CreatedAt)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { DebugId = debugId }, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<SymbolObservationEntity>(command);
|
||||
return rows.ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<SymbolObservationEntity?> GetLatestByDebugIdAsync(string debugId, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
// Get the latest observation that is not superseded by another
|
||||
const string sql = """
|
||||
SELECT o.observation_id AS "ObservationId",
|
||||
o.source_id AS "SourceId",
|
||||
o.debug_id AS "DebugId",
|
||||
o.code_id AS "CodeId",
|
||||
o.binary_name AS "BinaryName",
|
||||
o.binary_path AS "BinaryPath",
|
||||
o.architecture AS "Architecture",
|
||||
o.distro AS "Distro",
|
||||
o.distro_version AS "DistroVersion",
|
||||
o.package_name AS "PackageName",
|
||||
o.package_version AS "PackageVersion",
|
||||
o.symbol_count AS "SymbolCount",
|
||||
o.symbols::text AS "SymbolsJson",
|
||||
o.build_metadata::text AS "BuildMetadataJson",
|
||||
o.provenance::text AS "ProvenanceJson",
|
||||
o.content_hash AS "ContentHash",
|
||||
o.supersedes_id AS "SupersedesId",
|
||||
o.created_at AS "CreatedAt"
|
||||
FROM groundtruth.symbol_observations o
|
||||
WHERE o.debug_id = @DebugId
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM groundtruth.symbol_observations s
|
||||
WHERE s.supersedes_id = o.observation_id
|
||||
)
|
||||
ORDER BY o.created_at DESC
|
||||
LIMIT 1
|
||||
""";
|
||||
// Get the latest observation that is not superseded by another.
|
||||
// Uses raw SQL because the NOT EXISTS subquery with self-join is more natural in SQL.
|
||||
var results = await dbContext.SymbolObservations
|
||||
.FromSqlInterpolated($"""
|
||||
SELECT o.observation_id, o.source_id, o.debug_id, o.code_id, o.binary_name, o.binary_path,
|
||||
o.architecture, o.distro, o.distro_version, o.package_name, o.package_version,
|
||||
o.symbol_count, o.symbols, o.build_metadata, o.provenance, o.content_hash,
|
||||
o.supersedes_id, o.created_at
|
||||
FROM groundtruth.symbol_observations o
|
||||
WHERE o.debug_id = {debugId}
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM groundtruth.symbol_observations s
|
||||
WHERE s.supersedes_id = o.observation_id
|
||||
)
|
||||
ORDER BY o.created_at DESC
|
||||
LIMIT 1
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { DebugId = debugId }, cancellationToken: ct);
|
||||
return await conn.QuerySingleOrDefaultAsync<SymbolObservationEntity>(command);
|
||||
return results.Count == 0 ? null : ToModel(results[0]);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -128,116 +84,74 @@ public sealed class SymbolObservationRepository : ISymbolObservationRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT observation_id AS "ObservationId",
|
||||
source_id AS "SourceId",
|
||||
debug_id AS "DebugId",
|
||||
code_id AS "CodeId",
|
||||
binary_name AS "BinaryName",
|
||||
binary_path AS "BinaryPath",
|
||||
architecture AS "Architecture",
|
||||
distro AS "Distro",
|
||||
distro_version AS "DistroVersion",
|
||||
package_name AS "PackageName",
|
||||
package_version AS "PackageVersion",
|
||||
symbol_count AS "SymbolCount",
|
||||
symbols::text AS "SymbolsJson",
|
||||
build_metadata::text AS "BuildMetadataJson",
|
||||
provenance::text AS "ProvenanceJson",
|
||||
content_hash AS "ContentHash",
|
||||
supersedes_id AS "SupersedesId",
|
||||
created_at AS "CreatedAt"
|
||||
FROM groundtruth.symbol_observations
|
||||
WHERE package_name = @PackageName
|
||||
AND (@PackageVersion IS NULL OR package_version = @PackageVersion)
|
||||
AND (@Distro IS NULL OR distro = @Distro)
|
||||
ORDER BY created_at DESC
|
||||
""";
|
||||
// Use raw SQL because EF Core cannot translate the (@Param IS NULL OR col = @Param) pattern
|
||||
// with nullable parameters efficiently for PostgreSQL.
|
||||
var results = await dbContext.SymbolObservations
|
||||
.FromSqlInterpolated($"""
|
||||
SELECT observation_id, source_id, debug_id, code_id, binary_name, binary_path,
|
||||
architecture, distro, distro_version, package_name, package_version,
|
||||
symbol_count, symbols, build_metadata, provenance, content_hash,
|
||||
supersedes_id, created_at
|
||||
FROM groundtruth.symbol_observations
|
||||
WHERE package_name = {packageName}
|
||||
AND ({packageVersion} IS NULL OR package_version = {packageVersion})
|
||||
AND ({distro} IS NULL OR distro = {distro})
|
||||
ORDER BY created_at DESC
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { PackageName = packageName, PackageVersion = packageVersion, Distro = distro },
|
||||
cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<SymbolObservationEntity>(command);
|
||||
return rows.ToList();
|
||||
return results.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<string?> GetExistingContentHashAsync(string observationId, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT content_hash
|
||||
FROM groundtruth.symbol_observations
|
||||
WHERE observation_id = @ObservationId
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(sql, new { ObservationId = observationId }, cancellationToken: ct);
|
||||
return await conn.QuerySingleOrDefaultAsync<string>(command);
|
||||
return await dbContext.SymbolObservations
|
||||
.AsNoTracking()
|
||||
.Where(e => e.ObservationId == observationId)
|
||||
.Select(e => e.ContentHash)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<bool> InsertAsync(SymbolObservationEntity observation, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
// Check if identical content already exists (idempotency)
|
||||
const string checkSql = """
|
||||
SELECT 1 FROM groundtruth.symbol_observations
|
||||
WHERE content_hash = @ContentHash
|
||||
LIMIT 1
|
||||
""";
|
||||
var exists = await dbContext.SymbolObservations
|
||||
.AsNoTracking()
|
||||
.AnyAsync(e => e.ContentHash == observation.ContentHash, ct);
|
||||
|
||||
var checkCommand = new CommandDefinition(checkSql, new { observation.ContentHash }, cancellationToken: ct);
|
||||
var exists = await conn.QuerySingleOrDefaultAsync<int?>(checkCommand);
|
||||
if (exists.HasValue)
|
||||
if (exists)
|
||||
{
|
||||
return false; // Already exists with same content
|
||||
}
|
||||
|
||||
const string sql = """
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var affected = await dbContext.Database.ExecuteSqlInterpolatedAsync($"""
|
||||
INSERT INTO groundtruth.symbol_observations (
|
||||
observation_id, source_id, debug_id, code_id, binary_name, binary_path,
|
||||
architecture, distro, distro_version, package_name, package_version,
|
||||
symbol_count, symbols, build_metadata, provenance, content_hash,
|
||||
supersedes_id, created_at
|
||||
) VALUES (
|
||||
@ObservationId, @SourceId, @DebugId, @CodeId, @BinaryName, @BinaryPath,
|
||||
@Architecture, @Distro, @DistroVersion, @PackageName, @PackageVersion,
|
||||
@SymbolCount, @SymbolsJson::jsonb, @BuildMetadataJson::jsonb, @ProvenanceJson::jsonb,
|
||||
@ContentHash, @SupersedesId, @Now
|
||||
{observation.ObservationId}, {observation.SourceId}, {observation.DebugId}, {observation.CodeId},
|
||||
{observation.BinaryName}, {observation.BinaryPath}, {observation.Architecture}, {observation.Distro},
|
||||
{observation.DistroVersion}, {observation.PackageName}, {observation.PackageVersion},
|
||||
{observation.SymbolCount}, {observation.SymbolsJson}::jsonb, {observation.BuildMetadataJson}::jsonb,
|
||||
{observation.ProvenanceJson}::jsonb, {observation.ContentHash}, {observation.SupersedesId}, {now}
|
||||
)
|
||||
ON CONFLICT (observation_id) DO NOTHING
|
||||
""";
|
||||
""", ct);
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
observation.ObservationId,
|
||||
observation.SourceId,
|
||||
observation.DebugId,
|
||||
observation.CodeId,
|
||||
observation.BinaryName,
|
||||
observation.BinaryPath,
|
||||
observation.Architecture,
|
||||
observation.Distro,
|
||||
observation.DistroVersion,
|
||||
observation.PackageName,
|
||||
observation.PackageVersion,
|
||||
observation.SymbolCount,
|
||||
observation.SymbolsJson,
|
||||
observation.BuildMetadataJson,
|
||||
observation.ProvenanceJson,
|
||||
observation.ContentHash,
|
||||
observation.SupersedesId,
|
||||
Now = DateTimeOffset.UtcNow
|
||||
},
|
||||
cancellationToken: ct);
|
||||
|
||||
var affected = await conn.ExecuteAsync(command);
|
||||
return affected > 0;
|
||||
}
|
||||
|
||||
@@ -248,57 +162,62 @@ public sealed class SymbolObservationRepository : ISymbolObservationRepository
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
// Use JSONB containment for symbol search
|
||||
const string sql = """
|
||||
SELECT observation_id AS "ObservationId",
|
||||
source_id AS "SourceId",
|
||||
debug_id AS "DebugId",
|
||||
code_id AS "CodeId",
|
||||
binary_name AS "BinaryName",
|
||||
binary_path AS "BinaryPath",
|
||||
architecture AS "Architecture",
|
||||
distro AS "Distro",
|
||||
distro_version AS "DistroVersion",
|
||||
package_name AS "PackageName",
|
||||
package_version AS "PackageVersion",
|
||||
symbol_count AS "SymbolCount",
|
||||
symbols::text AS "SymbolsJson",
|
||||
build_metadata::text AS "BuildMetadataJson",
|
||||
provenance::text AS "ProvenanceJson",
|
||||
content_hash AS "ContentHash",
|
||||
supersedes_id AS "SupersedesId",
|
||||
created_at AS "CreatedAt"
|
||||
FROM groundtruth.symbol_observations
|
||||
WHERE symbols @> @SearchPattern::jsonb
|
||||
ORDER BY created_at DESC
|
||||
LIMIT @Limit
|
||||
""";
|
||||
|
||||
// Search for symbol by name using JSONB array containment
|
||||
// Use JSONB containment for symbol search -- requires raw SQL
|
||||
var searchPattern = $"[{{\"name\":\"{symbolName}\"}}]";
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { SearchPattern = searchPattern, Limit = limit },
|
||||
cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<SymbolObservationEntity>(command);
|
||||
return rows.ToList();
|
||||
var results = await dbContext.SymbolObservations
|
||||
.FromSqlInterpolated($"""
|
||||
SELECT observation_id, source_id, debug_id, code_id, binary_name, binary_path,
|
||||
architecture, distro, distro_version, package_name, package_version,
|
||||
symbol_count, symbols, build_metadata, provenance, content_hash,
|
||||
supersedes_id, created_at
|
||||
FROM groundtruth.symbol_observations
|
||||
WHERE symbols @> {searchPattern}::jsonb
|
||||
ORDER BY created_at DESC
|
||||
LIMIT {limit}
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(ct);
|
||||
|
||||
return results.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IDictionary<string, long>> GetCountBySourceAsync(CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT source_id AS "SourceId", COUNT(*) AS "Count"
|
||||
FROM groundtruth.symbol_observations
|
||||
GROUP BY source_id
|
||||
""";
|
||||
var groups = await dbContext.SymbolObservations
|
||||
.AsNoTracking()
|
||||
.GroupBy(e => e.SourceId)
|
||||
.Select(g => new { SourceId = g.Key, Count = (long)g.Count() })
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<(string SourceId, long Count)>(command);
|
||||
return rows.ToDictionary(r => r.SourceId, r => r.Count);
|
||||
return groups.ToDictionary(g => g.SourceId, g => g.Count);
|
||||
}
|
||||
|
||||
private static SymbolObservationEntity ToModel(EfModels.SymbolObservationEntity entity) => new()
|
||||
{
|
||||
ObservationId = entity.ObservationId,
|
||||
SourceId = entity.SourceId,
|
||||
DebugId = entity.DebugId,
|
||||
CodeId = entity.CodeId,
|
||||
BinaryName = entity.BinaryName,
|
||||
BinaryPath = entity.BinaryPath,
|
||||
Architecture = entity.Architecture,
|
||||
Distro = entity.Distro,
|
||||
DistroVersion = entity.DistroVersion,
|
||||
PackageName = entity.PackageName,
|
||||
PackageVersion = entity.PackageVersion,
|
||||
SymbolCount = entity.SymbolCount,
|
||||
SymbolsJson = entity.Symbols,
|
||||
BuildMetadataJson = entity.BuildMetadata,
|
||||
ProvenanceJson = entity.Provenance,
|
||||
ContentHash = entity.ContentHash,
|
||||
SupersedesId = entity.SupersedesId,
|
||||
CreatedAt = new DateTimeOffset(entity.CreatedAt, TimeSpan.Zero)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
using Dapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using StellaOps.BinaryIndex.Persistence.Postgres;
|
||||
using EfModels = StellaOps.BinaryIndex.Persistence.EfCore.Models;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Persistence.Repositories.GroundTruth;
|
||||
|
||||
/// <summary>
|
||||
/// Repository implementation for symbol source management.
|
||||
/// EF Core repository implementation for symbol source management.
|
||||
/// </summary>
|
||||
public sealed class SymbolSourceRepository : ISymbolSourceRepository
|
||||
{
|
||||
private readonly BinaryIndexDbContext _dbContext;
|
||||
private const int CommandTimeoutSeconds = 30;
|
||||
|
||||
public SymbolSourceRepository(BinaryIndexDbContext dbContext)
|
||||
{
|
||||
@@ -18,168 +21,104 @@ public sealed class SymbolSourceRepository : ISymbolSourceRepository
|
||||
public async Task<IReadOnlyList<SymbolSourceEntity>> GetAllAsync(CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT source_id AS "SourceId",
|
||||
display_name AS "DisplayName",
|
||||
source_type AS "SourceType",
|
||||
base_url AS "BaseUrl",
|
||||
supported_distros AS "SupportedDistros",
|
||||
is_enabled AS "IsEnabled",
|
||||
config_json AS "ConfigJson",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM groundtruth.symbol_sources
|
||||
ORDER BY display_name
|
||||
""";
|
||||
var entities = await dbContext.SymbolSources
|
||||
.AsNoTracking()
|
||||
.OrderBy(e => e.DisplayName)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<SymbolSourceRow>(command);
|
||||
return rows.Select(r => r.ToEntity()).ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<SymbolSourceEntity?> GetByIdAsync(string sourceId, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT source_id AS "SourceId",
|
||||
display_name AS "DisplayName",
|
||||
source_type AS "SourceType",
|
||||
base_url AS "BaseUrl",
|
||||
supported_distros AS "SupportedDistros",
|
||||
is_enabled AS "IsEnabled",
|
||||
config_json AS "ConfigJson",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM groundtruth.symbol_sources
|
||||
WHERE source_id = @SourceId
|
||||
""";
|
||||
var entity = await dbContext.SymbolSources
|
||||
.AsNoTracking()
|
||||
.Where(e => e.SourceId == sourceId)
|
||||
.FirstOrDefaultAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, new { SourceId = sourceId }, cancellationToken: ct);
|
||||
var row = await conn.QuerySingleOrDefaultAsync<SymbolSourceRow>(command);
|
||||
return row?.ToEntity();
|
||||
return entity is null ? null : ToModel(entity);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IReadOnlyList<SymbolSourceEntity>> GetEnabledAsync(CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
SELECT source_id AS "SourceId",
|
||||
display_name AS "DisplayName",
|
||||
source_type AS "SourceType",
|
||||
base_url AS "BaseUrl",
|
||||
supported_distros AS "SupportedDistros",
|
||||
is_enabled AS "IsEnabled",
|
||||
config_json AS "ConfigJson",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
FROM groundtruth.symbol_sources
|
||||
WHERE is_enabled = true
|
||||
ORDER BY display_name
|
||||
""";
|
||||
var entities = await dbContext.SymbolSources
|
||||
.AsNoTracking()
|
||||
.Where(e => e.IsEnabled)
|
||||
.OrderBy(e => e.DisplayName)
|
||||
.ToListAsync(ct);
|
||||
|
||||
var command = new CommandDefinition(sql, cancellationToken: ct);
|
||||
var rows = await conn.QueryAsync<SymbolSourceRow>(command);
|
||||
return rows.Select(r => r.ToEntity()).ToList();
|
||||
return entities.Select(ToModel).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<SymbolSourceEntity> UpsertAsync(SymbolSourceEntity source, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
INSERT INTO groundtruth.symbol_sources (
|
||||
source_id, display_name, source_type, base_url, supported_distros,
|
||||
is_enabled, config_json, created_at, updated_at
|
||||
) VALUES (
|
||||
@SourceId, @DisplayName, @SourceType, @BaseUrl, @SupportedDistros,
|
||||
@IsEnabled, @ConfigJson::jsonb, @Now, @Now
|
||||
)
|
||||
ON CONFLICT (source_id) DO UPDATE SET
|
||||
display_name = EXCLUDED.display_name,
|
||||
source_type = EXCLUDED.source_type,
|
||||
base_url = EXCLUDED.base_url,
|
||||
supported_distros = EXCLUDED.supported_distros,
|
||||
is_enabled = EXCLUDED.is_enabled,
|
||||
config_json = EXCLUDED.config_json,
|
||||
updated_at = EXCLUDED.updated_at
|
||||
RETURNING source_id AS "SourceId",
|
||||
display_name AS "DisplayName",
|
||||
source_type AS "SourceType",
|
||||
base_url AS "BaseUrl",
|
||||
supported_distros AS "SupportedDistros",
|
||||
is_enabled AS "IsEnabled",
|
||||
config_json AS "ConfigJson",
|
||||
created_at AS "CreatedAt",
|
||||
updated_at AS "UpdatedAt"
|
||||
""";
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var supportedDistros = source.SupportedDistros.ToArray();
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new
|
||||
{
|
||||
source.SourceId,
|
||||
source.DisplayName,
|
||||
source.SourceType,
|
||||
source.BaseUrl,
|
||||
SupportedDistros = source.SupportedDistros.ToArray(),
|
||||
source.IsEnabled,
|
||||
source.ConfigJson,
|
||||
Now = DateTimeOffset.UtcNow
|
||||
},
|
||||
cancellationToken: ct);
|
||||
var results = await dbContext.SymbolSources
|
||||
.FromSqlInterpolated($"""
|
||||
INSERT INTO groundtruth.symbol_sources (
|
||||
source_id, display_name, source_type, base_url, supported_distros,
|
||||
is_enabled, config_json, created_at, updated_at
|
||||
) VALUES (
|
||||
{source.SourceId}, {source.DisplayName}, {source.SourceType}, {source.BaseUrl}, {supportedDistros},
|
||||
{source.IsEnabled}, {source.ConfigJson}::jsonb, {now}, {now}
|
||||
)
|
||||
ON CONFLICT (source_id) DO UPDATE SET
|
||||
display_name = EXCLUDED.display_name,
|
||||
source_type = EXCLUDED.source_type,
|
||||
base_url = EXCLUDED.base_url,
|
||||
supported_distros = EXCLUDED.supported_distros,
|
||||
is_enabled = EXCLUDED.is_enabled,
|
||||
config_json = EXCLUDED.config_json,
|
||||
updated_at = EXCLUDED.updated_at
|
||||
RETURNING source_id, display_name, source_type, base_url, supported_distros,
|
||||
is_enabled, config_json, created_at, updated_at
|
||||
""")
|
||||
.AsNoTracking()
|
||||
.ToListAsync(ct);
|
||||
|
||||
var row = await conn.QuerySingleAsync<SymbolSourceRow>(command);
|
||||
return row.ToEntity();
|
||||
return ToModel(results.First());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task SetEnabledAsync(string sourceId, bool enabled, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = await _dbContext.OpenConnectionAsync(ct);
|
||||
await using var dbContext = BinaryIndexPersistenceDbContextFactory.Create(conn, CommandTimeoutSeconds);
|
||||
|
||||
const string sql = """
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
await dbContext.Database.ExecuteSqlInterpolatedAsync($"""
|
||||
UPDATE groundtruth.symbol_sources
|
||||
SET is_enabled = @Enabled, updated_at = @Now
|
||||
WHERE source_id = @SourceId
|
||||
""";
|
||||
|
||||
var command = new CommandDefinition(
|
||||
sql,
|
||||
new { SourceId = sourceId, Enabled = enabled, Now = DateTimeOffset.UtcNow },
|
||||
cancellationToken: ct);
|
||||
|
||||
await conn.ExecuteAsync(command);
|
||||
SET is_enabled = {enabled}, updated_at = {now}
|
||||
WHERE source_id = {sourceId}
|
||||
""", ct);
|
||||
}
|
||||
|
||||
private sealed class SymbolSourceRow
|
||||
private static SymbolSourceEntity ToModel(EfModels.SymbolSourceEntity entity) => new()
|
||||
{
|
||||
public string SourceId { get; set; } = string.Empty;
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
public string SourceType { get; set; } = string.Empty;
|
||||
public string BaseUrl { get; set; } = string.Empty;
|
||||
public string[] SupportedDistros { get; set; } = [];
|
||||
public bool IsEnabled { get; set; }
|
||||
public string? ConfigJson { get; set; }
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
public DateTimeOffset UpdatedAt { get; set; }
|
||||
|
||||
public SymbolSourceEntity ToEntity() => new()
|
||||
{
|
||||
SourceId = SourceId,
|
||||
DisplayName = DisplayName,
|
||||
SourceType = SourceType,
|
||||
BaseUrl = BaseUrl,
|
||||
SupportedDistros = SupportedDistros,
|
||||
IsEnabled = IsEnabled,
|
||||
ConfigJson = ConfigJson,
|
||||
CreatedAt = CreatedAt,
|
||||
UpdatedAt = UpdatedAt
|
||||
};
|
||||
}
|
||||
SourceId = entity.SourceId,
|
||||
DisplayName = entity.DisplayName,
|
||||
SourceType = entity.SourceType,
|
||||
BaseUrl = entity.BaseUrl,
|
||||
SupportedDistros = entity.SupportedDistros,
|
||||
IsEnabled = entity.IsEnabled,
|
||||
ConfigJson = entity.ConfigJson,
|
||||
CreatedAt = new DateTimeOffset(entity.CreatedAt, TimeSpan.Zero),
|
||||
UpdatedAt = new DateTimeOffset(entity.UpdatedAt, TimeSpan.Zero)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,7 +9,19 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Migrations\*.sql" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Prevent automatic compiled-model binding so non-default schemas can build runtime models. -->
|
||||
<Compile Remove="EfCore\CompiledModels\BinaryIndexPersistenceDbContextAssemblyAttributes.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" />
|
||||
<PackageReference Include="Npgsql" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
|
||||
<PackageReference Include="Dapper" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||
</ItemGroup>
|
||||
@@ -21,10 +33,7 @@
|
||||
<ProjectReference Include="..\StellaOps.BinaryIndex.FixIndex\StellaOps.BinaryIndex.FixIndex.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.BinaryIndex.Fingerprints\StellaOps.BinaryIndex.Fingerprints.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Infrastructure.Postgres\StellaOps.Infrastructure.Postgres.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Infrastructure.EfCore\StellaOps.Infrastructure.EfCore.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Determinism.Abstractions\StellaOps.Determinism.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Migrations\*.sql" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -10,3 +10,8 @@ Source of truth: `docs-archived/implplan/2025-12-29-csproj-audit/SPRINT_20251229
|
||||
| AUDIT-0125-T | DONE | Test coverage audit for StellaOps.BinaryIndex.Persistence; revalidated 2026-01-06. |
|
||||
| AUDIT-0125-A | TODO | Revalidated 2026-01-06; open findings pending apply. |
|
||||
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
|
||||
| BINARY-EF-01 | DONE | SPRINT_20260222_090: Migration registry wiring verified. BinaryIndexMigrationModulePlugin added to Platform. |
|
||||
| BINARY-EF-02 | DONE | SPRINT_20260222_090: EF Core model baseline scaffolded (15 entities, binaries+groundtruth schemas). |
|
||||
| BINARY-EF-03 | DONE | SPRINT_20260222_090: 10 repositories converted from Dapper to EF Core. FunctionCorpusRepository deferred. |
|
||||
| BINARY-EF-04 | DONE | SPRINT_20260222_090: Compiled model (18 files) generated. UseModel() wired in runtime factory. |
|
||||
| BINARY-EF-05 | DONE | SPRINT_20260222_090: Sequential builds/tests validated. Module docs updated. |
|
||||
|
||||
Reference in New Issue
Block a user