/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

// DO NOT EDIT IT MANUALLY. This file is generated by opendal/dev/src/generate/dotnet.rs.

using OpenDAL.ServiceConfig.Abstractions;

namespace OpenDAL.ServiceConfig
{
    /// <summary>
    /// Configuration for service postgresql.
    /// </summary>
    public sealed class PostgresqlServiceConfig : IServiceConfig
    {
        /// <summary>
        /// The URL should be with a scheme of either `postgres://` or `postgresql://`. - `postgresql://user@localhost` - `postgresql://user:password@%2Fvar%2Flib%2Fpostgresql/mydb?connect_timeout=10` - `postgresql://user@host1:1234,host2,host3:5678?target_session_attrs=read-write` - `postgresql:///mydb?user=user&amp;host=/var/lib/postgresql` For more information, please visit &lt;https://docs.rs/sqlx/latest/sqlx/postgres/struct.PgConnectOptions.html&gt;.
        /// </summary>
        public string? ConnectionString { get; init; }
        /// <summary>
        /// the key field of postgresql
        /// </summary>
        public string? KeyField { get; init; }
        /// <summary>
        /// Root of this backend. All operations will happen under this root. Default to `/` if not set.
        /// </summary>
        public string? Root { get; init; }
        /// <summary>
        /// the table of postgresql
        /// </summary>
        public string? Table { get; init; }
        /// <summary>
        /// the value field of postgresql
        /// </summary>
        public string? ValueField { get; init; }

        public string Scheme => "postgresql";

        public IReadOnlyDictionary<string, string> ToOptions()
        {
            var map = new Dictionary<string, string>();
            if (ConnectionString is not null)
            {
                map["connection_string"] = Utilities.ToOptionString(ConnectionString);
            }
            if (KeyField is not null)
            {
                map["key_field"] = Utilities.ToOptionString(KeyField);
            }
            if (Root is not null)
            {
                map["root"] = Utilities.ToOptionString(Root);
            }
            if (Table is not null)
            {
                map["table"] = Utilities.ToOptionString(Table);
            }
            if (ValueField is not null)
            {
                map["value_field"] = Utilities.ToOptionString(ValueField);
            }
            return map;
        }
    }

}
