[View]  [Edit]  [Lock]  [References]  [Attachments]  [History]  [Home]  [Changes]  [Search]  [Help] 
[coco8] Accessing iOS local Databases with S8
How to access local databases  in iOS devices, using S8
The SQLite database engine is built-in to the iOS (and Android) operating system.
SQLite is considered an industry standard for lightweight embedded SQL database programming.
S8 currently accesses SQLite DB Engine by wrapping a third-party Objective-C library called  
FMDB. (Building a direct interface avoiding third-parties libs is a work in progress).
So... By now, Be sure to have installed the following FMDB classes in your XCode project:
- FMDatabase
 - FMDatabaseAdditions
 - FMDatabasePool
 - FMDatabaseQueue
 - FMDB
 - FMResultSet
 
(You can find the latest version of these classes  here )
S8 API for Local Database accessing
Creating a Database
A Database is an instance of FMDatabase
An FMDatabase is created with a path to an actual SQLite database file. If it doesn't exist it will be created.
The following snippet code create an instance of an FMDatabase on 'Sample.sqlite' sqlite database
 | db |
	db := FMDatabase withPath: 'Sample.sqlite' asLocalPathName.
 
Open and Close a Database
An instance of FMDatabase can be opened and closed using the standard protocol 
FMDatabase>>#open
and 
FMDatabase>>#close
both of them returns a boolean representing the success of the operation.
Sample Code
 | db |
	db := FMDatabase withPath: 'Sample.sqlite' asLocalPathName.
        db open ifTrue: [ self print: 'DB Opened Successfully'.].
        db close ifTrue: [ self print: 'DB Closed Successfully'.].
 
Create a Table
A table creation, as well as insertion, modification or deletion of data, is an update to the database, so, it will be done using the standard protocol 
FMDatabase>>#executeUpdate: sqlStatement
It  returns a boolean representing the success of the operation.
Sample Code
 | db |
	db := FMDatabase withPath: 'Sample.sqlite' asLocalPathName.
        db open ifTrue: [
		success := db executeUpdate:'create table if not exists Books(Id INTEGER PRIMARY KEY, Title TEXT, Author TEXT, Pages INTEGER)'.
		success ifTrue: [self print: 'Table Created successfully'.]
				ifFalse: [self print: 'Can not create the table - '. ].
		db close.
	].
 
Inserting Records
This is another update to the database, so, it will be done using the standard protocol 
FMDatabase>>#executeUpdate: sqlStatement
It  returns a boolean representing the success of the operation.
Sample Code
 | db |
	db open ifTrue: [
		db executeUpdate: 'insert into Books (Title, Author, Pages) values (?,?,?)' withArgumentsInArray: #('Smalltalk-80: The Language and its Implementation'  'Adele Goldberg' 714).
		db executeUpdate: 'insert into Books (Title, Author, Pages) values (?,?,?)' withArgumentsInArray: #('Smalltalk, Objects, and Design'  'Chamond Liu' 289).
		db executeUpdate: 'insert into Books (Title, Author, Pages) values (?,?,?)' withArgumentsInArray: #('Smalltalk With Style'  'Edward Klimas' 127).
		db executeUpdate: 'insert into Books (Title, Author, Pages) values (?,?,?)' withArgumentsInArray: #('Smalltalk Best Practice Patterns 1st Edition'  'Kent Beck' 240).
		db close. 
	]. 
 
Retrieving Records
 It will be done using the standard protocol 
FMDatabase>>#executeQuery: sqlQueryStatement
It  returns a FMResultSet.
In the following Sample Code, You can see how to retrieve records, and how to deal with the answered  resultSet
 | db |
		db open ifTrue: [
		rs := db executeQuery: 'select * from Books where Pages > 200'.
		[rs next ] whileTrue: [
			self print: (' // ', (rs stringForColumn: 'Title')). 
		].
		db close. 
	]. 
 
In addition to FMResultSet>>#stringForColumn: aColumnName
FMResultSet provides us with similar messages:
- FMResultSet>>#intForColumn: aColumnName
 - FMResultSet>>#doubleForColumn: aColumnName
 - FMResultSet>>#boolForColumn: aColumnName
 - FMResultSet>>#dataForColumn: aColumnName
 - FMResultSet>>#objectForColumn: aColumnName
 
And if You prefer to identify the column by its index instead of it's name:
- FMResultSet>>#StringForColumnIndex: aColumnIndex
 - FMResultSet>>#intForColumnIndex: aColumnIndex
 - FMResultSet>>#doubleForColumnIndex: aColumnIndex
 - FMResultSet>>#boolForColumnIndex: aColumnIndex
 - FMResultSet>>#dataForColumnIndex: aColumnIndex
 - FMResultSet>>#objectForColumnIndex: aColumnIndex