/*

    ========== licence begin  GPL
    Copyright (c) 2005 SAP AG

    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, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end

*/

#include "hak01.h"
#include "hak101.h"
#include "hak51.h"
#include "hgg01_3.h"

#include "SQLManager/Catalog/Catalog_Instance.hpp"
#include "SQLManager/SQLMan_Context.hpp"
#include "SQLManager/KernelSQL/KSQL_Connection.hpp"
#include "SQLManager/Catalog/Catalog_Messages.hpp"
#include "RunTime/Synchronisation/RTESync_RWRegion.hpp"
#include "RunTime/MemoryManagement/RTEMem_RawAllocator.hpp"

SINGLETON_INIT_MEMBER(Catalog_Instance);

Catalog_Interface& Catalog_Interface::GetInstance()
{
    return Catalog_Instance::Instance();
}

//-------------------------------------------------------------------------------------------------

Catalog_Instance::Catalog_Instance()
: m_ddlLock(0)
{
    static RTESync_BaseSpinlockPool pool((SAPDB_UTF8*) "Catalog_DDL_Lock", 1, RTEMem_RawAllocator::Instance());
    m_ddlLock = RTESync_CreateRWRegion(1, pool, RTEMem_RawAllocator::Instance());
    if (!m_ddlLock)
    {
        RTE_Crash(SAPDBErr_MessageList("Catalog", __CONTEXT__, CATALOG_ERR_RW_LOCK_CREATE_FAILED));
    }
}

//-------------------------------------------------------------------------------------------------

void Catalog_Instance::DDLShareLock(bool releaseLock, RTE_TaskId pid)
{
    const bool exclusive = true;
    if (releaseLock)
    {
        m_ddlLock->leave(!exclusive, pid);
    }
    else
    {
        m_ddlLock->enter(!exclusive, pid);
    }
}

//-------------------------------------------------------------------------------------------------

void Catalog_Instance::DDLExclusiveLock(bool releaseLock, RTE_TaskId pid)
{
    const bool exclusive = true;
    if (releaseLock)
    {
        m_ddlLock->leave(exclusive, pid);
    }
    else
    {
        m_ddlLock->enter(exclusive, pid);
    }
}

//-------------------------------------------------------------------------------------------------

void Catalog_Instance::Abort(const SAPDBErr_MessageList& errorList)
{
    SQLMan_Context* pContext = SQLMan_Context::GetContext();
    if (pContext)
    {
        SAPDBErr_MessageList& list = pContext->GetErrorList();
        list.AppendNewMessage(errorList);
        RTE_Crash(list);
    }
    RTE_Crash(errorList);
}

#if defined(KERNEL80)

static const char* TheCatalogDomains[] = {
  "create domain catalog_objectid char(8) byte"
    ,
    "create domain catalog_identifier char(32)"
};

