You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

596 lines
23 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
package net.micode.notes.data;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
/**
* 1.作用:笔记应用数据库辅助类
* 2.用处:管理 SQLite 数据库的创建、版本升级和表结构定义
* 实现了单例模式以确保全局唯一数据库实例
*/
public class NotesDatabaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "note.db";
private static final int DB_VERSION = 4;
/**
* 1.作用:表名接口定义
* 2.内容:包含笔记表 (note) 和数据内容表 (data)
*/
public interface TABLE {
public static final String NOTE = "note";
public static final String DATA = "data";
}
private static final String TAG = "NotesDatabaseHelper";
private static NotesDatabaseHelper mInstance;
/**
* 1.作用:创建笔记主表结构
* 2.变量名CREATE_NOTE_TABLE_SQL
* 3.类型String
* 3.功能:
* 存储笔记基本信息和元数据
* 支持文件夹嵌套结构
* 自动记录创建 / 修改时间
* 关联桌面小部件和同步功能
*/
private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," +
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," +
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" +
")";
/**
* 1.作用:创建笔记内容表结构
* 2.变量名CREATE_DATA_TABLE_SQL
* 3.类型String
* 4.功能:
* 存储不同类型的笔记内容
* 支持一对多关系(一个笔记可包含多个内容项)
* 通用字段设计DATA1-DATA5适配不同类型数据
*/
private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," +
DataColumns.MIME_TYPE + " TEXT NOT NULL," +
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA1 + " INTEGER," +
DataColumns.DATA2 + " INTEGER," +
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
")";
/**
* 1.作用:优化笔记内容查询性能
* 2.变量名CREATE_DATA_NOTE_ID_INDEX_SQL
* 3.类型String
* 4.功能:
* 加速通过笔记 ID 查询相关内容的操作
* 减少 JOIN 操作时的全表扫描
* 提升批量数据查询效率
*/
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
/**
* Increase folder's note count when move note to the folder
*/
/**
* 1. 笔记文件夹计数触发器:
* 2.作用:更新笔记父文件夹时自动维护文件夹的笔记数量统计
* 3.功能描述:
* - 当笔记的父文件夹(parent_id)发生变更时,自动增加新父文件夹的笔记计数
* - 触发器在UPDATE操作后执行确保计数更新与数据变更同步
* - 通过维护冗余计数字段避免频繁执行代价高昂的COUNT(*)查询
*/
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_update "+
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
/**
* Decrease folder's note count when move note from folder
*/
/**
* 1.作用:维护笔记文件夹计数的完整性
* 2.变量名NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER
* 3.类型String
* 4.功能:
* 当笔记移动到新文件夹时,减少原文件夹的笔记计数
* 确保文件夹中的笔记数量统计始终保持准确
* 防止计数出现负值通过条件检查确保计数≥0
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_update " +
" AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
" END";
/**
* Increase folder's note count when insert new note to the folder
*/
/**
* 1.作用:维护笔记文件夹计数的实时性和准确性
* 2.变量名NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER
* 3.类型String
* 4.功能:
* 当新笔记创建时,自动增加其父文件夹的笔记计数
* 确保文件夹中的笔记数量统计始终保持准确
* 避免手动维护计数可能导致的数据不一致问题
*/
private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =
"CREATE TRIGGER increase_folder_count_on_insert " +
" AFTER INSERT ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
" WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
" END";
/**
* Decrease folder's note count when delete note from the folder
*/
/**
* 1.作用:维护笔记文件夹计数的完整性
* 2.变量名NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER
* 3.类型String
* 4.功能:
* 当笔记被删除时,自动减少其父文件夹的笔记计数
* 确保文件夹中的笔记数量统计始终保持准确
* 通过条件检查防止计数出现负值
*/
private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
"CREATE TRIGGER decrease_folder_count_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN " +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
" WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
" AND " + NoteColumns.NOTES_COUNT + ">0;" +
" END";
/**
* Update note's content when insert data with type {@link DataConstants#NOTE}
*/
/**
/**
* 1.作用:维护笔记内容与数据记录的同步性
* 2.变量名DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER
* 3.类型String
* 4.功能:
* 当新的笔记数据记录插入时,自动更新关联笔记的摘要内容
* 确保笔记列表中能快速显示最新的笔记内容片段
* 仅对MIME类型为笔记的数据记录生效避免处理其他类型数据
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER =
"CREATE TRIGGER update_note_content_on_insert " +
" AFTER INSERT ON " + TABLE.DATA +
" WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
/**
* Update note's content when data with {@link DataConstants#NOTE} type has changed
*/
/**
* 1.作用:维护笔记摘要与内容数据的实时同步
* 2.变量名DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER
* 3.类型String
* 4.功能:
* 当笔记内容数据更新时,自动同步更新笔记的摘要字段
* 确保笔记列表中显示的内容预览始终反映最新修改
* 通过条件过滤仅处理MIME类型为笔记的数据记录
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER =
"CREATE TRIGGER update_note_content_on_update " +
" AFTER UPDATE ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
" WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
" END";
/**
* Update note's content when data with {@link DataConstants#NOTE} type has deleted
*/
/**
* 1.作用:维护笔记摘要与内容数据的一致性
* 2.变量名DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER
* 3.类型String
* 4.功能:
* 当笔记内容数据被删除时,自动清空关联笔记的摘要字段
* 确保笔记列表中不会显示已删除的内容预览
* 通过条件过滤仅处理MIME类型为笔记的数据记录
*/
private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER =
"CREATE TRIGGER update_note_content_on_delete " +
" AFTER delete ON " + TABLE.DATA +
" WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.SNIPPET + "=''" +
" WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
" END";
/**
* Delete datas belong to note which has been deleted
*/
/**
* 1.作用:维护数据完整性,实现级联删除
* 2.变量名NOTE_DELETE_DATA_ON_DELETE_TRIGGER
* 3.类型String
* 4.功能:
* 当笔记主记录被删除时,自动删除该笔记关联的所有内容数据
* 确保数据库中不会残留无主的数据记录
* 实现逻辑上的级联删除,避免数据孤岛
*/
private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER =
"CREATE TRIGGER delete_data_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.DATA +
" WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
" END";
/**
* Delete notes belong to folder which has been deleted
*/
/**
* 1.作用:维护文件夹层级结构的完整性,实现级联删除
* 2.变量名FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER
* 3.类型String
* 4.功能:
* 当文件夹被删除时,自动删除该文件夹下的所有子笔记
* 确保数据库中不会残留无主的笔记记录
* 实现树形结构中的级联删除,避免数据孤岛
*/
private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER =
"CREATE TRIGGER folder_delete_notes_on_delete " +
" AFTER DELETE ON " + TABLE.NOTE +
" BEGIN" +
" DELETE FROM " + TABLE.NOTE +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
/**
* Move notes belong to folder which has been moved to trash folder
*/
/**
* 1.作用:维护回收站功能的完整性,实现文件夹级联移动
* 2.变量名FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER
* 3.类型String
* 4.功能:
* 当文件夹被移入回收站时,自动将该文件夹下的所有子笔记也移入回收站
* 确保文件夹及其内容在回收站中保持层级关系
* 实现树形结构中的级联移动,避免子笔记遗留在原位置
*/
private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER =
"CREATE TRIGGER folder_move_notes_on_trash " +
" AFTER UPDATE ON " + TABLE.NOTE +
" WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" BEGIN" +
" UPDATE " + TABLE.NOTE +
" SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
" WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
" END";
public NotesDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
/**
* 1.作用:创建笔记主表
* 2.方法名createNoteTable
* 3.参数:
* SQLiteDatabase db数据库实例
* 4.返回类型void
* 5.功能:
* 执行 SQL 语句创建笔记表结构
* 重建相关数据库触发器
* 初始化系统文件夹数据
*/
public void createNoteTable(SQLiteDatabase db) {
db.execSQL(CREATE_NOTE_TABLE_SQL);
reCreateNoteTableTriggers(db);
createSystemFolder(db);
Log.d(TAG, "note table has been created");
}
/**
* 1.作用:重建笔记表触发器
* 2.方法名reCreateNoteTableTriggers
* 3.参数:
* SQLiteDatabase db数据库实例
* 4.返回类型void
* 5.功能:
* 删除旧版触发器
* 创建新版触发器
* 实现文件夹计数、级联删除等功能
*/
private void reCreateNoteTableTriggers(SQLiteDatabase db) {
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update");
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update");
db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS delete_data_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_insert");
db.execSQL("DROP TRIGGER IF EXISTS folder_delete_notes_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS folder_move_notes_on_trash");
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER);
db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER);
db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER);
db.execSQL(NOTE_DELETE_DATA_ON_DELETE_TRIGGER);
db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER);
db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER);
db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER);
}
/**
* 1.作用:创建系统默认文件夹
* 2.方法名createSystemFolder
* 3.参数:
* SQLiteDatabase db数据库实例
* 4.返回类型void
* 5.功能:
* 创建通话记录文件夹
* 创建根目录文件夹
* 创建临时文件夹
* 创建回收站文件夹
*/
private void createSystemFolder(SQLiteDatabase db) {
ContentValues values = new ContentValues();
/**
* call record foler for call notes
*/
values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
/**
* root folder which is default folder
*/
values.clear();
values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
/**
* temporary folder which is used for moving note
*/
values.clear();
values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
/**
* create trash folder
*/
values.clear();
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
}
/**
* 1.作用:创建系统默认文件夹
* 2.方法名createSystemFolder
* 3.参数:
* SQLiteDatabase db数据库实例
* 4.返回类型void
*/
public void createDataTable(SQLiteDatabase db) {
db.execSQL(CREATE_DATA_TABLE_SQL);
reCreateDataTableTriggers(db);
db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL);
Log.d(TAG, "data table has been created");
}
/**
* 1.作用:重建数据表相关触发器
* 2.方法名reCreateDataTableTriggers
* 3.参数:
* SQLiteDatabase db数据库实例
* 4.返回类型void
* 5.功能:
* 删除旧版触发器(插入/更新/删除)
*/
private void reCreateDataTableTriggers(SQLiteDatabase db) {
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert");
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update");
db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_delete");
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER);
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER);
db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER);
}
/**
* 1.作用获取NotesDatabaseHelper的单例实例
* 2.方法名getInstance
* 3.参数:
* Context context应用上下文
* 4.返回类型NotesDatabaseHelper
* 5.功能:
* 确保全局只有一个数据库帮助类实例
* 避免多实例导致的数据库连接冲突
* 提供线程安全的实例访问方式
*/
static synchronized NotesDatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new NotesDatabaseHelper(context);
}
return mInstance;
}
@Override
public void onCreate(SQLiteDatabase db) {
createNoteTable(db);
createDataTable(db);
}
/**
* 1.作用:执行数据库版本升级
* 2.方法名onUpgrade
* 3.参数:
* SQLiteDatabase db数据库实例
* int oldVersion当前数据库版本
* int newVersion目标数据库版本
* 4.返回类型void
* 5.功能:
* 处理跨版本升级路径
* 执行特定版本的升级脚本
* 在必要时重建触发器
* 验证升级是否成功完成
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
boolean reCreateTriggers = false;
boolean skipV2 = false;
if (oldVersion == 1) {
upgradeToV2(db);
skipV2 = true; // this upgrade including the upgrade from v2 to v3
oldVersion++;
}
if (oldVersion == 2 && !skipV2) {
upgradeToV3(db);
reCreateTriggers = true;
oldVersion++;
}
if (oldVersion == 3) {
upgradeToV4(db);
oldVersion++;
}
if (reCreateTriggers) {
reCreateNoteTableTriggers(db);
reCreateDataTableTriggers(db);
}
if (oldVersion != newVersion) {
throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ "fails");
}
}
/**
* 1.作用将数据库升级到版本2
* 2.方法名upgradeToV2
* 3.参数:
* SQLiteDatabase db数据库实例
* 4.返回类型void
* 5.功能:
* 删除旧版笔记表和数据表
* 重新创建新版笔记表和数据表
* 实现版本1到版本2的结构转换
*/
private void upgradeToV2(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE);
db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA);
createNoteTable(db);
createDataTable(db);
}
/**
* 1.作用将数据库升级到版本3
* 2.方法名upgradeToV3
* 3.参数:
* SQLiteDatabase db数据库实例
* 4.返回类型void
* 5.功能:
* 删除不再使用的触发器
* 添加Gtask ID字段用于Google任务同步
* 创建回收站系统文件夹
* 为版本3新增功能做准备
*
*/
private void upgradeToV3(SQLiteDatabase db) {
// drop unused triggers
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert");
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_delete");
db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_update");
// add a column for gtask id
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID
+ " TEXT NOT NULL DEFAULT ''");
// add a trash system folder
ContentValues values = new ContentValues();
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
}
private void upgradeToV4(SQLiteDatabase db) {
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0");
}
}