Implement RD update.
authorTodd Malsbary <todd.malsbary@intel.com>
Wed, 14 Dec 2016 23:17:39 +0000 (15:17 -0800)
committerHabib Virji <habib.virji@samsung.com>
Fri, 10 Feb 2017 10:04:56 +0000 (10:04 +0000)
Change-Id: I6d115b14ddefb60fbcfc289e40f69228b7878551
Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/15639
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Habib Virji <habib.virji@samsung.com>
resource/csdk/resource-directory/include/rd_client.h
resource/csdk/resource-directory/src/internal/rd_database.c
resource/csdk/resource-directory/src/rd_client.c
resource/csdk/resource-directory/unittests/rddatabase.cpp
resource/csdk/resource-directory/unittests/rdtests.cpp
resource/csdk/stack/src/oicresourcedirectory.c

index 6fafed8..84ef0b7 100644 (file)
@@ -34,7 +34,8 @@ extern "C" {
 
 #define OIC_RD_DEFAULT_RESOURCE 2
 
-#define DEFAULT_MESSAGE_TYPE "application/json"
+/** JSON media type. */
+#define OC_MEDIA_TYPE_APPLICATION_JSON   "application/json"
 
 /** Platform Model Number.*/
 #define OC_DATA_MODEL_NUMBER            "x.model"
index 9271643..f9d8f91 100644 (file)
@@ -18,6 +18,7 @@
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
+#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
 
 static sqlite3 *gRDDB = NULL;
 
-static const uint8_t device_index = 2;
-static const uint8_t ttl_index = 3;
-static const uint8_t address_index = 4;
-
-static const uint8_t uri_index = 2;
-static const uint8_t p_index = 5;
-static const uint8_t mt_index = 7;
-static const uint8_t d_index = 8;
-
-static const uint8_t rt_value_index = 1;
-static const uint8_t rt_link_id_index = 2;
-
-static const uint8_t if_value_index = 1;
-static const uint8_t if_link_id_index = 2;
-
 #define VERIFY_SQLITE(arg) \
     if (SQLITE_OK != (arg)) \
     { \
@@ -162,71 +148,88 @@ OCStackResult OCRDDatabaseClose()
     return OC_STACK_OK;
 }
 
-static int storeResourceType(char **link, size_t size, uint8_t rowid)
+static int storeResourceType(char **resourceTypes, size_t size, uint8_t rowid)
 {
     int res = 1;
     VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
 
-    const char *insertRT = "INSERT INTO RD_LINK_RT VALUES(?, ?)";
-    sqlite3_stmt *stmtRT = 0;
+    const char *deleteRT = "DELETE FROM RD_LINK_RT WHERE LINK_ID=@id";
+    const char *insertRT = "INSERT INTO RD_LINK_RT VALUES(@resourceType, @id)";
+    sqlite3_stmt *stmt = 0;
+
+    VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, deleteRT, strlen(deleteRT) + 1, &stmt, NULL));
+    VERIFY_SQLITE(sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
+    res = sqlite3_step(stmt);
+    VERIFY_SQLITE(sqlite3_finalize(stmt));
+    if (res != SQLITE_DONE)
+    {
+        sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
+        return res;
+    }
 
     for (size_t i = 0; i < size; i++)
     {
-        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertRT, strlen(insertRT) + 1, &stmtRT, NULL));
-        if (link[i])
+        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertRT, strlen(insertRT) + 1, &stmt, NULL));
+        if (resourceTypes[i])
         {
-            VERIFY_SQLITE(sqlite3_bind_text(stmtRT, rt_value_index, link[i],
-                                            strlen(link[i]), SQLITE_STATIC));
-
-            VERIFY_SQLITE(sqlite3_bind_int(stmtRT, rt_link_id_index, rowid));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@resourceType"),
+                                            resourceTypes[i], strlen(resourceTypes[i]), SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
         }
-        if (sqlite3_step(stmtRT) != SQLITE_DONE)
+        res = sqlite3_step(stmt);
+        VERIFY_SQLITE(sqlite3_finalize(stmt));
+        if (res != SQLITE_DONE)
         {
             sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
-            sqlite3_finalize(stmtRT);
             return res;
         }
     }
 
-    VERIFY_SQLITE(sqlite3_finalize(stmtRT));
-
     VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
     res = SQLITE_OK;
 
     return res;
 }
 
-
-static int storeInterfaceType(char **link, size_t size, uint8_t rowid)
+static int storeInterfaceType(char **interfaceTypes, size_t size, uint8_t rowid)
 {
     int res = 1;
-
     VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
 
-    const char *insertIF = "INSERT INTO RD_LINK_IF VALUES(?, ?)";
-    sqlite3_stmt *stmtIF = 0;
+    const char *deleteIF = "DELETE FROM RD_LINK_IF WHERE LINK_ID=@id";
+    const char *insertIF = "INSERT INTO RD_LINK_IF VALUES(@interfaceType, @id)";
+    sqlite3_stmt *stmt = 0;
 
-    for (size_t i = 0; i < size; i++)
+    VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, deleteIF, strlen(deleteIF) + 1, &stmt, NULL));
+    VERIFY_SQLITE(sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
+    res = sqlite3_step(stmt);
+    VERIFY_SQLITE(sqlite3_finalize(stmt));
+    if (res != SQLITE_DONE)
     {
-        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertIF, strlen(insertIF) + 1, &stmtIF, NULL));
+        sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
+        return res;
+    }
 
-        if (link[i])
+    for (size_t i = 0; i < size; i++)
+    {
+        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertIF, strlen(insertIF) + 1, &stmt, NULL));
+        if (interfaceTypes[i])
         {
-            VERIFY_SQLITE(sqlite3_bind_text(stmtIF, if_value_index, link[i], strlen(link[i]), SQLITE_STATIC));
-            VERIFY_SQLITE(sqlite3_bind_int(stmtIF, if_link_id_index, rowid));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@interfaceType"),
+                                            interfaceTypes[i], strlen(interfaceTypes[i]), SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
         }
-        if (sqlite3_step(stmtIF) != SQLITE_DONE)
+        res = sqlite3_step(stmt);
+        VERIFY_SQLITE(sqlite3_finalize(stmt));
+        if (res != SQLITE_DONE)
         {
             sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
-            res = sqlite3_finalize(stmtIF);
             return res;
         }
     }
-    VERIFY_SQLITE(sqlite3_finalize(stmtIF));
 
     VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
     res = SQLITE_OK;
