/***************************************************************************
 *   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>  *
 ***************************************************************************/
#ifndef SKGDEFINE_H
#define SKGDEFINE_H
/** @file
 * This file defines some macros.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include <QString>
#include <QStringBuilder>

#ifdef KDE4_FOUND
#include <KGlobal>
#endif

#include "skgbasemodeler_export.h"
/**
 * @var OBJECTSEPARATOR
 * Define the separator between object and subobject
 */
static const QString OBJECTSEPARATOR = " > ";

/**
 * @var DUMPSQLITE
 * To display SQLLITE internals (tables, views, indexes, ...)
 * @see dump
 */
static const int DUMPSQLITE = (2 << 0);

/**
 * @var DUMPPARAMETERS
 * To display parameters
 * @see dump
 */
static const int DUMPPARAMETERS = (2 << 1);

/**
 * @var DUMPTRANSACTIONS
 * To display transactions
 * @see dump
 */
static const int DUMPTRANSACTIONS = (2 << 2);

/**
 * @var DUMPNODES
 * To display nodes
 * @see dump
 */
static const int DUMPNODES = (2 << 3);

/**
 * @var DUMPALL
 * To display display all=@p DUMPSQLITE +@p DUMPPARAMETERS +@p DUMPTRANSACTIONS
 * @see dump
 */

static const int DUMPALL = ((2 << 10) - 1);

/**
 * @var SKG_UNDO_MAX_DEPTH
 * Default value for the max depth for the undo / redo mechanism
 */
static const int SKG_UNDO_MAX_DEPTH = 50;

/**
 * @var ERR_NOTIMPL
 * Error number
 */
static const int ERR_NOTIMPL = 1;

/**
 * @var ERR_NOINTERFACE
 * Error number
 */
static const int ERR_NOINTERFACE = 2;

/**
 * @var ERR_POINTER
 * Error number
 */
static const int ERR_POINTER = 3;

/**
 * @var ERR_ABORT
 * Error number
 */
static const int ERR_ABORT = 4;

/**
 * @var ERR_FAIL
 * Error number
 */
static const int ERR_FAIL = 5;

/**
 * @var ERR_HANDLE
 * Error number
 */
static const int ERR_HANDLE = 6;

/**
 * @var ERR_OUTOFMEMORY
 * Error number
 */
static const int ERR_OUTOFMEMORY = 7;

/**
 * @var ERR_INVALIDARG
 * Error number
 */
static const int ERR_INVALIDARG = 8;

/**
 * @var ERR_UNEXPECTED
 * Error number
 */
static const int ERR_UNEXPECTED = 9;

/**
 * @var ERR_WRITEACCESS
 * Error number
 */
static const int ERR_WRITEACCESS = 10;

/**
 * @var ERR_FORCEABLE
 * Error number
 */
static const int ERR_FORCEABLE = 11;

/**
 * @var ERR_ENCRYPTION
 * Error number
 */
static const int ERR_ENCRYPTION = 12;

/**
 * @var ERR_INSTALL
 * Error number
 */
static const int ERR_INSTALL = 13;

/**
 * @var ERR_CORRUPTION
 * Error number
 */
static const int ERR_CORRUPTION = 14;

/**
 * @var ERR_READACCESS
 * Error number
 */
static const int ERR_READACCESS = 15;

/**
 * @brief For a not modified field
 **/
static const QString NOUPDATE = "-------";

/**
  * @var EPSILON
  * Epsilon (for comparison)
  */
static const double EPSILON = 0.00001;

/**
 * @def DELETECASCADE
 * Define a standard trigger for cascaded delete
 */
#define DELETECASCADE(TABLEPARENT,ATTPARENT,TABLECHILD,ATTCHILD)\
            << QString()%"DROP TRIGGER IF EXISTS fkdc_"%TABLEPARENT%"_"%TABLECHILD%"_"%ATTPARENT%"_"%ATTCHILD \
            << QString()%"CREATE TRIGGER fkdc_"%TABLEPARENT%"_"%TABLECHILD%"_"%ATTPARENT%"_"%ATTCHILD%" "\
            "BEFORE DELETE ON "%TABLEPARENT%" "\
            "FOR EACH ROW BEGIN "\
            "    DELETE FROM "%TABLECHILD%" WHERE "%TABLECHILD%"."%ATTCHILD%" = OLD."%ATTPARENT%"; "\
            "END"

/**
 * @def INSERTUPDATECONSTRAINT
 * Define a standard trigger for foreign constraint
 */


