text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using LanguageExt;
using Nito.AsyncEx;
using SJP.Schematic.Core;
using SJP.Schematic.Core.Exceptions;
using SJP.Schematic.Core.Extensions;
using SJP.Schematic.Core.Utilities;
using SJP.Schematic.MySql.Queries;

namespace SJP.Schematic.MySql;

/// <summary>
/// A database table provider for MySQL.
/// </summary>
/// <seealso cref="IRelationalDatabaseTableProvider" />
public class MySqlRelationalDatabaseTableProvider : IRelationalDatabaseTableProvider
{
    /// <summary>
    /// Initializes a new instance of the <see cref="MySqlRelationalDatabaseTableProvider"/> class.
    /// </summary>
    /// <param name="connection">A database connection.</param>
    /// <param name="identifierDefaults">Identifier defaults for the given database.</param>
    /// <exception cref="ArgumentNullException"><paramref name="connection"/> or <paramref name="identifierDefaults"/> are <c>null</c>.</exception>
    public MySqlRelationalDatabaseTableProvider(ISchematicConnection connection, IIdentifierDefaults identifierDefaults)
    {
        Connection = connection ?? throw new ArgumentNullException(nameof(connection));
        IdentifierDefaults = identifierDefaults ?? throw new ArgumentNullException(nameof(identifierDefaults));

        _supportsChecks = new AsyncLazy<bool>(LoadHasCheckSupport);
    }

    /// <summary>
    /// A database connection that is specific to a given MySQL database.
    /// </summary>
    /// <value>A database connection.</value>
    protected ISchematicConnection Connection { get; }

    /// <summary>
    /// Identifier defaults for the associated database.
    /// </summary>
    /// <value>Identifier defaults.</value>
    protected IIdentifierDefaults IdentifierDefaults { get; }

    /// <summary>
    /// A database connection factory to query the database.
    /// </summary>
    /// <value>A connection factory.</value>
    protected IDbConnectionFactory DbConnection => Connection.DbConnection;

    /// <summary>
    /// The dialect for the associated database.
    /// </summary>
    /// <value>A database dialect.</value>
    protected IDatabaseDialect Dialect => Connection.Dialect;

    /// <summary>
    /// Creates a query cache for a given query context
    /// </summary>
    /// <returns>A query cache.</returns>
    protected MySqlTableQueryCache CreateQueryCache() => new(
        new AsyncCache<Identifier, Option<Identifier>, MySqlTableQueryCache>((tableName, _, token) => GetResolvedTableName(tableName, token)),
        new AsyncCache<Identifier, IReadOnlyList<IDatabaseColumn>, MySqlTableQueryCache>((tableName, _, token) => LoadColumnsAsync(tableName, token)),
        new AsyncCache<Identifier, Option<IDatabaseKey>, MySqlTableQueryCache>(LoadPrimaryKeyAsync),
        new AsyncCache<Identifier, IReadOnlyCollection<IDatabaseKey>, MySqlTableQueryCache>(LoadUniqueKeysAsync),
        new AsyncCache<Identifier, IReadOnlyCollection<IDatabaseRelationalKey>, MySqlTableQueryCache>(LoadParentKeysAsync)
    );

    /// <summary>
    /// Gets all database tables.
    /// </summary>
    /// <param name="cancellationToken">A cancellation token.</param>
    /// <returns>A collection of database tables.</returns>
    public virtual async IAsyncEnumerable<IRelationalDatabaseTable> GetAllTables([EnumeratorCancellation] CancellationToken cancellationToken = default)
    {
        var queryResults = await DbConnection.QueryAsync<GetAllTableNames.Result>(
            GetAllTableNames.Sql,
            new GetAllTableNames.Query { SchemaName = IdentifierDefaults.Schema! },
            cancellationToken
        ).ConfigureAwait(false);
        var tableNames = queryResults
            .Select(dto => Identifier.CreateQualifiedIdentifier(dto.SchemaName, dto.TableName))
            .Select(QualifyTableName);

        var queryCache = CreateQueryCache();
        foreach (var tableName in tableNames)
            yield return await LoadTableAsyncCore(tableName, queryCache, cancellationToken).ConfigureAwait(false);
    }

    /// <summary>
    /// Gets a database table.
    /// </summary>
    /// <param name="tableName">A database table name.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>A database table in the 'some' state if found; otherwise 'none'.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="tableName"/> is <c>null</c>.</exception>
    public OptionAsync<IRelationalDatabaseTable> GetTable(Identifier tableName, CancellationToken cancellationToken = default)
    {
        ArgumentNullException.ThrowIfNull(tableName);

        var queryCache = CreateQueryCache();
        var candidateTableName = QualifyTableName(tableName);
        return LoadTable(candidateTableName, queryCache, cancellationToken);
    }

    /// <summary>
    /// Gets the resolved name of the table. This enables non-strict name matching to be applied.
    /// </summary>
    /// <param name="tableName">A table name that will be resolved.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>A table name that, if available, can be assumed to exist and applied strictly.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="tableName"/> is <c>null</c>.</exception>
    protected Task<Option<Identifier>> GetResolvedTableName(Identifier tableName, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(tableName);

        tableName = QualifyTableName(tableName);
        var qualifiedTableName = DbConnection.QueryFirstOrNone<GetTableName.Result>(
            GetTableName.Sql,
            new GetTableName.Query { SchemaName = tableName.Schema!, TableName = tableName.LocalName },
            cancellationToken
        );

        return qualifiedTableName
            .Map(name => Identifier.CreateQualifiedIdentifier(tableName.Server, tableName.Database, name.SchemaName, name.TableName))
            .ToOption();
    }

    /// <summary>
    /// Retrieves a table from the database, if available.
    /// </summary>
    /// <param name="tableName">A table name.</param>
    /// <param name="queryCache">The query cache.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>A table, if available.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="tableName"/> or <paramref name="queryCache"/> is <c>null</c>.</exception>
    protected virtual OptionAsync<IRelationalDatabaseTable> LoadTable(Identifier tableName, MySqlTableQueryCache queryCache, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(tableName);
        ArgumentNullException.ThrowIfNull(queryCache);

        var candidateTableName = QualifyTableName(tableName);
        return GetResolvedTableName(candidateTableName, cancellationToken)
            .MapAsync(name => LoadTableAsyncCore(name, queryCache, cancellationToken));
    }

    private async Task<IRelationalDatabaseTable> LoadTableAsyncCore(Identifier tableName, MySqlTableQueryCache queryCache, CancellationToken cancellationToken)
    {
        var (
            columns,
            checks,
            triggers,
            indexes,
            primaryKey,
            uniqueKeys,
            parentKeys,
            childKeys
        ) = await TaskUtilities.WhenAll(
            queryCache.GetColumnsAsync(tableName, cancellationToken),
            LoadChecksAsync(tableName, cancellationToken),
            LoadTriggersAsync(tableName, cancellationToken),
            LoadIndexesAsync(tableName, queryCache, cancellationToken),
            queryCache.GetPrimaryKeyAsync(tableName, cancellationToken),
            queryCache.GetUniqueKeysAsync(tableName, cancellationToken),
            queryCache.GetForeignKeysAsync(tableName, cancellationToken),
            LoadChildKeysAsync(tableName, queryCache, cancellationToken)
        ).ConfigureAwait(false);

        return new RelationalDatabaseTable(
            tableName,
            columns,
            primaryKey,
            uniqueKeys,
            parentKeys,
            childKeys,
            indexes,
            checks,
            triggers
        );
    }

    /// <summary>
    /// Retrieves the primary key for the given table, if available.
    /// </summary>
    /// <param name="tableName">A table name.</param>
    /// <param name="queryCache">A query cache for the given context.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>A primary key, if available.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="tableName"/> or <paramref name="queryCache"/> are <c>null</c>.</exception>
    protected virtual Task<Option<IDatabaseKey>> LoadPrimaryKeyAsync(Identifier tableName, MySqlTableQueryCache queryCache, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(tableName);
        ArgumentNullException.ThrowIfNull(queryCache);

        return LoadPrimaryKeyAsyncCore(tableName, queryCache, cancellationToken);
    }

    private async Task<Option<IDatabaseKey>> LoadPrimaryKeyAsyncCore(Identifier tableName, MySqlTableQueryCache queryCache, CancellationToken cancellationToken)
    {
        var primaryKeyColumns = await DbConnection.QueryAsync<GetTablePrimaryKey.Result>(
            GetTablePrimaryKey.Sql,
            new GetTablePrimaryKey.Query { SchemaName = tableName.Schema!, TableName = tableName.LocalName },
            cancellationToken
        ).ConfigureAwait(false);

        if (primaryKeyColumns.Empty())
            return Option<IDatabaseKey>.None;

        var columns = await queryCache.GetColumnsAsync(tableName, cancellationToken).ConfigureAwait(false);
        var columnLookup = GetColumnLookup(columns);

        var groupedByName = primaryKeyColumns.GroupAsDictionary(static row => new { row.ConstraintName });
        var firstRow = groupedByName.First();
        var constraintName = firstRow.Key.ConstraintName;

        var keyColumns = groupedByName
            .Where(row => string.Equals(row.Key.ConstraintName, constraintName, StringComparison.Ordinal))
            .SelectMany(g => g.Value.ConvertAll(row => columnLookup[row.ColumnName!]))
            .ToList();

        var primaryKey = new MySqlDatabasePrimaryKey(keyColumns);
        return Option<IDatabaseKey>.Some(primaryKey);
    }

    /// <summary>
    /// Retrieves indexes that relate to the given table.
    /// </summary>
    /// <param name="tableName">A table name.</param>
    /// <param name="queryCache">A query cache for the given context.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>A collection of indexes.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="tableName"/> or <paramref name="queryCache"/> are <c>null</c>.</exception>
    protected virtual Task<IReadOnlyCollection<IDatabaseIndex>> LoadIndexesAsync(Identifier tableName, MySqlTableQueryCache queryCache, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(tableName);
        ArgumentNullException.ThrowIfNull(queryCache);

        return LoadIndexesAsyncCore(tableName, queryCache, cancellationToken);
    }

    private async Task<IReadOnlyCollection<IDatabaseIndex>> LoadIndexesAsyncCore(Identifier tableName, MySqlTableQueryCache queryCache, CancellationToken cancellationToken)
    {
        var queryResult = await DbConnection.QueryAsync<GetTableIndexes.Result>(
            GetTableIndexes.Sql,
            new GetTableIndexes.Query { SchemaName = tableName.Schema!, TableName = tableName.LocalName },
            cancellationToken
        ).ConfigureAwait(false);

        if (queryResult.Empty())
            return Array.Empty<IDatabaseIndex>();

        var indexColumns = queryResult.GroupAsDictionary(static row => new { row.IndexName, row.IsNonUnique }).ToList();
        if (indexColumns.Empty())
            return Array.Empty<IDatabaseIndex>();

        var columns = await queryCache.GetColumnsAsync(tableName, cancellationToken).ConfigureAwait(false);
        var columnLookup = GetColumnLookup(columns);

        var result = new List<IDatabaseIndex>(indexColumns.Count);

        foreach (var indexInfo in indexColumns)
        {
            var isUnique = !indexInfo.Key.IsNonUnique;
            var indexName = Identifier.CreateQualifiedIdentifier(indexInfo.Key.IndexName);

            var indexCols = indexInfo.Value
                .OrderBy(static row => row.ColumnOrdinal)
                .Select(row => columnLookup[row.ColumnName])
                .Select(col =>
                {
                    var expression = Dialect.QuoteName(col.Name);
                    return new MySqlDatabaseIndexColumn(expression, col);
                })
                .ToList();

            var index = new MySqlDatabaseIndex(indexName, isUnique, indexCols);
            result.Add(index);
        }

        return result;
    }