-
     return res;
 }
 
@@ -253,7 +256,11 @@ static int storeLinkPayload(OCRepPayload *rdPayload, int64_t rowid)
     }
     if (links != NULL)
     {
-        const char *insertDeviceLLList = "INSERT INTO RD_DEVICE_LINK_LIST VALUES(?,?,?,?,?,?,?,?)";
+        const char *insertDeviceLLList = "INSERT OR IGNORE INTO RD_DEVICE_LINK_LIST (ins, href, DEVICE_ID) "
+            "VALUES((SELECT ins FROM RD_DEVICE_LINK_LIST WHERE DEVICE_ID=@id AND href=@uri),@uri,@id)";
+        const char *updateDeviceLLList = "UPDATE RD_DEVICE_LINK_LIST SET bm=@bm,type=@mediaType "
+            "WHERE DEVICE_ID=@id AND href=@uri";
+
         sqlite3_stmt *stmt = 0;
 
         for (size_t i = 0; i < links->arr.dimensions[0]; i++)
@@ -262,55 +269,86 @@ static int storeLinkPayload(OCRepPayload *rdPayload, int64_t rowid)
             VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
 
             OCRepPayload *link = links->arr.objArray[i];
+            VERIFY_SQLITE(sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
             char *uri = NULL;
             if (OCRepPayloadGetPropString(link, OC_RSRVD_HREF, &uri))
             {
-                VERIFY_SQLITE(sqlite3_bind_text(stmt, uri_index, uri, strlen(uri), SQLITE_STATIC));
+                VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@uri"),
+                                                uri, strlen(uri), SQLITE_STATIC));
             }
+            if (sqlite3_step(stmt) != SQLITE_DONE)
+            {
+                sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
+                sqlite3_finalize(stmt);
+                return res;
+            }
+            VERIFY_SQLITE(sqlite3_finalize(stmt));
 
+            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, updateDeviceLLList, strlen(updateDeviceLLList) + 1,
+                                             &stmt, NULL));
+            VERIFY_SQLITE(sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
+            if (uri)
+            {
+                VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@uri"),
+                                                uri, strlen(uri), SQLITE_STATIC));
+            }
             OCRepPayload *p = NULL;
             if (OCRepPayloadGetPropObject(link, OC_RSRVD_POLICY, &p))
             {
                 int64_t bm = 0;
                 if (OCRepPayloadGetPropInt(p, OC_RSRVD_BITMAP, &bm))
                 {
-                    VERIFY_SQLITE(sqlite3_bind_int(stmt, p_index, bm));
+                    VERIFY_SQLITE(sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@bm"), bm));
                 }
             }
-
             size_t mtDim[MAX_REP_ARRAY_DEPTH] = {0};
             char **mediaType = NULL;
             if (OCRepPayloadGetStringArray(link, OC_RSRVD_MEDIA_TYPE, &mediaType, mtDim))
             {
-                VERIFY_SQLITE(sqlite3_bind_text(stmt, mt_index, mediaType[0], strlen(mediaType[0]), SQLITE_STATIC));
+                VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@mediaType"),
+                                                mediaType[0], strlen(mediaType[0]), SQLITE_STATIC));
             }
-
-            VERIFY_SQLITE(sqlite3_bind_int(stmt, d_index, rowid));
-
-            size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
-            char **rt = NULL;
-            OCRepPayloadGetStringArray(link, OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
-
-            size_t itfDim[MAX_REP_ARRAY_DEPTH] = {0};
-            char **itf = NULL;
-            OCRepPayloadGetStringArray(link, OC_RSRVD_INTERFACE, &itf, itfDim);
-
             if (sqlite3_step(stmt) != SQLITE_DONE)
             {
                 sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
                 sqlite3_finalize(stmt);
                 return res;
             }
+            VERIFY_SQLITE(sqlite3_finalize(stmt));
             VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
 
-            int64_t ins = sqlite3_last_insert_rowid(gRDDB);
-            if (!OCRepPayloadSetPropInt(link, OC_RSRVD_INS, ins))
+            char **rt = NULL;
+            size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
+            char **itf = NULL;
+            size_t itfDim[MAX_REP_ARRAY_DEPTH] = {0};
+            const char *input = "SELECT ins FROM RD_DEVICE_LINK_LIST WHERE DEVICE_ID=@id AND href=@uri";
+            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
+            VERIFY_SQLITE(sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
+            if (uri)
+            {
+                VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@uri"),
+                                                uri, strlen(uri), SQLITE_STATIC));
+            }
+            res = sqlite3_step(stmt);
+            if (res == SQLITE_ROW || res == SQLITE_DONE)
             {
-                OIC_LOG_V(ERROR, TAG, "Error setting 'ins' value");
-                return OC_STACK_ERROR;
+                int64_t ins = sqlite3_column_int64(stmt, 0);
+                VERIFY_SQLITE(sqlite3_finalize(stmt));
+                if (!OCRepPayloadSetPropInt(link, OC_RSRVD_INS, ins))
+                {
+                    OIC_LOG_V(ERROR, TAG, "Error setting 'ins' value");
+                    return OC_STACK_ERROR;
+                }
+                OCRepPayloadGetStringArray(link, OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
+                OCRepPayloadGetStringArray(link, OC_RSRVD_INTERFACE, &itf, itfDim);
+                VERIFY_SQLITE(storeResourceType(rt, rtDim[0], ins));
+                VERIFY_SQLITE(storeInterfaceType(itf, itfDim[0], ins));
             }
-            VERIFY_SQLITE(storeResourceType(rt, rtDim[0], ins));
-            VERIFY_SQLITE(storeInterfaceType(itf, itfDim[0], ins));
+            else
+            {
+                VERIFY_SQLITE(sqlite3_finalize(stmt));
+            }
+
             OICFree(uri);
             OCPayloadDestroy((OCPayload *)p);
             for (j = 0; j < mtDim[0]; j++)
@@ -318,22 +356,18 @@ static int storeLinkPayload(OCRepPayload *rdPayload, int64_t rowid)
                 OICFree(mediaType[j]);
             }
             OICFree(mediaType);
-
             for (j = 0; j < rtDim[0]; j++)
             {
                 OICFree(rt[j]);
             }
             OICFree(rt);
-
             for (j = 0; j < itfDim[0]; j++)
             {
                 OICFree(itf[j]);
             }
             OICFree(itf);
-
         }
 
-        VERIFY_SQLITE(sqlite3_finalize(stmt));
         res = SQLITE_OK;
     }
     return res;
