<commit_before>/*
* Copyright (C) 2011-2013 Klaralavdalens Datakonsult AB, a KDAB Group company, <EMAIL>
* Author: <NAME> <<EMAIL>>
*         <NAME> <<EMAIL>>
*/
#ifndef SQLSCHEMA_P_H
#define SQLSCHEMA_P_H

#include "SqlInternals_p.h"
#include "sqlate_export.h"
#include <QLatin1Literal>
#include <QUuid>

#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/comma_if.hpp>
#include <boost/preprocessor/seq.hpp>

#include <utility>

/**
 * @file SqlSchema_p.h
 * Database schema related internal classes and functions.
 */


/** Stringification of SQL identifier names, used in table and column classes. */
#define SQL_NAME( x ) \
   static QString sqlName() { return QLatin1String(x); }

/** Define who can have admin rights for the table. Users belonging to the group specified here are treated as admin user.*/
#define ADMIN_GROUP( x ) \
   static QString adminGroup() { return QLatin1String(x); }

/** Define the group name for regular users valid for this table.*/
#define USER_GROUP( x ) \
   static QString userGroup() { return QLatin1String(x); }

/** Convenience macro to create column types.
 *  Use inside a table declaration.
 */
#define COLUMN( name, type, ... ) \
    struct name ## Type : Column< name ## Type, type , ## __VA_ARGS__ > { SQL_NAME( #name ) } name

/** Convenience macro to create a column alias.
  * Use inside a table definition to asign a different name to an existing column.
  */
#define COLUMN_ALIAS( column, alias ) \
    typedef column ## Type alias ## Type; \
    alias ## Type alias

/** Convenience macro for creating foreign key columns with the default legacy fk_[table]_[col] name.
 *  Use inside a table declaration.
 */
#define FOREIGN_KEY( name, fkTab, fkCol, ... ) \
    struct name ## Type : ForeignKey< name ## Type, fkTab ## Type :: fkCol ## Type , ## __VA_ARGS__ > { \
        static QString sqlName() { return QLatin1Literal( "fk_" ) % referenced_column::table::tableName() % QLatin1Char('_' ) % referenced_column::sqlName(); } \
    } name

/** Convenience macro for creating foreign key columns .
 *  Use inside a table declaration.
 */
#define NAMED_FOREIGN_KEY( name, fkTab, fkCol, ... ) \
    struct name ## Type : ForeignKey< name ## Type, fkTab ## Type :: fkCol ## Type , ## __VA_ARGS__ > { SQL_NAME( #name ) } name

/** Convenience macro to create a table with non-updatable rows type. Put after one of the TABLE macros.*/
#define NO_USER_UPDATE \
    typedef boost::mpl::false_ update_rows;

/** Convenience macro to create a table with non-deletable rows type. Put after one of the TABLE macros.*/
#define NO_USER_DELETE \
    typedef boost::mpl::false_ delete_rows;

/** Convenience macro to create a table with non-insertable rows type. Put after one of the TABLE macros.*/
#define NO_USER_INSERT \
    typedef boost::mpl::false_ insert_rows;

/** Convenience macro to create a restricted table type: only SELECT is allowed. Put after one of the TABLE macros.
 * Same as using NO_USER_UPDATE, NO_USER_DELETE, NO_USER_INSERT together
 */
#define ONLY_USER_SELECT \
    typedef boost::mpl::true_ is_restricted;

/** Convenience macro to create a table type. */
#define TABLE( name, _EXPORT ) \
    struct name ## Type; \
    extern _EXPORT name ## Type name; \
    struct name ## Type : Table< name ## Type >

/** Convenience macro to create a lookup table type. */
#define LOOKUP_TABLE( name, _EXPORT ) \
    struct name ## Type; \
    extern _EXPORT name ## Type name; \
    struct name ## Type : LookupTable< name ## Type >

/** Convenience macro to create a n:m helper table type. */
#define RELATION( name, leftTab, leftCol, rightTab, rightCol,_EXPORT ) \
    struct name ## Type; \
    extern _EXPORT name ## Type name; \
    struct name ## Type : Relation< name ## Type, leftTab ## Type :: leftCol ## Type, rightTab ## Type :: rightCol ## Type>