    /// <summary>
    /// Retrieves unique keys that relate to the given table.
    /// </summary>
    /// <param name="tableName">A table name.</param>
    /// <param name="queryCache">A query cache for the given context.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>A collection of unique keys.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="tableName"/> or <paramref name="queryCache"/> are <c>null</c>.</exception>
    protected virtual Task<IReadOnlyCollection<IDatabaseKey>> LoadUniqueKeysAsync(Identifier tableName, MySqlTableQueryCache queryCache, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(tableName);
        ArgumentNullException.ThrowIfNull(queryCache);

        return LoadUniqueKeysAsyncCore(tableName, queryCache, cancellationToken);
    }

    private async Task<IReadOnlyCollection<IDatabaseKey>> LoadUniqueKeysAsyncCore(Identifier tableName, MySqlTableQueryCache queryCache, CancellationToken cancellationToken)
    {
        var uniqueKeyColumns = await DbConnection.QueryAsync<GetTableUniqueKeys.Result>(
            GetTableUniqueKeys.Sql,
            new GetTableUniqueKeys.Query { SchemaName = tableName.Schema!, TableName = tableName.LocalName },
            cancellationToken
        ).ConfigureAwait(false);

        if (uniqueKeyColumns.Empty())
            return Array.Empty<IDatabaseKey>();

        var columns = await queryCache.GetColumnsAsync(tableName, cancellationToken).ConfigureAwait(false);
        var columnLookup = GetColumnLookup(columns);

        var groupedByName = uniqueKeyColumns.GroupAsDictionary(static row => new { row.ConstraintName });
        var constraintColumns = groupedByName
            .Select(g => new
            {
                g.Key.ConstraintName,
                Columns = g.Value.ConvertAll(row => columnLookup[row.ColumnName!]),
            })
            .ToList();
        if (constraintColumns.Empty())
            return Array.Empty<IDatabaseKey>();

        var result = new List<IDatabaseKey>(constraintColumns.Count);
        foreach (var uk in constraintColumns)
        {
            var uniqueKey = new MySqlDatabaseKey(uk.ConstraintName, DatabaseKeyType.Unique, uk.Columns);
            result.Add(uniqueKey);
        }
        return result;
    }

    /// <summary>
    /// Retrieves child keys that relate to the given table.
    /// </summary>
    /// <param name="tableName">A table name.</param>
    /// <param name="queryCache">A query cache for the given context.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>A collection of child keys.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="tableName"/> or <paramref name="queryCache"/> are <c>null</c>.</exception>
    protected virtual Task<IReadOnlyCollection<IDatabaseRelationalKey>> LoadChildKeysAsync(Identifier tableName, MySqlTableQueryCache queryCache, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(tableName);
        ArgumentNullException.ThrowIfNull(queryCache);

        return LoadChildKeysAsyncCore(tableName, queryCache, cancellationToken);
    }

    private async Task<IReadOnlyCollection<IDatabaseRelationalKey>> LoadChildKeysAsyncCore(Identifier tableName, MySqlTableQueryCache queryCache, CancellationToken cancellationToken)
    {
        var queryResult = await DbConnection.QueryAsync<GetTableChildKeys.Result>(
            GetTableChildKeys.Sql,
            new GetTableChildKeys.Query { SchemaName = tableName.Schema!, TableName = tableName.LocalName },
            cancellationToken
        ).ConfigureAwait(false);

        if (queryResult.Empty())
            return Array.Empty<IDatabaseRelationalKey>();

        var groupedChildKeys = queryResult.GroupAsDictionary(static row =>
        new
        {
            row.ChildTableSchema,
            row.ChildTableName,
            row.ChildKeyName,
            row.ParentKeyName,
            row.ParentKeyType,
            row.DeleteAction,
            row.UpdateAction
        }).ToList();
        if (groupedChildKeys.Empty())
            return Array.Empty<IDatabaseRelationalKey>();

        var uniqueKeys = await queryCache.GetUniqueKeysAsync(tableName, cancellationToken).ConfigureAwait(false);
        var uniqueKeyLookup = GetDatabaseKeyLookup(uniqueKeys);

        var result = new List<IDatabaseRelationalKey>(groupedChildKeys.Count);

        foreach (var groupedChildKey in groupedChildKeys.Select(ck => ck.Key))
        {
            // ensure we have a key to begin with
            IDatabaseKey? parentKey = null;
            if (string.Equals(groupedChildKey.ParentKeyType, Constants.PrimaryKey, StringComparison.Ordinal))
            {
                var pk = await queryCache.GetPrimaryKeyAsync(tableName, cancellationToken).ConfigureAwait(false);
                pk.IfSome(k => parentKey = k);
            }
            else if (uniqueKeyLookup.ContainsKey(groupedChildKey.ParentKeyName))
            {
                parentKey = uniqueKeyLookup[groupedChildKey.ParentKeyName];
            }

            if (parentKey == null)
                continue;

            var candidateChildTableName = Identifier.CreateQualifiedIdentifier(groupedChildKey.ChildTableSchema, groupedChildKey.ChildTableName);
            var resolvedName = await queryCache.GetTableNameAsync(candidateChildTableName, cancellationToken).ConfigureAwait(false);

            await resolvedName
                .BindAsync(async name =>
                {
                    var childKeyName = Identifier.CreateQualifiedIdentifier(groupedChildKey.ChildKeyName);

                    var parentKeys = await queryCache.GetForeignKeysAsync(name, cancellationToken).ConfigureAwait(false);
                    var parentKeyLookup = GetDatabaseKeyLookup(parentKeys.Select(fk => fk.ChildKey).ToList());
                    if (!parentKeyLookup.TryGetValue(childKeyName, out var childKey))
                        return OptionAsync<IDatabaseRelationalKey>.None;

                    var deleteAction = ReferentialActionMapping[groupedChildKey.DeleteAction];
                    var updateAction = ReferentialActionMapping[groupedChildKey.UpdateAction];
                    var relationalKey = new MySqlRelationalKey(name, childKey, tableName, parentKey, deleteAction, updateAction);

                    return OptionAsync<IDatabaseRelationalKey>.Some(relationalKey);
                })
                .IfSome(key => result.Add(key))
                .ConfigureAwait(false);
        }

        return result;
    }

    /// <summary>
    /// Retrieves check constraints defined on a given table.
    /// </summary>
    /// <param name="tableName">A table name.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>A collection of check constraints.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="tableName"/> is <c>null</c>.</exception>
    protected virtual Task<IReadOnlyCollection<IDatabaseCheckConstraint>> LoadChecksAsync(Identifier tableName, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(tableName);

        return LoadChecksAsyncCore(tableName, cancellationToken);
    }

    private async Task<IReadOnlyCollection<IDatabaseCheckConstraint>> LoadChecksAsyncCore(Identifier tableName, CancellationToken cancellationToken)
    {
        var hasCheckSupport = await _supportsChecks.ConfigureAwait(false);
        if (!hasCheckSupport)
            return Array.Empty<IDatabaseCheckConstraint>();

        var queryResult = await DbConnection.QueryAsync<GetTableCheckConstraints.Result>(
            GetTableCheckConstraints.Sql,
            new GetTableCheckConstraints.Query { SchemaName = tableName.Schema!, TableName = tableName.LocalName },
            cancellationToken
        ).ConfigureAwait(false);
        if (queryResult.Empty())
            return Array.Empty<IDatabaseCheckConstraint>();

        var result = new List<IDatabaseCheckConstraint>();

        foreach (var row in queryResult)
        {
            var checkName = Identifier.CreateQualifiedIdentifier(row.ConstraintName);
            var isEnabled = string.Equals("YES", row.Enforced, StringComparison.OrdinalIgnoreCase);
            var check = new MySqlCheckConstraint(checkName, row.Definition, isEnabled);
            result.Add(check);
        }

        return result;
    }

    /// <summary>
    /// Retrieves foreign keys that relate to the given table.
    /// </summary>
    /// <param name="tableName">A table name.</param>
    /// <param name="queryCache">A query cache for the given context.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>A collection of foreign keys.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="tableName"/> or <paramref name="queryCache"/> are <c>null</c>.</exception>
    protected virtual Task<IReadOnlyCollection<IDatabaseRelationalKey>> LoadParentKeysAsync(Identifier tableName, MySqlTableQueryCache queryCache, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(tableName);
        ArgumentNullException.ThrowIfNull(queryCache);

        return LoadParentKeysAsyncCore(tableName, queryCache, cancellationToken);
    }

    private async Task<IReadOnlyCollection<IDatabaseRelationalKey>> LoadParentKeysAsyncCore(Identifier tableName, MySqlTableQueryCache queryCache, CancellationToken cancellationToken)
    {
        var queryResult = await DbConnection.QueryAsync<GetTableParentKeys.Result>(
            GetTableParentKeys.Sql,
            new GetTableParentKeys.Query { SchemaName = tableName.Schema!, TableName = tableName.LocalName },
            cancellationToken
        ).ConfigureAwait(false);

        if (queryResult.Empty())
            return Array.Empty<IDatabaseRelationalKey>();

        var foreignKeys = queryResult.GroupAsDictionary(static row => new
        {
            row.ChildKeyName,
            row.ParentTableSchema,
            row.ParentTableName,
            row.ParentKeyName,
            KeyType = row.ParentKeyType,
            row.DeleteAction,
            row.UpdateAction,
        }).ToList();
        if (foreignKeys.Empty())
            return Array.Empty<IDatabaseRelationalKey>();

        var columns = await queryCache.GetColumnsAsync(tableName, cancellationToken).ConfigureAwait(false);
        var columnLookup = GetColumnLookup(columns);

        var result = new List<IDatabaseRelationalKey>(foreignKeys.Count);
        foreach (var fkey in foreignKeys)
        {
            var candidateParentTableName = Identifier.CreateQualifiedIdentifier(fkey.Key.ParentTableSchema, fkey.Key.ParentTableName);
            var resolvedName = await queryCache.GetTableNameAsync(candidateParentTableName, cancellationToken).ConfigureAwait(false);

            Identifier? parentTableName = null;

            await resolvedName
                .BindAsync(async name =>
                {
                    parentTableName = name;
                    if (string.Equals(fkey.Key.KeyType, Constants.PrimaryKey, StringComparison.Ordinal))
                    {
                        var primaryKey = await queryCache.GetPrimaryKeyAsync(name, cancellationToken).ConfigureAwait(false);
                        return primaryKey.ToAsync();
                    }

                    var parentKeyName = Identifier.CreateQualifiedIdentifier(fkey.Key.ParentKeyName);

                    var parentUniqueKeys = await queryCache.GetUniqueKeysAsync(name, cancellationToken).ConfigureAwait(false);
                    var parentUniqueKeyLookup = GetDatabaseKeyLookup(parentUniqueKeys);
                    return parentUniqueKeyLookup.ContainsKey(parentKeyName.LocalName)
                        ? OptionAsync<IDatabaseKey>.Some(parentUniqueKeyLookup[parentKeyName.LocalName])
                        : OptionAsync<IDatabaseKey>.None;
                })
                .IfSome(key =>
                {
                    var childKeyName = Identifier.CreateQualifiedIdentifier(fkey.Key.ChildKeyName);
                    var childKeyColumns = fkey.Value
                        .OrderBy(static row => row.ConstraintColumnId)
                        .Select(row => columnLookup[row.ColumnName!])
                        .ToList();

                    var childKey = new MySqlDatabaseKey(childKeyName, DatabaseKeyType.Foreign, childKeyColumns);

                    var deleteAction = ReferentialActionMapping[fkey.Key.DeleteAction];
                    var updateAction = ReferentialActionMapping[fkey.Key.UpdateAction];

                    var relationalKey = new DatabaseRelationalKey(tableName, childKey, parentTableName!, key, deleteAction, updateAction);
                    result.Add(relationalKey);
                })
                .ConfigureAwait(false);
        }

        return result;
    }