@@ -343,28 +377,55 @@ OCStackResult OCRDDatabaseStoreResources(OCRepPayload *payload, const OCDevAddr
 {
     CHECK_DATABASE_INIT;
 
+    char *deviceId = NULL;
+    OCRepPayloadGetPropString(payload, OC_RSRVD_DEVICE_ID, &deviceId);
+    int64_t ttl = 0;
+    OCRepPayloadGetPropInt(payload, OC_RSRVD_DEVICE_TTL, &ttl);
+    char rdAddress[MAX_URI_LENGTH];
+    snprintf(rdAddress, MAX_URI_LENGTH, "%s:%d", address->addr, address->port);
+    OIC_LOG_V(DEBUG, TAG, "Address: %s", rdAddress);
+
+    /* INSERT OR IGNORE then UPDATE to update or insert the row without triggering the cascading deletes */
     VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
-    const char *insertDeviceList = "INSERT INTO RD_DEVICE_LIST VALUES(?,?,?,?)";
+
     sqlite3_stmt *stmt = 0;
+    const char *insertDeviceList = "INSERT OR IGNORE INTO RD_DEVICE_LIST (ID, di, ttl, ADDRESS) "
+        "VALUES ((SELECT ID FROM RD_DEVICE_LIST WHERE di=@deviceId), @deviceId, @ttl, @rdAddress)";
     VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertDeviceList, strlen(insertDeviceList) + 1, &stmt, NULL));
 
-    char *deviceid = NULL;
-    if (OCRepPayloadGetPropString(payload, OC_RSRVD_DEVICE_ID, &deviceid))
+    if (deviceId)
     {
-        VERIFY_SQLITE(sqlite3_bind_text(stmt, device_index, deviceid, strlen(deviceid), SQLITE_STATIC));
+        VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@deviceId"),
+                                        deviceId, strlen(deviceId), SQLITE_STATIC));
     }
-
-    int64_t ttl = 0;
-    if (OCRepPayloadGetPropInt(payload, OC_RSRVD_DEVICE_TTL, &ttl))
+    if (ttl)
     {
-        VERIFY_SQLITE(sqlite3_bind_int(stmt, ttl_index, ttl));
+        VERIFY_SQLITE(sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@ttl"), ttl));
     }
+    VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@rdAddress"),
+                                    rdAddress, strlen(rdAddress), SQLITE_STATIC));
+    if (sqlite3_step(stmt) != SQLITE_DONE)
+    {
+        sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
+        sqlite3_finalize(stmt);
+        return OC_STACK_ERROR;
+    }
+    VERIFY_SQLITE(sqlite3_finalize(stmt));
 
-    char rdAddress[MAX_URI_LENGTH];
-    snprintf(rdAddress, MAX_URI_LENGTH, "%s:%d", address->addr, address->port);
-    OIC_LOG_V(DEBUG, TAG, "Address: %s", rdAddress);
-    VERIFY_SQLITE(sqlite3_bind_text(stmt, address_index, rdAddress, strlen(rdAddress), SQLITE_STATIC));
-
+    const char *updateDeviceList = "UPDATE RD_DEVICE_LIST SET ttl=@ttl,ADDRESS=@rdAddress WHERE di=@deviceId";
+    VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, updateDeviceList, strlen(updateDeviceList) + 1,
+                                     &stmt, NULL));
+    if (deviceId)
+    {
+        VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@deviceId"),
+                                        deviceId, strlen(deviceId), SQLITE_STATIC));
+    }
+    if (ttl)
+    {
+        VERIFY_SQLITE(sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, "@ttl"), ttl));
+    }
+    VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@rdAddress"),
+                                    rdAddress, strlen(rdAddress), SQLITE_STATIC));
     if (sqlite3_step(stmt) != SQLITE_DONE)
     {
         sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
@@ -375,12 +436,27 @@ OCStackResult OCRDDatabaseStoreResources(OCRepPayload *payload, const OCDevAddr
 
     VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
 
-    int64_t rowid = sqlite3_last_insert_rowid(gRDDB);
-    if (rowid)
+    /* Store the rest of the payload */
+    const char *input = "SELECT ID FROM RD_DEVICE_LIST WHERE di=@deviceId";
+    VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
+    if (deviceId)
     {
+        VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@deviceId"),
+                                        deviceId, strlen(deviceId), SQLITE_STATIC));
+    }
+    int res = sqlite3_step(stmt);
+    if (res == SQLITE_ROW || res == SQLITE_DONE)
+    {
+        int64_t rowid = sqlite3_column_int64(stmt, 0);
+        VERIFY_SQLITE(sqlite3_finalize(stmt));
         VERIFY_SQLITE(storeLinkPayload(payload, rowid));
     }
-    OICFree(deviceid);
+    else
+    {
+        VERIFY_SQLITE(sqlite3_finalize(stmt));
+    }
+
+    OICFree(deviceId);
     return OC_STACK_OK;
 }
 
@@ -392,10 +468,11 @@ OCStackResult OCRDDatabaseDeleteResources(const char *deviceId, const uint8_t *i
     sqlite3_stmt *stmt = 0;
     if (!instanceIds || !nInstanceIds)
     {
-        char *delDevice = "DELETE FROM RD_DEVICE_LIST WHERE "XSTR(OC_RSRVD_DEVICE_ID)" = ?";
+        char *delDevice = "DELETE FROM RD_DEVICE_LIST WHERE di=@deviceId";
         VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, delDevice, strlen(delDevice) + 1, &stmt, NULL));
 
-        VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, deviceId, strlen(deviceId), SQLITE_STATIC));
+        VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@deviceId"),
+                                        deviceId, strlen(deviceId), SQLITE_STATIC));
     }
     else
     {
@@ -403,7 +480,7 @@ OCStackResult OCRDDatabaseDeleteResources(const char *deviceId, const uint8_t *i
             "WHERE ins IN ("
             "SELECT RD_DEVICE_LINK_LIST.ins FROM RD_DEVICE_LINK_LIST "
             "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
-            "WHERE RD_DEVICE_LIST.di = ? AND RD_DEVICE_LINK_LIST.ins IN (";
+            "WHERE RD_DEVICE_LIST.di=@deviceId AND RD_DEVICE_LINK_LIST.ins IN (";
         size_t inLen = nInstanceIds + (nInstanceIds - 1);
         const char post[] = "))";
         size_t len = sizeof(pre) + inLen + sizeof(post);
@@ -424,7 +501,9 @@ OCStackResult OCRDDatabaseDeleteResources(const char *deviceId, const uint8_t *i
         OICFree(delResource);
         VERIFY_SQLITE(prepareResult);
 
-        VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, deviceId, strlen(deviceId), SQLITE_STATIC));
+        VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@deviceId"),
+                                        deviceId, strlen(deviceId), SQLITE_STATIC));
+        assert(sqlite3_bind_parameter_index(stmt, "@deviceId") == 1);
         for (uint8_t i = 0; i < nInstanceIds; ++i)
         {
             VERIFY_SQLITE(sqlite3_bind_int(stmt, 2 + i, instanceIds[i]));
index 5439be3..c8041c0 100644 (file)
@@ -135,55 +135,19 @@ OCStackResult OCRDPublish(const char *host, OCConnectivityType connectivityType,
                                    cbData, qos);
 }
 
