Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DotPrompt.Sql.Cli/DotPrompt.Sql.Cli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="DotPrompt" Version="0.0.5.1" />
<PackageReference Include="DotPrompt" Version="0.0.6.1" />
</ItemGroup>

</Project>
30 changes: 16 additions & 14 deletions DotPrompt.Sql.Test/TestSqlPromptEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
private IDbConnection _connection;
private SqlPromptRepository _repository;

public SqlPromptRepositoryTests()

Check warning on line 20 in DotPrompt.Sql.Test/TestSqlPromptEntity.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable field '_repository' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.

Check warning on line 20 in DotPrompt.Sql.Test/TestSqlPromptEntity.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable field '_connection' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.

Check warning on line 20 in DotPrompt.Sql.Test/TestSqlPromptEntity.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable field '_repository' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.

Check warning on line 20 in DotPrompt.Sql.Test/TestSqlPromptEntity.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable field '_connection' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
{
_sqlServerContainer = new MsSqlBuilder()
.WithImage("mcr.microsoft.com/mssql/server:2022-latest")
Expand Down Expand Up @@ -59,7 +59,7 @@

// Read the embedded resource stream
using var stream = assembly.GetManifestResourceStream(fullResourceName);
using var reader = new StreamReader(stream);

Check warning on line 62 in DotPrompt.Sql.Test/TestSqlPromptEntity.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'stream' in 'StreamReader.StreamReader(Stream stream)'.

Check warning on line 62 in DotPrompt.Sql.Test/TestSqlPromptEntity.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'stream' in 'StreamReader.StreamReader(Stream stream)'.
return reader.ReadToEnd();
}
private async Task InitializeDatabase()
Expand All @@ -81,16 +81,17 @@
Model = "gpt4",
OutputFormat = "json",
MaxTokens = 500,
Temperature = 0.7f,
SystemPrompt = "Optimize SQL queries.",
UserPrompt = "Suggest indexing improvements.",
Parameters = new Dictionary<string, string>
{
{ "Temperature", "0.7" },
{ "TopP", "0.9" }
{ "query", "string" },
{ "topP", "number" }
},
Default = new Dictionary<string, object>
{
{ "Temperature", "0.5" }
{ "topP", "0.9" }
}
};

Expand All @@ -111,16 +112,17 @@
Model = "gpt4",
OutputFormat = "json",
MaxTokens = 200,
Temperature = 0.5f,
SystemPrompt = "Optimize SQL queries.",
UserPrompt = "Suggest indexing improvements.",
Parameters = new Dictionary<string, string>
{
{ "Temperature", "0.7" },
{ "TopP", "0.9" }
{ "query", "string" },
{ "topP", "number" }
},
Default = new Dictionary<string, object>
{
{ "Temperature", "0.5" }
{ "topP", "0.9" }
}
};

Expand All @@ -145,8 +147,8 @@
MaxTokens = 500,
SystemPrompt = "Optimize SQL queries.",
UserPrompt = "Suggest indexing improvements.",
Parameters = new Dictionary<string, string> { { "Temperature", "0.7" } },
Default = new Dictionary<string, object> { { "Temperature", "0.5" } }
Parameters = new Dictionary<string, string> { { "query", "string" } },
Default = new Dictionary<string, object> { { "query", "SELECT 1" } }
};

var entity2 = new SqlPromptEntity
Expand All @@ -157,8 +159,8 @@
MaxTokens = 512, // Changed value
SystemPrompt = "Optimize SQL queries.",
UserPrompt = "Suggest indexing improvements.",
Parameters = new Dictionary<string, string> { { "Temperature", "0.7" } },
Default = new Dictionary<string, object> { { "Temperature", "0.5" } }
Parameters = new Dictionary<string, string> { { "query", "string" } },
Default = new Dictionary<string, object> { { "query", "SELECT 1" } }
};

await _repository.AddSqlPrompt(entity1); // Insert first version
Expand All @@ -182,8 +184,8 @@
MaxTokens = 500,
SystemPrompt = "Optimize SQL queries.",
UserPrompt = "Suggest indexing improvements.",
Parameters = new Dictionary<string, string> { { "Temperature", "0.7" } },
Default = new Dictionary<string, object> { { "Temperature", "0.5" } }
Parameters = new Dictionary<string, string> { { "query", "string" } },
Default = new Dictionary<string, object> { { "query", "SELECT 1" } }
};

var entity2 = new SqlPromptEntity
Expand All @@ -194,8 +196,8 @@
MaxTokens = 512, // Changed value
SystemPrompt = "Optimize SQL queries 2.", // changed value
UserPrompt = "Suggest indexing improvements.",
Parameters = new Dictionary<string, string> { { "Temperature", "0.7" } },
Default = new Dictionary<string, object> { { "Temperature", "0.5" } }
Parameters = new Dictionary<string, string> { { "query", "string" } },
Default = new Dictionary<string, object> { { "query", "SELECT 1" } }
};