    /// <summary>
    /// Retrieves the columns for a given table.
    /// </summary>
    /// <param name="tableName">A table name.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>An ordered collection of columns.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="tableName"/> is <c>null</c>.</exception>
    protected virtual Task<IReadOnlyList<IDatabaseColumn>> LoadColumnsAsync(Identifier tableName, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(tableName);

        return LoadColumnsAsyncCore(tableName, cancellationToken);
    }

    private async Task<IReadOnlyList<IDatabaseColumn>> LoadColumnsAsyncCore(Identifier tableName, CancellationToken cancellationToken)
    {
        var query = await DbConnection.QueryAsync<GetTableColumns.Result>(
            GetTableColumns.Sql,
            new GetTableColumns.Query { SchemaName = tableName.Schema!, TableName = tableName.LocalName },
            cancellationToken
        ).ConfigureAwait(false);

        var result = new List<IDatabaseColumn>();

        foreach (var row in query)
        {
            var typeMetadata = new ColumnTypeMetadata
            {
                TypeName = Identifier.CreateQualifiedIdentifier(row.DataTypeName),
                Collation = !row.Collation.IsNullOrWhiteSpace()
                    ? Option<Identifier>.Some(Identifier.CreateQualifiedIdentifier(row.Collation))
                    : Option<Identifier>.None,
                MaxLength = row.CharacterMaxLength,
                NumericPrecision = new NumericPrecision(row.Precision, row.Scale)
            };
            var columnType = Dialect.TypeProvider.CreateColumnType(typeMetadata);

            var columnName = Identifier.CreateQualifiedIdentifier(row.ColumnName);
            var isAutoIncrement = row.ExtraInformation?.Contains(Constants.AutoIncrement, StringComparison.OrdinalIgnoreCase) == true;
            var autoIncrement = isAutoIncrement
                ? Option<IAutoIncrement>.Some(new AutoIncrement(1, 1))
                : Option<IAutoIncrement>.None;
            var isComputed = !row.ComputedColumnDefinition.IsNullOrWhiteSpace();
            var isNullable = !string.Equals(row.IsNullable, Constants.No, StringComparison.OrdinalIgnoreCase);
            var defaultValue = !row.DefaultValue.IsNullOrWhiteSpace()
                ? Option<string>.Some(row.DefaultValue)
                : Option<string>.None;
            var computedColumnDefinition = isComputed
                ? Option<string>.Some(row.ComputedColumnDefinition!)
                : Option<string>.None;

            var column = isComputed
                ? new DatabaseComputedColumn(columnName, columnType, isNullable, defaultValue, computedColumnDefinition)
                : new DatabaseColumn(columnName, columnType, isNullable, defaultValue, autoIncrement);

            result.Add(column);
        }

        return result;
    }

    /// <summary>
    /// Retrieves all triggers defined on a table.
    /// </summary>
    /// <param name="tableName">A table name.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>A collection of triggers.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="tableName"/> is <c>null</c>.</exception>
    protected virtual Task<IReadOnlyCollection<IDatabaseTrigger>> LoadTriggersAsync(Identifier tableName, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(tableName);

        return LoadTriggersAsyncCore(tableName, cancellationToken);
    }

    private async Task<IReadOnlyCollection<IDatabaseTrigger>> LoadTriggersAsyncCore(Identifier tableName, CancellationToken cancellationToken)
    {
        var queryResult = await DbConnection.QueryAsync<GetTableTriggers.Result>(
            GetTableTriggers.Sql,
            new GetTableTriggers.Query { SchemaName = tableName.Schema!, TableName = tableName.LocalName },
            cancellationToken
        ).ConfigureAwait(false);

        if (queryResult.Empty())
            return Array.Empty<IDatabaseTrigger>();

        var triggers = queryResult.GroupAsDictionary(static row => new
        {
            row.TriggerName,
            row.Definition,
            row.Timing
        }).ToList();
        if (triggers.Empty())
            return Array.Empty<IDatabaseTrigger>();

        var result = new List<IDatabaseTrigger>(triggers.Count);
        foreach (var trig in triggers)
        {
            var triggerName = Identifier.CreateQualifiedIdentifier(trig.Key.TriggerName);
            var queryTiming = Enum.TryParse(trig.Key.Timing, true, out TriggerQueryTiming timing) ? timing : TriggerQueryTiming.Before;
            var definition = trig.Key.Definition;

            var events = TriggerEvent.None;
            foreach (var trigEvent in trig.Value.Select(tr => tr.TriggerEvent))
            {
                if (string.Equals(trigEvent, Constants.Insert, StringComparison.Ordinal))
                    events |= TriggerEvent.Insert;
                else if (string.Equals(trigEvent, Constants.Update, StringComparison.Ordinal))
                    events |= TriggerEvent.Update;
                else if (string.Equals(trigEvent, Constants.Delete, StringComparison.Ordinal))
                    events |= TriggerEvent.Delete;
                else
                    throw new UnsupportedTriggerEventException(tableName, trigEvent ?? string.Empty);
            }

            var trigger = new MySqlDatabaseTrigger(triggerName, definition, queryTiming, events);
            result.Add(trigger);
        }

        return result;
    }

    /// <summary>
    /// Qualifies the name of a table, using known identifier defaults.
    /// </summary>
    /// <param name="tableName">A table name to qualify.</param>
    /// <returns>A table name that is at least as qualified as its input.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="tableName"/> is <c>null</c>.</exception>
    protected Identifier QualifyTableName(Identifier tableName)
    {
        ArgumentNullException.ThrowIfNull(tableName);

        var schema = tableName.Schema ?? IdentifierDefaults.Schema;
        return Identifier.CreateQualifiedIdentifier(IdentifierDefaults.Server, IdentifierDefaults.Database, schema, tableName.LocalName);
    }

    /// <summary>
    /// A mapping from the referential actions as described in MySQL, to a <see cref="ReferentialAction"/> instance.
    /// </summary>
    /// <value>A mapping dictionary.</value>
    protected IReadOnlyDictionary<string, ReferentialAction> ReferentialActionMapping { get; } = new Dictionary<string, ReferentialAction>(StringComparer.OrdinalIgnoreCase)
    {
        ["NO ACTION"] = ReferentialAction.NoAction,
        ["RESTRICT"] = ReferentialAction.Restrict,
        ["CASCADE"] = ReferentialAction.Cascade,
        ["SET NULL"] = ReferentialAction.SetNull,
        ["SET DEFAULT"] = ReferentialAction.SetDefault
    };

    private static IReadOnlyDictionary<Identifier, IDatabaseColumn> GetColumnLookup(IReadOnlyCollection<IDatabaseColumn> columns)
    {
        ArgumentNullException.ThrowIfNull(columns);

        var result = new Dictionary<Identifier, IDatabaseColumn>(columns.Count);

        foreach (var column in columns)
        {
            if (column.Name != null)
                result[column.Name.LocalName] = column;
        }

        return result;
    }

    private static IReadOnlyDictionary<Identifier, IDatabaseKey> GetDatabaseKeyLookup(IReadOnlyCollection<IDatabaseKey> keys)
    {
        ArgumentNullException.ThrowIfNull(keys);

        var result = new Dictionary<Identifier, IDatabaseKey>(keys.Count);

        foreach (var key in keys)
        {
            key.Name.IfSome(name => result[name.LocalName] = key);
        }

        return result;
    }

    private Task<bool> LoadHasCheckSupport()
    {
        const string sql = "select count(*) from information_schema.tables where table_schema = 'information_schema' and table_name = 'CHECK_CONSTRAINTS'";
        return DbConnection.ExecuteScalarAsync<bool>(sql, CancellationToken.None);
    }

    private readonly AsyncLazy<bool> _supportsChecks;

    private static class Constants
    {
        public const string AutoIncrement = "auto_increment";

        public const string Delete = "DELETE";

        public const string Insert = "INSERT";

        public const string No = "NO";

        public const string PrimaryKey = "PRIMARY KEY";

        public const string Update = "UPDATE";
    }

    /// <summary>
    /// A query cache provider for MySQL tables. Ensures that a given query only occurs at most once for a given query context.
    /// </summary>
    protected class MySqlTableQueryCache
    {
        private readonly AsyncCache<Identifier, Option<Identifier>, MySqlTableQueryCache> _tableNames;
        private readonly AsyncCache<Identifier, IReadOnlyList<IDatabaseColumn>, MySqlTableQueryCache> _columns;
        private readonly AsyncCache<Identifier, Option<IDatabaseKey>, MySqlTableQueryCache> _primaryKeys;
        private readonly AsyncCache<Identifier, IReadOnlyCollection<IDatabaseKey>, MySqlTableQueryCache> _uniqueKeys;
        private readonly AsyncCache<Identifier, IReadOnlyCollection<IDatabaseRelationalKey>, MySqlTableQueryCache> _foreignKeys;

        /// <summary>
        /// Initializes a new instance of the <see cref="MySqlTableQueryCache"/> class.
        /// </summary>
        /// <param name="tableNameLoader">A table name cache.</param>
        /// <param name="columnLoader">A column cache.</param>
        /// <param name="primaryKeyLoader">A primary key cache.</param>
        /// <param name="uniqueKeyLoader">A unique key cache.</param>
        /// <param name="foreignKeyLoader">A foreign key cache.</param>
        /// <exception cref="ArgumentNullException">Thrown when any of <paramref name="tableNameLoader"/>, <paramref name="columnLoader"/>, <paramref name="primaryKeyLoader"/>, <paramref name="uniqueKeyLoader"/> or <paramref name="foreignKeyLoader"/> are <c>null</c>.</exception>
        public MySqlTableQueryCache(
            AsyncCache<Identifier, Option<Identifier>, MySqlTableQueryCache> tableNameLoader,
            AsyncCache<Identifier, IReadOnlyList<IDatabaseColumn>, MySqlTableQueryCache> columnLoader,
            AsyncCache<Identifier, Option<IDatabaseKey>, MySqlTableQueryCache> primaryKeyLoader,
            AsyncCache<Identifier, IReadOnlyCollection<IDatabaseKey>, MySqlTableQueryCache> uniqueKeyLoader,
            AsyncCache<Identifier, IReadOnlyCollection<IDatabaseRelationalKey>, MySqlTableQueryCache> foreignKeyLoader
        )
        {
            _tableNames = tableNameLoader ?? throw new ArgumentNullException(nameof(tableNameLoader));
            _columns = columnLoader ?? throw new ArgumentNullException(nameof(columnLoader));
            _primaryKeys = primaryKeyLoader ?? throw new ArgumentNullException(nameof(primaryKeyLoader));
            _uniqueKeys = uniqueKeyLoader ?? throw new ArgumentNullException(nameof(uniqueKeyLoader));
            _foreignKeys = foreignKeyLoader ?? throw new ArgumentNullException(nameof(foreignKeyLoader));
        }