-OCStackResult OCRDPublishWithDeviceId(const char *host, const unsigned char *id,
-                                      OCConnectivityType connectivityType,
-                                      OCResourceHandle *resourceHandles, uint8_t nHandles,
-                                      OCCallbackData *cbData, OCQualityOfService qos)
+static OCRepPayload *RDPublishPayloadCreate(const unsigned char *id,
+                                            const OCResourceHandle *resourceHandles, uint8_t nHandles)
 {
-    // Validate input parameters.
-    if (!host || !cbData || !cbData->cb || !id)
-    {
-        return OC_STACK_INVALID_CALLBACK;
-    }
-
-    OIC_LOG_V(DEBUG, TAG, "Publish Resource to RD with device id [%s]", id);
-
-    OCResourceHandle *pubResHandle = resourceHandles;
-    OCResourceHandle defaultResHandles[OIC_RD_DEFAULT_RESOURCE] = { 0 };
-    uint8_t nPubResHandles = nHandles;
-
-    // if resource handles is null, "/oic/p" and "/oic/d" resource will be published to RD.
-    if (!pubResHandle)
-    {
-        // get "/oic/d" and "/oic/p" resource handle from stack.
-        defaultResHandles[0] = OCGetResourceHandleAtUri(OC_RSRVD_DEVICE_URI);
-        defaultResHandles[1] = OCGetResourceHandleAtUri(OC_RSRVD_PLATFORM_URI);
-
-        for (uint8_t j = 0; j < OIC_RD_DEFAULT_RESOURCE; j++)
-        {
-            if (defaultResHandles[j])
-            {
-                OIC_LOG_V(DEBUG, TAG, "Add virtual resource(%s) to resource handle list",
-                          OCGetResourceUri(defaultResHandles[j]));
-            }
-        }
-
-        pubResHandle = defaultResHandles;
-        nPubResHandles = OIC_RD_DEFAULT_RESOURCE;
-    }
-
-    char targetUri[MAX_URI_LENGTH] = { 0 };
-    snprintf(targetUri, MAX_URI_LENGTH, "%s%s?rt=%s", host,
-             OC_RSRVD_RD_URI, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
-    OIC_LOG_V(DEBUG, TAG, "Target URI: %s", targetUri);
-
     OCRepPayload *rdPayload =  (OCRepPayload *)OCRepPayloadCreate();
     if (!rdPayload)
     {
-        return OC_STACK_NO_MEMORY;
+        return NULL;
     }
 
-    OCRepPayloadSetPropString(rdPayload, OC_RSRVD_DEVICE_ID, (const char *) id);
+    if (id)
+    {
+        OCRepPayloadSetPropString(rdPayload, OC_RSRVD_DEVICE_ID, (const char*) id);
+    }
 
     char *deviceName = NULL;
     OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **) &deviceName);