await _repository.AddSqlPrompt(entity1); // Insert first version
Expand All @@ -206,7 +208,7 @@
var prompt = await _repository.GetLatestPromptByName("noprompt");

// Assert
Assert.Equal(entity2.MaxTokens, prompt.MaxTokens);

Check warning on line 211 in DotPrompt.Sql.Test/TestSqlPromptEntity.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.

Check warning on line 211 in DotPrompt.Sql.Test/TestSqlPromptEntity.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
Assert.Equal(entity2.SystemPrompt, prompt.SystemPrompt);
Assert.Equal(entity1.UserPrompt, prompt.UserPrompt);
}
Expand Down
2 changes: 1 addition & 1 deletion DotPrompt.Sql/DotPrompt.Sql.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="DotPrompt" Version="0.0.5.1" />
<PackageReference Include="DotPrompt" Version="0.0.6.1" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.1" />
<PackageReference Include="YamlDotNet" Version="16.3.0" />
</ItemGroup>
Expand Down
12 changes: 9 additions & 3 deletions DotPrompt.Sql/Resources/SqlQueries/AddSqlPrompt.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ CREATE OR ALTER PROCEDURE sp_AddSqlPrompt
@PromptName VARCHAR(255),
@Model VARCHAR(255),
@OutputFormat VARCHAR(255),
@OutputSchema NVARCHAR(MAX),
@MaxTokens INT,
@Temperature FLOAT,
@SystemPrompt NVARCHAR(MAX),
@UserPrompt NVARCHAR(MAX),
@FewShots NVARCHAR(MAX),
@Parameters PromptParameterType READONLY, -- Table-Valued Parameter
@Defaults ParameterDefaultType READONLY, -- Table-Valued Parameter
@IsNewVersion BIT OUTPUT -- New Output Parameter
Expand Down Expand Up @@ -34,9 +37,12 @@ SET @NewVersion = ISNULL(@ExistingVersion, 0) + 1;
WHERE PromptId = @ExistingPromptId
AND Model = @Model
AND OutputFormat = @OutputFormat
AND MaxTokens = @MaxTokens
AND (OutputSchema = @OutputSchema OR (OutputSchema IS NULL AND @OutputSchema IS NULL))
AND (MaxTokens = @MaxTokens OR (MaxTokens IS NULL AND @MaxTokens IS NULL))
AND (Temperature = @Temperature OR (Temperature IS NULL AND @Temperature IS NULL))
AND SystemPrompt = @SystemPrompt
AND UserPrompt = @UserPrompt
AND (FewShots = @FewShots OR (FewShots IS NULL AND @FewShots IS NULL))
)
OR EXISTS (
-- Parameters changed?
Expand Down Expand Up @@ -64,8 +70,8 @@ SET @NewVersion = ISNULL(@ExistingVersion, 0) + 1;
)
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, default-value change detection only checks for defaults present in @Defaults that are missing/changed in the DB. If a default is removed (exists in ParameterDefaults for the existing version but not in @Defaults), this won’t trigger a new version. Consider adding an inverse EXISTS check for DB defaults not present in @Defaults.

Suggested change
)
)
OR EXISTS (
-- Defaults removed?
SELECT 1
FROM ParameterDefaults pd
JOIN PromptParameters pp ON pd.ParameterId = pp.ParameterId
WHERE pp.PromptId = @ExistingPromptId
AND pp.VersionNumber = @ExistingVersion
AND pd.VersionNumber = @ExistingVersion
AND NOT EXISTS (
SELECT 1
FROM @Defaults d
WHERE d.ParameterName = pp.ParameterName
AND d.DefaultValue = pd.DefaultValue
)
)

Copilot uses AI. Check for mistakes.
BEGIN
-- Insert new version of the prompt
INSERT INTO PromptFile (PromptName, VersionNumber, CreatedAt, ModifiedAt, Model, OutputFormat, MaxTokens, SystemPrompt, UserPrompt)
VALUES (@PromptName, @NewVersion, GETUTCDATE(), GETUTCDATE(), @Model, @OutputFormat, @MaxTokens, @SystemPrompt, @UserPrompt);
INSERT INTO PromptFile (PromptName, VersionNumber, CreatedAt, ModifiedAt, Model, OutputFormat, OutputSchema, MaxTokens, Temperature, SystemPrompt, UserPrompt, FewShots)
VALUES (@PromptName, @NewVersion, GETUTCDATE(), GETUTCDATE(), @Model, @OutputFormat, @OutputSchema, @MaxTokens, @Temperature, @SystemPrompt, @UserPrompt, @FewShots);

SET @NewPromptId = SCOPE_IDENTITY();