        /// <summary>
        /// Retrieves the table name from the cache, querying the database when not populated.
        /// </summary>
        /// <param name="tableName">A table name.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A table name, if matched in the database.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="tableName"/> is <c>null</c>.</exception>
        public Task<Option<Identifier>> GetTableNameAsync(Identifier tableName, CancellationToken cancellationToken)
        {
            ArgumentNullException.ThrowIfNull(tableName);

            return _tableNames.GetByKeyAsync(tableName, this, cancellationToken);
        }

        /// <summary>
        /// Retrieves a table's columns from the cache, querying the database when not populated.
        /// </summary>
        /// <param name="tableName">A table name.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A collection of columns.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="tableName"/> is <c>null</c>.</exception>
        public Task<IReadOnlyList<IDatabaseColumn>> GetColumnsAsync(Identifier tableName, CancellationToken cancellationToken)
        {
            ArgumentNullException.ThrowIfNull(tableName);

            return _columns.GetByKeyAsync(tableName, this, cancellationToken);
        }

        /// <summary>
        /// Retrieves a table's primary key from the cache, querying the database when not populated.
        /// </summary>
        /// <param name="tableName">A table name.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A primary key, if available.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="tableName"/> is <c>null</c>.</exception>
        public Task<Option<IDatabaseKey>> GetPrimaryKeyAsync(Identifier tableName, CancellationToken cancellationToken)
        {
            ArgumentNullException.ThrowIfNull(tableName);

            return _primaryKeys.GetByKeyAsync(tableName, this, cancellationToken);
        }

        /// <summary>
        /// Retrieves a table's unique keys from the cache, querying the database when not populated.
        /// </summary>
        /// <param name="tableName">A table name.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A collection of unique keys.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="tableName"/> is <c>null</c>.</exception>
        public Task<IReadOnlyCollection<IDatabaseKey>> GetUniqueKeysAsync(Identifier tableName, CancellationToken cancellationToken)
        {
            ArgumentNullException.ThrowIfNull(tableName);

            return _uniqueKeys.GetByKeyAsync(tableName, this, cancellationToken);
        }

        /// <summary>
        /// Retrieves a table's foreign keys from the cache, querying the database when not populated.
        /// </summary>
        /// <param name="tableName">A table name.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A collection of foreign keys.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="tableName"/> is <c>null</c>.</exception>
        public Task<IReadOnlyCollection<IDatabaseRelationalKey>> GetForeignKeysAsync(Identifier tableName, CancellationToken cancellationToken)
        {
            ArgumentNullException.ThrowIfNull(tableName);

            return _foreignKeys.GetByKeyAsync(tableName, this, cancellationToken);
        }
    }
}


Enter a 4K world expanding entertainment with Toshiba U86 series.
This distinctive TV, featuring OPERA TV SOTRE lets you enjoy apps, content and games on the screen.
Sit back and enjoy the ulimited entertaiment possibilities!


This refreshing Summer Fruit Salad with Lime, Mint and Honey is an easy and healthy side dish. Perfect for any Summer gathering.
Add all of the ingredients together in large bowl. Toss to combine. Refrigerate for at least an hour to let the flavors develop.


text:
> 'Right-wing infighting over sovereignty plan hurts us'
'Right-wing infighting over sovereignty plan hurts us'
MK Uzi Dayan says right-wing leaders harm Israel's ability to get anything by being divided as Israel negotiates with US over sovereignty.
Shimon Cohen
כ"ג בסיון תש"פ 22:15 15.06.20
Uzi Dayan Sovereignty
Uzi Dayan Eliran Aharon
MK Maj. Gen. (res.) Uzi Dayan (Likud) addressed the controversy which has erupted on the right over the Trump Administration's 'Deal of the Century' and the application of sovereignty in Judea and Samaria.
"This is not annexation because annexation from a legal point of view is over another country's territory. Here, at most, it is a disputed area. We are applying Israeli sovereignty, namely Israeli law and administration," Dayan told Arutz Sheva,
Turning to the infighting on the right and the leaders of the Jewish communities of Judea and Samaria over the plan, Dayan said: "There is an argument and I am not in a hurry to attack anyone who doesn't think like me. We are having an argument which is a harmful argument and infighting, because the American left opposes us, as do the Europeans and the Arabs. Also the left in Israel is opposed to it. We know this, but when there is a fight within the right it is not good. This is the mistake the Palestinians committed. The Americans brought the plan to them to tell them, we are offering you a state, but in order for this to happen you have to recognize the Jewish State, disarm Hamas, and other things I don't think the Palestinians will do. In addition, the Americans told them, if you don't want it, you don't have to take it, but we won't make you a better offer. That's the importance of the American proposal. So I say that concerns are real and I understand them, but we have to seize this opportunity with both hands."
On the security implications of the plan, Dayan said: "There are always political and security matters which are at risk, but this time that is not the case. First of all, we have a chance to establish our eastern border on the Jordan, where we crossed the Jordan on the way to the conquest of the land during the time of Joshua. Topographically, this is an important place for us to develop far beyond 6,000 inhabitants. It is an opportunity to set a buffer between Jordan and the Palestinians, and the Jordanians do not need to have the Palestinians on their border. This border gives us strategic depth and the ability to cope with an external enemy and to do so with recognition as we have formal recognition on the Golan."
"As for the dangers, opponents say one thing. They say that if you agree to one thing then you have to agree to everything. That's not true. This was the case when the state was established with the partition and no Jerusalem which was declared international. The approach was to take what we could and then we would add another dunam and another dunam. The approach should be that of Ben Gurion. We want the maximum and they offer us the minimum. That we accept the minimum does not mean that we are giving up on the maximum, and here there are no concessions.
According to Dayan, "We have to do the best we can to get the maximum we can now. I'm not saying I'm willing to pay any price and I understand the concerns there are. We have to go for it together, and it is at times like these that I regret that Yamina is not in the government. By the way, it's not too late. I call on everyone to find a way to increase the size of the right-wing bloc. The differences of opinion are not that big."
MK Dayan believes that it is completely unrealistic to believe that a Palestinian Arab state will be created. and that the Palestinian Authority has proven time and time again that it is "unfit."
"The peace process has become a dead process, and the ones who killed the peace process were the Palestinians, because of their attitude of saying 'no' to everything, and now they're being told that we'll move on without them.
Dayan said that "the maps are not finalized yet. This is still not settled and it is time to take things down a notch. I'm not saying that you have to accept any situation, but in my opinion you can come to the Americans with greater Israeli support and cohesion, and what we're taking would leave us in a much better situation than today, and later it will be possible to enlarge and expand it."
Addressing the fear that communities would become isolated under the current sovereignty maps, Dayan said: "I remind you that until a short while ago everyone who spoke with us saw that they would not be [isolated]at all. It is now possible to recognize our sovereignty over these communities. It does not solve all the problems, but it is necessary to remember that the overall security control remains our own, so we can take certain risks and I say that these gains are not reversible. This is the time to get down to the nitty-gritty, and that's what need to be done in order to get the maximum number of months before November because we don't know what will be with US and what the agenda will be then. So instead of saying 'no' first, lets get the maximum that we can achieve and then we can deal with the difficult decision of whether to agree to this or not. In any case, we have to realize that are not facing the choice of nothing or a Palestinian state. That's not the case."
Addressing claims by left-wing critics that applying sovereignty would lead to the end of the peace treaty with Jordan, Dayan said that he himself was the head of the Security Committee involved in the drafting of the agreement, and he indeed believes that the agreement is good, but it should be understood that it is a strategic asset to both parties. The treaty provides for vital security cooperation with Jordan. "But it is important to understand what the agreement gives the Jordanians. If they endanger the agreement, they endanger the regime. We are the national insurance and security for the Jordan. This was put to the test in 1975 and on other occasions. In addition, the Jordanians cannot even say in the economic aspect that it does not concern them. It is a mature country and the last thing it needs is the Palestinians. Therefore even if they are not satisfied they will not break the tools because these are the tools that keep them in power. They won't say no to the US. King Hussein once told me that they are a small country surrounded by friends and it is much more difficult than to be a small country surrounded by enemies like us. That's why I'm really not afraid of this thing. The Jordanians have much more to lose."

redpajama_set_name: RedPajamaCommonCrawl


Western Digital (WD) introduces its fastest My Book external hard drive system ever, the My Book VelociRaptor Duo dual-drive storage system built to deliver ultimate performance to Mac users and creative professionals. The system combines two 1TB 10,000RPM WD VelociRaptor hard drives with two Thunderbolt ports for ultimate speed and performance.
With high-speed, high-capacity drive and super fast data port, the VelociRaptor Duo is ideal for editing high resolution video, 3D rendering, graphic design, and other demanding digital media applications. The dual-drive system delivers data transfer rates of up to 400 MB/s. According to WD, the system can transfer 22 GB full-length HD movies in less than 65 seconds, 2000 5 MB pictures in less than 33 seconds and over 500 5 MB songs in less than 8 seconds.
The My Book VelociRaptor Duo can be configured to operate in RAID 1 mode for speed and capacity or in RAID 1 for data protection and security. The two drives inside the VelociRaptor Duo can also be set to JBOD (Just a Bunch Of Disks) mode to use as two individual drives and select between HFS+J or ExFAT per disk. With two Thunderbolt ports, you can daisy chain more drives for more speed and large storage capacity. The unit is user-servicable that in case you want to replace a drive, you can simply open the case and replace the drive with another one.
The My Book VelociRaptor Duo Thunderbolt storage device starts at $899.99.


text:
5G mast to be constructed at one of Southport's busiest roundabouts
The proposal is an upgrade by EE and Three aimed at both providing 5G services in the area and improving existing 4G provision.
Jamie LopezSenior Reporter
A 5G phone mast will be erected at Kew roundabout in Southport, replacing existing equipment
A 5G mast will be erected by one of Southport's busiest roundabouts to help deliver faster internet connections.
The 20m-tall tower with 12 antennae will replace existing equipment next to Kew roundabout after plans were approved by Sefton Council.
5G is the next generation of mobile data communications, with mobile internet speeds potentially several times greater than that of 4G.
The introduction of the technology has been fought in many towns and cities, with campaigners claiming more information is needed to determine whether the masts could be dangerous to those living nearby.
Conspiracy theories surrounding 5G technology has been shared far and wide on social media, despite having little base in fact. Earlier this month, the international body in charge of setting limits on exposure to radiation - International Commission on Non‐Ionizing Radiation Protection (ICNIRP) - updated its guidelines to make clear that the technology was safe.
Southport dad killed in brutal gang murder after 'running over man'
Three further coronavirus related deaths confirmed at Southport & Ormskirk Hospitals
The proposed site for Southport would be surrounded by supermarkets, retail parks, McDonalds and the Old Duke pub and would be passed by heavy traffic every day.
The application states: "It is considered that this proposal is the optimum solution in terms of providing 5G provision from a single site for two operators, minimising any adverse impacts on local amenity. The height of the proposed mast (at 20 metres to the top) is the absolute operational minimum to clear the immediate environment and provide coverage."


Since 1984, The Kansas Masonic All-State High School Marching Band has been a continuous and positive presence at the annual Kansas Shrine Bowl. The concept of this band, and its related camp, were designed to fill a void at the summer Shrine Bowl, when most high school bands weren't available.
The band camp is held in the summer each year at the Bowl. Annually, a total of 180 to 225 of Kansas' best high school musicians are showcased, which includes pre-game and halftime performances. The band also performs before the Shrine Bowl Banquet on the Friday night prior to the game, and at a downtown parade the following morning.
For more information on attending the Kansas Masonic All-State High School Marching Band Camp, contact the Kansas Shrine Bowl at 1-800-530-5524 or by email to secretary@kansasshrinebowl.com. All proceeds are used to support the Shriners Hospitals for Children.


