-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-PRAGMA user_version = 107;
+PRAGMA user_version = 108;
PRAGMA journal_mode = WAL;
CREATE TABLE schedule_table
has_exception INTEGER DEFAULT 0,
has_extended INTEGER DEFAULT 0,
freq INTEGER DEFAULT 0,
-is_allday INTEGER DEFAULT 0
+is_allday INTEGER DEFAULT 0,
+link_count INTEGER DEFAULT 0,
+link_base_id INTEGER DEFAULT 0
);
CREATE INDEX sch_idx1 ON schedule_table(type);
CREATE INDEX sch_idx2 ON schedule_table(calendar_id);
UPDATE schedule_table SET is_deleted = 1 WHERE original_event_id = old.id;
END;
+CREATE TRIGGER trg_link_mod AFTER UPDATE OF link_count ON schedule_table
+ BEGIN
+ UPDATE schedule_table SET link_count = link_count + (SELECT link_count FROM schedule_table WHERE link_base_id = new.id) WHERE id = new.id; -- base is linked to new base
+ UPDATE schedule_table SET link_base_id = new.id WHERE link_base_id = (SELECT id FROM schedule_table WHERE link_base_id = new.id); -- new is linked to base
+ UPDATE schedule_table SET link_count = 0 WHERE link_base_id = new.id; -- set count 0
+ END;
+
+CREATE TRIGGER trg_link_del BEFORE DELETE ON schedule_table
+ BEGIN
+ UPDATE schedule_table SET link_base_id = 0 WHERE link_base_id = old.id; -- when base record is deleted.
+ UPDATE schedule_table SET link_count = link_count -1 WHERE id = old.link_base_id; -- when linked record is deleted.
+ END;
+
CREATE TRIGGER trg_schedule_del AFTER DELETE ON schedule_table
BEGIN
DELETE FROM rrule_table WHERE event_id = old.id;
return ret;
}
+/*
+ * when record is linked or unlinked
+ * we should consider how to handle alarm, attendee, exception, extended.
+ * ONLY supported in event view.
+ */
+EXPORT_API int calendar_db_link_record(int base_id, int record_id)
+{
+ CAL_FN_CALL();
+
+ RETV_IF(base_id <= 0, CALENDAR_ERROR_INVALID_PARAMETER);
+ RETV_IF(record_id <= 0, CALENDAR_ERROR_INVALID_PARAMETER);
+
+ int ret = 0;
+ calendar_h handle = NULL;
+ ret = cal_client_handle_get_p(&handle);
+ RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "cal_client_handle_get_p() Fail(%d)", ret);
+ CAL_DBUS_RETRY_CALL(ret, cal_dbus_link_record(handle, base_id, record_id));
+ return ret;
+}
+
+EXPORT_API int calendar_db_unlink_record(int record_id)
+{
+ CAL_FN_CALL();
+
+ RETV_IF(record_id <= 0, CALENDAR_ERROR_INVALID_PARAMETER);
+
+ int ret = 0;
+ calendar_h handle = NULL;
+ ret = cal_client_handle_get_p(&handle);
+ RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "cal_client_handle_get_p() Fail(%d)", ret);
+ CAL_DBUS_RETRY_CALL(ret, cal_dbus_unlink_record(handle, record_id));
+ return ret;
+}
+
return ret;
}
+int cal_dbus_link_record(calendar_h handle, int base_id, int record_id)
+{
+ RETV_IF(NULL == handle, CALENDAR_ERROR_INVALID_PARAMETER);
+ RETV_IF(base_id <= 0, CALENDAR_ERROR_INVALID_PARAMETER);
+ RETV_IF(record_id <= 0, CALENDAR_ERROR_INVALID_PARAMETER);
+
+ int ret = 0;
+ GError *error = NULL;
+ GVariant *arg_handle = cal_dbus_utils_handle_to_gvariant(handle);
+ cal_dbus_call_link_record_sync(cal_dbus_object, arg_handle, base_id, record_id,
+ &ret, NULL, &error);
+ if (error) {
+ /* LCOV_EXCL_START */
+ ERR("cal_dbus_call_link_record() Fail[%s]", error->message);
+ if (G_DBUS_ERROR_ACCESS_DENIED == error->code)
+ ret = CALENDAR_ERROR_PERMISSION_DENIED;
+ else
+ ret = CALENDAR_ERROR_IPC;
+ g_error_free(error);
+ g_variant_unref(arg_handle);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+ return ret;
+}
+
+int cal_dbus_unlink_record(calendar_h handle, int record_id)
+{
+ RETV_IF(NULL == handle, CALENDAR_ERROR_INVALID_PARAMETER);
+ RETV_IF(record_id <= 0, CALENDAR_ERROR_INVALID_PARAMETER);
+
+ int ret = 0;
+ GError *error = NULL;
+ GVariant *arg_handle = cal_dbus_utils_handle_to_gvariant(handle);
+ cal_dbus_call_unlink_record_sync(cal_dbus_object, arg_handle, record_id,
+ &ret, NULL, &error);
+ if (error) {
+ /* LCOV_EXCL_START */
+ ERR("cal_dbus_call_unlink_record() Fail[%s]", error->message);
+ if (G_DBUS_ERROR_ACCESS_DENIED == error->code)
+ ret = CALENDAR_ERROR_PERMISSION_DENIED;
+ else
+ ret = CALENDAR_ERROR_IPC;
+ g_error_free(error);
+ g_variant_unref(arg_handle);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+ return ret;
+}
+
int cal_dbus_replace_vcalendars(calendar_h handle, const char *stream, int *ids,
int count);
int cal_dbus_recovery(void);
+int cal_dbus_link_record(calendar_h handle, int base_id, int record_id);
+int cal_dbus_unlink_record(calendar_h handle, int record_id);
#endif /* __CAL_CLIENT_DBUS_H__ */
case CAL_PROPERTY_EVENT_IS_ALLDAY:
*out_value = (rec->is_allday);
break;
+ case CAL_PROPERTY_EVENT_LINK_COUNT:
+ *out_value = (rec->link_count);
+ break;
+ case CAL_PROPERTY_EVENT_LINK_BASE_ID:
+ *out_value = (rec->link_base_id);
+ break;
default:
return CALENDAR_ERROR_INVALID_PARAMETER;
}
cal_list_s *attendee_list;
cal_list_s *exception_list;
cal_list_s *extended_list;
+ int link_count;
+ int link_base_id;
} cal_event_s;
typedef struct {
.calendar_attendee = CAL_PROPERTY_EVENT_CALENDAR_ATTENDEE,
.exception = CAL_PROPERTY_EVENT_EXCEPTION,
.extended = CAL_PROPERTY_EVENT_EXTENDED,
- .is_allday = CAL_PROPERTY_EVENT_IS_ALLDAY
+ .is_allday = CAL_PROPERTY_EVENT_IS_ALLDAY,
+ .link_count = CAL_PROPERTY_EVENT_LINK_COUNT,
+ .link_base_id = CAL_PROPERTY_EVENT_LINK_BASE_ID,
};
EXPORT_API const _calendar_todo_property_ids _calendar_todo = {
{CAL_PROPERTY_EVENT_EXCEPTION, NULL},
{CAL_PROPERTY_EVENT_EXTENDED, NULL},
{CAL_PROPERTY_EVENT_IS_ALLDAY, "is_allday"},
+ {CAL_PROPERTY_EVENT_LINK_COUNT, "link_count"},
+ {CAL_PROPERTY_EVENT_LINK_BASE_ID, "link_base_id"},
};
const cal_property_info_s __property_todo[] = {
CAL_PROPERTY_EVENT_EXCEPTION = (CAL_PROPERTY_EVENT|CAL_PROPERTY_DATA_TYPE_REC) + 54,
CAL_PROPERTY_EVENT_EXTENDED = (CAL_PROPERTY_EVENT|CAL_PROPERTY_DATA_TYPE_REC) + 55,
CAL_PROPERTY_EVENT_IS_ALLDAY = (CAL_PROPERTY_EVENT|CAL_PROPERTY_DATA_TYPE_INT|CAL_PROPERTY_FLAGS_READ_ONLY) + 56,
+ CAL_PROPERTY_EVENT_LINK_COUNT = (CAL_PROPERTY_EVENT|CAL_PROPERTY_DATA_TYPE_INT|CAL_PROPERTY_FLAGS_READ_ONLY) + 57,
+ CAL_PROPERTY_EVENT_LINK_BASE_ID = (CAL_PROPERTY_EVENT|CAL_PROPERTY_DATA_TYPE_INT|CAL_PROPERTY_FLAGS_READ_ONLY) + 58,
CAL_PROPERTY_TODO_ID = (CAL_PROPERTY_TODO|CAL_PROPERTY_DATA_TYPE_INT|CAL_PROPERTY_FLAGS_READ_ONLY),
CAL_PROPERTY_TODO_BOOK_ID = (CAL_PROPERTY_TODO|CAL_PROPERTY_DATA_TYPE_INT) + 1,
<arg type="i" name="ret" direction="out"/>
<arg type="i" name="version" direction="out"/>
</method>
+ <method name="link_record">
+ <arg type="(ii)" name="handle" direction="in"/>
+ <arg type="i" name="base_id" direction="in"/>
+ <arg type="i" name="record_id" direction="in"/>
+ <arg type="i" name="ret" direction="out"/>
+ </method>
+ <method name="unlink_record">
+ <arg type="(ii)" name="handle" direction="in"/>
+ <arg type="i" name="record_id" direction="in"/>
+ <arg type="i" name="ret" direction="out"/>
+ </method>
</interface>
</node>
*/
int calendar_db_clean_after_sync(int calendar_book_id, int calendar_db_version);
+/**
+ * @brief Links a record to another record.
+ * @since_tizen 4.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/calendar.write
+ * @param[in] base_id The base record ID
+ * @param[in] record_id The record ID to link to
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #CALENDAR_ERROR_NONE Successful
+ * @retval #CALENDAR_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #CALENDAR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #CALENDAR_ERROR_DB_FAILED Database operation failure
+ * @retval #CALENDAR_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #CALENDAR_ERROR_FILE_NO_SPACE File system is full
+ * @retval #CALENDAR_ERROR_IPC Unknown IPC error
+ * @pre calendar_connect() should be called to open a connection to the calendar service.
+ * @see calendar_connect()
+ */
+int calendar_db_link_record(int base_id, int record_id);
+
+/**
+ * @brief Unlinks a record from base record.
+ * @since_tizen 4.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/calendar.write
+ * @param[in] record_id The record ID to unlink
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #CALENDAR_ERROR_NONE Successful
+ * @retval #CALENDAR_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #CALENDAR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #CALENDAR_ERROR_DB_FAILED Database operation failure
+ * @retval #CALENDAR_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #CALENDAR_ERROR_FILE_NO_SPACE File system is full
+ * @retval #CALENDAR_ERROR_IPC Unknown IPC error
+ * @pre calendar_connect() should be called to open a connection to the calendar service.
+ * @see calendar_connect()
+ */
+int calendar_db_unlink_record(int record_id);
/**
* @}
* <tr><td> child list </td><td> exception </td><td> read, write </td><td>The exception mod event list of the event</td></tr>
* <tr><td> child list </td><td> extended </td><td> read, write </td><td>The extended property list of the event. Refer to the @ref CAPI_SOCIAL_CALENDAR_SVC_VIEW_MODULE_calendar_extended_property</td></tr>
* <tr><td> interger </td><td> is_allday </td><td> read only </td><td>The event is an allday event or not </td></tr>
+ * <tr><td> interger </td><td> link_count </td><td> read only </td><td>The event is a linked event (Since 4.0)</td></tr>
+ * <tr><td> interger </td><td> link_base_id </td><td> read only </td><td>The event is a base linked event (Since 4.0)</td></tr>
* </table>
*/
_CALENDAR_BEGIN_VIEW()
_CALENDAR_PROPERTY_CHILD_MULTIPLE(exception)
_CALENDAR_PROPERTY_CHILD_MULTIPLE(extended)
_CALENDAR_PROPERTY_INT(is_allday) /* read only */
+ _CALENDAR_PROPERTY_INT(link_count) /* read only */
+ _CALENDAR_PROPERTY_INT(link_base_id) /* read only */
_CALENDAR_END_VIEW(_calendar_event)
<check send_destination="@DBUS_INTERFACE@"
send_interface="@DBUS_INTERFACE@" send_member="replace_vcalendars"
privilege="http://tizen.org/privilege/calendar.write"/>
+ <check send_destination="@DBUS_INTERFACE@"
+ send_interface="@DBUS_INTERFACE@" send_member="link_record"
+ privilege="http://tizen.org/privilege/calendar.write"/>
+ <check send_destination="@DBUS_INTERFACE@"
+ send_interface="@DBUS_INTERFACE@" send_member="unlink_record"
+ privilege="http://tizen.org/privilege/calendar.write"/>
</policy>
</busconfig>
{
int ret = 0;
char query[CAL_DB_SQL_MAX_LEN] = {0};
- snprintf(query, sizeof(query), "SELECT event_id,remind_tick_unit,remind_tick,"
- "alarm_type,alarm_utime,alarm_datetime "
- "FROM %s WHERE remind_tick_unit =%d AND alarm_type =%d AND alarm_utime %s %ld %s",
- CAL_TABLE_ALARM, CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_UTIME,
+ snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
+ "A.alarm_type, A.alarm_utime, A.alarm_datetime "
+ "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
+ "WHERE S.link_base_id = 0 AND A.remind_tick_unit = %d AND A.alarm_type = %d "
+ "AND A.alarm_utime %s %ld %s",
+ CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_UTIME,
true == get_all ? "=" : ">", utime,
true == get_all ? "" : "ORDER BY alarm_utime ASC LIMIT 1");
{
int ret = 0;
char query[CAL_DB_SQL_MAX_LEN] = {0};
- snprintf(query, sizeof(query), "SELECT event_id,remind_tick_unit,remind_tick,"
- "alarm_type,alarm_utime,alarm_datetime "
- "FROM %s WHERE remind_tick_unit=%d AND alarm_type=%d AND alarm_datetime %s '%s' %s",
- CAL_TABLE_ALARM, CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_LOCALTIME,
+ snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
+ "A.alarm_type, A.alarm_utime, A.alarm_datetime "
+ "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
+ "WHERE S.link_base_id = 0 AND A.remind_tick_unit = %d AND A.alarm_type = %d "
+ "AND A.alarm_datetime %s '%s' %s",
+ CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_LOCALTIME,
true == get_all ? "=" : ">", datetime,
true == get_all ? "" : "ORDER BY alarm_datetime ASC LIMIT 1");
char query[CAL_DB_SQL_MAX_LEN] = {0};
snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick, "
"A.alarm_type,B.dtstart_utime,A.alarm_datetime "
- "FROM %s as A, %s as B ON A.event_id = B.event_id "
- "WHERE A.remind_tick_unit >%d AND (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
- CAL_TABLE_ALARM, CAL_TABLE_UTIME_INSTANCE, CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
+ "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_UTIME_INSTANCE" as B, "CAL_TABLE_SCHEDULE" as S "
+ "ON A.event_id = B.event_id AND B.event_id = S.id "
+ "WHERE S.link_base_id = 0 AND A.remind_tick_unit > %d "
+ "AND (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
+ CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
true == get_all ? "=" : ">", utime,
true == get_all ? "" : "ORDER BY (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1");
* B:localtime
*/
char query[CAL_DB_SQL_MAX_LEN] = {0};
- snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick, "
- "A.alarm_type,A.alarm_utime,B.dtstart_datetime "
- "FROM %s as A, %s as B ON A.event_id = B.event_id "
- "WHERE A.remind_tick_unit >%d AND "
+ snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, "
+ "A.alarm_type, A.alarm_utime, B.dtstart_datetime "
+ "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_LOCALTIME_INSTANCE" as B, "CAL_TABLE_SCHEDULE" as S "
+ "ON A.event_id = B.event_id AND B.event_id = S.id "
+ "WHERE S.link_base_id = 0 AND A.remind_tick_unit >%d AND "
"(strftime('%%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
- CAL_TABLE_ALARM, CAL_TABLE_LOCALTIME_INSTANCE, CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
+ CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
datetime, true == get_all ? "=" : ">",
true == get_all ? "" : "ORDER BY (strftime('%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
sqlite3_stmt *stmt = NULL;
int ret = 0;
/*
* A:alarm
- * B:todo(utime)
+ * S:todo(utime)
*/
char query[CAL_DB_SQL_MAX_LEN] = {0};
- snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick,"
- "A.alarm_type,B.dtend_utime,A.alarm_datetime "
- "FROM %s as A, %s as B ON A.event_id = B.id "
- "WHERE A.remind_tick_unit >%d AND B.type =%d "
- "AND (B.dtend_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
- CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE,
+ snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
+ "A.alarm_type, S.dtend_utime, A.alarm_datetime "
+ "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
+ "WHERE A.remind_tick_unit > %d AND S.type = %d "
+ "AND (S.dtend_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
true == get_all ? "=" : ">", utime,
- true == get_all ? "" : "ORDER BY (B.dtend_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
+ true == get_all ? "" : "ORDER BY (S.dtend_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
sqlite3_stmt *stmt = NULL;
ret = cal_db_util_query_prepare(query, &stmt);
char query[CAL_DB_SQL_MAX_LEN] = {0};
snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick,"
"A.alarm_type,A.alarm_utime,B.dtend_datetime "
- "FROM %s as A, %s as B ON A.event_id = B.id "
+ "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as B ON A.event_id = B.id "
"WHERE A.remind_tick_unit >%d AND B.type =%d "
"AND (strftime('%%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
- CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE,
CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
datetime, true == get_all ? "=" : ">",
true == get_all ? "" : "ORDER BY (strftime('%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
return CALENDAR_ERROR_NONE;
}
+static gboolean _handle_link_record(calDbus *object, GDBusMethodInvocation *invocation,
+ GVariant *arg_handle, int base_id, int record_id)
+{
+ int ret = 0;
+ ret = cal_db_link_record(base_id, record_id);
+ cal_dbus_complete_link_record(object, invocation, ret);
+
+ cal_server_ondemand_start();
+ return TRUE;
+}
+
+static gboolean _handle_unlink_record(calDbus *object, GDBusMethodInvocation *invocation,
+ GVariant *arg_handle, int record_id)
+{
+ int ret = 0;
+ ret = cal_db_unlink_record(record_id);
+ cal_dbus_complete_unlink_record(object, invocation, ret);
+
+ cal_server_ondemand_start();
+ return TRUE;
+}
+
static void _delete_sender(cal_sender_s *sender)
{
RET_IF(NULL == sender);
G_CALLBACK(_handle_insert_vcalendars), NULL);
g_signal_connect(dbus_object, "handle-replace-vcalendars",
G_CALLBACK(_handle_replace_vcalendars), NULL);
+ g_signal_connect(dbus_object, "handle-link-record",
+ G_CALLBACK(_handle_link_record), NULL);
+ g_signal_connect(dbus_object, "handle-unlink-record",
+ G_CALLBACK(_handle_unlink_record), NULL);
ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(dbus_object),
conn, CAL_DBUS_OBJPATH, &error);
if (SQLITE_OK != ret) {
/* LCOV_EXCL_START */
ERR("sqlite3_exec() Fail[%s]", errmsg);
+ ERR("[%s]", schema_query);
sqlite3_free(errmsg);
db_util_close(db);
return -1;
#include "cal_internal.h"
#include "cal_db.h"
-#define __USER_VERSION 107
+#define __USER_VERSION 108
/* LCOV_EXCL_START */
static int _cal_server_update_get_db_version(sqlite3 *db, int *version)
* added field is_alldy on schedule_table
*/
- /* add field: is_allday in deleted_table */
+ /* add field: is_allday in schedule_table */
ret = sqlite3_exec(__db, "ALTER TABLE schedule_table ADD COLUMN is_allday INTEGER DEFAULT 0", NULL, 0, &errmsg);
if (SQLITE_OK != ret) {
ERR("ALTER TABLE schedule_table failed(%d:%s)", ret, errmsg);
}
/* ----------------------- end modified 2016/09/06
*/
+ old_version = 107;
+ }
+ if (old_version == 107) {
+ /*
+ * ----------------------- start modified 2017/04/17
+ */
+
+ /* add field: link_count in schedule_table */
+ ret = sqlite3_exec(__db, "ALTER TABLE schedule_table ADD COLUMN link_count INTEGER DEFAULT 0", NULL, 0, &errmsg);
+ if (SQLITE_OK != ret) {
+ ERR("ALTER TABLE schedule_table failed(%d:%s)", ret, errmsg);
+ sqlite3_free(errmsg);
+ }
+ /* add field: link_base_id in schedule_table */
+ ret = sqlite3_exec(__db, "ALTER TABLE schedule_table ADD COLUMN link_base_id INTEGER DEFAULT 0", NULL, 0, &errmsg);
+ if (SQLITE_OK != ret) {
+ ERR("ALTER TABLE schedule_table failed(%d:%s)", ret, errmsg);
+ sqlite3_free(errmsg);
+ }
+ /* add trigger: update record when link_count is modified */
+ ret = sqlite3_exec(__db,
+ "CREATE TRIGGER trg_link_mod AFTER UPDATE OF link_count ON schedule_table "
+ " BEGIN "
+ " UPDATE schedule_table SET link_count = link_count + (SELECT link_count FROM schedule_table WHERE link_base_id = new.id) WHERE id = new.id; " /* base is linked to new base */
+ " UPDATE schedule_table SET link_base_id = new.id WHERE link_base_id = (SELECT id FROM schedule_table WHERE link_base_id = new.id); " /* new is linked to base */
+ " UPDATE schedule_table SET link_count = 0 WHERE link_base_id = new.id; " /* set count 0 */
+ " END; ",
+ NULL, 0, &errmsg);
+ if (SQLITE_OK != ret) {
+ ERR("CREATE TRIGGER trg_link_mod failed(%d:%s)", ret, errmsg);
+ sqlite3_free(errmsg);
+ }
+
+ /* add trigger: update record when link record is deleted */
+ ret = sqlite3_exec(__db,
+ "CREATE TRIGGER trg_link_del BEFORE DELETE ON schedule_table "
+ " BEGIN "
+ " UPDATE schedule_table SET link_base_id = 0 WHERE link_base_id = old.id; " /* when base record is deleted. */
+ " UPDATE schedule_table SET link_count = link_count -1 WHERE id = old.link_base_id; " /* when linked record is deleted. */
+ " END; ",
+ NULL, 0, &errmsg);
+ if (SQLITE_OK != ret) {
+ ERR("CREATE TRIGGER trg_link_mod failed(%d:%s)", ret, errmsg);
+ sqlite3_free(errmsg);
+ }
+
+ /* ----------------------- end modified 2017/04/17
+ */
old_version = __USER_VERSION;
}
+ /* drop views */
+ snprintf(query, sizeof(query), "DROP VIEW [IF EXISTS] event_view");
+ ret = sqlite3_exec(__db, query, NULL, 0, &errmsg);
+ if (SQLITE_OK != ret) {
+ ERR("sqlite3_exec() failed(%d) [%s]", ret, errmsg);
+ sqlite3_free(errmsg);
+ db_util_close(__db);
+ return CALENDAR_ERROR_SYSTEM;
+ }
+ snprintf(query, sizeof(query), "DROP VIEW [IF EXISTS] todo_view");
+ sqlite3_exec(__db, query, NULL, 0, &errmsg);
+ snprintf(query, sizeof(query), "DROP VIEW [IF EXISTS] todo_view");
+ sqlite3_exec(__db, query, NULL, 0, &errmsg);
+ snprintf(query, sizeof(query), "DROP VIEW [IF EXISTS] event_book_view");
+ sqlite3_exec(__db, query, NULL, 0, &errmsg);
+ snprintf(query, sizeof(query), "DROP VIEW [IF EXISTS] todo_book_view");
+ sqlite3_exec(__db, query, NULL, 0, &errmsg);
+ snprintf(query, sizeof(query), "DROP VIEW [IF EXISTS] event_calendar_attendee_view");
+ sqlite3_exec(__db, query, NULL, 0, &errmsg);
+ snprintf(query, sizeof(query), "DROP VIEW [IF EXISTS] utime_instance_view");
+ sqlite3_exec(__db, query, NULL, 0, &errmsg);
+ snprintf(query, sizeof(query), "DROP VIEW [IF EXISTS] localtime_instance_view");
+ sqlite3_exec(__db, query, NULL, 0, &errmsg);
+ snprintf(query, sizeof(query), "DROP VIEW [IF EXISTS] utime_instance_view_extended");
+ sqlite3_exec(__db, query, NULL, 0, &errmsg);
+ snprintf(query, sizeof(query), "DROP VIEW [IF EXISTS] localtime_instance_view_extended");
+ sqlite3_exec(__db, query, NULL, 0, &errmsg);
+
+
/* update DB user_version */
snprintf(query, sizeof(query), "PRAGMA user_version = %d", __USER_VERSION);
ret = sqlite3_exec(__db, query, NULL, 0, &errmsg);
"A.dtstart_type, A.dtstart_utime, A.dtstart_datetime, A.dtstart_tzid, "\
"A.dtend_type, A.dtend_utime, A.dtend_datetime, A.dtend_tzid, "\
"A.last_mod, A.rrule_id, A.recurrence_id, A.rdate, A.has_attendee, A.has_alarm, A.system_type, A.updated, "\
- "A.sync_data1, A.sync_data2, A.sync_data3, A.sync_data4, A.has_exception, A.has_extended, A.freq, A.is_allday "
+ "A.sync_data1, A.sync_data2, A.sync_data3, A.sync_data4, A.has_exception, A.has_extended, A.freq, "\
+ "A.is_allday, A.link_count, A.link_base_id "
typedef int (*cal_db_get_record_cb)(int id, calendar_record_h* out_record);
typedef int (*cal_db_insert_record_cb)(calendar_record_h record, int* id);
int cal_db_append_string(char **dst, const char *src);
cal_db_plugin_cb_s* _cal_db_get_plugin(cal_record_type_e type);
+int cal_db_link_record(int base_id, int record_id);
+int cal_db_unlink_record(int record_id);
+
#endif /* __CAL_DB_H__ */
--- /dev/null
+/*
+ * Calendar Service
+ *
+ * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#include "cal_internal.h"
+#include "cal_typedef.h"
+#include "cal_view.h"
+#include "cal_record.h"
+#include "cal_db.h"
+#include "cal_db_util.h"
+#include "cal_db_plugin_event.h"
+#include "cal_db_plugin_event_helper.h"
+#include "cal_db_plugin_attendee_helper.h"
+#include "cal_db_plugin_alarm_helper.h"
+#include "cal_db_plugin_extended_helper.h"
+
+int cal_db_link_record(int base_id, int record_id)
+{
+ int ret = 0;
+ char query[CAL_DB_SQL_MAX_LEN] = {0};
+
+ ret = cal_db_util_begin_trans();
+ RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "cal_db_util_begin_trans() Fail");
+
+ calendar_record_h record = NULL;
+ ret = cal_db_get_record(_calendar_event._uri, record_id, &record);
+ if (CALENDAR_ERROR_NONE != ret) {
+ /* LCOV_EXCL_START */
+ ERR("cal_db_get_record() Fail(%d)", ret);
+ cal_db_util_end_trans(false);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* base record and linked record have even type */
+ snprintf(query, sizeof(query), "UPDATE "CAL_TABLE_SCHEDULE" SET link_base_id = %d "
+ "WHERE id = %d AND type = %d "
+ "AND (SELECT type FROM "CAL_TABLE_SCHEDULE" WHERE id = %d) = %d ",
+ base_id, record_id, CALENDAR_BOOK_TYPE_EVENT, base_id, CALENDAR_BOOK_TYPE_EVENT);
+
+ ret = cal_db_util_query_exec(query);
+ if (CALENDAR_ERROR_NONE != ret) {
+ /* LCOV_EXCL_START */
+ ERR("cal_db_util_query_exec() Fail(%d)", ret);
+ SECURE("[%s]", query);
+ calendar_record_destroy(record, true);
+ cal_db_util_end_trans(false);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* update base record's link_count */
+ snprintf(query, sizeof(query), "UPDATE "CAL_TABLE_SCHEDULE" SET link_count = link_count + 1 "
+ "WHERE id = %d ", base_id);
+
+ ret = cal_db_util_query_exec(query);
+ if (CALENDAR_ERROR_NONE != ret) {
+ /* LCOV_EXCL_START */
+ ERR("cal_db_util_query_exec() Fail(%d)", ret);
+ SECURE("[%s]", query);
+ calendar_record_destroy(record, true);
+ cal_db_util_end_trans(false);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* To check alarm, attendee, exception, extended
+ * case 1: merge alarm
+ * case 2: remove linked record alarm
+ * we choose case 1. so modify alarm logic not to pick liked record alarm.
+ */
+
+ calendar_record_destroy(record, true);
+ cal_db_util_end_trans(true);
+
+ return ret;
+}
+
+int cal_db_unlink_record(int record_id)
+{
+ int ret = 0;
+ int base_id = 0;
+ char query[CAL_DB_SQL_MAX_LEN] = {0};
+
+ ret = cal_db_util_begin_trans();
+ RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "cal_db_util_begin_trans() Fail");
+
+ /* get record */
+ calendar_record_h record = NULL;
+ ret = cal_db_get_record(_calendar_event._uri, record_id, &record);
+ if (CALENDAR_ERROR_NONE != ret) {
+ /* LCOV_EXCL_START */
+ ERR("cal_db_get_record() Fail(%d)", ret);
+ cal_db_util_end_trans(false);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+ cal_event_s *event = (cal_event_s *)record;
+ base_id = event->link_base_id;
+
+ /* update base record's link_count */
+ snprintf(query, sizeof(query), "UPDATE "CAL_TABLE_SCHEDULE" SET link_count = link_count - 1 "
+ "WHERE id = %d AND link_count > 0", base_id);
+
+ ret = cal_db_util_query_exec(query);
+ if (CALENDAR_ERROR_NONE != ret) {
+ /* LCOV_EXCL_START */
+ ERR("cal_db_util_query_exec() Fail(%d)", ret);
+ SECURE("[%s]", query);
+ calendar_record_destroy(record, true);
+ cal_db_util_end_trans(false);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* base record and linked record have even type */
+ snprintf(query, sizeof(query), "UPDATE "CAL_TABLE_SCHEDULE" SET link_base_id = 0 "
+ "WHERE id = %d AND type = %d "
+ "AND (SELECT type FROM "CAL_TABLE_SCHEDULE" WHERE id = %d) = %d ",
+ record_id, CALENDAR_BOOK_TYPE_EVENT, base_id, CALENDAR_BOOK_TYPE_EVENT);
+
+ ret = cal_db_util_query_exec(query);
+ if (CALENDAR_ERROR_NONE != ret) {
+ /* LCOV_EXCL_START */
+ ERR("cal_db_util_query_exec() Fail(%d)", ret);
+ SECURE("[%s]", query);
+ calendar_record_destroy(record, true);
+ cal_db_util_end_trans(false);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ calendar_record_destroy(record, true);
+ cal_db_util_end_trans(true);
+
+ return ret;
+}
+
--- /dev/null
+/*
+ * Calendar Service
+ *
+ * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __CAL_DB_LINK_H__
+#define __CAL_DB_LINK_H__
+
+int cal_db_link_record(int base_id, int record_id);
+int cal_db_unlink_record(int record_id);
+
+#endif /* __CAL_DB_LINK_H__ */
/*
* static function
*/
-static void _cal_db_event_get_stmt(sqlite3_stmt *stmt, bool is_view_table, calendar_record_h record, int *exception, int *extended);
+void cal_db_event_get_stmt(sqlite3_stmt *stmt, bool is_view_table, calendar_record_h record, int *exception, int *extended);
static void _cal_db_event_get_property_stmt(sqlite3_stmt *stmt, unsigned int property, int *stmt_count, calendar_record_h record);
static void _cal_db_event_get_projection_stmt(sqlite3_stmt *stmt, const unsigned int *projection, const int projection_count, calendar_record_h record);
-static int _cal_db_event_exception_get_records(int original_id, cal_list_s *list);
+int cal_db_event_exception_get_records(int original_id, cal_list_s *list);
static int _cal_db_event_exception_get_ids(int original_id, GList **out_list);
static int _cal_db_event_exception_update(cal_list_s *exception_list_s, int original_id, int calendar_id, int is_dirty_in_time, time_t time_diff, int old_type, int new_type);
static int _cal_db_event_get_deleted_data(int id, int* calendar_book_id, int* created_ver, int* original_event_id, char** recurrence_id);
/* LCOV_EXCL_STOP */
}
- _cal_db_event_get_stmt(stmt, false, *out_record, &exception, &extended);
+ cal_db_event_get_stmt(stmt, false, *out_record, &exception, &extended);
sqlite3_finalize(stmt);
stmt = NULL;
cal_db_attendee_get_records(event->index, event->attendee_list);
if (exception == 1)
- _cal_db_event_exception_get_records(event->index, event->exception_list);
+ cal_db_event_exception_get_records(event->index, event->exception_list);
if (extended == 1)
cal_db_extended_get_records(event->index, CALENDAR_RECORD_TYPE_EVENT, event->extended_list);
return ret;
/* LCOV_EXCL_STOP */
}
- _cal_db_event_get_stmt(stmt, true, record, &exception, &extended);
+ cal_db_event_get_stmt(stmt, true, record, &exception, &extended);
/* child */
int has_attendee = 0, has_alarm = 0;
}
if (exception == 1)
- _cal_db_event_exception_get_records(record_id, pevent->exception_list);
+ cal_db_event_exception_get_records(record_id, pevent->exception_list);
if (extended == 1)
cal_db_extended_get_records(record_id, CALENDAR_RECORD_TYPE_EVENT, pevent->extended_list);
return ret;
/* LCOV_EXCL_STOP */
}
+
+ cal_event_s* pevent = (cal_event_s*)record;
if (0 < que->projection_count) {
cal_record_set_projection(record, que->projection, que->projection_count, que->property_count);
_cal_db_event_get_projection_stmt(stmt, que->projection, que->projection_count, record);
} else {
- cal_event_s *event = NULL;
- _cal_db_event_get_stmt(stmt, true, record, &exception, &extended);
- event = (cal_event_s*)(record);
- if (event) {
- attendee = event->has_attendee;
- alarm = event->has_alarm;
- }
+ cal_db_event_get_stmt(stmt, true, record, &exception, &extended);
+ attendee = pevent->has_attendee;
+ alarm = pevent->has_alarm;
}
/* child */
if (cal_db_query_find_projection_property(query, CAL_PROPERTY_EVENT_CALENDAR_ALARM) == true && alarm == 1) {
- cal_event_s* pevent = (cal_event_s*) record;
cal_db_alarm_get_records(pevent->index, pevent->alarm_list);
}
if (cal_db_query_find_projection_property(query, CAL_PROPERTY_EVENT_CALENDAR_ATTENDEE) == true && attendee == 1) {
- cal_event_s* pevent = (cal_event_s*) record;
cal_db_attendee_get_records(pevent->index, pevent->attendee_list);
}
if (cal_db_query_find_projection_property(query, CAL_PROPERTY_EVENT_EXCEPTION) == true && exception == 1) {
- cal_event_s* pevent = (cal_event_s*) record;
- _cal_db_event_exception_get_records(pevent->index, pevent->exception_list);
+ cal_db_event_exception_get_records(pevent->index, pevent->exception_list);
}
if (cal_db_query_find_projection_property(query, CAL_PROPERTY_EVENT_EXTENDED) == true && extended == 1) {
- cal_event_s* pevent = (cal_event_s*) record;
cal_db_extended_get_records(pevent->index, CALENDAR_RECORD_TYPE_EVENT, pevent->extended_list);
}
return CALENDAR_ERROR_NONE;
}
-static void _cal_db_event_get_stmt(sqlite3_stmt *stmt, bool is_view_table, calendar_record_h record,
+void cal_db_event_get_stmt(sqlite3_stmt *stmt, bool is_view_table, calendar_record_h record,
int *exception, int *extended)
{
cal_event_s *event = NULL;
event->freq = sqlite3_column_int(stmt, count++);
event->is_allday = sqlite3_column_int(stmt, count++);
+ event->link_count = sqlite3_column_int(stmt, count++);
+ event->link_base_id = sqlite3_column_int(stmt, count++);
if (is_view_table == true) {
if (event->freq <= 0)
case CAL_PROPERTY_EVENT_IS_ALLDAY:
event->is_allday = sqlite3_column_int(stmt, *stmt_count);
break;
+ case CAL_PROPERTY_EVENT_LINK_COUNT:
+ event->link_count = sqlite3_column_int(stmt, *stmt_count);
+ break;
+ case CAL_PROPERTY_EVENT_LINK_BASE_ID:
+ event->link_base_id = sqlite3_column_int(stmt, *stmt_count);
+ break;
default:
/* LCOV_EXCL_START */
ERR("invalid (0x%x)", property);
return ret;
}
-static int _cal_db_event_exception_get_records(int original_id, cal_list_s *list)
+int cal_db_event_exception_get_records(int original_id, cal_list_s *list)
{
int ret;
char query[CAL_DB_SQL_MAX_LEN] = {0};
/* LCOV_EXCL_STOP */
}
- _cal_db_event_get_stmt(stmt, false, record, &exception, &extended);
+ cal_db_event_get_stmt(stmt, false, record, &exception, &extended);
cal_rrule_s *rrule = NULL;
cal_event_s *event = (cal_event_s *)record;
cal_db_attendee_get_records(event->index, event->attendee_list);
if (exception == 1)
- _cal_db_event_exception_get_records(event->index, event->exception_list);
+ cal_db_event_exception_get_records(event->index, event->exception_list);
if (extended == 1)
cal_db_extended_get_records(event->index, CALENDAR_RECORD_TYPE_EVENT, event->extended_list);
--- /dev/null
+/*
+ * Calendar Service
+ *
+ * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __CAL_DB_PLUGIN_EVENT_H__
+#define __CAL_DB_PLUGIN_EVENT_H__
+
+void cal_db_event_get_stmt(sqlite3_stmt *stmt, bool is_view_table, calendar_record_h record,
+ int *exception, int *extended);
+int cal_db_event_exception_get_records(int original_id, cal_list_s *list);
+
+#endif /* __CAL_DB_PLUGIN_EVENT_H__ */
instance->sync_data1 = cal_strdup((const char*)temp);
break;
case CAL_PROPERTY_INSTANCE_LOCALTIME_IS_ALLDAY:
- instance->is_allday = sqlite3_column_int64(stmt, *stmt_count);
+ instance->is_allday = sqlite3_column_int(stmt, *stmt_count);
break;
-
default:
sqlite3_column_int(stmt, *stmt_count);
break;
return ret;
/* LCOV_EXCL_STOP */
}
+
+ cal_todo_s* ptodo = (cal_todo_s*)record;
if (0 < que->projection_count) {
cal_record_set_projection(record,
que->projection, que->projection_count, que->property_count);
que->projection, que->projection_count,
record);
} else {
- cal_todo_s *todo = NULL;
_cal_db_todo_get_stmt(stmt, true, record, &extended);
- todo = (cal_todo_s*)(record);
- if (todo) {
- attendee = todo->has_attendee;
- alarm = todo->has_alarm;
- }
+ attendee = ptodo->has_attendee;
+ alarm = ptodo->has_alarm;
}
/* child */
if (cal_db_query_find_projection_property(query, CAL_PROPERTY_TODO_CALENDAR_ALARM) == true && alarm == 1) {
- cal_todo_s* todo = (cal_todo_s*) record;
- cal_db_alarm_get_records(todo->index, todo->alarm_list);
+ cal_db_alarm_get_records(ptodo->index, ptodo->alarm_list);
}
if (cal_db_query_find_projection_property(query, CAL_PROPERTY_TODO_CALENDAR_ATTENDEE) == true && attendee == 1) {
- cal_todo_s* todo = (cal_todo_s*) record;
- cal_db_attendee_get_records(todo->index, todo->attendee_list);
+ cal_db_attendee_get_records(ptodo->index, ptodo->attendee_list);
}
if (cal_db_query_find_projection_property(query, CAL_PROPERTY_TODO_EXTENDED) == true && extended == 1) {
- cal_todo_s* todo = (cal_todo_s*) record;
- cal_db_extended_get_records(todo->index, CALENDAR_RECORD_TYPE_TODO, todo->extended_list);
+ cal_db_extended_get_records(ptodo->index, CALENDAR_RECORD_TYPE_TODO, ptodo->extended_list);
}
ret = calendar_list_add(*out_list, record);
todo->freq = sqlite3_column_int(stmt, count++);
todo->is_allday = sqlite3_column_int(stmt, count++);
+ count++; /* link_count */
+ count++; /* link_base_id */
if (is_view_table == true) {
if (todo->freq <= 0)