@@ -203,17 +167,17 @@ OCStackResult OCRDPublishWithDeviceId(const char *host, const unsigned char *id,
 
     OCRepPayloadSetPropInt(rdPayload, OC_RSRVD_DEVICE_TTL, OIC_RD_PUBLISH_TTL);
 
-    OCRepPayload **linkArr = OICCalloc(nPubResHandles, sizeof(OCRepPayload *));
+    OCRepPayload **linkArr = (OCRepPayload**)OICCalloc(nHandles, sizeof(OCRepPayload *));
     if (!linkArr)
     {
         OCRepPayloadDestroy(rdPayload);
-        return OC_STACK_NO_MEMORY;
+        return NULL;
     }
 
-    size_t dimensions[MAX_REP_ARRAY_DEPTH] = {nPubResHandles, 0, 0};
-    for (uint8_t j = 0; j < nPubResHandles; j++)
+    size_t dimensions[MAX_REP_ARRAY_DEPTH] = {nHandles, 0, 0};
+    for (uint8_t j = 0; j < nHandles; j++)
     {
-        OCResourceHandle handle = pubResHandle[j];
+        OCResourceHandle handle = resourceHandles[j];
         if (handle)
         {
             OCRepPayload *link = OCRepPayloadCreate();
@@ -252,22 +216,28 @@ OCStackResult OCRDPublishWithDeviceId(const char *host, const unsigned char *id,
                 OCRepPayloadSetStringArrayAsOwner(link, OC_RSRVD_INTERFACE, itf, ifDim);
             }
 
+            uint8_t ins = 0;
+            if (OC_STACK_OK == OCGetResourceIns(handle, &ins))
+            {
+                OCRepPayloadSetPropInt(link, OC_RSRVD_INS, ins);
+            }
+
             size_t mtDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
             char **mediaType = (char **)OICMalloc(sizeof(char *) * 1);
             if (!mediaType)
             {
                 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
 
-                for(uint8_t i = 0; i < nPubResHandles; i++)
+                for(uint8_t i = 0; i < nHandles; i++)
                 {
                     OCRepPayloadDestroy(linkArr[i]);
                 }
                 OICFree(linkArr);
                 OCRepPayloadDestroy(rdPayload);
-                return OC_STACK_NO_MEMORY;
+                return NULL;
             }
 
-            mediaType[0] = OICStrdup(DEFAULT_MESSAGE_TYPE);
+            mediaType[0] = OICStrdup(OC_MEDIA_TYPE_APPLICATION_JSON);
             OCRepPayloadSetStringArrayAsOwner(link, OC_RSRVD_MEDIA_TYPE, mediaType,
             mtDim);
 
@@ -284,12 +254,63 @@ OCStackResult OCRDPublishWithDeviceId(const char *host, const unsigned char *id,
     OCRepPayloadSetPropObjectArray(rdPayload, OC_RSRVD_LINKS, (const OCRepPayload **)linkArr, dimensions);
     OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) rdPayload);
 
-    for (uint8_t i = 0; i < nPubResHandles; i++)
+    for (uint8_t i = 0; i < nHandles; i++)
     {
         OCRepPayloadDestroy(linkArr[i]);
     }
     OICFree(linkArr);
 
+    return rdPayload;
+}
+
+OCStackResult OCRDPublishWithDeviceId(const char *host, const unsigned char *id,
+                                      OCConnectivityType connectivityType,
+                                      OCResourceHandle *resourceHandles, uint8_t nHandles,
+                                      OCCallbackData *cbData, OCQualityOfService qos)
+{
+    // Validate input parameters.
+    if (!host || !cbData || !cbData->cb || !id)
+    {
+        return OC_STACK_INVALID_CALLBACK;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "Publish Resource to RD with device id [%s]", id);
+
+    OCResourceHandle *pubResHandle = resourceHandles;
+    OCResourceHandle defaultResHandles[OIC_RD_DEFAULT_RESOURCE] = { 0 };
+    uint8_t nPubResHandles = nHandles;
+
+    // if resource handles is null, "/oic/p" and "/oic/d" resource will be published to RD.
+    if (!pubResHandle)
+    {
+        // get "/oic/d" and "/oic/p" resource handle from stack.
+        defaultResHandles[0] = OCGetResourceHandleAtUri(OC_RSRVD_DEVICE_URI);
+        defaultResHandles[1] = OCGetResourceHandleAtUri(OC_RSRVD_PLATFORM_URI);
+
+        for (uint8_t j = 0; j < OIC_RD_DEFAULT_RESOURCE; j++)
+        {
+            if (defaultResHandles[j])
+            {
+                OIC_LOG_V(DEBUG, TAG, "Add virtual resource(%s) to resource handle list",
+                          OCGetResourceUri(defaultResHandles[j]));
+            }
+        }
+
+        pubResHandle = defaultResHandles;
+        nPubResHandles = OIC_RD_DEFAULT_RESOURCE;
+    }
+
+    char targetUri[MAX_URI_LENGTH] = { 0 };
+    snprintf(targetUri, MAX_URI_LENGTH, "%s%s?rt=%s", host,
+             OC_RSRVD_RD_URI, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
+    OIC_LOG_V(DEBUG, TAG, "Target URI: %s", targetUri);
+
+    OCRepPayload *rdPayload = RDPublishPayloadCreate(id, pubResHandle, nPubResHandles);
+    if (!rdPayload)
+    {
+        return OC_STACK_ERROR;
+    }
+
     OCCallbackData *rdPublishContext = (OCCallbackData*)OICMalloc(sizeof(OCCallbackData));
     if (!rdPublishContext)
     {
index ed20436..7a73174 100644 (file)
@@ -55,7 +55,6 @@ using namespace std;
 namespace itst = iotivity::test;
 
 #define DEFAULT_CONTEXT_VALUE 0x99
-#define DEFAULT_MESSAGE_TYPE "application/json"
 
 //-----------------------------------------------------------------------------
 // Private variables
@@ -87,67 +86,68 @@ class RDDatabaseTests : public testing::Test {
     }
 };
 
-static OCRepPayload *CreateResources(const char *deviceId)
+typedef struct Resource
+{
+    const char *uri;
+    const char *rt;
+    const char *itf;
+    const char *mt;
+    uint8_t bm;
+} Resource;
+
+static OCRepPayload *CreateRDPublishPayload(const char *deviceId,
+                                            Resource *resources,
+                                            size_t nresources)
 {
     OCRepPayload *repPayload = OCRepPayloadCreate();
     EXPECT_TRUE(repPayload != NULL);
+    EXPECT_TRUE(deviceId != NULL);
     EXPECT_TRUE(OCRepPayloadSetPropString(repPayload, OC_RSRVD_DEVICE_ID, deviceId));
     EXPECT_TRUE(OCRepPayloadSetPropInt(repPayload, OC_RSRVD_DEVICE_TTL, 86400));
-    OCDevAddr address;
-    address.port = 54321;
-    OICStrcpy(address.addr,MAX_ADDR_STR_SIZE, "192.168.1.1");
-
-    std::string resourceURI_thermostat = "/a/thermostat";
-    std::string resourceTypeName_thermostat = "core.thermostat";
-    std::string resourceURI_light = "/a/light";
-    std::string resourceTypeName_light = "core.light";
-
-    const OCRepPayload *linkArr[2];
-    size_t dimensions[MAX_REP_ARRAY_DEPTH] = {2, 0, 0};
-
-    OCRepPayload *link = OCRepPayloadCreate();
-    OCRepPayloadSetPropString(link, OC_RSRVD_HREF, resourceURI_thermostat.c_str());
-    size_t rtDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
-    char **rt = (char **)OICMalloc(sizeof(char *) * 1);
-    rt[0] = OICStrdup(resourceTypeName_thermostat.c_str());
-    OCRepPayloadSetStringArray(link, OC_RSRVD_RESOURCE_TYPE, (const char **)rt,
-                               rtDim);
-
-    size_t itfDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
-    char **itf = (char **)OICMalloc(sizeof(char *) * 1);
-    itf[0] = OICStrdup(OC_RSRVD_INTERFACE_DEFAULT);
-    OCRepPayloadSetStringArray(link, OC_RSRVD_INTERFACE, (const char **)itf,
-                              itfDim);
-    OCRepPayloadSetPropInt(link, OC_RSRVD_INS, 0);
-    size_t mtDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
-    char **mt = (char **)OICMalloc(sizeof(char *) * 1);
-    mt[0] = OICStrdup(DEFAULT_MESSAGE_TYPE);
-    OCRepPayloadSetStringArray(link, OC_RSRVD_MEDIA_TYPE, (const char **)mt,
-                               mtDim);
-    OCRepPayload *policy = OCRepPayloadCreate();
-    OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, OC_DISCOVERABLE);
-    OCRepPayloadSetPropObjectAsOwner(link, OC_RSRVD_POLICY, policy);
-    linkArr[0] = link;
-
-    OCRepPayload *link1 = OCRepPayloadCreate();
-    OCRepPayloadSetPropString(link1, OC_RSRVD_HREF, resourceURI_light.c_str());
-    char **rt1 = (char **)OICMalloc(sizeof(char *) * 1);
-    rt1[0] = OICStrdup(resourceTypeName_light.c_str());
-    OCRepPayloadSetStringArray(link1, OC_RSRVD_RESOURCE_TYPE, (const char **)rt1,
-                               rtDim);
-    OCRepPayloadSetStringArray(link1, OC_RSRVD_INTERFACE, (const char **)itf,
-                              itfDim);
-    OCRepPayloadSetPropInt(link1, OC_RSRVD_INS, 1);
-    OCRepPayloadSetStringArray(link1, OC_RSRVD_MEDIA_TYPE, (const char **)mt,
-                               mtDim);
-    OCRepPayloadSetPropObjectAsOwner(link1, OC_RSRVD_POLICY, policy);
-    linkArr[1] = link1;
+
+    const OCRepPayload *linkArr[nresources];
+    size_t dimensions[MAX_REP_ARRAY_DEPTH] = {nresources, 0, 0};
+
+    for (size_t i = 0; i < nresources; ++i)
+    {
+        OCRepPayload *link = OCRepPayloadCreate();
+        OCRepPayloadSetPropString(link, OC_RSRVD_HREF, resources[i].uri);
+        size_t rtDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
+        char **rt = (char **)OICMalloc(sizeof(char *) * 1);
+        rt[0] = OICStrdup(resources[i].rt);
+        OCRepPayloadSetStringArray(link, OC_RSRVD_RESOURCE_TYPE, (const char **)rt,
+                                   rtDim);
+        size_t itfDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
+        char **itf = (char **)OICMalloc(sizeof(char *) * 1);
+        itf[0] = OICStrdup(resources[i].itf);
+        OCRepPayloadSetStringArray(link, OC_RSRVD_INTERFACE, (const char **)itf,
+                                   itfDim);
+        size_t mtDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
+        char **mt = (char **)OICMalloc(sizeof(char *) * 1);
+        mt[0] = OICStrdup(resources[i].mt);
+        OCRepPayloadSetStringArray(link, OC_RSRVD_MEDIA_TYPE, (const char **)mt,
+                                   mtDim);
+        OCRepPayload *policy = OCRepPayloadCreate();
+        OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, resources[i].bm);
+        OCRepPayloadSetPropObjectAsOwner(link, OC_RSRVD_POLICY, policy);
+        linkArr[i] = link;
+    }
+
     OCRepPayloadSetPropObjectArray(repPayload, OC_RSRVD_LINKS, linkArr, dimensions);
 
     OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)repPayload);
     return repPayload;
 }
 
