From 00b4601f97deaa6acc206ffb4fc649d66e2f70fe Mon Sep 17 00:00:00 2001 From: Matt Rice Date: Sun, 1 Oct 2006 07:29:49 +0000 Subject: [PATCH] * EOAdaptors/SQLiteAdaptor/: Initial import of SQLite3 adaptor. * configure: Regenerate. * config/sqlite3.m4: New file. * configure.ac: Add detection for sqlite3. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@23691 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 7 + EOAdaptors/SQLiteAdaptor/GNUmakefile.in | 49 ++ EOAdaptors/SQLiteAdaptor/SQLite3Adaptor.h | 37 ++ EOAdaptors/SQLiteAdaptor/SQLite3Adaptor.m | 140 ++++++ EOAdaptors/SQLiteAdaptor/SQLite3Channel.h | 45 ++ EOAdaptors/SQLiteAdaptor/SQLite3Channel.m | 486 +++++++++++++++++++ EOAdaptors/SQLiteAdaptor/SQLite3Context.h | 37 ++ EOAdaptors/SQLiteAdaptor/SQLite3Context.m | 125 +++++ EOAdaptors/SQLiteAdaptor/SQLite3Expression.h | 37 ++ EOAdaptors/SQLiteAdaptor/SQLite3Expression.m | 171 +++++++ EOAdaptors/SQLiteAdaptor/TODO | 4 + config/sqlite3.m4 | 59 +++ configure | 402 ++++++++++++++- configure.ac | 17 +- 14 files changed, 1588 insertions(+), 28 deletions(-) create mode 100644 EOAdaptors/SQLiteAdaptor/GNUmakefile.in create mode 100644 EOAdaptors/SQLiteAdaptor/SQLite3Adaptor.h create mode 100644 EOAdaptors/SQLiteAdaptor/SQLite3Adaptor.m create mode 100644 EOAdaptors/SQLiteAdaptor/SQLite3Channel.h create mode 100644 EOAdaptors/SQLiteAdaptor/SQLite3Channel.m create mode 100644 EOAdaptors/SQLiteAdaptor/SQLite3Context.h create mode 100644 EOAdaptors/SQLiteAdaptor/SQLite3Context.m create mode 100644 EOAdaptors/SQLiteAdaptor/SQLite3Expression.h create mode 100644 EOAdaptors/SQLiteAdaptor/SQLite3Expression.m create mode 100644 EOAdaptors/SQLiteAdaptor/TODO create mode 100644 config/sqlite3.m4 diff --git a/ChangeLog b/ChangeLog index 0845e6f..0fec89a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2006-10-01 Matt Rice + + * EOAdaptors/SQLiteAdaptor/: Initial import of SQLite3 adaptor. + * configure: Regenerate. + * config/sqlite3.m4: New file. + * configure.ac: Add detection for sqlite3. + 2006-09-28 Matt Rice * EOAccess/EOSQLExpression.m diff --git a/EOAdaptors/SQLiteAdaptor/GNUmakefile.in b/EOAdaptors/SQLiteAdaptor/GNUmakefile.in new file mode 100644 index 0000000..956c95f --- /dev/null +++ b/EOAdaptors/SQLiteAdaptor/GNUmakefile.in @@ -0,0 +1,49 @@ +# SQLite3 Adaptor makefile for GNUstep Database Library. +# +# Copyright (C) 2006 Free Software Foundation, Inc. +# +# Author: Matt Rice +# +# This file is part of the GNUstep Database Library. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; see the file COPYING.LIB. +# If not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +include $(GNUSTEP_MAKEFILES)/common.make + +# Install into the System root by default +GNUSTEP_INSTALLATION_DIR = $(GNUSTEP_SYSTEM_ROOT) + +ADDITIONAL_INCLUDE_DIRS+=@SQLITE3_INCLUDES@ +ADDITIONAL_LIB_DIRS+=@SQLITE3_LIB_DIRS@ +LIBRARIES_DEPEND_UPON+=@SQLITE3_LIBS@ +FRAMEWORK_NAME=SQLite3EOAdaptor + +ADDITIONAL_NATIVE_LIB_DIRS+=../EOControl ../EOAccess +ADDITIONAL_NATIVE_LIBS+=EOControl EOAccess +ADDITIONAL_INCLUDE_DIRS+=-I../../ + +SQLite3EOAdaptor_PRINCIPAL_CLASS=SQLite3Adaptor +SQLite3EOAdaptor_OBJC_FILES=SQLite3Adaptor.m \ +SQLite3Context.m SQLite3Expression.m \ +SQLite3Channel.m + + +include ../../common.make +include $(GNUSTEP_MAKEFILES)/framework.make +-include Makefile.postamble + +after-distclean:: + rm -rf GNUmakefile diff --git a/EOAdaptors/SQLiteAdaptor/SQLite3Adaptor.h b/EOAdaptors/SQLiteAdaptor/SQLite3Adaptor.h new file mode 100644 index 0000000..25e28c2 --- /dev/null +++ b/EOAdaptors/SQLiteAdaptor/SQLite3Adaptor.h @@ -0,0 +1,37 @@ +/* + SQLite3Adaptor.h + + Copyright (C) 2006 Free Software Foundation, Inc. + + Author: Matt Rice + Date: 2006 + + This file is part of the GNUstep Database Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __SQLite3_Adaptor_H + +#include +extern NSString *SQLite3AdaptorExceptionName; + +@interface SQLite3Adaptor : EOAdaptor + +@end + +#define __SQLite3_Adaptor_H +#endif diff --git a/EOAdaptors/SQLiteAdaptor/SQLite3Adaptor.m b/EOAdaptors/SQLiteAdaptor/SQLite3Adaptor.m new file mode 100644 index 0000000..49df690 --- /dev/null +++ b/EOAdaptors/SQLiteAdaptor/SQLite3Adaptor.m @@ -0,0 +1,140 @@ + +/* + SQLite3Adaptor.m + + Copyright (C) 2006 Free Software Foundation, Inc. + + Author: Matt Rice + Date: 2006 + + This file is part of the GNUstep Database Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "SQLite3Adaptor.h" +#include "SQLite3Context.h" +#include "SQLite3Expression.h" + +NSString *SQLite3AdaptorExceptionName = @"SQLite3AdaptorException"; + +@implementation SQLite3Adaptor : EOAdaptor +- (id) init +{ + return [self initWithName:@"SQLite3Adaptor"]; +} + +static NSString *types[][2] = +{ + {@"INTEGER", @"NSDecimalNumber"}, + {@"TEXT", @"NSString"}, + {@"BLOB", @"NSData"}, + {@"DATE", @"NSCalendarDate"}, + {@"REAL", @"NSNumber"}, + {@"VARCHAR", @"NSString"}, + {@"DOUBLE", @"NSNumber"}, + {@"NULL", @"EONull"}, +}; + ++ (NSDictionary *)externalToInternalTypeMap +{ + static NSDictionary *externalToInternalTypeMap = nil; + + if (!externalToInternalTypeMap) + { + int i; + NSString *external[sizeof(types)/sizeof(types[0])]; + NSString *internal[sizeof(types)/sizeof(types[0])]; + + for (i = 0; i < sizeof(types)/sizeof(types[0]); i++); + { + external[i] = types[i][0]; + internal[i] = types[i][1]; + } + externalToInternalTypeMap = [[NSDictionary dictionaryWithObjects:internal forKeys:external count:i] retain]; + } + + return externalToInternalTypeMap; +} + ++ (NSString *)internalTypeForExternalType:(NSString *)extType model:(EOModel *)model +{ + return [[self externalToInternalTypeMap] objectForKey:extType]; +} + ++ (NSString *)defaultExternalType +{ + return types[1][0]; +} + ++ (void)assignExternalTypeForAttribute:(EOAttribute *)attribute +{ + [attribute setExternalType:types[[attribute adaptorValueType]][0]]; +} + +- (EOAdaptorContext *)createAdaptorContext +{ + return AUTORELEASE([[SQLite3Context alloc] initWithAdaptor: self]); +} + +- (Class)defaultExpressionClass +{ + return [SQLite3Expression class]; +} + +- (Class)expressionClass +{ + return [SQLite3Expression class]; +} + +- (BOOL)isValidQualifierType:(NSString *)typeName model:(EOModel *)model +{ + return ![typeName isEqualToString:@"BLOB"]; +} + +- (void)assertConnectionDictionaryIsValid +{ + NSString *dbPath = [[self connectionDictionary] objectForKey:@"databasePath"]; + // don't check if it exists because might be creating it. + NSAssert(dbPath, @"invalid connection dictionary"); +} + +- (NSString *)fetchedValueForString: (NSString *)value + attribute: (EOAttribute *)attribute +{ + return value; +} + +- (NSNumber *)fetchedValueForNumberValue: (NSNumber *)value + attribute: (EOAttribute *)attribute +{ + return value; // TODO scale and precision +} + +- (NSCalendarDate *)fetchedValueForDateValue: (NSCalendarDate *)value + attribute: (EOAttribute *)attribute +{ + return value; +} + +- (NSData *)fetchedValueForDataValue: (NSData *)value + attribute: (EOAttribute *)attribute +{ + return value; +} + +@end + diff --git a/EOAdaptors/SQLiteAdaptor/SQLite3Channel.h b/EOAdaptors/SQLiteAdaptor/SQLite3Channel.h new file mode 100644 index 0000000..b362ce6 --- /dev/null +++ b/EOAdaptors/SQLiteAdaptor/SQLite3Channel.h @@ -0,0 +1,45 @@ +/* + SQLite3Channel.h + + Copyright (C) 2006 Free Software Foundation, Inc. + + Author: Matt Rice + Date: 2006 + + This file is part of the GNUstep Database Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __SQLITE3_CHANNEL_H + +#include "SQLite3Expression.h" +#include +#include + + +@interface SQLite3Channel : EOAdaptorChannel +{ + sqlite3 *_sqlite3Conn; + BOOL _isFetchInProgress; + sqlite3_stmt *_currentStmt; + int _status; + NSArray *_attributesToFetch; +} +@end + +#define __SQLITE3_CHANNEL_H +#endif diff --git a/EOAdaptors/SQLiteAdaptor/SQLite3Channel.m b/EOAdaptors/SQLiteAdaptor/SQLite3Channel.m new file mode 100644 index 0000000..217c303 --- /dev/null +++ b/EOAdaptors/SQLiteAdaptor/SQLite3Channel.m @@ -0,0 +1,486 @@ + +/* + SQLite3Channel.m + + Copyright (C) 2006 Free Software Foundation, Inc. + + Author: Matt Rice + Date: 2006 + + This file is part of the GNUstep Database Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "SQLite3Channel.h" +#include "SQLite3Adaptor.h" +#include "SQLite3Context.h" +#include "SQLite3Expression.h" + +#include +#include +#include +#include +@interface SQLite3Channel (Private) +-(void) _raise; +- (void) _raiseWith:(id)statement; +@end + +@implementation SQLite3Channel + +static id newNumberValue(const unsigned char *data, EOAttribute *attrib) +{ + id ret = nil; + char t = '\0'; + Class valueClass = NSClassFromString([attrib valueClassName]); + NSString *valueType = [attrib valueType]; + + if ([valueType length]) + t = [valueType characterAtIndex:0]; + if (valueClass == [NSDecimalNumber class]) + { + NSString *tmp = [[NSString alloc] initWithCString:data]; + return [[NSDecimalNumber alloc] initWithString:tmp]; + } + switch (t) + { + case 'i': + ret = [[NSNumber alloc] initWithInt:atoi(data)]; + break; + case 'I': + ret = [[NSNumber alloc] initWithUnsignedInt:(unsigned int)atoi(data)]; + break; + case 'c': + ret = [[NSNumber alloc] initWithChar:atoi(data)]; + break; + case 'C': + ret = [[NSNumber alloc] initWithUnsignedChar:(unsigned char)atoi(data)]; + break; + case 's': + ret = [[NSNumber alloc] initWithShort:(short)atoi(data)]; + break; + case 'S': + ret = [[NSNumber alloc] initWithUnsignedShort:(unsigned short)atoi(data)]; + break; + case 'l': + ret = [[NSNumber alloc] initWithLong:atol(data)]; + break; + case 'L': + ret = [[NSNumber alloc] initWithUnsignedLong:strtoul(data,NULL,10)]; + break; + case 'u': + ret = [[NSNumber alloc] initWithLongLong:atoll(data)]; + break; + case 'U': + ret = [[NSNumber alloc] initWithUnsignedLongLong:strtoul(data, NULL, 10)]; + break; + case 'f': + ret = [[NSNumber alloc] initWithFloat:(float)strtod(data, NULL)]; + break; + case 'd': + case '\0': + ret = [[NSNumber alloc] initWithDouble:strtod(data, NULL)]; + break; + default: + [[NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"Unknown attribute valueTypeChar: %c for attribute: %@", t, attrib] userInfo:nil] raise]; + } + return ret; +} + +- (BOOL) isOpen +{ + return _sqlite3Conn != NULL; +} + +- (void) openChannel +{ + NSString *filename; + EOAdaptor *adaptor = [[self adaptorContext] adaptor]; + + [adaptor assertConnectionDictionaryIsValid]; + filename = [[adaptor connectionDictionary] objectForKey:@"databasePath"]; + if (sqlite3_open([filename cString], &_sqlite3Conn) != SQLITE_OK) + { + _sqlite3Conn = NULL; + [self _raise]; + } +} + +- (void) closeChannel +{ + [self cancelFetch]; + NSAssert((sqlite3_close(_sqlite3Conn) == SQLITE_OK), + [NSString stringWithCString:sqlite3_errmsg(_sqlite3Conn)]); + _sqlite3Conn = NULL; +} + + +- (BOOL) isFetchInProgress +{ + return _isFetchInProgress; +} + +- (void) cancelFetch +{ + if (_isFetchInProgress && _currentStmt) + { + sqlite3_finalize(_currentStmt); + _currentStmt = NULL; + } + _isFetchInProgress = NO; +} + +- (NSArray *)attributesToFetch +{ + return _attributesToFetch; +} + +- (void) setAttributesToFetch:(NSArray *)attributes +{ + ASSIGN(_attributesToFetch, attributes); +} + +- (void) selectAttributes:(NSArray *)attributes + fetchSpecification:(EOFetchSpecification *)fetchSpec + lock:(BOOL)flag + entity:(EOEntity *)entity +{ + EOSQLExpression *expr; + + NSAssert([self isOpen], @"Channel not open"); + NSAssert(!_isFetchInProgress, @"Fetch already in progress"); + + ASSIGN(_attributesToFetch,attributes); + expr = [SQLite3Expression selectStatementForAttributes:attributes + lock:flag + fetchSpecification:fetchSpec + entity:entity]; + [self evaluateExpression:expr]; +} + +- (void) insertRow:(NSDictionary *)row forEntity:(EOEntity *)entity +{ + EOSQLExpression *expr; + NSAssert([self isOpen], @"channel not open"); + NSAssert(!_isFetchInProgress, @"called while fetch is in progress"); + NSAssert(row && entity, @"row and entity arguments must not be nil"); + + expr = [SQLite3Expression insertStatementForRow:row entity:entity]; + + [self evaluateExpression:expr]; +} + +- (unsigned)deleteRowsDescribedByQualifier: (EOQualifier *)qualifier + entity: (EOEntity *)entity +{ + EOSQLExpression *sqlexpr = nil; + unsigned rows = 0; + SQLite3Context *adaptorContext; + + NSAssert([self isOpen], @"channel is not open"); + NSAssert((qualifier || entity), @"qualifier and entity arguments are nil"); + NSAssert((![self isFetchInProgress]), @"fetch is in progress"); + + adaptorContext = (SQLite3Context *)[self adaptorContext]; + + sqlexpr = [[[adaptorContext adaptor] expressionClass] + deleteStatementWithQualifier: qualifier + entity: entity]; + + [self evaluateExpression: sqlexpr]; + + rows = (unsigned)sqlite3_changes(_sqlite3Conn); + return rows; +} + +- (void) evaluateExpression:(EOSQLExpression *)sqlExpr +{ + + NSString *statement = [sqlExpr statement]; + int length = [statement length]; + const char *sql = [statement cString]; + + if ([_delegate respondsToSelector:@selector(adaptorChannel:shouldEvaluateExpression:)]) + if (![_delegate adaptorChannel:self shouldEvaluateExpression:sqlExpr]) + return; + + if (![self isOpen]) return; + + if (_currentStmt) + { + NSAssert(!_currentStmt, + @"unfinalized statement found when executing expression"); + sqlite3_finalize(_currentStmt); + _currentStmt = NULL; + } + + _status = sqlite3_prepare(_sqlite3Conn, sql, length, &_currentStmt, NULL); + _isFetchInProgress = sqlite3_column_count(_currentStmt) != 0; + + if (_status != SQLITE_OK) + { + _status = sqlite3_finalize(_currentStmt); + _currentStmt = NULL; + [self _raiseWith:statement]; + } + else + { + while ((_status = sqlite3_step(_currentStmt)) == SQLITE_BUSY) + { + // FIXME sleep? + } + } + + if (_status != SQLITE_ROW) + { + sqlite3_finalize(_currentStmt); + _currentStmt = NULL; + + if (_status == SQLITE_ERROR) + [self _raiseWith:statement]; + } +} + +- (void) _raise +{ + [self _raiseWith:nil]; +} + +- (void) _raiseWith:(id)statement +{ + NSDictionary *userInfo = nil; + + if (statement) + [NSDictionary dictionaryWithObject:statement forKey:@"statement"]; + + [[NSException exceptionWithName:SQLite3AdaptorExceptionName + reason:[NSString stringWithCString:sqlite3_errmsg(_sqlite3Conn)] + userInfo:userInfo] raise]; +} + +- (NSMutableDictionary *) fetchRowWithZone:(NSZone *)zone +{ + if ([self isFetchInProgress]) + { + /* the docs say nothing about this but the postgres adaptor does it. */ + if (!_attributesToFetch) + { + _attributesToFetch = [self describeResults]; + } + + if (_status == SQLITE_DONE) + { + if ([_delegate respondsToSelector:@selector(adaptorChannelDidFinishFetching:)]) + { + [_delegate adaptorChannelDidFinishFetching:self]; + } + [self cancelFetch]; + return nil; + } + else if (_status == SQLITE_ROW) + { + NSMutableDictionary *ret; + unsigned i, c = [_attributesToFetch count]; + id *values; + + values = NSZoneMalloc(zone, c * sizeof(id)); + + for (i = 0; i < c; i++) + { + EOAttribute *attr = [_attributesToFetch objectAtIndex:i]; + + switch ([attr adaptorValueType]) + { + case EOAdaptorNumberType: + { + const unsigned char *text; + text = sqlite3_column_text(_currentStmt, i); + values[i] = newNumberValue(text, attr); + } + break; + case EOAdaptorCharactersType: + { + const unsigned char *text = sqlite3_column_text(_currentStmt, i); + int bytes = sqlite3_column_bytes(_currentStmt, i); + values[i] = bytes + ? [attr newValueForBytes:text + length:bytes + encoding:[NSString defaultCStringEncoding]] + : [EONull null]; + } + break; + case EOAdaptorDateType: + { + const unsigned char *text; + text = sqlite3_column_text(_currentStmt, i); + if (text) + { + NSString *tmp = [[NSString alloc] initWithCString:text]; + values[i] = [[NSCalendarDate alloc] initWithString:tmp]; + RELEASE(tmp); + } + else values[i] = [EONull null]; + } + break; + case EOAdaptorBytesType: + { + int bytes = sqlite3_column_bytes(_currentStmt, i); + const void *blob = sqlite3_column_blob(_currentStmt, i); + values[i] = blob ? [attr newValueForBytes:blob + length:bytes] + : [EONull null]; + } + break; + default: + [[NSException exceptionWithName:SQLite3AdaptorExceptionName reason:@"unsupported adaptor value type" userInfo:nil] raise]; + break; + } + } + + ret = [self dictionaryWithObjects:values + forAttributes:_attributesToFetch zone:zone]; + NSZoneFree(zone, values); + if ([_delegate respondsToSelector:@selector(adaptorChannel:didFetchRow:)]) + [_delegate adaptorChannel:self didFetchRow:ret]; + + + while ((_status = sqlite3_step(_currentStmt)) == SQLITE_BUSY) + { + // FIXME sleep? + } + + if (_status != SQLITE_ROW) + { + sqlite3_finalize(_currentStmt); + _currentStmt = NULL; + } + return ret; + } + } + return nil; +} + +- (NSDictionary *) primaryKeyForNewRowWithEntity:(EOEntity *)ent +{ + NSMutableDictionary *ret = [NSMutableDictionary dictionary]; + NSArray *pk = [ent primaryKeyAttributes]; + int i; + int nRows; + int nCols; + char **results; + + // FIXME should probably stop using sqlite3_get_table.. + for (i = 0; i < [pk count]; i++) + { + NSString *tableName = [ent externalName]; + NSString *keyName = [[pk objectAtIndex:i] name]; + NSString *stmt = [NSString stringWithFormat:@"select key from SQLiteEOAdaptorKeySequences where tableName = '%@' AND attributeName = '%@'", tableName, keyName]; + id pkVal; + char *errMsg; + + sqlite3_get_table(_sqlite3Conn, + [stmt cString], + &results, + &nRows, + &nCols, + &errMsg); + if (nRows > 0) + { + pkVal = [NSNumber numberWithInt:atoi(results[1]) + 1]; + stmt = [NSString stringWithFormat:@"UPDATE " \ + @"SQLiteEOAdaptorKeySequences " \ + @"SET key = %i " + @"WHERE tableName = '%@' AND attributeName = '%@'", + [pkVal intValue], tableName, keyName]; + } + else + { + pkVal = [NSNumber numberWithInt:1]; + stmt = [NSString stringWithFormat:@"INSERT into " \ + @"SQLiteEOAdaptorKeySequences " \ + @"(key, tableName, attributeName) " \ + @"VALUES(%i, '%@', '%@')", + [pkVal intValue], tableName, keyName]; + } + + sqlite3_get_table(_sqlite3Conn, + [stmt cString], + &results, + &nRows, + &nCols, + &errMsg); + + [ret setObject: pkVal + forKey:keyName]; + } + return ret; +} + +- (unsigned int) updateValues:(NSDictionary *)values +inRowsDescribedByQualifier:(EOQualifier *)qualifier +entity:(EOEntity *)ent +{ + EOAdaptorContext *ctxt; + EOSQLExpression *expr; + + NSAssert([self isOpen], @"channel is not open"); + NSAssert(!_isFetchInProgress, @"called while fetch in progress"); + + ctxt = [self adaptorContext]; + + + expr = [SQLite3Expression updateStatementForRow:values + qualifier:qualifier + entity:ent]; + [self evaluateExpression:expr]; + return sqlite3_changes(_sqlite3Conn); +} + +- (NSArray *) describeTableNames +{ + NSString *stmt = @"select name from sqlite_master where type='table'"; + EOSQLExpression *expr = [SQLite3Expression expressionForString:stmt]; + EOAttribute *attrib = [[[EOAttribute alloc] init] autorelease]; + NSDictionary *val; + NSMutableArray *arr = [[NSMutableArray alloc] init]; + + [attrib setName:@"tableName"]; + [attrib setColumnName:@"name"]; + [attrib setExternalType:@"TEXT"]; + [attrib setValueClassName:@"NSString"]; + + + + [self evaluateExpression:expr]; + [self setAttributesToFetch:[NSArray arrayWithObject:attrib]]; + while ((val = [self fetchRowWithZone:NULL])) + { + NSString *name = [val objectForKey:@"tableName"]; + if (!([name isEqual:@"SQLiteEOAdaptorKeySequences"] + || [name isEqualToString:@"sqlite_sequence"])) + [arr addObject:name]; + RELEASE(name); + } + return AUTORELEASE([AUTORELEASE(arr) copy]); +} + + +- (NSArray *)describeResults +{ + // FIXME + return [NSArray array]; +} +@end diff --git a/EOAdaptors/SQLiteAdaptor/SQLite3Context.h b/EOAdaptors/SQLiteAdaptor/SQLite3Context.h new file mode 100644 index 0000000..804e5a1 --- /dev/null +++ b/EOAdaptors/SQLiteAdaptor/SQLite3Context.h @@ -0,0 +1,37 @@ +/* + SQLite3Context.h + + Copyright (C) 2006 Free Software Foundation, Inc. + + Author: Matt Rice + Date: 2006 + + This file is part of the GNUstep Database Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef __SQLite3_Context_H + +#include + +@interface SQLite3Context : EOAdaptorContext +{ +} +@end + +#define __SQLite3_Context_H +#endif diff --git a/EOAdaptors/SQLiteAdaptor/SQLite3Context.m b/EOAdaptors/SQLiteAdaptor/SQLite3Context.m new file mode 100644 index 0000000..eb9c683 --- /dev/null +++ b/EOAdaptors/SQLiteAdaptor/SQLite3Context.m @@ -0,0 +1,125 @@ + +/* + SQLite3Context.m + + Copyright (C) 2006 Free Software Foundation, Inc. + + Author: Matt Rice + Date: 2006 + + This file is part of the GNUstep Database Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "SQLite3Adaptor.h" +#include "SQLite3Context.h" +#include "SQLite3Channel.h" + +@implementation SQLite3Context + +- (EOAdaptorChannel *)createAdaptorChannel +{ + return AUTORELEASE([[SQLite3Channel alloc] initWithAdaptorContext:self]); +} + +- (void)beginTransaction +{ + int i, c; + NSAssert(![self transactionNestingLevel], @"nested transactions unsupported"); + NSAssert([self hasOpenChannels], @"no open channels"); + NSAssert(![self hasBusyChannels], @"busy channels during commit."); + + + if (_delegateRespondsTo.shouldBegin) + { + NSAssert([_delegate adaptorContextShouldBegin: self], + @"delegate refuses"); + } + + for (i = 0, c = [_channels count]; i < c; i++) + { + id channel = [[_channels objectAtIndex:i] nonretainedObjectValue]; + if ([channel isOpen]) + { + [channel evaluateExpression: + [EOSQLExpression expressionForString:@"BEGIN TRANSACTION"]]; + break; + } + } + + [self transactionDidBegin]; + + if (_delegateRespondsTo.didBegin) + [_delegate adaptorContextDidBegin: self]; + +} + +- (void) commitTransaction +{ + int i, c; + + NSAssert([self hasOpenTransaction], @"No open transactions to commit"); + NSAssert(![self hasBusyChannels], @"busy channels during commit"); + + if (_delegateRespondsTo.shouldCommit) + NSAssert([_delegate adaptorContextShouldCommit:self], @"delegate refuses to commit"); + + for (i = 0, c = [_channels count]; i < c; i++) + { + id channel = [[_channels objectAtIndex:i] nonretainedObjectValue]; + if ([channel isOpen]) + { + [channel evaluateExpression: + [EOSQLExpression expressionForString:@"COMMIT TRANSACTION"]]; + break; + } + } + [self transactionDidCommit]; + + if (_delegateRespondsTo.didCommit) + [_delegate adaptorContextDidCommit: self]; + +} +- (void) rollbackTransaction +{ + int i, c; + + NSAssert([self hasOpenTransaction], @"No open transactions to rollback"); + NSAssert(![self hasBusyChannels], @"busy channels during rollback"); + + if (_delegateRespondsTo.shouldRollback) + NSAssert([_delegate adaptorContextShouldRollback:self], @"delegate refuses to rollback"); + + for (i = 0, c = [_channels count]; i < c; i++) + { + id channel = [[_channels objectAtIndex:i] nonretainedObjectValue]; + if ([channel isOpen]) + { + [channel evaluateExpression: + [EOSQLExpression expressionForString:@"ROLLBACK TRANSACTION"]]; + break; + } + } + [self transactionDidCommit]; + + if (_delegateRespondsTo.didRollback) + [_delegate adaptorContextDidRollback: self]; + +} + +@end + diff --git a/EOAdaptors/SQLiteAdaptor/SQLite3Expression.h b/EOAdaptors/SQLiteAdaptor/SQLite3Expression.h new file mode 100644 index 0000000..60bb89b --- /dev/null +++ b/EOAdaptors/SQLiteAdaptor/SQLite3Expression.h @@ -0,0 +1,37 @@ +/* + SQLite3Expression.h + + Copyright (C) 2006 Free Software Foundation, Inc. + + Author: Matt Rice + Date: 2006 + + This file is part of the GNUstep Database Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include + +#ifndef SQLite3_SQL_EXPRESSION_H + + +@interface SQLite3Expression : EOSQLExpression + +@end + +#define SQLite3_SQL_EXPRESSION_H +#endif diff --git a/EOAdaptors/SQLiteAdaptor/SQLite3Expression.m b/EOAdaptors/SQLiteAdaptor/SQLite3Expression.m new file mode 100644 index 0000000..ece81c3 --- /dev/null +++ b/EOAdaptors/SQLiteAdaptor/SQLite3Expression.m @@ -0,0 +1,171 @@ + +/* + SQLite3Expression.m + + Copyright (C) 2006 Free Software Foundation, Inc. + + Author: Matt Rice + Date: 2006 + + This file is part of the GNUstep Database Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef GNUSTEP +#include +#include +#endif +#include "SQLite3Expression.h" +#include +#include +#include +#include +#include + +@implementation SQLite3Expression +static NSString *escapeString(NSString *value) +{ + int length = 0, dif, i; + NSMutableString *string = [NSMutableString stringWithFormat: @"%@", value]; + const char *tempString; + + length=[string cStringLength]; + tempString = [string cString]; + + for (i = 0, dif = 0; i < length; i++) + { + switch (tempString[i]) + { + case '\'': + [string insertString: @"'" atIndex: dif + i]; + dif++; + break; + default: + break; + } + } + return string; +} + ++ (NSString *)formatValue: (id)value + forAttribute: (EOAttribute *)attribute +{ + NSString *externalType = [attribute externalType]; + + if (!value) + { + return @"NULL"; + } + else if ([value isEqual: [EONull null]]) + { + return [value sqlString]; + } + else if ([externalType isEqual:@"TEXT"]) + { + return [NSString stringWithFormat:@"'%@'", escapeString(value)]; + } + else if ([externalType isEqual:@"BLOB"]) + { + return [NSString stringWithFormat:@"X'%@'", [(NSData *)value hexadecimalRepresentation]]; + } + else + { + return [NSString stringWithFormat:@"'%@'", escapeString(value)]; + } +} +- (NSString *)lockClause +{ + return @""; // does not support locking.. +} + +- (NSString *)assembleSelectStatementWithAttributes: (NSArray *)attributes + lock: (BOOL)lock + qualifier: (EOQualifier *)qualifier + fetchOrder: (NSArray *)fetchOrder + selectString: (NSString *)selectString + columnList: (NSString *)columnList + tableList: (NSString *)tableList + whereClause: (NSString *)whereClause + joinClause: (NSString *)joinClause + orderByClause: (NSString *)orderByClause + lockClause: (NSString *)lockClause +{ + NSMutableString *sqlString; + + sqlString = [NSMutableString stringWithFormat: @"%@ %@ FROM %@", + selectString, + columnList, + tableList]; + if (whereClause && joinClause) + { + [sqlString appendFormat: @" WHERE (%@) AND (%@)", + whereClause, + joinClause]; + } + else if (whereClause || joinClause) + { + [sqlString appendFormat: @" WHERE %@", + (whereClause ? whereClause : joinClause)]; + } + + if (orderByClause) + [sqlString appendFormat: @" ORDER BY %@", orderByClause]; + + return sqlString; +} + +- (NSString *)columnTypeStringForAttribute:(EOAttribute *)attribute +{ + NSString *typeString = [super columnTypeStringForAttribute:attribute]; + if ([[[attribute entity] primaryKeyAttributes] containsObject:attribute]) + { + return [NSString stringWithFormat:@"%@ %@", typeString, @"PRIMARY KEY"]; + } + return typeString; +} + + ++ (NSArray *)primaryKeySupportStatementsForEntityGroup: (NSArray *)entityGroup +{ + return [NSArray array]; +} + ++ (NSArray *)dropPrimaryKeySupportStatementsForEntityGroup: (NSArray *)entityGroup +{ + return [NSArray array]; +} + +// TODO find a better way to do this? ++ (NSArray *)primaryKeyConstraintStatementsForEntityGroup:(NSArray *)entityGroup +{ + NSString *keyTable; + keyTable = @"CREATE TABLE IF NOT EXISTS 'SQLiteEOAdaptorKeySequences' (" \ + @"seq_key INTEGER PRIMARY KEY AUTOINCREMENT, " \ + @"tableName TEXT, " \ + @"attributeName TEXT, " \ + @"key INTEGER" \ + @")"; + return [NSArray arrayWithObject:[self expressionForString:keyTable]]; +} + ++ (NSArray *)dropPrimaryKeyConstraintStatementsForEntityGroup:(NSArray *)entityGroup +{ + return [NSArray arrayWithObject:[self expressionForString:@"DROP TABLE 'SQLiteEOAdaptorKeySequences'"]]; +} + +@end + diff --git a/EOAdaptors/SQLiteAdaptor/TODO b/EOAdaptors/SQLiteAdaptor/TODO new file mode 100644 index 0000000..97f3193 --- /dev/null +++ b/EOAdaptors/SQLiteAdaptor/TODO @@ -0,0 +1,4 @@ +login panel.. +verify delegate messages.. +stored procedures.. + diff --git a/config/sqlite3.m4 b/config/sqlite3.m4 new file mode 100644 index 0000000..29e7794 --- /dev/null +++ b/config/sqlite3.m4 @@ -0,0 +1,59 @@ +dnl AM_PATH_SQLITE3([, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +AC_DEFUN(AM_PATH_SQLITE3,[ + AC_ARG_WITH(sqlite3-include, + [ --with-sqlite3-include=PATH include path for sqlite3 headers], + sqlite3_incdir="$withval", sqlite3_incdir=) + + AC_ARG_WITH(sqlite3-library, + [ --with-sqlite3-library=PATH library path for sqlite3 libraries], + sqlite3="$withval", sqlite3_libdir=) + + cppflags_temp="$CPPFLAGS" + libs_temp=$LIBS + + AC_CHECK_PROG(PKGCONFIG, pkg-config, yes, no) + + if test $PKGCONFIG = "yes" ; then + if test -z "$sqlite3_incdir" ; then + sqlite3_incdir=`pkg-config sqlite3 --cflags` + fi + if test -z "$sqlite3_libdir" ; then + sqlite3_libdir=`pkg-config sqlite3 --libs-only-L` + fi + fi + + CPPFLAGS="$sqlite3_incdir $CPPFLAGS" + LIBS="$sqlite3_libdir $LIBS" + + SQLITE3_DATABASE="no" + + AC_CHECK_HEADERS(sqlite3.h) + if test $ac_cv_header_sqlite3_h = yes; then + AC_CHECK_LIB(sqlite3, main, sqlite3_ok=yes, sqlite3_ok=no) + + if test "$sqlite3_ok" = yes; then + SQLITE3_INCLUDES="$CPPFLAGS" + SQLITE3_LIB_DIRS="$LIBS" + SQLITE3_LIBS="-lsqlite3" + SQLITE3_DATABASE="yes" + fi + fi + + AC_MSG_CHECKING(for SQLite3 database) + if test $SQLITE3_DATABASE = yes; then + AC_MSG_RESULT(yes) + ifelse([$1], , :, [$1]) + else + AC_MSG_RESULT(no) + ifelse([$2], , :, [$2]) + fi + + CPPFLAGS="$cppflags_temp" + LIBS="$libs_temp" + + AC_SUBST(SQLITE3_DATABASE) + AC_SUBST(SQLITE3_INCLUDES) + AC_SUBST(SQLITE3_LIB_DIRS) + AC_SUBST(SQLITE3_LIBS) +]) + diff --git a/configure b/configure index 4e4d77c..46d5a61 100755 --- a/configure +++ b/configure @@ -308,7 +308,7 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS PG_CONFIG CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP POSTGRES_DATABASE POSTGRES_INCLUDES POSTGRES_LIB_DIRS POSTGRES_LIBS EOADAPTORS SUBPROJECTS VERSION MAJOR_VERSION MINOR_VERSION SUBMINOR_VERSION GCC_VERSION LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS PG_CONFIG CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP POSTGRES_DATABASE POSTGRES_INCLUDES POSTGRES_LIB_DIRS POSTGRES_LIBS PKGCONFIG SQLITE3_DATABASE SQLITE3_INCLUDES SQLITE3_LIB_DIRS SQLITE3_LIBS EOADAPTORS SUBPROJECTS VERSION MAJOR_VERSION MINOR_VERSION SUBMINOR_VERSION GCC_VERSION LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -718,13 +718,13 @@ echo X"$0" | /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then + if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi -if test ! -r $srcdir/$ac_unique_file; then +if test ! -r "$srcdir/$ac_unique_file"; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } @@ -733,7 +733,7 @@ if test ! -r $srcdir/$ac_unique_file; then { (exit 1); exit 1; }; } fi fi -(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || +(cd $srcdir && test -r "./$ac_unique_file") 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` @@ -846,6 +846,8 @@ Optional Packages: --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pgsql-include=PATH include path for postgres headers --with-pgsql-library=PATH library path for pgsql libraries + --with-sqlite3-include=PATH include path for sqlite3 headers + --with-sqlite3-library=PATH library path for sqlite3 libraries Some influential environment variables: CC C compiler command @@ -947,7 +949,7 @@ esac else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi - cd "$ac_popdir" + cd $ac_popdir done fi @@ -1877,7 +1879,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -1935,7 +1938,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2051,7 +2055,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2105,7 +2110,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2150,7 +2156,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2194,7 +2201,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2517,7 +2525,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2687,7 +2696,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2827,7 +2837,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2975,7 +2986,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3062,7 +3074,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3135,7 +3148,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3187,6 +3201,8 @@ fi if test $enable_pgsql = yes; then EOADAPTORS="$EOADAPTORS PostgreSQLAdaptor" + ac_config_files="$ac_config_files EOAdaptors/PostgreSQLAdaptor/GNUmakefile EOAdaptors/PostgreSQLAdaptor/config.mak" + HAVE_PGSQL=1 # AC_DEFINE(HAVE_LIBXML,1, @@ -3195,6 +3211,335 @@ else HAVE_PGSQL=0 fi +#-------------------------------------------------------------------- +# Check for SQLite3 database +#-------------------------------------------------------------------- + + +# Check whether --with-sqlite3-include or --without-sqlite3-include was given. +if test "${with_sqlite3_include+set}" = set; then + withval="$with_sqlite3_include" + sqlite3_incdir="$withval" +else + sqlite3_incdir= +fi; + + +# Check whether --with-sqlite3-library or --without-sqlite3-library was given. +if test "${with_sqlite3_library+set}" = set; then + withval="$with_sqlite3_library" + sqlite3="$withval" +else + sqlite3_libdir= +fi; + + cppflags_temp="$CPPFLAGS" + libs_temp=$LIBS + + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_PKGCONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$PKGCONFIG"; then + ac_cv_prog_PKGCONFIG="$PKGCONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PKGCONFIG="yes" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_PKGCONFIG" && ac_cv_prog_PKGCONFIG="no" +fi +fi +PKGCONFIG=$ac_cv_prog_PKGCONFIG +if test -n "$PKGCONFIG"; then + echo "$as_me:$LINENO: result: $PKGCONFIG" >&5 +echo "${ECHO_T}$PKGCONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + + if test $PKGCONFIG = "yes" ; then + if test -z "$sqlite3_incdir" ; then + sqlite3_incdir=`pkg-config sqlite3 --cflags` + fi + if test -z "$sqlite3_libdir" ; then + sqlite3_libdir=`pkg-config sqlite3 --libs-only-L` + fi + fi + + CPPFLAGS="$sqlite3_incdir $CPPFLAGS" + LIBS="$sqlite3_libdir $LIBS" + + SQLITE3_DATABASE="no" + + +for ac_header in sqlite3.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + if test $ac_cv_header_sqlite3_h = yes; then + echo "$as_me:$LINENO: checking for main in -lsqlite3" >&5 +echo $ECHO_N "checking for main in -lsqlite3... $ECHO_C" >&6 +if test "${ac_cv_lib_sqlite3_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsqlite3 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_sqlite3_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_sqlite3_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_sqlite3_main" >&5 +echo "${ECHO_T}$ac_cv_lib_sqlite3_main" >&6 +if test $ac_cv_lib_sqlite3_main = yes; then + sqlite3_ok=yes +else + sqlite3_ok=no +fi + + + if test "$sqlite3_ok" = yes; then + SQLITE3_INCLUDES="$CPPFLAGS" + SQLITE3_LIB_DIRS="$LIBS" + SQLITE3_LIBS="-lsqlite3" + SQLITE3_DATABASE="yes" + fi + fi + + echo "$as_me:$LINENO: checking for SQLite3 database" >&5 +echo $ECHO_N "checking for SQLite3 database... $ECHO_C" >&6 + if test $SQLITE3_DATABASE = yes; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + enable_sqlite3=yes + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + enable_sqlite3=no + fi + + CPPFLAGS="$cppflags_temp" + LIBS="$libs_temp" + + + + + + +if test $enable_sqlite3 = yes; then + EOADAPTORS="$EOADAPTORS SQLiteAdaptor" + ac_config_files="$ac_config_files EOAdaptors/SQLiteAdaptor/GNUmakefile" + + HAVE_SQLITE3=1 +else + HAVE_SQLITE3=0 +fi + @@ -3232,7 +3577,7 @@ echo "${ECHO_T}$VERSION" >&6 #-------------------------------------------------------------------- # Write the Makefiles #-------------------------------------------------------------------- - ac_config_files="$ac_config_files gdl2.make GNUmakefile EOAdaptors/GNUmakefile EOAdaptors/PostgreSQLAdaptor/GNUmakefile EOAdaptors/PostgreSQLAdaptor/config.mak" + ac_config_files="$ac_config_files gdl2.make GNUmakefile EOAdaptors/GNUmakefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -3758,11 +4103,12 @@ for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. + "EOAdaptors/PostgreSQLAdaptor/GNUmakefile" ) CONFIG_FILES="$CONFIG_FILES EOAdaptors/PostgreSQLAdaptor/GNUmakefile" ;; + "EOAdaptors/PostgreSQLAdaptor/config.mak" ) CONFIG_FILES="$CONFIG_FILES EOAdaptors/PostgreSQLAdaptor/config.mak" ;; + "EOAdaptors/SQLiteAdaptor/GNUmakefile" ) CONFIG_FILES="$CONFIG_FILES EOAdaptors/SQLiteAdaptor/GNUmakefile" ;; "gdl2.make" ) CONFIG_FILES="$CONFIG_FILES gdl2.make" ;; "GNUmakefile" ) CONFIG_FILES="$CONFIG_FILES GNUmakefile" ;; "EOAdaptors/GNUmakefile" ) CONFIG_FILES="$CONFIG_FILES EOAdaptors/GNUmakefile" ;; - "EOAdaptors/PostgreSQLAdaptor/GNUmakefile" ) CONFIG_FILES="$CONFIG_FILES EOAdaptors/PostgreSQLAdaptor/GNUmakefile" ;; - "EOAdaptors/PostgreSQLAdaptor/config.mak" ) CONFIG_FILES="$CONFIG_FILES EOAdaptors/PostgreSQLAdaptor/config.mak" ;; "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} @@ -3862,6 +4208,11 @@ s,@POSTGRES_DATABASE@,$POSTGRES_DATABASE,;t t s,@POSTGRES_INCLUDES@,$POSTGRES_INCLUDES,;t t s,@POSTGRES_LIB_DIRS@,$POSTGRES_LIB_DIRS,;t t s,@POSTGRES_LIBS@,$POSTGRES_LIBS,;t t +s,@PKGCONFIG@,$PKGCONFIG,;t t +s,@SQLITE3_DATABASE@,$SQLITE3_DATABASE,;t t +s,@SQLITE3_INCLUDES@,$SQLITE3_INCLUDES,;t t +s,@SQLITE3_LIB_DIRS@,$SQLITE3_LIB_DIRS,;t t +s,@SQLITE3_LIBS@,$SQLITE3_LIBS,;t t s,@EOADAPTORS@,$EOADAPTORS,;t t s,@SUBPROJECTS@,$SUBPROJECTS,;t t s,@VERSION@,$VERSION,;t t @@ -4033,6 +4384,11 @@ esac + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ @@ -4071,12 +4427,6 @@ echo "$as_me: error: cannot find input file: $f" >&2;} fi;; esac done` || { (exit 1); exit 1; } - - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub diff --git a/configure.ac b/configure.ac index 2ef821d..40a4ca9 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA builtin(include, config/postgres.m4)dnl - +builtin(include, config/sqlite3.m4)dnl AC_INIT if test -z "$GNUSTEP_SYSTEM_ROOT"; then @@ -40,6 +40,7 @@ AC_CONFIG_HEADER(config.h) AM_PATH_PGSQL(enable_pgsql=yes, enable_pgsql=no) if test $enable_pgsql = yes; then EOADAPTORS="$EOADAPTORS PostgreSQLAdaptor" + AC_CONFIG_FILES([EOAdaptors/PostgreSQLAdaptor/GNUmakefile EOAdaptors/PostgreSQLAdaptor/config.mak]) HAVE_PGSQL=1 # AC_DEFINE(HAVE_LIBXML,1, @@ -48,6 +49,18 @@ else HAVE_PGSQL=0 fi +#-------------------------------------------------------------------- +# Check for SQLite3 database +#-------------------------------------------------------------------- +AM_PATH_SQLITE3(enable_sqlite3=yes, enable_sqlite3=no) +if test $enable_sqlite3 = yes; then + EOADAPTORS="$EOADAPTORS SQLiteAdaptor" + AC_CONFIG_FILES([EOAdaptors/SQLiteAdaptor/GNUmakefile]) + HAVE_SQLITE3=1 +else + HAVE_SQLITE3=0 +fi + AC_SUBST(EOADAPTORS) @@ -79,5 +92,5 @@ AC_SUBST(GCC_VERSION) #-------------------------------------------------------------------- # Write the Makefiles #-------------------------------------------------------------------- -AC_CONFIG_FILES([gdl2.make GNUmakefile EOAdaptors/GNUmakefile EOAdaptors/PostgreSQLAdaptor/GNUmakefile EOAdaptors/PostgreSQLAdaptor/config.mak]) +AC_CONFIG_FILES([gdl2.make GNUmakefile EOAdaptors/GNUmakefile]) AC_OUTPUT