2007-12-30 17:41:49 +01:00
|
|
|
/***************************************************************************
|
|
|
|
|
|
|
|
sqlite.c
|
|
|
|
|
2013-08-03 17:38:01 +02:00
|
|
|
(c) 2000-2013 Benoît Minisini <gambas@users.sourceforge.net>
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
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
|
2009-08-17 12:41:51 +02:00
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
2007-12-30 17:41:49 +01:00
|
|
|
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
|
2011-06-03 02:51:09 +02:00
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
2011-12-31 03:39:20 +01:00
|
|
|
MA 02110-1301, USA.
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#define __SQLITE_C
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <libgen.h>
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* Internal function to check whether a file is a sqlite database file */
|
|
|
|
|
|
|
|
static bool is_sqlite2_database(char *filename)
|
|
|
|
{
|
|
|
|
FILE* fp;
|
|
|
|
bool res;
|
|
|
|
char magic_text[48];
|
|
|
|
|
|
|
|
fp = fopen(filename, "r");
|
|
|
|
if (!fp)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
res = fread(magic_text, 1, 47, fp) == 47;
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
if (!res)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
magic_text[47] = '\0';
|
|
|
|
|
|
|
|
if (strcmp(magic_text, "** This file contains an SQLite 2.1 database **"))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool is_sqlite3_database(char *filename)
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
bool res;
|
|
|
|
char magic_text[16];
|
|
|
|
|
|
|
|
fp = fopen(filename, "r");
|
|
|
|
if (!fp)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
res = fread(magic_text, 1, 15, fp) == 15;
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
if (!res)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
magic_text[15] = '\0';
|
|
|
|
|
|
|
|
if (strcmp(magic_text, "SQLite format 3"))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool IsDatabaseFile(char *filename)
|
|
|
|
{
|
|
|
|
return is_sqlite3_database(filename) || is_sqlite2_database(filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *FindDatabase(char *name, char *hostName)
|
|
|
|
{
|
|
|
|
char *dbhome = NULL;
|
|
|
|
char *fullpath = NULL;
|
|
|
|
|
|
|
|
/* Does Name includes fullpath */
|
|
|
|
if (strcmp(basename(name), name))
|
|
|
|
{
|
|
|
|
if (IsDatabaseFile(name))
|
2010-06-05 01:48:53 +02:00
|
|
|
fullpath = GB.NewZeroString(name);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
return fullpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Hostname contains home area */
|
2010-06-05 01:48:53 +02:00
|
|
|
fullpath = GB.NewZeroString(hostName);
|
2011-09-07 21:43:11 +02:00
|
|
|
fullpath = GB.AddChar(fullpath, '/');
|
|
|
|
fullpath = GB.AddString(fullpath, name, 0);
|
2007-12-30 17:41:49 +01:00
|
|
|
if (IsDatabaseFile(fullpath))
|
|
|
|
{
|
|
|
|
return fullpath;
|
|
|
|
}
|
|
|
|
GB.FreeString(&fullpath);
|
|
|
|
|
|
|
|
/* Check the GAMBAS_SQLITE_DBHOME setting */
|
|
|
|
dbhome = getenv("GAMBAS_SQLITE_DBHOME");
|
|
|
|
|
|
|
|
if (dbhome != NULL)
|
|
|
|
{
|
2010-06-05 01:48:53 +02:00
|
|
|
fullpath = GB.NewZeroString(dbhome);
|
2011-09-07 21:43:11 +02:00
|
|
|
fullpath = GB.AddChar(fullpath, '/');
|
|
|
|
fullpath = GB.AddString(fullpath, name, 0);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
if (IsDatabaseFile(fullpath))
|
|
|
|
{
|
|
|
|
return fullpath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
fullpath = GB.NewZeroString(GB.TempDir());
|
2011-09-07 21:43:11 +02:00
|
|
|
fullpath = GB.AddString(fullpath, "/sqlite/", 0);
|
|
|
|
fullpath = GB.AddString(fullpath, name, 0);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
if (IsDatabaseFile(fullpath))
|
|
|
|
{
|
|
|
|
return fullpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
GB.FreeString(&fullpath);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
|
|
|
|
open_database()
|
|
|
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
static int open_database(DB_DESC *desc, DB_DATABASE * db)
|
|
|
|
{
|
|
|
|
char *db_fullpath = NULL;
|
|
|
|
bool ver2 = FALSE;
|
|
|
|
|
|
|
|
if (!desc->name) // memory database
|
|
|
|
goto __SQLITE;
|
|
|
|
|
|
|
|
db_fullpath = FindDatabase(desc->name, desc->host);
|
|
|
|
if (!db_fullpath)
|
|
|
|
{
|
2009-07-12 23:49:13 +02:00
|
|
|
GB.Error("Unable to locate database: &1", desc->name);
|
2007-12-30 17:41:49 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ver2 = is_sqlite2_database(db_fullpath);
|
|
|
|
|
|
|
|
GB.FreeString(&db_fullpath);
|
|
|
|
|
|
|
|
if (ver2)
|
|
|
|
goto __SQLITE2;
|
|
|
|
else
|
|
|
|
goto __SQLITE3;
|
|
|
|
|
|
|
|
__SQLITE:
|
|
|
|
|
2012-05-08 17:32:33 +02:00
|
|
|
GB.Component.Load("gb.db.sqlite3");
|
2007-12-30 17:41:49 +01:00
|
|
|
GB.Error(NULL);
|
|
|
|
|
2012-05-08 17:32:33 +02:00
|
|
|
if (GB.Component.Exist("gb.db.sqlite3"))
|
2007-12-30 17:41:49 +01:00
|
|
|
goto __SQLITE3;
|
|
|
|
else
|
|
|
|
goto __SQLITE2;
|
|
|
|
|
|
|
|
__SQLITE2:
|
|
|
|
DB_TryAnother("sqlite2");
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
__SQLITE3:
|
|
|
|
DB_TryAnother("sqlite3");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
|
|
|
|
The driver interface
|
|
|
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
DB_DRIVER DB_sqlite_pseudo_driver =
|
|
|
|
{
|
|
|
|
"sqlite",
|
|
|
|
open_database,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|