Within 3 weeks, the alarm was no longer going off and he was getting up on his own. He wakes up dry every morning and I find him very joyful and more confident.
Wish I had bought this 2 years ago, Totally worth the cost.
This was the best! It worked!! I bought this for my little older son about a month ago. Have been beyond happy with this purchase.
This alarm works as it's supposed to. The mat senses moisture, even small amounts, and gives off a loud alarm with vibration designed to wake the bedwetter. We wanted to avoid medication for our 10-year-old deep sleeper bedwetter and after trying dozens of other tricks it seemed like our only hope. Within 3 weeks, my son was dry every night when he had been soaking through his undies before.
The first week was really hard he would not get up many times and slept wet but there was tremendous improvement in the next weeks. If you have a bedwetting child who does not like wearable alarm then I would highly recommend buy this alarm stick with it, it will work.
The features of this magic tool did the trick after no success from any other type of potty training at night.
My 11 1/2-year-old son has never had a dry night before we started using this alarm he was just as frustrated as we were. After using the alarm for about two months he is waking up dry on his own!
I thought it would take several months for it to work for him since he is a very sound sleeper but it worked in just two weeks. I am so happy for him that he no longer has to deal with the embarrassing bed wetting problem.
This product has literally been a lifesaver.


text:
package lfs_test // avoid import cycle

import (
	"fmt"
	"sort"
	"testing"

	"github.com/git-lfs/git-lfs/lfs"
	"github.com/git-lfs/git-lfs/test"
	"github.com/stretchr/testify/assert"
)

func TestAllCurrentObjectsNone(t *testing.T) {
	repo := test.NewRepo(t)
	repo.Pushd()
	defer func() {
		repo.Popd()
		repo.Cleanup()
	}()

	actual := lfs.AllObjects()
	if len(actual) > 0 {
		for _, file := range actual {
			t.Logf("Found: %v", file)
		}
		t.Error("Should be no objects")
	}
}

func TestAllCurrentObjectsSome(t *testing.T) {
	repo := test.NewRepo(t)
	repo.Pushd()
	defer func() {
		repo.Popd()
		repo.Cleanup()
	}()

	// We're not testing commits here, just storage, so just create a single
	// commit input with lots of files to generate many oids
	numFiles := 20
	files := make([]*test.FileInput, 0, numFiles)
	for i := 0; i < numFiles; i++ {
		// Must be >=16 bytes for each file to be unique
		files = append(files, &test.FileInput{Filename: fmt.Sprintf("file%d.txt", i), Size: 30})
	}

	inputs := []*test.CommitInput{
		{Files: files},
	}

	outputs := repo.AddCommits(inputs)

	expected := make([]*lfs.Pointer, 0, numFiles)
	for _, f := range outputs[0].Files {
		expected = append(expected, f)
	}

	actualObjects := lfs.AllObjects()
	actual := make([]*lfs.Pointer, len(actualObjects))
	for idx, f := range actualObjects {
		actual[idx] = lfs.NewPointer(f.Oid, f.Size, nil)
	}

	// sort to ensure comparison is equal
	sort.Sort(test.PointersByOid(expected))
	sort.Sort(test.PointersByOid(actual))
	assert.Equal(t, expected, actual, "Oids from disk should be the same as in commits")

}

redpajama_set_name: RedPajamaGithub


Los Angeles, California, 7 July 2016. / PRWeb / -- Jason Turner, CEO and President of Venbrook Insurance Services, a national-leader in insurance solutions and risk management, announced that William Clark has been added as a Warehouse and Logistics Consultant for Venbrook Insurance Services.
Bill has over 50 years' experience in property and casualty insurance and over 35 years of insuring public warehouses. He was president and owner of The Clark Group, a large property and casualty insurance agency in New Jersey. In 1992, he formed the Warehouse Insurance Management Company (WIMCO) and subsequently designed the first total insurance package for the warehousing industry. This program was initially underwritten by Fireman's Fund/Famex and endorsed by the American Warehouse Association. In 2002, he was hired by Marsh Advantage America to join their Custom Program Division and in 2006 he joined Pridemark-Everest Insurance Services, part of the nationwide Leavitt Group.
Bill has written and co-authored many articles regarding warehouse legal liability, bailment liability, and motor truck cargo legal liability for various trade magazines and journals. He is the author of the most comprehensive Warehouse Legal Liability Policy, Lessons from Losses - A History of 3PL Losses. He has also spoken before many warehouse trade groups and conventions including the International Warehouse Logistics Association, Southeastern Warehouse Association, Wisconsin Warehouse Association, Texas Warehouse Association, and the Warehouse Educational Research Council.
Bill received his Charter Property and Casualty Underwriters (CPCU) designation in 1971. He has taught various insurance courses including the Chartered Property and Casualty Underwriters degree course at Seton Hall University. He was board member of the New Jersey Professional Insurance Agents Association where he chaired the legislative committee and the industry liaison committee. He was chairman of the New York, New Jersey, and Connecticut Risk Retention advisory committee, a member of the New Jersey Governors Automobile Insurance Reform Task Force, and a certified teacher for the New Jersey insurance licensing course. He currently is a member of the Southeastern Warehouse Association as the first associate member to be elected to their Board of Directors, and an Associate Member of the International Warehouse Logistics Association.
"Lessons from Losses: A History of Warehouse Legal Liability Claims and Other Losses Experienced by Third Party Logistic Providers," published August 25, 2015 on Amazon and Barnes & Noble.


text:
package com.hubspot.jinjava.lib.filter;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import com.hubspot.jinjava.doc.annotations.JinjavaDoc;
import com.hubspot.jinjava.doc.annotations.JinjavaParam;
import com.hubspot.jinjava.doc.annotations.JinjavaSnippet;
import com.hubspot.jinjava.interpret.JinjavaInterpreter;

@JinjavaDoc(
    value = "Converts URLs in plain text into clickable links.",
    params = {
        @JinjavaParam(value = "value", desc = "string URL to convert to an anchor"),
        @JinjavaParam(value = "trim_url_limit", type = "number", desc = "Sets a character limit"),
        @JinjavaParam(value = "nofollow", type = "boolean", defaultValue = "False", desc = "Adds nofollow to generated link tag"),
        @JinjavaParam(value = "target", desc = "Adds target attr to generated link tag")
    },
    snippets = {
        @JinjavaSnippet(
            desc = "links are shortened to 40 chars and defined with rel=\"nofollow\"",
            code = "{{ \"http://www.hubspot.com\"|urlize(40) }}"),
        @JinjavaSnippet(
            desc = "If target is specified, the target attribute will be added to the  tag",
            code = "{{ \"http://www.hubspot.com\"|urlize(10, true, target='_blank') }}"),
    })
public class UrlizeFilter implements Filter {

  @Override
  public String getName() {
    return "urlize";
  }

  @Override
  public Object filter(Object var, JinjavaInterpreter interpreter, String... args) {
    Matcher m = URL_RE.matcher(Objects.toString(var, ""));
    StringBuffer result = new StringBuffer();

    int trimUrlLimit = Integer.MAX_VALUE;
    if (args.length > 0) {
      trimUrlLimit = NumberUtils.toInt(args[0], Integer.MAX_VALUE);
    }

    String fmt = " 1) {
      nofollow = BooleanUtils.toBoolean(args[1]);
    }

    String target = "";
    if (args.length > 2) {
      target = args[2];
    }

    if (nofollow) {
      fmt += " rel=\"nofollow\"";
    }

    if (StringUtils.isNotBlank(target)) {
      fmt += " target=\"" + target + "\"";
    }

    fmt += ">%s";

    while (m.find()) {
      String url = m.group();
      String urlShort = StringUtils.abbreviate(url, trimUrlLimit);

      m.appendReplacement(result, String.format(fmt, url, urlShort));
    }

    m.appendTail(result);
    return result.toString();
  }

  private static final Pattern URL_RE = Pattern.compile(
      "(https?)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]",
      Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

}


text:
Daniel J. Song
Daniel J. Song is a Canadian lawyer practising in Vancouver, British Columbia, Canada...
To get in touch with Daniel J. Song our records indicate that you can do so via their most recent address of SUITE 1720, 355 BURRARD STREET, Vancouver, British Columbia, Canada, V6C2G8 or by phone: 604-669-7447. For a map to this location, scroll down and we've provided a map showing the approximate location of Daniel J. Song.
Have Additional Information on Daniel J. Song?
This listing can be enhanced to add additional details about Daniel J. Song including a description of services rendered, categories of services provided, contact email, and links to websites. You can also upload images (such as business cards and promotional materials) and link to Twitter, FaceBook, and LinkedIn profiles for Daniel J. Song. It's extremely easy to add these features and increase your exposure to new clients. Simply upgrade this listing to get started.
Canadian Lawyers Near Daniel J. Song
By scanning Canada Lawyer List's database of more than 20,000 Canadian lawyers, we've compiled a listing of additional Canadian lawyers and Canadian law firms that are related to Daniel J. Song via operating their business in the same location (most likely the same office building) in Vancouver, British Columbia, Canada. While each of these lawyers or law firms may have zero affiliation with Daniel J. Song we've compiled this list as an estimate of the potential size of the resources around Daniel J. Song. This list is meant only to give you a feel for the resources in this business location:
Mandanici, Sandra
Mines, Michael
Song, Daniel J
SUITE 1720, 355 BURRARD STREET
V6C2G8
Lawyers in Vancouver
Brampton, Nick | Schroeder, Speier | Bardos, M A | Fretwell, Gordon J Law Corp | Frost, David | Deering, Robert A | Jevning, Douglas J | Penny, Lehan Law Corp | Thorsteinssons, Llp | Thomas, David B.
Lawyers in British Columbia
Morley, Jane B | Carfra, James S | Patola, Todd | Heng, Pheng C | Leung, John | Mott, Preston S | Mclachlan, William A | Mackinnon, Ian D | Butterfield, John S | Anderson, Troy D
SUITE 1720, 355 BURRARD STREET, Vancouver, British Columbia, Canada, V6C2G8


text:
Biotehnološko oružje razvija se zahvaljujući povezivanju prirodnih i inženjerskih znanosti.

Razvoj biotehnološkog oružja

Prvi svjetski rat specifičan je zbog uporabe oko 120 000 tona (NATO izvor) "neposredno" izumljenih i sintetiziranih bojnih otrova i kemijskog oružja, dok je II. svjetski rat zaobišla ta nekonvencionalna ugroza, ali zato je bio "okrunjen" nuklearnim eksplozijama, proizvodom željno očekivanog izuma - nuklearne energije, koja se tada iskoristila protiv čovjeka. Zaljevske ratove obilježio je golemi porast prisutnosti štetnih tvari i pojava kemijskog, radiološkog i biološkog podrijetla.
Osim toga, devedesetih godina prošloga stoljeća svjedoci smo revolucije informacijsko-komunikacijske tehnologije. Nagli napredak informacijsko-komunikacijske tehnologije i njezina primjena u suvremenom ratovanju imali su pozitivan učinak - manji broj žrtava, kako vojnika tako i civila, a taj trend smanjivanja broja nedužnih žrtava će biti u porastu u narednim vojnim operacijama. Koliko se toga samo u posljednjih pedesetak godina promijenilo u načinu ratovanja zbog naglog razvoja raznih tehnologija.
Iako postoji uzrečica "povijest se ponavlja", svaki je događaj sam po sebi jedinstven, pa je teško predvidjeti što bi moglo karakterizirati buduće sukobe i ratove.
S obzirom na trend, očito se može pretpostaviti veća uporaba i širenje sredstava za masovno uništavanje, nekonvencionalnih ugroza, ali i ugroza koje prijete na molekularnoj razini.
Biotehnologija je znanost koja se strahovito razvila u posljednjih desetak godina i ima golemi utjecaj na ostale znanosti i tehnologije, ali i na globalnu ekonomiju i industriju. Nije to više tehnologija koja služi samo za dobivanje piva ili penicilinskih lijekova, već mnogo više od toga. Za vojne potrebe, dostignuća te znanstvene discipline najviše se rabe za potrebe medicinske zaštite. No, sudeći po razvoju metoda i pronalascima, to će u bližoj budućnosti biti samo jedan dio u kojem će ta tehnologija biti prisutna.

