diff --git a/src/EdgeDB.Net.Driver/Binary/Common/ConnectionParam.cs b/src/EdgeDB.Net.Driver/Binary/Common/ConnectionParam.cs index 296fc73a..cb35a244 100644 --- a/src/EdgeDB.Net.Driver/Binary/Common/ConnectionParam.cs +++ b/src/EdgeDB.Net.Driver/Binary/Common/ConnectionParam.cs @@ -9,7 +9,7 @@ public int Size public string Name { get; init; } - public string Value { get; init; } + public string? Value { get; init; } public void Write(ref PacketWriter writer) { diff --git a/src/EdgeDB.Net.Driver/Binary/PacketWriter.cs b/src/EdgeDB.Net.Driver/Binary/PacketWriter.cs index e370cf39..a106815a 100644 --- a/src/EdgeDB.Net.Driver/Binary/PacketWriter.cs +++ b/src/EdgeDB.Net.Driver/Binary/PacketWriter.cs @@ -255,7 +255,7 @@ public void Write(ref ReadOnlyMemory memory) pin.Dispose(); } - public void Write(string value) + public void Write(string? value) { if (value is null) Write((uint)0); diff --git a/src/EdgeDB.Net.Driver/Binary/Protocol/V1.0/V1ProtocolProvider.cs b/src/EdgeDB.Net.Driver/Binary/Protocol/V1.0/V1ProtocolProvider.cs index cc3f7bbe..d08c3d66 100644 --- a/src/EdgeDB.Net.Driver/Binary/Protocol/V1.0/V1ProtocolProvider.cs +++ b/src/EdgeDB.Net.Driver/Binary/Protocol/V1.0/V1ProtocolProvider.cs @@ -420,24 +420,22 @@ public virtual ITypeDescriptor GetDescriptor(ref PacketReader reader) return descriptor; } - public virtual Sendable Handshake() => - new ClientHandshake + public virtual Sendable Handshake() + { + return new ClientHandshake { MajorVersion = Version.Major, MinorVersion = Version.Minor, - ConnectionParameters = _client.Connection.SecretKey is not null - ? new ConnectionParam[] - { - new() {Name = "user", Value = _client.Connection.Username!}, - new() {Name = "database", Value = _client.Connection.Database!}, - new() {Name = "secret_key", Value = _client.Connection.SecretKey} - } - : new ConnectionParam[] - { - new() {Name = "user", Value = _client.Connection.Username!}, - new() {Name = "database", Value = _client.Connection.Database!} - } + ConnectionParameters = new ConnectionParam[] + { + new() {Name = "user", Value = _client.Connection.Username}, + new() {Name = "database", Value = _client.Connection.Database}, + new() {Name = "secret_key", Value = _client.Connection.SecretKey}, + new() {Name = "branch", Value = _client.Connection.Branch} + } }; + } + public virtual ValueTask ProcessAsync(in T message) where T : IReceiveable { diff --git a/src/EdgeDB.Net.Driver/EdgeDBConnection.cs b/src/EdgeDB.Net.Driver/EdgeDBConnection.cs index 9af97e4b..2f8d2405 100644 --- a/src/EdgeDB.Net.Driver/EdgeDBConnection.cs +++ b/src/EdgeDB.Net.Driver/EdgeDBConnection.cs @@ -19,6 +19,7 @@ public sealed class EdgeDBConnection private const string EDGEDB_USER_ENV_NAME = "EDGEDB_USER"; private const string EDGEDB_PASSWORD_ENV_NAME = "EDGEDB_PASSWORD"; private const string EDGEDB_DATABASE_ENV_NAME = "EDGEDB_DATABASE"; + private const string EDGEDB_BRANCH_ENV_NAME = "EDGEDB_BRANCH"; private const string EDGEDB_HOST_ENV_NAME = "EDGEDB_HOST"; private const string EDGEDB_PORT_ENV_NAME = "EDGEDB_PORT"; private const string EDGEDB_CLOUD_PROFILE_ENV_NAME = "EDGEDB_CLOUD_PROFILE"; @@ -142,13 +143,46 @@ public int Port /// Gets or sets the database name to use when connecting. /// /// - /// This property defaults to edgedb + /// This property defaults to edgedb. It is mutually exclusive with . /// + /// already contains a value; they're mutually exclusive [JsonProperty("database")] public string? Database { - get => _database ?? "edgedb"; - set => _database = value; + get => _database ?? _branch ?? "edgedb"; + set + { + if (_branch is not null) + { + throw new InvalidOperationException( + "Cannot set database: database conflicts with already provided branch"); + } + + _database = value; + } + } + + /// + /// Gets or sets the branch name to use when connecting. + /// + /// + /// This property defaults to __default__. It is mutually exclusive with + /// + /// already contains a value; they're mutually exclusive + [JsonProperty("branch")] + public string? Branch + { + get => _database ?? _branch ?? "__default__"; + set + { + if (_database is not null) + { + throw new InvalidOperationException( + "Cannot set branch: branch conflicts with already provided database"); + } + + _branch = value; + } } /// @@ -213,6 +247,7 @@ public string CloudProfile private string? _user; private string? _database; + private string? _branch; private string? _hostname; private string? _cloudProfile; private int? _port; @@ -366,7 +401,7 @@ void SetArgument(string name, string? value, EdgeDBConnection conn) conn.Hostname = value; break; - case "database": + case "database" or "branch": if (database is not null) throw new ArgumentException("Database ambiguity mismatch"); @@ -404,6 +439,13 @@ void SetArgument(string name, string? value, EdgeDBConnection conn) } } + if (args.Any(x => x.Key.StartsWith("branch", StringComparison.InvariantCultureIgnoreCase)) && args.Any(x => + x.Key.StartsWith("database", StringComparison.InvariantCultureIgnoreCase))) + { + throw new ArgumentException("branch conflicts with database"); + } + + // query arguments foreach (var arg in args) { @@ -421,7 +463,7 @@ void SetArgument(string name, string? value, EdgeDBConnection conn) var val = Environment.GetEnvironmentVariable(arg.Value, EnvironmentVariableTarget.Process); if (val == null) - throw new KeyNotFoundException($"Enviroment variable \"{arg.Value}\" couldn't be found"); + throw new KeyNotFoundException($"Environment variable \"{arg.Value}\" couldn't be found"); SetArgument(envMatch.Groups[1].Value, val, conn); } @@ -699,10 +741,19 @@ public static EdgeDBConnection Parse(string? instance = null, string? dsn = null if (env.Contains(EDGEDB_DATABASE_ENV_NAME)) { + if (env.Contains(EDGEDB_BRANCH_ENV_NAME)) + throw new ArgumentException($"{EDGEDB_DATABASE_ENV_NAME} conflicts with {EDGEDB_BRANCH_ENV_NAME}"); + connection ??= new EdgeDBConnection(); connection.Database = (string)env[EDGEDB_DATABASE_ENV_NAME]!; } + if (env.Contains(EDGEDB_BRANCH_ENV_NAME)) + { + connection ??= new EdgeDBConnection(); + connection.Branch = (string)env[EDGEDB_BRANCH_ENV_NAME]!; + } + #endregion if (instance is not null)