Expand Down
32 changes: 31 additions & 1 deletion DotPrompt.Sql/Resources/SqlQueries/CreateDefaultPromptTables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ CREATE TABLE PromptFile (
ModifiedAt DATETIMEOFFSET NULL,
Model VARCHAR(255) NULL,
OutputFormat VARCHAR(255) NOT NULL DEFAULT '',
MaxTokens INT NOT NULL,
OutputSchema NVARCHAR(MAX) NULL,
MaxTokens INT NULL,
Temperature FLOAT NULL,
SystemPrompt NVARCHAR(MAX) NOT NULL DEFAULT '',
UserPrompt NVARCHAR(MAX) NOT NULL DEFAULT '',
FewShots NVARCHAR(MAX) NULL,
CONSTRAINT UQ_PromptName_Version UNIQUE (PromptName, VersionNumber)
);
END;
Expand All @@ -27,6 +30,33 @@ ALTER TABLE PromptFile ADD CONSTRAINT UQ_PromptName_Version UNIQUE (PromptName,
END;
END;

-- Add OutputSchema column to PromptFile (if not exists)
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PromptFile' AND COLUMN_NAME = 'OutputSchema')
BEGIN
ALTER TABLE PromptFile ADD OutputSchema NVARCHAR(MAX) NULL;
END;

-- Make MaxTokens nullable (if currently NOT NULL)
IF EXISTS (
SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'PromptFile' AND COLUMN_NAME = 'MaxTokens' AND IS_NULLABLE = 'NO'
)
BEGIN
ALTER TABLE PromptFile ALTER COLUMN MaxTokens INT NULL;
END;

-- Add Temperature column to PromptFile (if not exists)
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PromptFile' AND COLUMN_NAME = 'Temperature')
BEGIN
ALTER TABLE PromptFile ADD Temperature FLOAT NULL;
END;

-- Add FewShots column to PromptFile (if not exists)
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PromptFile' AND COLUMN_NAME = 'FewShots')
BEGIN
ALTER TABLE PromptFile ADD FewShots NVARCHAR(MAX) NULL;
END;

-- Create the PromptParameters table if it doesn't exist
IF NOT EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'PromptParameters')
BEGIN
Expand Down
8 changes: 7 additions & 1 deletion DotPrompt.Sql/Resources/SqlQueries/GetLatestPromptByName.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ WITH LatestPrompts AS (
ModifiedAt,
Model,
OutputFormat,
OutputSchema,
MaxTokens,
Temperature,
SystemPrompt,
UserPrompt,
FewShots,
ROW_NUMBER() OVER (PARTITION BY PromptName ORDER BY VersionNumber DESC) AS RowNum
FROM PromptFile
)
Expand All @@ -21,8 +24,11 @@ SELECT
lp.ModifiedAt,
lp.Model,
lp.OutputFormat,
lp.OutputSchema,
lp.MaxTokens,
lp.Temperature,
lp.SystemPrompt,
lp.UserPrompt
lp.UserPrompt,
lp.FewShots
FROM LatestPrompts lp
WHERE lp.PromptName = @PromptName AND lp.RowNum = 1;
4 changes: 2 additions & 2 deletions DotPrompt.Sql/Resources/SqlQueries/InsertPromptFile.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
INSERT INTO PromptFile (PromptName, CreatedAt, ModifiedAt, Model, OutputFormat, MaxTokens, SystemPrompt, UserPrompt)
INSERT INTO PromptFile (PromptName, CreatedAt, ModifiedAt, Model, OutputFormat, OutputSchema, MaxTokens, Temperature, SystemPrompt, UserPrompt, FewShots)
OUTPUT INSERTED.PromptId
VALUES (@PromptName, @CreatedAt, @ModifiedAt, @Model, @OutputFormat, @MaxTokens, @SystemPrompt, @UserPrompt)
VALUES (@PromptName, @CreatedAt, @ModifiedAt, @Model, @OutputFormat, @OutputSchema, @MaxTokens, @Temperature, @SystemPrompt, @UserPrompt, @FewShots)
6 changes: 6 additions & 0 deletions DotPrompt.Sql/Resources/SqlQueries/LoadPrompts.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ WITH LatestPrompts AS (
ModifiedAt,
Model,
OutputFormat,
OutputSchema,
MaxTokens,
Temperature,
SystemPrompt,
UserPrompt,
FewShots,
VersionNumber,
ROW_NUMBER() OVER (PARTITION BY PromptName ORDER BY VersionNumber DESC) AS RowNum
Comment on lines 13 to 16
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VersionNumber is selected but not aliased to Version, so Dapper won’t populate SqlPromptEntity.Version (it will stay at the default 1). Since ToPromptFile() uses Version, loaded prompt files will report the wrong version. Consider aliasing VersionNumber AS Version in both the CTE and final SELECT (or renaming the C# property to VersionNumber).

Copilot uses AI. Check for mistakes.
FROM PromptFile
Expand All @@ -20,9 +23,12 @@ SELECT
lp.ModifiedAt,
lp.Model,
lp.OutputFormat,
lp.OutputSchema,
lp.MaxTokens,
lp.Temperature,
lp.SystemPrompt,
lp.UserPrompt,
lp.FewShots,
pp.ParameterId,
pp.ParameterName,
pp.ParameterValue,
Expand Down
Loading
Loading