Veliku ulogu u istraživanjima i širenjima spoznaja od zemlje prema moru, zraku i svemiru imaju elektronika i informatika.
Identično tome, kao što te grane i djelatnosti imaju golemu ulogu u istraživanju (makro)prostora i u gospodarenju njime, tako i suvremena biotehnologija vlada jednim drugim prostorom - mikrokosmosom životnih struktura. Metode biotehnologije omogućuju izravan pristup u mikrokozmos samog bića - u organizam, pojedine organe, strukture, tkiva i metaboličke puteve. I manipulaciju njime. Ako se te spoznaje uporabe na onome koji ratuje, može se smanjiti njegova učinkovitost, a dobiva se i precizna kontrola njegove učinkovitosti. I sve to samo djelovanjem na molekularnoj razini.

Pruski strateg Carl von Clausewitz rekao je jednom prilikom: "Rat. .. to je čin nasilja u kojem prisiljavamo našeg protivnika da ispuni naša htijenja". Njegov sljedbenik Wu Qiong nadodao je: "Koncepcijski gledano, oduzeti neprijatelju snagu kojom pruža otpor, realni je cilj ratovanja".
Ovo je era genetičkog inženjerstva i biotehnologije. To potvrđuje i činjenica da od 90-ih godina na ovamo, više od polovice značajnih događaja ("Breakthroughs of Year") u području znanosti i tehnologije otpada na biotehnologiju i biomedicinu (po izvoru Science magazina). Ti pronalasci su velika vrijednost za svakodnevni život, ali i za vojne svrhe. Najznačajniji projekt iz tih područja je Human Genome Project (HGP).
Human Genome Project (HGP) izveden je pomoću tehnika i metoda genetičkog inženjerstva i biotehnologije, a dobivene spoznaje o strukturi DNA i funkcioniranju prijenosa informacija na molekularnoj razini još više su potaknule razvoj biotehnologije. Tim projektom definiran je mikrokosmos živoga, ušlo se u područja više-manje svih razina u organizmu i stekla cjelokupna slika funkcioniranja živog svijeta. Otkrića genetičkih struktura, proučavanja odnosa: struktura - funkcija i odnosa: struktura - zdravlje, šire mogućnosti primjene biotehnologije na molekularnoj razini.

U načelu, kada se spozna struktura i funkcija nekog živog sustava, tehnikama biotehnologije može se utjecati i na strukturu i na funkciju živoga sustava. To svakako stvara dobru podlogu za vojnu uporabu.
Bioinformatika prikuplja sva saznanja o genima i proteinima. Onaj tko bude imao više bioinformacija, imat će i premoć u razvoju i primjeni biotehnologije.
Mnoga otkrića molekularne biologije zanimljiva su i za vojne svrhe, kao npr.: rekombinacija DNK, modifikacija gena, kloniranje gena, ekspresija gena, markiranje gena, tehnologija matičnih stanica, manipulacija s kulturom tkiva, itd.
Za dobivanje "kompletne slike" o funkcioniranju genoma, potreban je širi pristup od pristupa genetike. U te svrhe razvila se genomika - aktivnost koja proučava fukcioniranje svih gena (genoma) u cjelini i pronalazi veze između gena i "cjelokupnog zdravlja i bolesti".
Genomička istraživanja omogućuju praćenje biokemije bolesti ljudske populacije, odnosno fizioloških poremećaja pomoću odnosa bolest - "sumnjivi" gen.
Da bi istraživanja na molekularnoj razini bila sveobuhvatna, rade se i proteomička istraživanja. Proteomika, kao važna znanstvena disciplina za dobivanje bioinformacija, izučava vezu između strukture i funkcije proteina. Iz perspektive vojne medicine, ona je most između vojnog cilja i praktične tehnologije. S razvojem proteomike, znanstvenici mogu otkrivati i objašnjavati "proteinski ključ", funkciju i ulogu proteina u pojedinoj fiziološkoj funkciji u organizmu, ali i vešestruke fiziološke funkcije proteina pojedinačno. Svi ti biopodaci mogu osigurati vrlo precizne modele za vojni napad ili obranu i pomoći razvoju zaštite i oružja na molekularnoj razini. Utrka u stvaranju oružja i zaštite je slučaj kao i s utrkom u stvaranju računalnih virusa i antivirusnih programa.
Tehnikama genetičkog inženjerstva moguće je postići još jedan zanimljiv postupak u biotehnologiji, a to je transgeneza.
Transgeneza je postupak ugradnje gena (odnosno rekombinantne DNA) u genom nekog organizma koji taj gen ili gene prirodno ne posjeduje, a u svrhu dobivanja određenih svojstava ili čak proizvoda. Danas se transgeneza može uspješno provesti na ribama, ovcama, kozama, govedima i za potrebe istraživanja na mišjem modelu. Takva (vrlo uspješno) kontrolirana genska manipulacija te kontrola genske ekspresije zanimljiva je svakako i za vojne svrhe.

Humana i "agresivna" biotehnologija

Moderna biotehnologija ima važnu ulogu u tretmanu ratnih ozljeda i ostalih posljedica, prevenciji i dijagnozi raznih bolesti i zaštiti od kemijskih i bioloških agensa te toksina. Metodama koje se rabe u genomici i proteomici može se u humane svrhe modificirati ljudsko tkivo.
S druge strane, primjene biotehnoloških tehnika i proizvoda na ljudski organizam mogu biti i štetne, na način da se promijene (poremete) njegove biološke funkcije.
Razjašnjavanje veze između strukture i funkcije, kako određenih spojeva tako i ciklusa u ljudskom organizmu, pomoglo je da se pronađu i mnogi fiziološki aktivni spojevi, tj. molekule aktivne u "živom mediju".
Već sada postoje uvjeti za dizajniranje, kontrolu i rekonstrukciju molekula ili biokemijskih spojeva, koje mogu biti jako slične ili potpuno iste (ovisno o potrebi i željenom učinku) kao molekule i spojevi koji postoje u organizmu, a nazivaju se bioregulatori i imaju svoju konkretnu funkciju u organizmu.
Tako dizajnirane makromolekule su ustvari simulanti, mogu unosom u organizam u vrlo malim dozama poremetiti biokemijsku ravnotežu u stanici i stvoriti narušeno fiziološko stanje, primjerice poremetiti krvni tlak, rad srca, kontrakcije mišića, itd.
Možemo reći da je cilj "agresivne" biotehnologije u prvom redu poremetiti ravnotežu u nekom biosustavu.
Pojednostavljeno rečeno: rat je jednostavan ljudski čin kojim se želi slomiti snaga neprijatelja, biotehnološko oružje uporabljeno u ratovanju imalo bi za posljedicu samo slamanje neprijateljske snage, ali nekontrolirana uporaba mogla bi imati dugosežne posljedice (namjerno željenu ili čak neželjenu i nepredviđenu) na ljudsku populaciju.

Biotehnološko oružje s obzirom na cilj

Taktički gledano, vrsta i snaga biotehnološkog oružja može se izabrati s obzirom na željeni cilj, tako da mete mogu biti: geni, proteini, stanice, tkiva ili organi.
Višestruka oštećenja organizma nastaju od posebno dizajniranog biotehnološkog oružja.
Za izradu takvog oružja potrebni su geni koji mogu sintetizirati proteine štetne na bilo koji način za organizam.
Načelno je postupak sljedeći: kada se dva ili više gena ili neka DNK regija izolira, potrebno ih je ugraditi u vektor. Vektor služi za prijenos takvih gena do stanice ljudskog organizma, nakon čega dolazi do njihove ekspresije i sinteze proteina koji uzrokuju poremećaje i oštećenja. Za vektor se obično uzimaju kratke neovisne dvolančane DNA, tzv. plazmidi. Plazmidi se prirodno nalaze u stanicama bakterija i neovisni su o bakterijskoj DNA.
Ugradnjom segmenta DNA s izoliranim genima dobiva se konstrukt koji svojim djelovanjem može prouzročiti višestruka oštećenja na razne načine. Ekspresijom tih gena mogu se dobivati razni toksini, bioregulatori i razne druge makromolekule slične ili iste kao i neki stanični ili signalni proteini koji svojim prisustvom mogu poremetiti biokemijsku ravnotežu prvo u stanici, a zatim i u cijelom organizmu. Simptomi mogu biti zakašnjeli, pa kada se već bolest razvije, terapija može biti neučinkovita.
Osim navedenih plazmida, zanimljivi za prijenos genetskog (DNA) materijala (kao vektori) su i virusi. Virusi, posebice retro - i adenovirusi, iako organizmi na granici živog i neživog, i bez metabolizma, poznati su po prijenosu i zamjenjivanju, "transfekciji" gena, kako međusobno tako i s drugim organizmima.
Osim manipulacije genima, promjene na molekularnoj razini mogu se izvesti i mutacijama DNA izazvanim izravno induciranom energijom.
U ovom slučaju ne radi se o oružju u obliku agensa, koji mora napasti organizam da bi prouzročio štetu, već o ultravioletnim zrakama vrlo visokog inteziteta. U načelu, UV zrake uzrokuju pucanje jednog ili oba lanca DNA. Popravci jednog lanca DNA jako su česti (oko 20 000 puta dnevno), a nastaju zbog izlaganja sunčevom UV zračenju, i na sreću su jednostavni i ostvarivi uz pomoć enzima, ali jedna precizna UV zraka visokog inteziteta na "strateški" važno mjesto na DNA može dovesti do trajnih oštećenja na određenom lokusu (mjestu DNA) ili genu, i to lomom oba lanca. Takvo oštećenje u stanici ne može se popraviti i dovodi do promjene ili gubitka funkcije.

Humani primjer izravne ugradnje DNA vezan je za gensku terapiju. Znanstvenici fakulteta u Wisconsinu uspjeli su za potrebe genske terapije "ogoliti" DNA, odnosno izolirati dio te molekule koja im je potrebna za terapiju i injektirati u krvnu žilu. Taj genetski materijal krvnom žilom lako je dostupan mišićnim stanicama.
Spoznaje proizašle iz ovih istraživanja provedive su i za dostavu određenih spojeva ili same DNA u organizam u svrhe poremećaja biokemijske ravnoteže. Za prijenos takvog biokemijskog oružja potrebno je konstruirati "mikrometak" (makromolekulu) na čijoj površini će biti "ogoljena" DNA ili pak plazmidnu DNA s patogenim genima. "Mikrometak" se može dostaviti u organizam na razne načine, primjerice inhalacijom.
Tako dostavljena DNA s patogenim genima izravno u organizam integrira se u stanici i uzrokuje bolest ili točno ciljano oštećenje na DNA.

Superiornost biotehnološkog oružja

