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
8 changes: 4 additions & 4 deletions Postgrest/Attributes/ColumnAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,22 @@ public class ColumnAttribute : Attribute
/// <summary>
/// The name in postgres of this column.
/// </summary>
public string ColumnName { get; set; }
public string ColumnName { get; }

/// <summary>
/// Specifies what should be serialied in the event this column's value is NULL
/// Specifies what should be serialized in the event this column's value is NULL
/// </summary>
public NullValueHandling NullValueHandling { get; set; }

/// <summary>
/// If the performed query is an Insert or Upsert, should this value be ignored?
/// </summary>
public bool IgnoreOnInsert { get; set; }
public bool IgnoreOnInsert { get; }

/// <summary>
/// If the performed query is an Update, should this value be ignored?
/// </summary>
public bool IgnoreOnUpdate { get; set; }
public bool IgnoreOnUpdate { get; }

public ColumnAttribute([CallerMemberName] string? columnName = null, NullValueHandling nullValueHandling = NullValueHandling.Include, bool ignoreOnInsert = false, bool ignoreOnUpdate = false)
{
Expand Down
4 changes: 2 additions & 2 deletions Postgrest/Attributes/PrimaryKeyAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ namespace Postgrest.Attributes
[AttributeUsage(AttributeTargets.Property)]
public class PrimaryKeyAttribute : Attribute
{
public string ColumnName { get; set; }
public string ColumnName { get; }

/// <summary>
/// Would be set to false in the event that the database handles the generation of this property.
/// </summary>
public bool ShouldInsert { get; set; }
public bool ShouldInsert { get; }

public PrimaryKeyAttribute([CallerMemberName] string? columnName = null, bool shouldInsert = false)
{
Expand Down
48 changes: 15 additions & 33 deletions Postgrest/Attributes/ReferenceAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Newtonsoft.Json;
using Postgrest.Extensions;
using Postgrest.Models;

Expand All @@ -28,12 +28,12 @@ public class ReferenceAttribute : Attribute
/// <summary>
/// Table name of model
/// </summary>
public string TableName { get; private set; }
public string TableName { get; }

/// <summary>
/// Columns that exist on the model we will select from.
/// </summary>
public List<string> Columns { get; } = new List<string>();
public List<string> Columns { get; } = new();

/// <summary>
/// If the performed query is an Insert or Upsert, should this value be ignored? (DEFAULT TRUE)
Expand All @@ -48,14 +48,14 @@ public class ReferenceAttribute : Attribute
/// <summary>
/// If Reference should automatically be included in queries on this reference. (DEFAULT TRUE)
/// </summary>
public bool IncludeInQuery { get; private set; }
public bool IncludeInQuery { get; }

/// <summary>
/// As to whether the query will filter top-level rows.
///
/// See: https://postgrest.org/en/stable/api.html#resource-embedding
/// </summary>
public bool ShouldFilterTopLevel { get; private set; }
public bool ShouldFilterTopLevel { get; }

/// <param name="model">Model referenced</param>
/// <param name="includeInQuery">Should referenced be included in queries?</param>
Expand All @@ -64,11 +64,12 @@ public class ReferenceAttribute : Attribute
/// <param name="shouldFilterTopLevel">As to whether the query will filter top-level rows.</param>
/// <param name="propertyName"></param>
/// <exception cref="Exception"></exception>
public ReferenceAttribute(Type model, bool includeInQuery = true, bool ignoreOnInsert = true, bool ignoreOnUpdate = true, bool shouldFilterTopLevel = true, [CallerMemberName] string propertyName = "")
public ReferenceAttribute(Type model, bool includeInQuery = true, bool ignoreOnInsert = true,
bool ignoreOnUpdate = true, bool shouldFilterTopLevel = true, [CallerMemberName] string propertyName = "")
{
if (!IsDerivedFromBaseModel(model))
{
throw new Exception("RefernceAttribute must be used with Postgrest BaseModels.");
throw new Exception("ReferenceAttribute must be used with Postgrest BaseModels.");
}

Model = model;
Expand Down Expand Up @@ -102,36 +103,17 @@ public ReferenceAttribute(Type model, bool includeInQuery = true, bool ignoreOnI
{
Columns.Add(pk.ColumnName);
}
else if (item is ReferenceAttribute refAttr)
else if (item is ReferenceAttribute { IncludeInQuery: true } refAttr)
{
if (refAttr.IncludeInQuery)
{
if (ShouldFilterTopLevel)
{
Columns.Add($"{refAttr.TableName}!inner({string.Join(",", refAttr.Columns.ToArray())})");
}
else
{
Columns.Add($"{refAttr.TableName}({string.Join(",", refAttr.Columns.ToArray())})");
}
}
Columns.Add(ShouldFilterTopLevel
? $"{refAttr.TableName}!inner({string.Join(",", refAttr.Columns.ToArray())})"
: $"{refAttr.TableName}({string.Join(",", refAttr.Columns.ToArray())})");
}
}
}
}
private bool IsDerivedFromBaseModel(Type type)
{
var isDerived = false;
foreach (var t in type.GetInheritanceHierarchy())
{
if (t == typeof(BaseModel))
{
isDerived = true;
break;
}
}

return isDerived;
}
private bool IsDerivedFromBaseModel(Type type) =>
type.GetInheritanceHierarchy().Any(t => t == typeof(BaseModel));
}
}
}
12 changes: 6 additions & 6 deletions Postgrest/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static JsonSerializerSettings SerializerSettings(ClientOptions? options =
/// <summary>
/// Function that can be set to return dynamic headers.
///
/// Headers specified in the constructor options will ALWAYS take precendece over headers returned by this function.
/// Headers specified in the constructor options will ALWAYS take precedence over headers returned by this function.
/// </summary>
public Func<Dictionary<string, string>>? GetHeaders { get; set; }

Expand All @@ -81,9 +81,11 @@ public Client(string baseUrl, ClientOptions? options = null)
/// <returns></returns>
public IPostgrestTable<T> Table<T>() where T : BaseModel, new()
{
var table = new Table<T>(BaseUrl, SerializerSettings(Options), Options);
table.GetHeaders = GetHeaders;

var table = new Table<T>(BaseUrl, SerializerSettings(Options), Options)
{
GetHeaders = GetHeaders
};

return table;
}

Expand Down Expand Up @@ -111,9 +113,7 @@ public Task<BaseResponse> Rpc(string procedureName, Dictionary<string, object> p
new Dictionary<string, string>(Options.Headers), Options);

if (GetHeaders != null)
{
headers = GetHeaders().MergeLeft(headers);
}

// Send request
var request = Helpers.MakeRequest(Options, HttpMethod.Post, canonicalUri, serializerSettings, data, headers);
Expand Down
3 changes: 1 addition & 2 deletions Postgrest/Constants.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Postgrest.Attributes;
using Supabase.Core.Attributes;
using Supabase.Core.Attributes;

namespace Postgrest
{
Expand Down
39 changes: 39 additions & 0 deletions Postgrest/Exceptions/FailureHint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using static Postgrest.Exceptions.FailureHint.Reason;

namespace Postgrest.Exceptions
{
/// <summary>
/// https://postgrest.org/en/v10.2/errors.html?highlight=exception#http-status-codes
/// </summary>
public static class FailureHint
{
public enum Reason
{
Unknown,
NotAuthorized,
ForeignKeyViolation,
UniquenessViolation,
Internal,
UndefinedTable,
UndefinedFunction
}

public static Reason DetectReason(PostgrestException pgex)
{
if (pgex.Content == null)
return Unknown;

return pgex.StatusCode switch
{
401 => NotAuthorized,
403 when pgex.Content.Contains("apikey") => NotAuthorized,
404 when pgex.Content.Contains("42883") => UndefinedTable,
404 when pgex.Content.Contains("42P01") => UndefinedFunction,
409 when pgex.Content.Contains("23503") => ForeignKeyViolation,
409 when pgex.Content.Contains("23505") => UniquenessViolation,
500 => Internal,
_ => Unknown
};
}
}
}
29 changes: 29 additions & 0 deletions Postgrest/Exceptions/PostgrestException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Net.Http;

namespace Postgrest.Exceptions
{
/// <summary>
/// Errors from Postgrest are wrapped by this exception
/// </summary>
public class PostgrestException : Exception
{
public PostgrestException(string? message) : base(message) { }
public PostgrestException(string? message, Exception? innerException) : base(message, innerException) { }

public HttpResponseMessage? Response { get; internal set; }

public string? Content { get; internal set; }

public int StatusCode { get; internal set; }

public FailureHint.Reason Reason { get; private set; }

public void AddReason()
{
Reason = FailureHint.DetectReason(this);
}

}
}

1 change: 0 additions & 1 deletion Postgrest/Extensions/TypeExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Postgrest.Extensions
{
Expand Down
2 changes: 0 additions & 2 deletions Postgrest/Extensions/UriExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Postgrest.Extensions
{
Expand Down
Loading