static const char* TheCatalogTables[] = {
  "create table tables "
  "(objectid             catalog_objectid,"
  " owner                catalog_objectid,"
  " tablename            catalog_identifier,"
  " linkinfo             char(1) byte,"
  " fileid               char(40) byte,"
  " colcount             fixed(4),"
  " maxreclength         fixed(5),"
  " keycount             fixed(2),"
  " lenfixedcol          fixed(5),"
  " varcolcount          fixed(4),"
  " droppedcolcount      fixed(4),"
  " longcolcount         fixed(4),"
  " longvarcolcount      fixed(4),"
  " hascomment           boolean,"
  " avgrowlength         fixed(5),"
  " datecreate           fixed(10),"
  " timecreate           fixed(10),"
  " updstatdate          fixed(10),"
  " updstattime          fixed(10),"
  " pagecount            fixed(10),"
  " rowcount             fixed(10),"
  " alterdate            fixed(10),"
  " baltertime           fixed(10),"
  " sample               fixed(10),"
  " privallset           char(1) byte,"
  " privcolexist         char(1) byte,"
  " unloaded             boolean,"
  " indexexist           boolean,"
  " viewlevel            fixed(4),"
  " viewtabcount         fixed(4),"
  " viewtablekind        char(1) byte,"
  " viewcheckoption      boolean,"
  " viewqualexist        boolean,"
  " viewdistinct         char(1) byte,"
  " viewlist             boolean,"
  " defaultstamp         boolean,"
  " viewcorrelated       boolean,"
  " sqlmode              char(1) byte,"
  " namedconstraintcount fixed(5),"
  " showkind             char(1) byte,"
  " recreate_view        boolean,"
  " viewshowkind         char(1) byte,"
  " attributes           char(1) byte,"
  "primary key(objectid))"
  ,
  "create table columns (objectid catalog_objectid, columnname catalog_identifier)"
  ,
  "create table roleschemausernamespace ("
  "name catalog_identifier,"
  "id   catalog_objectid,"
  "primary key (name))"
  ,
  "create table schemas ("
  "schemaid   catalog_objectid,"
  "owner      catalog_objectid,"
  "createdate timestamp,"
  "schemaNo   fixed(10),"
  "primary key(schemaid))"
  ,
  "create table users ("
  "userid             catalog_objectid,"
  "defaultcode        char(7) ascii,"
  "roleinfo           fixed(1),"
  "userkind           fixed(1),"
  "issysdba           boolean,"
  "isexclusive        boolean,"
  "isreplication      boolean,"
  "password           char(24) byte,"
  "supportpassword    char(24) byte,"
  "groupid            catalog_objectid,"
  "owner              catalog_objectid,"
  "createdate         timestamp,"
  "passwordchangedate timestamp,"
  "alterdate          timestamp,"
  "timeout            fixed(5),"
  "costwarning        fixed(10),"
  "costlimit          fixed(10),"
  "cachelimit         fixed(10),"
  "rolecount          integer,"
  "primary key(userid))"
};

externC tsp00_TaskId a362OnlineTaskId;

//-------------------------------------------------------------------------------------------------

int Catalog_Instance::create()
{
    SQLMan_Context* pContext = SQLMan_Context::GetContext();
    if (pContext)
    {
        SQLMan_Identifier initUser;
        a51switch_user (*pContext, g01glob.sysuser_name, initUser);
        if (pContext->IsOk()) 
        {
            a362OnlineTaskId = pContext->TransContext().trTaskId_gg00;
            KSQL_Connection con;
            if (con.isConnected())
            {
              createCatalogObject(con, "create user catalog password catalog resource");
              this->createCatalogDomains(con);
              a51switch_user (*pContext, a01_i_catalog, initUser);
              this->createCatalogTables(con);
            }
            a362OnlineTaskId = UNDEF_SP00;
        }
    }
    return 0;
}

//-------------------------------------------------------------------------------------------------

void Catalog_Instance::createCatalogDomains (KSQL_Connection& con)
{
    for (int ix = 0; ix < sizeof(TheCatalogDomains) / sizeof(TheCatalogDomains[0]); ++ix)
    {
        this->createCatalogObject(con, TheCatalogDomains[ix]); 
    }
}

//-------------------------------------------------------------------------------------------------

void Catalog_Instance::createCatalogTables (KSQL_Connection& con)
{
    for (int ix = 0; ix < sizeof(TheCatalogTables) / sizeof(TheCatalogTables[0]); ++ix)
    {
        this->createCatalogObject(con, TheCatalogTables[ix]); 
    }
}

//-------------------------------------------------------------------------------------------------

void Catalog_Instance::createCatalogObject(KSQL_Connection& con, const char* createStatement)
{
    KSQL_Statement stmt = con.createStatement();
    int errCode = stmt.asciiExecute(createStatement);
    if (0 != errCode)
    {
        SAPDB_ToStringClass errCodeStr = ToStr(errCode);
        SAPDBErr_MessageList msg ("Catalog", __CONTEXT__, 
            SAPDBErr_MessageList::Error, CATALOG_ERR_CREATE_CATALOG_OBJECT_FAILED_ID,
            "Create Catalog Object failed", 2, createStatement, errCodeStr);
        this->abort(msg);
    }
}

//-------------------------------------------------------------------------------------------------

integer a101_CreateCatalog ()
{
    return Catalog_Instance::Instance().Create();
}

#endif