Humanost u vođenju ratovanja je u posljednje vrijeme stavljena u središte pažnje. Bespotrebne žrtve se nastoje svesti na minimum, a protiv neprijatelja se izabiru sredstva i oružja koja će slomiti samo njegov otpor i odvratiti ga od namjera. Oružja za masovno uništenje, pošto nemaju ograničeno djelovanje, štoviše, u većini slučajeva mogu imati i nepredviđeno, zbog navedenoga se sve više pokušavaju staviti pod kontrolu nadzorima i konvencijama (zabranama).
Vremena zahtijevaju nova oružja, a moderna biotehnologija može pridonijeti izradi jednog takvog oružja kao "humanog", s ograničenim i vrlo preciznim djelovanjem uz lako praćenje karakteristika ozljeđivanja.
Još je nepoznato kako danas orijentirati modernu biotehnologiju za izradu istoimenih oružja, za precizno napadanje mete u organizmu i stvaranje "ultramikro", neletalnih i reverzibilnih oštećenja, ali takva oružja konačno mogu zamijeniti metode "fizičkog uništenja", sa svojom sposobnosti "uništavanja unutar granica smrtnosti", koje je bila karakteristika ratovanja prije izuma baruta.
Kada bi se uzele u obzir sadašnje mogućnosti biotehnologije u civilne svrhe te iskoristile za izradu biotehnološkog oružja, izdvaja se nekoliko njegovih specifičnosti.

Specifičnost ranjavanja

Specifičnost ranjavanja je u tome što se od tako modeliranog oružja dobivaju precizni pogodci u organizmu, tj. preciznost ozljeđivanja organizma je maksimalna, a ozljeđivanje je time minimalno, odnosno dostatno za odvraćanje ili lomljenje neprijateljeve sile. Tom ostvarenju specifičnosti najviše pridonose bioinformacije dobivene u Projektu izrade ljudskog genoma (Human Genome Project, HGP) i od istraživanja iz proteomike. Ako postoje bioinformacije o ciljanom genomu ili proteomu određene populacije, uključujući svakako etničke skupine ili pojedince, može se dizajnirati takav "reverzibilni ranjavajući" agens koji napada samo neprijatelja, dok je ostali dio populacije koji ne ulazi u kategoriju neprijatelja pošteđen tog oružja. Sve se praktično svodi na raznolikost svojstava unutar ljudske vrste. Učestalost svojstava slična je u istih populacija i različita između različitih populacija. Primjerice, domaća (urođenička) populacija američkog kontinenta središnje i južne Amerike ima karakteristične krvne grupe jer im u sustavu ABO krvnih grupa nedostaju geni za A i B. Drugi primjer je vezan za stanovništvo zapadne Afrike. Naime, ta populacija ima neobično visoku učestalost srpaste anemije koja je također genetski prouzročena.
Takvih primjera ima mnogo, jer svaka populacija na razini nacije ili rase ima neka svoja specifična svojstva koja niti jedna druga populacija nema, a informacija je zapisana u genima. Proučavanjem genetske šifre s aspekta populacijske genomike moguće je doći do konkretnih spoznaja o različitostima među populacijama i sličnostima među jedinkama iste populacije izrađujući kartu svih gena ("gene pool") neke populacije. Ti podaci mogu biti neobično korisni zbog uporabe precizno modeliranog onesposobljavajućeg biotehnološkog oružja s ograničenim i "humanim" djelovanjem, a mogu biti i štetni ako se iskoriste, primjerice, u terorističke svrhe. Oštećenja (ozljede) mogu biti ograničene na specifičnu gensku sekvencu ili na specifičnu proteinsku strukturu. Ali, postoji mogućnost usmjeriti napad i na točno određenu molekularnu razinu u organizmu.
Manipuliranjem genima, može se napasti ili ozlijediti jedna ili više ključnih fizioloških ljudskih funkcija (sposobnost učenja, pamćenja, održavanja ravnoteže ili izvođenje jedne ili više motoričkih aktivnosti), i to bez opasnosti za život (reverzibilno).

Ultramikro oštećenja

Prilikom odabira načina napada biotehnološkim oružjem postoje dva izbora: nukleotidne sekvence (DNA) ili proteinske strukture. To znači da se može uzrokovati fiziološki poremećaj u organizmu izazivanjem ultramikro oštećenja na genskoj ili proteinskoj strukturi. Precizno ultramikro oštećenje na mete kao što su geni i proteini jedna je od specifičnosti biotehnološkog oružja, dok sva ostala oružja izravno oštećuju mišiće i organe.

Tajnovitost (skrovitost)

Detekcija i predviđanje konkretnih učinaka ovog oružja za neprijatelja je gotovo nemoguća. Tek nakon očite onesposobljenosti svojih snaga, neprijatelj će shvatiti da je napadnut.
U tom smislu, biotehnološko oružje je oružje izrazito taktičke prirode.

Sposobnost kontrole i sposobnost obnavljanja

Stupanj oštećenja koje biotehnološko oružje proizvodi u danom trenutku može se u laboratoriju precizno odrediti. Može se čak osigurati antidot ili terapija. Pružanje takvih bioinformacija neprijatelju bila bi prava "milost" prema njemu.

Teškoće u poduzimanju mjera zaštite za neprijatelja

Zbog velikog broja živih (mikro)organizama kojima se može koristiti vojna biotehnologija u konstrukciji biotehnološkog oružja i zbog toga što tako mnogo mjesta na ljudskom genomu i proteomu mogu biti napadnuti i oštećeni na tako mnogo načina, konačna dijagnoza i brzo liječenje je otežano. Raspored gena ili proteinske strukture je poput specifičnog ključa. Samo konstruktor takvog oružja ima ključ, a neprijatelj nema baš mogućnosti pronaći "profil" tog ključa.

Usporedba biotehnološkog s biološkim oružjem

Kada bi suvremena biotehnologija bila primijenjena u vojnom području - za proizvodnju oružja kao izlaznog proizvoda, to oružje bilo bi fundamentalno različito od tradicionalnog biološkog (bakteriološkog) oružja.
"Tradicionalno" biološko oružje usmjereno je na masovno uništenje. Ono ovisi o mikrobiologiji koja se koristi destruktivnim bakterijama, virusima i toksinima dobivenim izravno iz prirode ili metodama genetičkog inženjerstva. Može prouzročiti velike ljudske gubitke, a posebice može utjecati na borbeni moral. Zbog svojih karakteristika, to oružje je teško predvidljivo, teško ga je obuzdati i suprotstaviti mu se. Osim što pogubno djeluje na čovjeka, biološko oružje djeluje i na stoku, usjeve i devastira ekološki sustav. Biološko oružje osmišljeno je na ideji da što više ubija i izaziva veću katastrofu, to bolje. Ono je subjekt prirode, teško ga je kontrolirati i ima ireverzibilan učinak.
Biotehnološko oružje označavale bi sasvim drukčije karakteristike. Ono je strogo selektivno, precizno, za metu uzima molekularne razine u organizmu, ne mora biti smrtonosno i ima reverzibilan učinak. Taktički gledano, kao što je informacijsko-komunikacijska tehnologija spomenuta na početku ove priče u pozitivnom kotekstu, koja je bila uporabljena u suvremenim sukobima i ratovima te smanjila broj žrtava, tako i biotehnološko oružje može smanjiti broj nepotrebnih žrtava. Jedini cilj tog oružja bi bio da se slomi snaga neprijatelja i da se (samo) on privremeno ili trajno onesposobi za daljnja djelovanja. Takve karakteristike ga svrstavaju u kategoriju "humanih oružja"
Osim toga, razvojem vojne biotehnologije pridonosit će se detekciji raznih bioloških agenasa, od prirodnih do genetski modificiranih.

Vojna biotehnologija još nije postala instrument vojne snage. Zakoni, pravila i osnovne karakteristike vojne biotehnologije i oružja još nisu sasvim poznati.
Za potpunu kontrolu pri uporabi, potreban je veći napredak u području genomike i proteomike zbog važnih bioinformacija, ali i napredak u tehnikama biotehnologije. Unatoč tome, brzi razvoj moderne biotehnologije govori u prilog tome da dan kada će ona imati punu vojnu primjenu nije tako daleko.  Uz sve navedene karakteristike "humanog oružja", biotehnološko oružje može se itekako zloporabiti. U te svrhe trebaju se stvoriti jasna pravila igre i zakoni koji će kontrolirati takvo oružje. Razvoj biotehnologije i molekularne biologije ne može se zaustaviti, ali se njihova primjena može pravnim sredstvima staviti u okvire etičnog, moralnog i čovjeku korisnog.
U svakom slučaju, u bliskoj budućnosti, kada se vojna biotehnologija razvije, imat će revolucionarni učinak na organiziranje vojnih snaga i vojnu taktiku u cjelini.

Oružje za masovno uništenje

redpajama_set_name: RedPajamaWikipedia


text:
Cabel peut se référer à :

Patronyme
 Marie Cabel (1827-1885), soprano d'opéra belge ;
  (1832-1888), ténor d'opéra français et frère de Marie ;
  (1959-), homme politique israélien et député à la Knesset ;
 Stéphane Cabel, scénariste français

Autres
 Cabel, surnom de Arent Arentsz, peintre néerlandais.

Voir aussi

Homonymie de patronyme


Johannesburg, August 10, 2016 – Net 1 UEPS Technologies, Inc. ("Net1" or the "Company") (NasdaqGS: UEPS; JSE: NT1) today announced that the Competition Commission of South Africa (the "Commission") has declined to refer a complaint lodged against the Company and Grindrod Bank Limited ("Grindrod Bank") by the Hon. Elza van Lingen, a Member of Parliament, to the Competition Tribunal (the "Tribunal") for consideration.
The complaint alleged that Cash Paymaster Services Proprietary Limited ("CPS"), a subsidiary of the Company, provided other associates of the Company as well as Grindrod Bank with access to the database of social grant beneficiaries that CPS maintains as part of CPS's contract with the South African Social Security Agency. The complaint further alleged that access to this database had the effect of placing Grindrod Bank and Net1 at an advantage over other banks for the provision of insurance policies, loans and prepaid airtime and electricity.
Following an investigation of the complaint, the Commission decided not to refer the matter to the Tribunal for consideration and advised the Hon. Van Lingen that she had the option of referring the matter directly to the Tribunal if she disagreed with the Commission's decision. The Hon. Van Lingen has not referred the matter within the prescribed time and the matter has accordingly been closed.


