A newer version of this documentation is available.

View Latest

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.

    Example 1. Sample code
    • 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;
    }