// Should these strings be translated ??? They look far too SQLish for that purpose
#define INSERTUPDATECONSTRAINT(TABLEPARENT,ATTPARENT,TABLECHILD,ATTCHILD)\
            << QString()%"DROP TRIGGER IF EXISTS fki_"%TABLECHILD%"_"%TABLEPARENT%"_"%ATTCHILD%"_"%ATTPARENT \
            << QString()%"CREATE TRIGGER fki_"%TABLECHILD%"_"%TABLEPARENT%"_"%ATTCHILD%"_"%ATTPARENT%" "\
            "BEFORE INSERT ON "%TABLECHILD%" "\
            "FOR EACH ROW BEGIN "\
            "  SELECT RAISE(ABORT, '"%SKGServices::stringToSqlString(i18nc("Error message", "Impossible to insert object (%1 is used by %2).\nConstraint name: %3",TABLEPARENT, TABLECHILD, "fki_"%TABLECHILD%"_"%TABLEPARENT%"_"%ATTCHILD%"_"%ATTPARENT))%"') "\
            "  WHERE NEW."%ATTCHILD%"!=0 AND NEW."%ATTCHILD%"!='' AND (SELECT "%ATTPARENT%" FROM "%TABLEPARENT%" WHERE "%ATTPARENT%" = NEW."%ATTCHILD%") IS NULL; "\
            "END"\
            << QString()%"DROP TRIGGER IF EXISTS fku_"%TABLECHILD%"_"%TABLEPARENT%"_"%ATTCHILD%"_"%ATTPARENT \
            << QString()%"CREATE TRIGGER fku_"%TABLECHILD%"_"%TABLEPARENT%"_"%ATTCHILD%"_"%ATTPARENT%" "\
            "BEFORE UPDATE ON "%TABLECHILD%" "\
            "FOR EACH ROW BEGIN "\
            "    SELECT RAISE(ABORT, '"%SKGServices::stringToSqlString(i18nc("Error message", "Impossible to update object (%1 is used by %2).\nConstraint name: %3",TABLEPARENT, TABLECHILD, "fku_"%TABLECHILD%"_"%TABLEPARENT%"_"%ATTCHILD%"_"%ATTPARENT))%"') "\
            "      WHERE NEW."%ATTCHILD%"!=0 AND NEW."%ATTCHILD%"!='' AND (SELECT "%ATTPARENT%" FROM "%TABLEPARENT%" WHERE "%ATTPARENT%" = NEW."%ATTCHILD%") IS NULL; "\
            "END"

/**
 * @def FOREIGNCONSTRAINT
 * Define a standard trigger for foreign constraint
 */
#define FOREIGNCONSTRAINT(TABLEPARENT,ATTPARENT,TABLECHILD,ATTCHILD)\
    INSERTUPDATECONSTRAINT(TABLEPARENT,ATTPARENT,TABLECHILD,ATTCHILD)\
            << QString()%"DROP TRIGGER IF EXISTS fkd_"%TABLECHILD%"_"%TABLEPARENT%"_"%ATTCHILD%"_"%ATTPARENT \
            << QString()%"CREATE TRIGGER fkd_"%TABLECHILD%"_"%TABLEPARENT%"_"%ATTCHILD%"_"%ATTPARENT%" "\
            "BEFORE DELETE ON "%TABLEPARENT%" "\
            "FOR EACH ROW BEGIN "\
            "    SELECT RAISE(ABORT, '"%SKGServices::stringToSqlString(i18nc("Error message", "Impossible to delete used object (%1 is used by %2).\nConstraint name: %3",TABLEPARENT, TABLECHILD, "fkd_"%TABLECHILD%"_"%TABLEPARENT%"_"%ATTCHILD%"_"%ATTPARENT))%"') "\
            "    WHERE (SELECT "%ATTCHILD%" FROM "%TABLECHILD%" WHERE "%ATTCHILD%" = OLD."%ATTPARENT%") IS NOT NULL; "\
            "END"

/**
 * @def FOREIGNCONSTRAINTUPDATE
 * Define a standard trigger for foreign constraint
 */
#define FOREIGNCONSTRAINTUPDATE(TABLEPARENT,ATTPARENT,TABLECHILD,ATTCHILD)\
    INSERTUPDATECONSTRAINT(TABLEPARENT,ATTPARENT,TABLECHILD,ATTCHILD)\
            << QString()%"DROP TRIGGER IF EXISTS fkd_"%TABLECHILD%"_"%TABLEPARENT%"_"%ATTCHILD%"_"%ATTPARENT \
            << QString()%"CREATE TRIGGER fkd_"%TABLECHILD%"_"%TABLEPARENT%"_"%ATTCHILD%"_"%ATTPARENT%" "\
            "BEFORE DELETE ON "%TABLEPARENT%" "\
            "FOR EACH ROW BEGIN "\
            "    UPDATE "%TABLECHILD%" SET "%ATTCHILD%"=0 WHERE "%ATTCHILD%"=OLD."%ATTPARENT%"; "\
            "END"

/**
 * @def FOREIGNCONSTRAINTCASCADE
 * Define a standard trigger for foreign constraint cascade delete
 */
#define FOREIGNCONSTRAINTCASCADE(TABLEPARENT,ATTPARENT,TABLECHILD,ATTCHILD)\
    INSERTUPDATECONSTRAINT(TABLEPARENT,ATTPARENT,TABLECHILD,ATTCHILD)\
    DELETECASCADE(TABLEPARENT,ATTPARENT,TABLECHILD,ATTCHILD)

/**
 * @def DELETECASCADEPARAMETER
 * Define a cascaded delete to delete parameters associated with an object
 */
#define DELETECASCADEPARAMETER(TABLE) \
            << QString()%"DROP TRIGGER IF EXISTS fkdc_"%TABLE%"_parameters_uuid" \
            << QString()%"CREATE TRIGGER fkdc_"%TABLE%"_parameters_uuid "\
            "BEFORE DELETE ON "%TABLE%" "\
            "FOR EACH ROW BEGIN "\
            "    DELETE FROM parameters WHERE parameters.t_uuid_parent=OLD.id||'-'||'"%TABLE%"'; "\
            "END"

#endif