text:
Mr Suresh Chandrashekar
MBBS, MS Orth., FRCS Ed.
3 specialists
3 years as a specialist
Laura Coultry
"Very competent, knowledgeble consultant. He made me feel at ease."
31 Old Broad Street By Tower 42, London, United Kingdom, EC2N 1HT
London Bridge Hospital
27 Tooley Street, London, United Kingdom, SE1 2PR
Mr Suresh Chandrashekar is a Consultant Foot and Ankle Orthopaedic Surgeon in the UK. He is also the current clinical director of the Trauma and Orthopaedic Department at th Homerton University Hospitals NHS Foundation Trust in London.
Mr Chandrashekar graduated 2001 from the University of Mumbai, India. Following this, he undertook residency training in Surgery in general and Trauma & Orthopaedics, from the St. Petersburg State Medical Academy, Russia during 2001-2004
Mr Chandrashekar, furthered his U.K training in trauma and orthopaedics. This has taken him through specialty rotation across various subspecialty firms in NHS trusts in Manchester, Harlow (Essex) and Royal London Hospital. He successfully passed the Royal College of Surgeons exams securing the Fellowship Diploma for FRCS (Orth) and went on to undertake sub-speciality fellowship training in Foot and Ankle Orthopaedic surgery at The University Hospitals of Southampton Foundation Trust.
He has also been on additional visiting fellowship training in Germany for Orthopedic trauma and Joint replacement in Freiburg and specialist Foot and Ankle visitation to Klinik Rummelsberg, near Nuremberg with the European Foot Society president, Prof. Dr. med. Martinus Richter. His Foot society connected visitation helped him gain experience and skills in managing complex foot and ankle injuries and Cartilage disorders in young and old.
Mr Chandrashekar practices minimally invasive surgery, when indicated and supports enhanced patient recovery and early rehabilitation. He is committed to research projects for foot surgery and has peer-reviewed publications, successfully presenting at international and national medical conferences. Besides speaking English as his first language, he is fluent in Hindi, Tamil and caters to Russian speaking clients as well.
Mr Chandrashekar is passionate about teaching and actively trains medical students and orthopaedic trainees within the NHS as well as acting as an examiner/faculty for The Royal College of Surgeons in England F.R.C.S. Orth. Revision courses. He has extensive experience in Foot and Ankle surgery with a specialist interest in sports injuries and cartilage injuries of ankle joint in young and sporty population.
It is important that HCA is transparent about our relationship with those doctors who provide us with clinical guidance on delivering the best possible care to patients and operating our hospitals safely and efficiently. We set out here some of the ways in which we work together and the amount we pay this doctor for such services.
Ankle Replacement Surgery
Ankle Surgery and Ankle Arthroscopy
Cartilage Operation
Extracorporeal Shock Wave Therapy ESWT
Foot surgery for toe problems
Ganglion Removal Treatment
Lower Limb Reconstruction
Osteotomy Surgery
Rheumatoid foot reconstruction for Rheumatoid arthritis
Open reduction internal fixation - ORIF
Minimally Invasive Foot & Ankle Surgery
Sports injuries (ankle sprains and instability)
Cartilage damage and keyhole surgeries of ankle joints
Achilles tendon management
Toenail surgery
Limb fractures
Ankle fractures (fractures and dislocations/contact sport-related trauma)
Foot fractures including fractures of os-calcis, metatarsal fractures and toe injuries
Ankle replacement and fusion surgeries
MB BS 2001 University of Mumbai
Trauma and orthopaedic surgery From 02 Feb 2017
Further Qualifications
M.S Orthopaedics and traumatology The State Paediatric Medical Academy, St Petersburg, Russia. 2004
Fellow of Royal College of Surgeons of Edinburgh Royal College of Surgeons of Edinburgh 2012
Royal College of Surgeons of Edinburgh
British Orthopaedic Foot and Ankle Society
European Foot and Ankle Society
Alliance Medical Indemnity Scheme
Advanced Trauma Life Support
Read reviews Read all 2 reviews
Read reviews Read all 1 review
Patient seen for:
Foot & Ankle Surgery Arthroscopy
I had been suffering with my ankle for months, getting nowhere. I went to see Mr Chandrashekar with no expectations and was blown away by his knowledge and how he took the time to go through everything with me. From diagnosis, realistic expectations and the surgery I would need. As a patient it's so important to have things explained in a manner that is easy to understand. As my job is very active I was really nervous about what the surgery would mean and how it would affect my life but I felt confident in his abilities and feel like I am getting the best advice and treatment I could ask for.
Dr. Chandrashekar has been brilliant for the entire duration of my diagnosis, treatment and recovery. It was an unusual issue in a very specific area and unlike other consultants who had trouble identifying the problem, he was able to pinpoint it every time we met. We explored every non-invasive option before electing for surgery and six months on, I am completely healed and able to run on it again. I'm delighted with the outcome of an issue that had plagued me for many years and am confident that the action we took will prevent it from re-occurring. In addition to his professional capability, Dr Chandrashekar is very personable individual, an intent listener and clearly enjoys his work. If I have any future injuries of this nature, Dr Chandrashekar will be the first person I call.
Thank you for your generous words and feedback.
Mr Chandrashekar has provided truly excellent care. Not only am I extremely pleased with the results of my revision surgery, I have been very impressed by how attentive, warm and approachable he has been throughout. I have always felt listened to and able to ask questions. I would thoroughly recommend him as a specialist.
I waa advised by my GP to see Dr Chandrashekar as my foot didn't appear to be getting any better after being fouled from football. The MRI scan showed I had torn my ATF ligament. We discussed the treatment options which were surgery or rest and physio. We agreed on resting,physio, and re-stengthening the foot as surgery wasn't guaranteed to work. 6 months later, after less than 10physio treatments, and lots of gym work, I am back to playing football with confidence. All thanks to the help and advice provided by Dr Chandrashekar
After not getting the answers I needed from my GP I was put in touch with Dr Suresh for an persistent ankle injury I'd had for a number of months. He immediately knew something wasn't right and his suspicions were confirmed in the scan. He was diligent, the operation went fantastically and just 3 months later I've been running, playing football and hitting the gym. Dr. Suresh I can't thank you enough for your help and support. You've been bloody fantastic! Cheers to us hopefully never meeting again unless it's to discuss our watch collections!
Thanks for such a wonderful feedback. Very pleased to see that we were able to achieve the goals for you and get you on your way. All the best.
Really great experience with Mr Suresh. He was thorough and discussed all options with me . He was patient. I felt like he was empathetic to my situation as a self paying patient. After my operation he followed up a few times which was really welcome and helpful. He continued to devote time and energy long after the operation.
Thanks for an honest and sincere feedback.
I never write reviews but feel compelled to write this one, as Mr Chandrashekar has been an incredible sounding board of advice with regards to my ankle injury. He gave knowledgeable & in-depth information at every point, which made me always feel at ease with the situation & heading in the right direction. I'm now on the road to full recovery and it couldn't have been done without him.
Hiya, Many thanks for taking the time to provide a feedback. I am glad that we were able to find a solution for your injury that you were comfortable with.
I suffered an ankle Injury in June 2018, I had fractured a bone and torn my ATFL. Dr. Suresh Chandrashekar assisted me throughout the healing and recovery period. Providing detailed explanations when asked and plenty of helpful guidance all the way through. He shared scan results promptly and advised me on physiotherapy too. I also appreciated the personal touch he was able to provide (e.g. remembering and asking about upcoming/past holidays) as it ensured i did not feel like a number on a chart. Overall, i consider myself lucky to have had Dr. Chandrashekar take care of me and would recommend him to anyone suffering with similar injuries.
I fell from one flight of stair and sprained my right ankle few-it was just an ankle and not my head that is injured I thought and I completely ignored it. After few weeks my ankle gave away once again and this time it was in my working hours on the busy pedestrian walk. I was rushed to the hospital and referred to consult Mr Suresh Chandrashekar, the team undertook a MRI which confirmed a tear in my right ligament. Mr Chandrashekar gave a complete run through on what, why, how in the language I understood ( I do not have medical background and was in shock to comprehend information). I had no choice than to have a surgery to mend my ankle, which I wasn't prepared for-so I declined the surgery. Mr Chandrashekar assisted in referring me for physiotherapy as an alternative treatment to strengthen my ankle muscles. After few months of physiotherapy and wearing ankle braces, my ankle was still giving away and it only made me less confident to do activities around my children and also walking down the stairs was daunting to me. I then finally decided to undergo a surgery to fix myself. Mr Chandrashekar, really put my mind at ease in the various consultations I had with him before the surgery. He answered all my questions very professionally and patiently- he also showed me video to help me understand about the surgery. All my concerns and queries about the surgery was dealt with promptness and sincerity. The medical team on the day of the surgery too dealt with me very professionally and I was sent home the same day. My post surgery appointment with Mr Chandrashekar has assured me & put my mind at rest. He has made me feel confident that I can resume my active life in few months. Mr Chandrashekar's friendly approach and his skills and knowledge in his field made me feel positive about the care I was offered. I would definitely recommend my family and friends to Mr Chandrashekar. Good luck
Thank you so much for such a detailed feedback. I am sure that other patients who pass through this page will benefit from your positive experience.
I have found Mr. Suresh Chandrashekar to be an extremely competent, professional and compassionate practitioner, who diagnoses the problem promptly, consults the patient openly and honestly, and acts in a most dignified manner. He is up-to-date with research (historically and specifically). I cannot praise him highly enough, and shall stick with him and whomever he recommends for other related treatments.
Cannot recommend Suresh highly enough. Always made time for me. Checked up on me after the operation, made me feel welcome and valued. A credit to the NHS. Thank you.
I was having a lot of issues with the ankle twisting whilst walking or playing football. Since the operation I feel that the ankle ligament reconstruction has restored the mobility and I have confidence in the ankle to walk better. I hope to be back to playing football without any issues and I can only thank the surgeon for the superb job he has done.
Dr Suresh is an extremely talented doctor who really takes care of the patients. He provided very useful advise for my ankle fracture and helped me pick the best course of action for the tricky injury I had. Thanks a lot Dr Suresh.
Very impressed with the operation performed by the operation by Mr. Chandrashekar on my left foot. I was given Excellent service by Mr. Chandrashekar and his whole team. Can't wait for him to perform similar operation on my right foot soon. Many thanks to Mr. Chandrashekar.
Suresh was great at explaining the rational for my operation and exactly what was going to happen. So far the operation seems to have been a success and I am recovering well.
Excellent advice throughout my patient journey, and extremely happy with the results. I would highly recommend Dr Chandrashekar for anyone considering this procedure.
I was super happy to have Mr Chandrashekar as my surgeon. He was very professional and technical. He was patient, listening and caring. He was willing to help. I really appreciate his kindness and his full medical support with warm heart.
Thank you for your supportive feedback, I am glad that you have had a positive experience.
A really quick and effective diagnosis and treatment. I am pain free as a result after 4 years - wish I had sought help earlier! On s personal note Dr Chandrasekhar has a wonderful manner and treats you with respect giving you information which will help you make treatment choices. I really appreciated that as it meant I chose a less invasive procedure that worked for me. Thanks for a great overall experience.
I really appreciate you taking time to leave a feedback and the warm words. Happy to helped you in making a choice that worked for you.
Dear Mr Chandrashekar, I would like to thank you for your help with my ruptured Achilles in June/July 2016 following the operation I have fully recovered. I found that the lump at the side of the Achilles gives me no problems. I am back in competitive athletics and I am doing well,almost back at my previous form.currently, I am training at the European Masters indoor Athletics championships which are being held in Madrid. It is thanks to you that I am able to do this again.This opportunity has also impacted the training group, they have seen the slow methodical way an athlete can recover. So Thank you a thousand times.
Recommended by 3 doctors for:
Mr Rohit Madhav
Mr Suresh Chandrashekar has great rapport, brilliant diagnostic and technical skills and would not hesitate to see him for opinion and treatment of any foot and ankle conditions.
For specialty: Orthopaedic Surgery
For conditions: Sports Injuries
For procedures: Ankle Joint Fusion, Flatfoot Correction, Bunionette Deformity Correction, Bunion (Hallux Valgus) Correction
Mr Vivek Gulati
Suresh is an outstanding foot and ankle surgeon who has a brilliant bedside manner.
Mr Deepu Sethi
Mr Chandrashekar is an excellent Foot & Ankle surgeon who is up to date with all the latest evidence based techniques in his sub-speciality. He has an excellent bed side manner and delivers patient centred care. Without hesitation I would recommend anyone with a foot or ankle condition to see Mr Chandrashekar.
Contact Mr Suresh Chandrashekar