+static OCRepPayload *CreateResources(const char *deviceId)
+{
+    Resource resources[] = {
+        { "/a/thermostat", "core.thermostat", OC_RSRVD_INTERFACE_DEFAULT, OC_MEDIA_TYPE_APPLICATION_JSON, OC_DISCOVERABLE },
+        { "/a/light", "core.light", OC_RSRVD_INTERFACE_DEFAULT, OC_MEDIA_TYPE_APPLICATION_JSON, OC_DISCOVERABLE }
+    };
+    return CreateRDPublishPayload(deviceId, resources, 2);
+}
+
 TEST_F(RDDatabaseTests, Create)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
@@ -160,7 +160,7 @@ TEST_F(RDDatabaseTests, StoreResources)
     OCRepPayload *repPayload = CreateResources(deviceId);
     OCDevAddr address;
     address.port = 54321;
-    OICStrcpy(address.addr,MAX_ADDR_STR_SIZE, "192.168.1.1");
+    OICStrcpy(address.addr, MAX_ADDR_STR_SIZE, "192.168.1.1");
 
     EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
 
@@ -181,6 +181,176 @@ TEST_F(RDDatabaseTests, StoreResources)
     OCPayloadDestroy((OCPayload *)repPayload);
 }
 
+TEST_F(RDDatabaseTests, AddResources)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+    const char *deviceId = "7a960f46-a52e-4837-bd83-460b1a6dd56b";
+    OCDevAddr address;
+    address.port = 54321;
+    OICStrcpy(address.addr, MAX_ADDR_STR_SIZE, "192.168.1.1");
+
+    OCRepPayload *repPayload = CreateResources(deviceId);
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    OCPayloadDestroy((OCPayload *)repPayload);
+
+    Resource resources[] = {
+        { "/a/light2", "core.light", OC_RSRVD_INTERFACE_DEFAULT, OC_MEDIA_TYPE_APPLICATION_JSON, OC_DISCOVERABLE }
+    };
+    repPayload = CreateRDPublishPayload(deviceId, resources, 1);
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    OCPayloadDestroy((OCPayload *)repPayload);
+
+    OCDiscoveryPayload *discPayload = NULL;
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDiscoveryPayloadCreate(OC_RSRVD_INTERFACE_LL, NULL, &discPayload));
+    bool foundThermostat = false;
+    bool foundLight = false;
+    bool foundLight2 = false;
+    for (OCResourcePayload *resource = discPayload->resources; resource; resource = resource->next)
+    {
+        if (!strcmp("/a/thermostat", resource->uri))
+        {
+            foundThermostat = true;
+        }
+        else if (!strcmp("/a/light", resource->uri))
+        {
+            foundLight = true;
+        }
+        else if (!strcmp("/a/light2", resource->uri))
+        {
+            foundLight2 = true;
+        }
+    }
+    EXPECT_TRUE(foundThermostat);
+    EXPECT_TRUE(foundLight);
+    EXPECT_TRUE(foundLight2);
+    OCDiscoveryPayloadDestroy(discPayload);
+    discPayload = NULL;
+
+    OCPayloadDestroy((OCPayload *)repPayload);
+}
+
+TEST_F(RDDatabaseTests, UpdateResources)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+    const char *deviceId = "7a960f46-a52e-4837-bd83-460b1a6dd56b";
+    OCDevAddr address;
+    address.port = 54321;
+    OICStrcpy(address.addr, MAX_ADDR_STR_SIZE, "192.168.1.1");
+
+    OCRepPayload *repPayload = CreateResources(deviceId);
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    OCPayloadDestroy((OCPayload *)repPayload);
+
+    Resource resources[] = {
+        { "/a/thermostat", "x.core.r.thermostat", "x.core.if.thermostat", "application/cbor", OC_DISCOVERABLE | OC_OBSERVABLE },
+        { "/a/light", "x.core.r.light", "x.core.if.light", "application/cbor", OC_DISCOVERABLE | OC_OBSERVABLE }
+    };
+    repPayload = CreateRDPublishPayload(deviceId, resources, 2);
+    address.port = 12345;
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    OCPayloadDestroy((OCPayload *)repPayload);
+
+    OCDiscoveryPayload *discPayload = NULL;
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDiscoveryPayloadCreate(OC_RSRVD_INTERFACE_LL, NULL, &discPayload));
+    EXPECT_STREQ("192.168.1.1:12345", discPayload->baseURI);
+    bool foundThermostat = false;
+    bool foundLight = false;
+    for (OCResourcePayload *resource = discPayload->resources; resource; resource = resource->next)
+    {
+        if (!strcmp("/a/thermostat", resource->uri))
+        {
+            foundThermostat = true;
+            EXPECT_STREQ("x.core.r.thermostat", resource->types->value);
+            EXPECT_TRUE(resource->types->next == NULL);
+            EXPECT_STREQ("x.core.if.thermostat", resource->interfaces->value);
+            EXPECT_TRUE(resource->interfaces->next == NULL);
+            EXPECT_EQ(OC_DISCOVERABLE | OC_OBSERVABLE, resource->bitmap);
+        }
+        else if (!strcmp("/a/light", resource->uri))
+        {
+            foundLight = true;
+            EXPECT_STREQ("x.core.r.light", resource->types->value);
+            EXPECT_TRUE(resource->types->next == NULL);
+            EXPECT_STREQ("x.core.if.light", resource->interfaces->value);
+            EXPECT_TRUE(resource->interfaces->next == NULL);
+            EXPECT_EQ(OC_DISCOVERABLE | OC_OBSERVABLE, resource->bitmap);
+        }
+    }
+    EXPECT_TRUE(foundThermostat);
+    EXPECT_TRUE(foundLight);
+    OCDiscoveryPayloadDestroy(discPayload);
+    discPayload = NULL;
+
+    OCPayloadDestroy((OCPayload *)repPayload);
+}
+
+TEST_F(RDDatabaseTests, AddAndUpdateResources)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+    const char *deviceId = "7a960f46-a52e-4837-bd83-460b1a6dd56b";
+    OCDevAddr address;
+    address.port = 54321;
+    OICStrcpy(address.addr, MAX_ADDR_STR_SIZE, "192.168.1.1");
+
+    OCRepPayload *repPayload = CreateResources(deviceId);
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    OCPayloadDestroy((OCPayload *)repPayload);
+
+    Resource resources[] = {
+        { "/a/thermostat", "x.core.r.thermostat", "x.core.if.thermostat", "application/cbor", OC_DISCOVERABLE | OC_OBSERVABLE },
+        { "/a/light", "x.core.r.light", "x.core.if.light", "application/cbor", OC_DISCOVERABLE | OC_OBSERVABLE },
+        { "/a/light2", "core.light", OC_RSRVD_INTERFACE_DEFAULT, OC_MEDIA_TYPE_APPLICATION_JSON, OC_DISCOVERABLE }
+    };
+    repPayload = CreateRDPublishPayload(deviceId, resources, 3);
+    address.port = 12345;
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
+    OCPayloadDestroy((OCPayload *)repPayload);
+
+    OCDiscoveryPayload *discPayload = NULL;
+    EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDiscoveryPayloadCreate(OC_RSRVD_INTERFACE_LL, NULL, &discPayload));
+    EXPECT_STREQ("192.168.1.1:12345", discPayload->baseURI);
+    bool foundThermostat = false;
+    bool foundLight = false;
+    bool foundLight2 = false;
+    for (OCResourcePayload *resource = discPayload->resources; resource; resource = resource->next)
+    {
+        if (!strcmp("/a/thermostat", resource->uri))
+        {
+            foundThermostat = true;
+            EXPECT_STREQ("x.core.r.thermostat", resource->types->value);
+            EXPECT_TRUE(resource->types->next == NULL);
+            EXPECT_STREQ("x.core.if.thermostat", resource->interfaces->value);
+            EXPECT_TRUE(resource->interfaces->next == NULL);
+            EXPECT_EQ(OC_DISCOVERABLE | OC_OBSERVABLE, resource->bitmap);
+        }
+        else if (!strcmp("/a/light", resource->uri))
+        {
+            foundLight = true;
+            EXPECT_STREQ("x.core.r.light", resource->types->value);
+            EXPECT_TRUE(resource->types->next == NULL);
+            EXPECT_STREQ("x.core.if.light", resource->interfaces->value);
+            EXPECT_TRUE(resource->interfaces->next == NULL);
+            EXPECT_EQ(OC_DISCOVERABLE | OC_OBSERVABLE, resource->bitmap);
+        }
+        else if (!strcmp("/a/light2", resource->uri))
+        {
+            foundLight2 = true;
+            EXPECT_STREQ("core.light", resource->types->value);
+            EXPECT_TRUE(resource->types->next == NULL);
+            EXPECT_STREQ(OC_RSRVD_INTERFACE_DEFAULT, resource->interfaces->value);
+            EXPECT_TRUE(resource->interfaces->next == NULL);
+            EXPECT_EQ(OC_DISCOVERABLE, resource->bitmap);
+        }
+    }
+    EXPECT_TRUE(foundThermostat);
+    EXPECT_TRUE(foundLight);
+    EXPECT_TRUE(foundLight2);
+    OCDiscoveryPayloadDestroy(discPayload);
+    discPayload = NULL;
+
+    OCPayloadDestroy((OCPayload *)repPayload);
+}
+
 TEST_F(RDDatabaseTests, DeleteResourcesDevice)
 {
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
@@ -194,7 +364,7 @@ TEST_F(RDDatabaseTests, DeleteResourcesDevice)
     payloads[1] = CreateResources(deviceIds[1]);
     OCDevAddr address;
     address.port = 54321;
-    OICStrcpy(address.addr,MAX_ADDR_STR_SIZE, "192.168.1.1");
+    OICStrcpy(address.addr, MAX_ADDR_STR_SIZE, "192.168.1.1");
     EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(payloads[0], &address));
     EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(payloads[1], &address));
 