/** Convenience macro to create a n:m helper table type. */
#define UNIQUE_RELATION( name, leftTab, leftCol, rightTab, rightCol,_EXPORT ) \
    struct name ## Type; \
    extern _EXPORT name ## Type name; \
    struct name ## Type : UniqueRelation< name ## Type, leftTab ## Type :: leftCol ## Type, rightTab ## Type :: rightCol ## Type>

/** Convenience macro to create a recursive n:m helper table type. */
#define RECURSIVE_RELATION( name, tab, col, _EXPORT ) \
    struct name ## Type; \
    extern _EXPORT name ## Type name; \
    struct name ## Type : RecursiveRelation< name ## Type, tab ## Type :: col ## Type >

/** Convenience macro to create a recursive n:m helper table type. */
#define UNIQUE_RECURSIVE_RELATION( name, tab, col, _EXPORT ) \
    struct name ## Type; \
    extern _EXPORT name ## Type name; \
    struct name ## Type : UniqueRecursiveRelation< name ## Type, tab ## Type :: col ## Type >

/** Convenience macro to create the schema declaration. */
#define DECLARE_SCHEMA_MAKE_TYPE( r, unused, i, t ) BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(t, Type)
#define DECLARE_SCHEMA( name, seq ) typedef boost::mpl::vector<BOOST_PP_SEQ_FOR_EACH_I(DECLARE_SCHEMA_MAKE_TYPE, ~, seq)> name

/** Convenience macro to create the schema definition. */
#define DEFINE_SCHEMA_MAKE_DEF( r, unused, t ) BOOST_PP_CAT(t, Type) t;
#define DEFINE_SCHEMA( seq ) BOOST_PP_SEQ_FOR_EACH(DEFINE_SCHEMA_MAKE_DEF, ~, seq)


