Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Added support for explicit ":memory:" database path. #117

Open
wants to merge 5 commits into from

2 participants

@dodikk

The user will be able to pass ":memory:" database path explicitly
EmbeddedSources@a34f2fd

@ccgus
Owner

I'm not sure an explicit :memory: method is needed- what's wrong with the current method? Is there something I'm missing? And I'm not sure a new classes for errors is needed either. I don't want to add anything that isn't needed.

@dodikk

I'm not sure an explicit :memory: method is needed- what's wrong with the current method?

Well, users of libSqlite.a are used to explicit ":memory:" constant usage. I had some issues in my prototype and was not sure whether [ @":memory:" fileSystemRepresentation ] left it as is.
Anyway, this explicit check makes the code more clear and you no longer depend on "fileSystemRepresentation" API that may be changed by Apple.

And I'm not sure a new classes for errors is needed either.

This will make easier to handle errors in the application code. Sometimes you need to replace the low level error message with some more user friendly one.
In other words, you no more write |if ( [ error_.domain isEqualToString: @"FMDatabase" ] )| to achieve this. Instead you write a categories for your custom error classes. |@interface FMError( UserFriendlyError )|

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
4 .gitignore
@@ -4,3 +4,7 @@ build
*.xcodeproj/*.perspectivev3
*.xcodeproj/xcuserdata
fmdb.xcodeproj/*.mode1v3
+._*
+*xcworkspace*
+*xcuserdata*
+
View
13 FMError.h
@@ -0,0 +1,13 @@
+//
+// FMError.h
+// fmdb
+//
+// Created by Oleksandr Dodatko on 1/10/13.
+//
+//
+
+#import <Foundation/Foundation.h>
+
+@interface FMError : NSError
+
+@end
View
13 FMError.m
@@ -0,0 +1,13 @@
+//
+// FMError.m
+// fmdb
+//
+// Created by Oleksandr Dodatko on 1/10/13.
+//
+//
+
+#import "FMError.h"
+
+@implementation FMError
+
+@end
View
37 fmdb.xcodeproj/project.pbxproj
@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
+ 7E98261F169F252F00013023 /* FMError.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E98261D169F252F00013023 /* FMError.h */; };
+ 7E982620169F252F00013023 /* FMError.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E98261E169F252F00013023 /* FMError.m */; };
8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
8DD76F9F0486AA7600D96B5E /* fmdb.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6859EA3029092ED04C91782 /* fmdb.1 */; };
CC47A00F148581E9002CCDAB /* FMDatabaseQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = CC47A00D148581E9002CCDAB /* FMDatabaseQueue.h */; };
@@ -51,6 +53,8 @@
/* Begin PBXFileReference section */
08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
32A70AAB03705E1F00C91783 /* fmdb_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fmdb_Prefix.pch; sourceTree = "<group>"; };
+ 7E98261D169F252F00013023 /* FMError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMError.h; sourceTree = "<group>"; };
+ 7E98261E169F252F00013023 /* FMError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMError.m; sourceTree = "<group>"; };
8DD76FA10486AA7600D96B5E /* fmdb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fmdb; sourceTree = BUILT_PRODUCTS_DIR; };
C6859EA3029092ED04C91782 /* fmdb.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = fmdb.1; sourceTree = "<group>"; };
CC47A00D148581E9002CCDAB /* FMDatabaseQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FMDatabaseQueue.h; path = src/FMDatabaseQueue.h; sourceTree = "<group>"; };
@@ -128,6 +132,8 @@
CC9E4EB813B31188005F9210 /* FMDatabasePool.m */,
32A70AAB03705E1F00C91783 /* fmdb_Prefix.pch */,
CCC24EBE0A13E34D00A6D3E3 /* fmdb.m */,
+ 7E98261D169F252F00013023 /* FMError.h */,
+ 7E98261E169F252F00013023 /* FMError.m */,
);
name = Source;
sourceTree = "<group>";
@@ -171,15 +177,16 @@
EE42910912B42FD00088BD94 /* FMResultSet.h in Headers */,
CC9E4EBA13B31188005F9210 /* FMDatabasePool.h in Headers */,
CC47A00F148581E9002CCDAB /* FMDatabaseQueue.h in Headers */,
+ 7E98261F169F252F00013023 /* FMError.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
- 8DD76F960486AA7600D96B5E /* fmdb */ = {
+ 8DD76F960486AA7600D96B5E /* fmdb-demo */ = {
isa = PBXNativeTarget;
- buildConfigurationList = 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "fmdb" */;
+ buildConfigurationList = 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "fmdb-demo" */;
buildPhases = (
8DD76F990486AA7600D96B5E /* Sources */,
8DD76F9B0486AA7600D96B5E /* Frameworks */,
@@ -189,7 +196,7 @@
);
dependencies = (
);
- name = fmdb;
+ name = "fmdb-demo";
productInstallPath = "$(HOME)/bin";
productName = fmdb;
productReference = 8DD76FA10486AA7600D96B5E /* fmdb */;
@@ -234,7 +241,7 @@
projectDirPath = "";
projectRoot = "";
targets = (
- 8DD76F960486AA7600D96B5E /* fmdb */,
+ 8DD76F960486AA7600D96B5E /* fmdb-demo */,
EE4290EE12B42F870088BD94 /* FMDB */,
);
};
@@ -263,6 +270,7 @@
EE42910A12B42FD20088BD94 /* FMResultSet.m in Sources */,
CC9E4EBB13B31188005F9210 /* FMDatabasePool.m in Sources */,
CC47A011148581E9002CCDAB /* FMDatabaseQueue.m in Sources */,
+ 7E982620169F252F00013023 /* FMError.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -282,9 +290,7 @@
GCC_PREFIX_HEADER = fmdb_Prefix.pch;
INSTALL_PATH = "$(HOME)/bin";
LIBRARY_SEARCH_PATHS = "$(LIBRARY_SEARCH_PATHS)";
- MACOSX_DEPLOYMENT_TARGET = 10.7;
PRODUCT_NAME = fmdb;
- SDKROOT = macosx;
};
name = Debug;
};
@@ -300,9 +306,7 @@
GCC_PREFIX_HEADER = fmdb_Prefix.pch;
INSTALL_PATH = "$(HOME)/bin";
LIBRARY_SEARCH_PATHS = "$(LIBRARY_SEARCH_PATHS)";
- MACOSX_DEPLOYMENT_TARGET = 10.7;
PRODUCT_NAME = fmdb;
- SDKROOT = macosx;
};
name = Release;
};
@@ -310,26 +314,22 @@
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
- GCC_C_LANGUAGE_STANDARD = c99;
- GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_MISSING_PARENTHESES = YES;
GCC_WARN_PEDANTIC = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.7;
};
name = Debug;
};
1DEB927A08733DD40010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- GCC_C_LANGUAGE_STANDARD = c99;
- GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.7;
};
name = Release;
};
@@ -337,10 +337,14 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.0;
PRODUCT_NAME = FMDB;
+ SDKROOT = iphoneos;
};
name = Debug;
};
@@ -348,9 +352,12 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ENABLE_OBJC_ARC = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ IPHONEOS_DEPLOYMENT_TARGET = 5.0;
PRODUCT_NAME = FMDB;
+ SDKROOT = iphoneos;
ZERO_LINK = NO;
};
name = Release;
@@ -358,7 +365,7 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
- 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "fmdb" */ = {
+ 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "fmdb-demo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB927508733DD40010E9CD /* Debug */,
View
75 src/FMDatabase.m
@@ -2,6 +2,8 @@
#import "unistd.h"
#import <objc/runtime.h>
+#import "FMError.h"
+
@interface FMDatabase ()
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args;
@@ -72,12 +74,50 @@ - (sqlite3*)sqliteHandle {
return _db;
}
-- (BOOL)open {
- if (_db) {
++(BOOL)isMemoryPath:( NSString* )dbPath_
+{
+ if ( nil == dbPath_ )
+ {
+ return YES;
+ }
+ else if ( [dbPath_ isEqualToString: @":memory:" ] )
+ {
return YES;
}
+
+ return NO;
+}
+
+-(BOOL)isMemoryPath:( NSString* )dbPath_
+{
+ return [ [ self class ] isMemoryPath: dbPath_ ];
+}
+
+-(const char* )fileNameForOpening
+{
+ const char* fileName_ = NULL;
+ if ( [ self isMemoryPath: self->_databasePath ] )
+ {
+ fileName_ = ":memory:";
+ }
+ else
+ {
+ fileName_ = [ self->_databasePath fileSystemRepresentation ];
+ }
+
+ return fileName_;
+}
+
+- (BOOL)open
+{
+ if (_db)
+ {
+ return YES;
+ }
+
+ const char* fileName_ = [ self fileNameForOpening ];
+ int err = sqlite3_open( fileName_, &_db );
- int err = sqlite3_open((_databasePath ? [_databasePath fileSystemRepresentation] : ":memory:"), &_db );
if(err != SQLITE_OK) {
NSLog(@"error opening!: %d", err);
return NO;
@@ -87,9 +127,12 @@ - (BOOL)open {
}
#if SQLITE_VERSION_NUMBER >= 3005000
-- (BOOL)openWithFlags:(int)flags {
- int err = sqlite3_open_v2((_databasePath ? [_databasePath fileSystemRepresentation] : ":memory:"), &_db, flags, NULL /* Name of VFS module to use */);
- if(err != SQLITE_OK) {
+- (BOOL)openWithFlags:(int)flags
+{
+ const char* fileName_ = [ self fileNameForOpening ];
+ int err = sqlite3_open_v2( fileName_, &_db, flags, NULL /* Name of VFS module to use */);
+ if(err != SQLITE_OK)
+ {
NSLog(@"error opening!: %d", err);
return NO;
}
@@ -288,15 +331,14 @@ - (int)lastErrorCode {
return sqlite3_errcode(_db);
}
-
-(NSError*)errorWithMessage:( NSString* )message_
{
NSDictionary* errorMessage_ = [ NSDictionary dictionaryWithObject: message_
forKey: NSLocalizedDescriptionKey];
- return [NSError errorWithDomain:@"FMDatabase"
- code:sqlite3_errcode(_db)
- userInfo:errorMessage_];
+ return [ FMError errorWithDomain:@"FMDatabase"
+ code:sqlite3_errcode(_db)
+ userInfo:errorMessage_];
}
-(NSError*)lastError
@@ -708,9 +750,20 @@ - (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArra
do {
retry = NO;
rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0);
- if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) {
+
+ // SQLITE_ERROR is received instead of SQLITE_LOCKED on indexing a table when some parallel "insert" operations executing.
+ BOOL createIndexWorkaroundCondition_ = (SQLITE_ERROR == rc);
+
+ if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc || createIndexWorkaroundCondition_ )
+ {
retry = YES;
usleep(20);
+
+ if ( createIndexWorkaroundCondition_ )
+ {
+ NSLog( @"[FMDatabase] : CREATE INDEX workaround applied." );
+ NSLog( @"DB path : %@", self->_databasePath );
+ }
if (_busyRetryTimeout && (numberOfRetries++ > _busyRetryTimeout)) {
NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]);
View
3  src/FMDatabaseAdditions.m
@@ -8,6 +8,7 @@
#import "FMDatabase.h"
#import "FMDatabaseAdditions.h"
+#import "FMError.h"
@interface FMDatabase (PrivateStuff)
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args;
@@ -139,7 +140,7 @@ - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error {
else if (rc != SQLITE_OK) {
validationSucceeded = NO;
if (error) {
- *error = [NSError errorWithDomain:NSCocoaErrorDomain
+ *error = [FMError errorWithDomain: @"FMDatabase"
code:[self lastErrorCode]
userInfo:[NSDictionary dictionaryWithObject:[self lastErrorMessage]
forKey:NSLocalizedDescriptionKey]];
Something went wrong with that request. Please try again.