Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 747958d

Browse files
committed
Fix for inserting and selecting binary values in PostgreSQLDialectProvider.
Previously a base64 encoded string of the byte array was written to the database, and read back.
1 parent 9f4d6c9 commit 747958d

File tree

2 files changed

+45
-9
lines changed

2 files changed

+45
-9
lines changed

src/ServiceStack.OrmLite.PostgreSQL.Tests/TypeWithByteArrayFieldTests.cs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@
44
namespace ServiceStack.OrmLite.PostgreSQL.Tests
55
{
66
public class TypeWithByteArrayFieldTests : OrmLiteTestBase
7-
{
7+
{
8+
TypeWithByteArrayField getSampleObject()
9+
{
10+
var testByteArray = new byte[256];
11+
for(int i = 0; i < 256; i++) { testByteArray[i] = (byte)i; }
12+
13+
return new TypeWithByteArrayField { Id = 1, Content = testByteArray };
14+
}
15+
816
[Test]
917
public void CanInsertAndSelectByteArray()
1018
{
11-
var orig = new TypeWithByteArrayField { Id = 1, Content = new byte[] { 0, 17, 0, 17, 0, 7 } };
19+
var orig = getSampleObject();
1220

1321
using (var db = ConnectionString.OpenDbConnection())
1422
{
@@ -26,7 +34,7 @@ public void CanInsertAndSelectByteArray()
2634
[Test]
2735
public void CanInsertAndSelectByteArray__manual_insert__manual_select()
2836
{
29-
var orig = new TypeWithByteArrayField { Id = 1, Content = new byte[] { 0, 17, 0, 17, 0, 7 } };
37+
var orig = getSampleObject();
3038

3139
using(var db = ConnectionString.OpenDbConnection()) {
3240
//insert and select manually - ok
@@ -40,7 +48,7 @@ public void CanInsertAndSelectByteArray__manual_insert__manual_select()
4048
[Test]
4149
public void CanInsertAndSelectByteArray__InsertParam_insert__manual_select()
4250
{
43-
var orig = new TypeWithByteArrayField { Id = 1, Content = new byte[] { 0, 17, 0, 17, 0, 7 } };
51+
var orig = getSampleObject();
4452

4553
using(var db = ConnectionString.OpenDbConnection()) {
4654
//insert using InsertParam, and select manually - ok
@@ -54,7 +62,7 @@ public void CanInsertAndSelectByteArray__InsertParam_insert__manual_select()
5462
[Test]
5563
public void CanInsertAndSelectByteArray__InsertParam_insert__GetById_select()
5664
{
57-
var orig = new TypeWithByteArrayField { Id = 1, Content = new byte[] { 0, 17, 0, 17, 0, 7 } };
65+
var orig = getSampleObject();
5866

5967
using(var db = ConnectionString.OpenDbConnection()) {
6068
//InsertParam + GetByID - fails
@@ -71,7 +79,7 @@ public void CanInsertAndSelectByteArray__InsertParam_insert__GetById_select()
7179
[Test]
7280
public void CanInsertAndSelectByteArray__Insert_insert__GetById_select()
7381
{
74-
var orig = new TypeWithByteArrayField { Id = 1, Content = new byte[] { 0, 17, 0, 17, 0, 7 } };
82+
var orig = getSampleObject();
7583

7684
using(var db = ConnectionString.OpenDbConnection()) {
7785
//InsertParam + GetByID - fails
@@ -88,7 +96,7 @@ public void CanInsertAndSelectByteArray__Insert_insert__GetById_select()
8896
[Test]
8997
public void CanInsertAndSelectByteArray__Insert_insert__manual_select()
9098
{
91-
var orig = new TypeWithByteArrayField { Id = 1, Content = new byte[] { 0, 17, 0, 17, 0, 7 } };
99+
var orig = getSampleObject();
92100

93101
using(var db = ConnectionString.OpenDbConnection()) {
94102
//InsertParam + GetByID - fails
@@ -115,7 +123,7 @@ private static void _selectAndVerifyManually(TypeWithByteArrayField orig, System
115123
private static void _insertManually(TypeWithByteArrayField orig, System.Data.IDbConnection db)
116124
{
117125
using(var cmd = db.CreateCommand()) {
118-
cmd.CommandText = @"INSERT INTO ""TypeWithByteArrayField"" (""Id"",""Content"") VALUES (@Id, @Content) --manual insert";
126+
cmd.CommandText = @"INSERT INTO ""TypeWithByteArrayField"" (""Id"",""Content"") VALUES (@Id, @Content) --manual parameterized insert";
119127

120128
var p_id = cmd.CreateParameter();
121129
p_id.ParameterName = "@Id";

src/ServiceStack.OrmLite.PostgreSQL/PostgreSQLDialectProvider.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,20 @@ public override string GetQuotedValue(object value, Type fieldType)
120120
var guidValue = (Guid)value;
121121
return base.GetQuotedValue(guidValue.ToString("N"), typeof(string));
122122
}
123+
if(fieldType == typeof(byte[]))
124+
{
125+
return "E'" + ToBinary(value) + "'";
126+
}
123127

124128
return base.GetQuotedValue(value, fieldType);
125129
}
126130

127131
public override object ConvertDbValue(object value, Type type)
128132
{
129133
if (value == null || value is DBNull) return null;
130-
134+
135+
if(type == typeof(byte[])) { return value; }
136+
131137
return base.ConvertDbValue(value, type);
132138
}
133139

@@ -194,5 +200,27 @@ public override string GetQuotedTableName(ModelDefinition modelDef)
194200
string escapedSchema = modelDef.Schema.Replace(".", "\".\"");
195201
return string.Format("\"{0}\".\"{1}\"", escapedSchema, base.NamingStrategy.GetTableName(modelDef.ModelName));
196202
}
203+
204+
/// <summary>
205+
/// based on Npgsql2's source: Npgsql2\src\NpgsqlTypes\NpgsqlTypeConverters.cs
206+
/// </summary>
207+
/// <param name="TypeInfo"></param>
208+
/// <param name="NativeData"></param>
209+
/// <param name="ForExtendedQuery"></param>
210+
/// <returns></returns>
211+
internal static String ToBinary(Object NativeData)
212+
{
213+
Byte[] byteArray = (Byte[])NativeData;
214+
StringBuilder res = new StringBuilder(byteArray.Length * 5);
215+
foreach(byte b in byteArray)
216+
if(b >= 0x20 && b < 0x7F && b != 0x27 && b != 0x5C)
217+
res.Append((char)b);
218+
else
219+
res.Append("\\\\")
220+
.Append((char)('0' + (7 & (b >> 6))))
221+
.Append((char)('0' + (7 & (b >> 3))))
222+
.Append((char)('0' + (7 & b)));
223+
return res.ToString();
224+
}
197225
}
198226
}

0 commit comments

Comments
 (0)