namespace Sql {

/**
 * Properties of SQL columns.
 */
enum ColumnProperties
{
    Null = 0, ///< column can be NULL
    NotNull = 1, ///< column must not be NULL
    Unique = 2, ///< column content must be unique
    PrimaryKey = 4 | NotNull | Unique, ///< column is the primary key
    Default = 8, ///< Use default value
    OnDeleteCascade = 16, ///< For foreign key constraints, cascade on deletion.
    OnDeleteRestrict = 32, ///< for foreign key constraints, restrict deletion.
    OnUserUpdateRestrict = 64, ///< Restrict update for regular users. For this to work there must be an is_administrator() stored procedure that checks if the current user is administrator or not.
    Notify = 128 ///< When an UPDATE is made on a row, emit a signal containing the content of the column for this row, and an encoded string corresponding to the column name.
};


/**Type trait to check if a class has a certain method*/

#define HAS_MEMBER_METHOD(name, method) \
template <typename T>                   \
class name                              \
{                                       \
    struct Yes {char unused[1];};       \
    struct No {char unused[2];};        \
                                        \
    template <typename C>               \
    static Yes test(decltype(std::declval< const C>().method())*); \
    template <typename C>               \
    static No test(...);                \
public:                                 \
    static const bool value = (sizeof(test<T>(0)) == sizeof(Yes)); \
};

HAS_MEMBER_METHOD(hasAdminGroup, adminGroup);
HAS_MEMBER_METHOD(hasUserGroup, userGroup);

/**
 * Multi-column uniqeness table constraint.
 * @tparam ColList An MPL sequence of columns whose tuple needs to be unique table-wide
 */
template <typename ColList>
struct UniqueConstraint
{
    typedef ColList columns;
};


/**
 * Base class for SQL table types.
 * @tparam DerivedTable CRTP
 */
template<typename DerivedTable>
struct Table
{
    typedef boost::mpl::false_ is_lookup_table;
    typedef boost::mpl::false_ is_relation;
    typedef boost::mpl::false_ is_restricted; //regular users can only select it
    typedef boost::mpl::true_ delete_rows;    //regular users can delete rows from it. _is_restricted takes precendece<commit_msg>enable the type-trait only for g++, because on: - msvc: didn't have energy to find the reason, but it fails to compile - clang/osx: needs -stdlib=libc++ but with that it has problems compiling Qt 4.8.2 code, a new Qt needs new XCode, so I gave up for now ;)<commit_after>/*
* Copyright (C) 2011-2013 Klaralavdalens Datakonsult AB, a KDAB Group company, <EMAIL>
* Author: <NAME> <<EMAIL>>
*         <NAME> <<EMAIL>>
*/
#ifndef SQLSCHEMA_P_H
#define SQLSCHEMA_P_H

#include "SqlInternals_p.h"
#include "sqlate_export.h"
#include <QLatin1Literal>
#include <QUuid>

#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/comma_if.hpp>
#include <boost/preprocessor/seq.hpp>

#include <utility>

/**
 * @file SqlSchema_p.h
 * Database schema related internal classes and functions.
 */


/** Stringification of SQL identifier names, used in table and column classes. */
#define SQL_NAME( x ) \
   static QString sqlName() { return QLatin1String(x); }

/** Define who can have admin rights for the table. Users belonging to the group specified here are treated as admin user.*/
#define ADMIN_GROUP( x ) \
   static QString adminGroup() { return QLatin1String(x); }

/** Define the group name for regular users valid for this table.*/
#define USER_GROUP( x ) \
   static QString userGroup() { return QLatin1String(x); }

/** Convenience macro to create column types.
 *  Use inside a table declaration.
 */
#define COLUMN( name, type, ... ) \
    struct name ## Type : Column< name ## Type, type , ## __VA_ARGS__ > { SQL_NAME( #name ) } name

/** Convenience macro to create a column alias.
  * Use inside a table definition to asign a different name to an existing column.
  */
#define COLUMN_ALIAS( column, alias ) \
    typedef column ## Type alias ## Type; \
    alias ## Type alias

/** Convenience macro for creating foreign key columns with the default legacy fk_[table]_[col] name.
 *  Use inside a table declaration.
 */
#define FOREIGN_KEY( name, fkTab, fkCol, ... ) \
    struct name ## Type : ForeignKey< name ## Type, fkTab ## Type :: fkCol ## Type , ## __VA_ARGS__ > { \
        static QString sqlName() { return QLatin1Literal( "fk_" ) % referenced_column::table::tableName() % QLatin1Char('_' ) % referenced_column::sqlName(); } \
    } name

/** Convenience macro for creating foreign key columns .
 *  Use inside a table declaration.
 */
#define NAMED_FOREIGN_KEY( name, fkTab, fkCol, ... ) \
    struct name ## Type : ForeignKey< name ## Type, fkTab ## Type :: fkCol ## Type , ## __VA_ARGS__ > { SQL_NAME( #name ) } name

/** Convenience macro to create a table with non-updatable rows type. Put after one of the TABLE macros.*/
#define NO_USER_UPDATE \
    typedef boost::mpl::false_ update_rows;

/** Convenience macro to create a table with non-deletable rows type. Put after one of the TABLE macros.*/
#define NO_USER_DELETE \
    typedef boost::mpl::false_ delete_rows;

/** Convenience macro to create a table with non-insertable rows type. Put after one of the TABLE macros.*/
#define NO_USER_INSERT \
    typedef boost::mpl::false_ insert_rows;

/** Convenience macro to create a restricted table type: only SELECT is allowed. Put after one of the TABLE macros.
 * Same as using NO_USER_UPDATE, NO_USER_DELETE, NO_USER_INSERT together
 */
#define ONLY_USER_SELECT \
    typedef boost::mpl::true_ is_restricted;

/** Convenience macro to create a table type. */
#define TABLE( name, _EXPORT ) \
    struct name ## Type; \
    extern _EXPORT name ## Type name; \
    struct name ## Type : Table< name ## Type >

/** Convenience macro to create a lookup table type. */
#define LOOKUP_TABLE( name, _EXPORT ) \
    struct name ## Type; \
    extern _EXPORT name ## Type name; \
    struct name ## Type : LookupTable< name ## Type >

/** Convenience macro to create a n:m helper table type. */
#define RELATION( name, leftTab, leftCol, rightTab, rightCol,_EXPORT ) \
    struct name ## Type; \
    extern _EXPORT name ## Type name; \
    struct name ## Type : Relation< name ## Type, leftTab ## Type :: leftCol ## Type, rightTab ## Type :: rightCol ## Type>

/** Convenience macro to create a n:m helper table type. */
#define UNIQUE_RELATION( name, leftTab, leftCol, rightTab, rightCol,_EXPORT ) \
    struct name ## Type; \
    extern _EXPORT name ## Type name; \
    struct name ## Type : UniqueRelation< name ## Type, leftTab ## Type :: leftCol ## Type, rightTab ## Type :: rightCol ## Type>

/** Convenience macro to create a recursive n:m helper table type. */
#define RECURSIVE_RELATION( name, tab, col, _EXPORT ) \
    struct name ## Type; \
    extern _EXPORT name ## Type name; \
    struct name ## Type : RecursiveRelation< name ## Type, tab ## Type :: col ## Type >

/** Convenience macro to create a recursive n:m helper table type. */
#define UNIQUE_RECURSIVE_RELATION( name, tab, col, _EXPORT ) \
    struct name ## Type; \
    extern _EXPORT name ## Type name; \
    struct name ## Type : UniqueRecursiveRelation< name ## Type, tab ## Type :: col ## Type >

/** Convenience macro to create the schema declaration. */
#define DECLARE_SCHEMA_MAKE_TYPE( r, unused, i, t ) BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(t, Type)
#define DECLARE_SCHEMA( name, seq ) typedef boost::mpl::vector<BOOST_PP_SEQ_FOR_EACH_I(DECLARE_SCHEMA_MAKE_TYPE, ~, seq)> name

/** Convenience macro to create the schema definition. */
#define DEFINE_SCHEMA_MAKE_DEF( r, unused, t ) BOOST_PP_CAT(t, Type) t;
#define DEFINE_SCHEMA( seq ) BOOST_PP_SEQ_FOR_EACH(DEFINE_SCHEMA_MAKE_DEF, ~, seq)


namespace Sql {

/**
 * Properties of SQL columns.
 */
enum ColumnProperties
{
    Null = 0, ///< column can be NULL
    NotNull = 1, ///< column must not be NULL
    Unique = 2, ///< column content must be unique
    PrimaryKey = 4 | NotNull | Unique, ///< column is the primary key
    Default = 8, ///< Use default value
    OnDeleteCascade = 16, ///< For foreign key constraints, cascade on deletion.
    OnDeleteRestrict = 32, ///< for foreign key constraints, restrict deletion.
    OnUserUpdateRestrict = 64, ///< Restrict update for regular users. For this to work there must be an is_administrator() stored procedure that checks if the current user is administrator or not.
    Notify = 128 ///< When an UPDATE is made on a row, emit a signal containing the content of the column for this row, and an encoded string corresponding to the column name.
};


/**Type trait to check if a class has a certain method*/

#ifdef __GCC__
#define HAS_MEMBER_METHOD(name, method) \
template <typename T>                   \
class name                              \
{                                       \
    struct Yes {char unused[1];};       \
    struct No {char unused[2];};        \
                                        \
    template <typename C>               \
    static Yes test(decltype(std::declval< const C>().method())*); \
    template <typename C>               \
    static No test(...);                \
public:                                 \
    static const bool value = (sizeof(test<T>(0)) == sizeof(Yes)); \
};
#else
#define HAS_MEMBER_METHOD(name, method) \
    template <typename T>                   \
    class name                              \
    {                                       \
    public:                                 \
        static const bool value = true; \
    };
#endif
HAS_MEMBER_METHOD(hasAdminGroup, adminGroup);
HAS_MEMBER_METHOD(hasUserGroup, userGroup);

/**
 * Multi-column uniqeness table constraint.
 * @tparam ColList An MPL sequence of columns whose tuple needs to be unique table-wide
 */
template <typename ColList>
struct UniqueConstraint
{
    typedef ColList columns;
};


/**
 * Base class for SQL table types.
 * @tparam DerivedTable CRTP
 */
template<typename DerivedTable>
struct Table
{
    typedef boost::mpl::false_ is_lookup_table;
    typedef boost::mpl::false_ is_relation;
    typedef boost::mpl::false_ is_restricted; //regular users can only select it
    typedef boost::mpl::true_ delete_rows;    //regular users can delete rows from it. _is_restricted takes precendece
{'fraction_non_alphanumeric': 0.11239721695129665, 'fraction_numerical': 0.004111321948134092, 'mean_word_length': 3.155321944809461, 'pattern_counts': {'":': 0, '<': 90, '<?xml version=': 0, '>': 72, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6108252', 'n_tokens_mistral': 4877, 'n_tokens_neox': 4636, 'n_words': 1719}