index 2fa9319..b3dcbd0 100644 (file)
@@ -564,7 +564,7 @@ TEST_F(RDDiscoverTests, ResourceQueryMatchesRemoteOnly)
     SetStringArray(link, OC_RSRVD_RESOURCE_TYPE, resourceTypeName_light.c_str());
     SetStringArray(link, OC_RSRVD_INTERFACE, OC_RSRVD_INTERFACE_DEFAULT);
     OCRepPayloadSetPropInt(link, OC_RSRVD_INS, 0);
-    SetStringArray(link, OC_RSRVD_MEDIA_TYPE, DEFAULT_MESSAGE_TYPE);
+    SetStringArray(link, OC_RSRVD_MEDIA_TYPE, OC_MEDIA_TYPE_APPLICATION_JSON);
     OCRepPayload *policy = OCRepPayloadCreate();
     OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, OC_DISCOVERABLE);
     OCRepPayloadSetPropObjectAsOwner(link, OC_RSRVD_POLICY, policy);
index ec80d90..20e7289 100644 (file)
@@ -162,9 +162,9 @@ static OCStackResult ResourcePayloadCreate(sqlite3_stmt *stmt, OCDiscoveryPayloa
         }
 
         sqlite3_stmt *stmtRT = 0;
-        const char *rt = "SELECT rt FROM RD_LINK_RT WHERE LINK_ID=?";
+        const char *rt = "SELECT rt FROM RD_LINK_RT WHERE LINK_ID=@id";
         VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, rt, strlen(rt) + 1, &stmtRT, NULL));
