Build and Run
Description — Build and run a starter app to validate your install of Couchbase Lite on C
- Steps in Getting Started
-
Install | Build
Verify Install
Now you have Couchbase Lite for C installed, you can verify that your apps build correctly.
Enter the C and C++ code from Example 1 into your editor of choice and build it.
Running it creates a database, adds a document, retrieves the document, updates the document and then deletes the document.
-
C
-
C++
// Purpose-- provide an overview of available crud and sync functionality
//
// Get the database (and create it if it doesn't exist)
CBLError err = {};
CBLDatabase* database = CBLDatabase_Open(FLSTR("mydb"), NULL, &err);
if(!database) {
// Error handling. For brevity, this is truncated in the rest of the snippet
// and omitted in other doc code snippets
fprintf(stderr, "Error opening database (%d / %d)\n", err.domain, err.code);
FLSliceResult msg = CBLError_Message(&err);
fprintf(stderr, "%.*s\n", (int)msg.size, (const char *)msg.buf);
FLSliceResult_Release(msg);
return;
}
// All CRUD operations must be carried out via a collection.
// Remember to release the collection using CBLCollection_Release() when done.
CBLCollection* collection = CBLDatabase_DefaultCollection(database, &err);
// The lack of 'const' indicates this document is mutable
// Create a new document (i.e. a record) in the database
CBLDocument* mutableDoc = CBLDocument_Create();
FLMutableDict properties = CBLDocument_MutableProperties(mutableDoc);
FLMutableDict_SetFloat(properties, FLSTR("version"), 3.0f);
// Save it to the database
if(!CBLCollection_SaveDocument(collection, mutableDoc, &err)) {
// Failed to save, do error handling as above
return;
}
// Since we will release the document, make a copy of the ID since it
// is an internal pointer. Whenever we create or get an FLSliceResult
// or FLStringResult we will need to free it later too!
FLString id = CBLDocument_ID(mutableDoc);
CBLDocument_Release(mutableDoc);
// Update a document
mutableDoc = CBLCollection_GetMutableDocument(collection, id, &err);
if(!mutableDoc) {
// Failed to retrieve, do error handling as above. NOTE: error code 0 simply means
// the document does not exist.
return;
}
properties = CBLDocument_MutableProperties(mutableDoc);
FLMutableDict_SetString(properties, FLSTR("language"), FLSTR("C"));
if(!CBLCollection_SaveDocument(collection, mutableDoc, &err)) {
// Failed to save, do error handling as above
return;
}
// Note const here, means readonly
const CBLDocument* docAgain = CBLCollection_GetDocument(collection, id, &err);
if(!docAgain) {
// Failed to retrieve, do error handling as above. NOTE: error code 0 simply means
// the document does not exist.
return;
}
// No copy this time, so no release later (notice it is not FLStringResult this time)
FLString retrievedID = CBLDocument_ID(docAgain);
FLDict retrievedProperties = CBLDocument_Properties(docAgain);
FLString retrievedLanguage = FLValue_AsString(FLDict_Get(retrievedProperties, FLSTR("language")));
printf("Document ID :: %.*s\n", (int)retrievedID.size, (const char *)retrievedID.buf);
printf("Learning %.*s\n", (int)retrievedLanguage.size, (const char *)retrievedLanguage.buf);
CBLDocument_Release(mutableDoc);
CBLDocument_Release(docAgain);
// Create a query to fetch documents of type SDK
int errorPos;
CBLQuery* query = CBLDatabase_CreateQuery(
database,
kCBLN1QLLanguage,
FLSTR("SELECT * FROM _ WHERE type = \"SDK\""), &errorPos, &err);
if(!query) {
// Failed to create query, do error handling as above
// Note that errorPos will contain the position in the N1QL string
// that the parse failed, if applicable
return;
}
CBLResultSet* result = CBLQuery_Execute(query, &err);
if(!result) {
// Failed to run query, do error handling as above
return;
}
CBLResultSet_Release(result);
CBLQuery_Release(query);
// Create replicator to push and pull changes to and from the cloud
CBLCollectionConfiguration collectionConfig = {};
collectionConfig.collection = collection;
CBLEndpoint* targetEndpoint = CBLEndpoint_CreateWithURL(FLSTR("ws://localhost:4984/getting-started-db"), &err);
if(!targetEndpoint) {
// Failed to create endpoint, do error handling as above
return;
}
CBLReplicatorConfiguration replConfig = {};
replConfig.collections = &collectionConfig;
replConfig.collectionCount = 1;
replConfig.endpoint = targetEndpoint;
CBLAuthenticator* basicAuth = CBLAuth_CreatePassword(FLSTR("john"), FLSTR("pass"));
replConfig.authenticator = basicAuth;
CBLReplicator* replicator = CBLReplicator_Create(&replConfig, &err);
CBLAuth_Free(basicAuth);
CBLEndpoint_Free(targetEndpoint);
if(!replicator) {
// Failed to create replicator, do error handling as above
return;
}
// Assume a function like the following sample
//
// static void getting_started_change_listener(void* context, CBLReplicator* repl, const CBLReplicatorStatus* status) {
// if(status->error.code != 0) {
// printf("Error %d / %d\n", status->error.domain, status->error.code);
// }
// }
CBLListenerToken* token = CBLReplicator_AddChangeListener(replicator, getting_started_change_listener, NULL);
CBLReplicator_Start(replicator, false);
// Later, stop and release the replicator
// When finished release resources ... eg
CBLListener_Remove(token);
stop_replicator(replicator);
CBLCollection_Release(collection);
CBLDatabase_Release(database);
// Purpose-- provide an overview of available CRUD and sync functionality
//
// The C++ API reports failures by throwing cbl::Error. For brevity this
// try/catch is shown only here and is omitted in the other doc snippets.
try {
// Get the database (and create it if it doesn't exist)
cbl::Database database("mydb");
// All CRUD operations must be carried out via a collection. C++ objects
// are ref-counted, so there is no explicit release/close to remember.
cbl::Collection collection = database.getDefaultCollection();
// Create a new document (i.e. a record) in the database. Passing nullptr
// gives it an auto-generated ID. 'Mutable' means its properties can change.
cbl::MutableDocument mutableDoc(nullptr);
mutableDoc["version"] = 3.0f;
// Save it to the database
collection.saveDocument(mutableDoc);
// Keep the auto-generated ID so we can fetch the document again
std::string id = mutableDoc.id();
// Update a document
mutableDoc = collection.getMutableDocument(id);
mutableDoc["language"] = "C++";
collection.saveDocument(mutableDoc);
// Read it back (a cbl::Document, unlike cbl::MutableDocument, is read-only)
cbl::Document docAgain = collection.getDocument(id);
std::cout << "Document ID :: " << docAgain.id() << std::endl;
std::cout << "Learning " << docAgain["language"].asstring() << std::endl;
// Create a query to fetch documents of type SDK
cbl::Query query(database, kCBLN1QLLanguage,
"SELECT * FROM _ WHERE type = \"SDK\"");
cbl::ResultSet result = query.execute();
// Create a replicator to push and pull changes to and from the cloud
cbl::ReplicatorConfiguration config(
{ cbl::CollectionConfiguration(collection) },
cbl::Endpoint::urlEndpoint("ws://localhost:4984/getting-started-db"));
config.authenticator = cbl::Authenticator::basicAuthenticator("john", "pass");
cbl::Replicator replicator(config);
// Listen for replicator status changes
auto token = replicator.addChangeListener(
[](cbl::Replicator r, const CBLReplicatorStatus& status) {
if (status.error.code != 0) {
std::cerr << "Error " << status.error.domain
<< " / " << status.error.code << std::endl;
}
});
replicator.start();
// Later, stop the replicator. Ref-counted objects free themselves once
// the last reference goes away (here, when this scope ends).
replicator.stop();
} catch (const cbl::Error& e) {
// Error handling. For brevity, this is truncated here and omitted in the
// other doc code snippets.
std::cerr << "Error: " << e.what() << std::endl;
}