-        VERIFY_SQLITE(sqlite3_bind_int(stmtRT, 1, id));
+        VERIFY_SQLITE(sqlite3_bind_int(stmtRT, sqlite3_bind_parameter_index(stmtRT, "@id"), id));
         while (SQLITE_ROW == sqlite3_step(stmtRT))
         {
             const unsigned char *rt1 = sqlite3_column_text(stmtRT, rt_value_index);
@@ -177,9 +177,9 @@ static OCStackResult ResourcePayloadCreate(sqlite3_stmt *stmt, OCDiscoveryPayloa
         VERIFY_SQLITE(sqlite3_finalize(stmtRT));
 
         sqlite3_stmt *stmtIF = 0;
-        const char *itf = "SELECT if FROM RD_LINK_IF WHERE LINK_ID=?";
+        const char *itf = "SELECT if FROM RD_LINK_IF WHERE LINK_ID=@id";
         VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, itf, strlen(itf) + 1, &stmtIF, NULL));
-        VERIFY_SQLITE(sqlite3_bind_int(stmtIF, 1, id));
+        VERIFY_SQLITE(sqlite3_bind_int(stmtIF, sqlite3_bind_parameter_index(stmtIF, "@id"), id));
         while (SQLITE_ROW == sqlite3_step(stmtIF))
         {
             const unsigned char *itf = sqlite3_column_text(stmtIF, if_value_index);
@@ -196,13 +196,13 @@ static OCStackResult ResourcePayloadCreate(sqlite3_stmt *stmt, OCDiscoveryPayloa
 
         const char *address = "SELECT di, address FROM RD_DEVICE_LIST "
             "INNER JOIN RD_DEVICE_LINK_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID = RD_DEVICE_LIST.ID "
-            "WHERE RD_DEVICE_LINK_LIST.DEVICE_ID=?";
+            "WHERE RD_DEVICE_LINK_LIST.DEVICE_ID=@deviceId";
         const uint8_t di_index = 0;
         const uint8_t address_index = 1;
 
         sqlite3_stmt *stmt1 = 0;
         VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, address, strlen(address) + 1, &stmt1, NULL));
-        VERIFY_SQLITE(sqlite3_bind_int(stmt1, 1, deviceId));
+        VERIFY_SQLITE(sqlite3_bind_int(stmt1, sqlite3_bind_parameter_index(stmt1, "@deviceId"), deviceId));
 
         res = sqlite3_step(stmt1);
         if (SQLITE_ROW == res || SQLITE_DONE == res)
@@ -260,11 +260,12 @@ static OCStackResult CheckResources(const char *interfaceType, const char *resou
             const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
                                 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
                                 "INNER JOIN RD_LINK_RT ON RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID "
-                                "WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_RT.rt LIKE ?2";
+                                "WHERE RD_DEVICE_LIST.di LIKE @di AND RD_LINK_RT.rt LIKE @resourceType";
             VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
-            VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
-                                            SQLITE_STATIC));
-            VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, resourceType, strlen(resourceType), SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@di"),
+                                            discPayload->sid, strlen(discPayload->sid), SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@resourceType"),
+                                            resourceType, strlen(resourceType), SQLITE_STATIC));
         }
         else
         {
@@ -272,12 +273,16 @@ static OCStackResult CheckResources(const char *interfaceType, const char *resou
                                 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
                                 "INNER JOIN RD_LINK_RT ON RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID "
                                 "INNER JOIN RD_LINK_IF ON RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID "
-                                "WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_RT.rt LIKE ?2 AND RD_LINK_IF.if LIKE ?3";
+                                "WHERE RD_DEVICE_LIST.di LIKE @di "
+                                "AND RD_LINK_RT.rt LIKE @resourceType "
+                                "AND RD_LINK_IF.if LIKE @interfaceType";
             VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
-            VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
-                                            SQLITE_STATIC));
-            VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, resourceType, strlen(resourceType), SQLITE_STATIC));
-            VERIFY_SQLITE(sqlite3_bind_text(stmt, 3, interfaceType, strlen(interfaceType), SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@di"),
+                                            discPayload->sid, strlen(discPayload->sid), SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@resourceType"),
+                                            resourceType, strlen(resourceType), SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@interfaceType"),
+                                            interfaceType, strlen(interfaceType), SQLITE_STATIC));
         }
         result = ResourcePayloadCreate(stmt, discPayload);
     }
@@ -287,21 +292,22 @@ static OCStackResult CheckResources(const char *interfaceType, const char *resou
         {
             const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
                                 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
-                                "WHERE RD_DEVICE_LIST.di LIKE ?1";
+                                "WHERE RD_DEVICE_LIST.di LIKE @di";
             VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
-            VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
-                                            SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@di"),
+                                            discPayload->sid, strlen(discPayload->sid), SQLITE_STATIC));
         }
         else
         {
             const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
                                 "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
                                 "INNER JOIN RD_LINK_IF ON RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID "
-                                "WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_IF.if LIKE ?2";
+                                "WHERE RD_DEVICE_LIST.di LIKE @di AND RD_LINK_IF.if LIKE @interfaceType";
             VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
-            VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
-                                            SQLITE_STATIC));
-            VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, interfaceType, strlen(interfaceType), SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@di"),
+                                            discPayload->sid, strlen(discPayload->sid), SQLITE_STATIC));
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@interfaceType"),
+                                            interfaceType, strlen(interfaceType), SQLITE_STATIC));
         }
         result = ResourcePayloadCreate(stmt, discPayload);
     }