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.
text123/NotesDatabaseHelper.java

378 lines
19 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;
// NotesDatabaseHelper类负责管理笔记应用的数据库包括创建、升级和维护数据库表结构
public class NotesDatabaseHelper extends SQLiteOpenHelper {
// 数据库名称
private static final String DB_NAME = "note.db";
// 数据库版本号
private static final int DB_VERSION = 4;
// 定义数据库表名的接口
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;
// 创建笔记表的SQL语句
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," + // 父笔记的ID默认值为0
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," + // 提醒日期默认值为0
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," + // 背景颜色ID默认值为0
NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 创建日期,默认值为当前时间戳
NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," + // 是否有附件默认值为0
NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," + // 修改日期,默认值为当前时间戳
NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," + // 文件夹中的笔记数量默认值为0
NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," + // 文件夹名称或笔记内容摘要,默认值为空字符串
NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," + // 文件类型笔记或文件夹默认值为0
NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," + // 小部件ID默认值为0
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," + // 小部件类型,默认值为-1
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," + // 同步ID默认值为0
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," + // 本地修改标志默认值为0
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + // 移动到临时文件夹前的原始父ID默认值为0
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + // gtask ID默认值为空字符串
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + // 版本号默认值为0
")";
// 创建数据表的SQL语句
private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," + // 数据的唯一标识,作为主键
DataColumns.MIME_TYPE + " TEXT NOT NULL," + // MIME类型不能为空
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," + // 所属笔记的ID默认值为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," + // 通用数据列1类型为整数
DataColumns.DATA2 + " INTEGER," + // 通用数据列2类型为整数
DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," + // 通用数据列3类型为文本默认值为空字符串
DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," + // 通用数据列4类型为文本默认值为空字符串
DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" + // 通用数据列5类型为文本默认值为空字符串
")";
// 创建数据表中note_id索引的SQL语句
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
// 当更新笔记的父ID即移动笔记到文件夹增加目标文件夹的笔记数量的触发器
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";
// 当更新笔记的父ID即从文件夹移出笔记减少原文件夹的笔记数量的触发器
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";
// 当插入新笔记到文件夹时,增加目标文件夹的笔记数量的触发器
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";
// 当从文件夹删除笔记时,减少该文件夹的笔记数量的触发器
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";
// 当插入数据且数据类型为文本笔记时,更新对应笔记内容的触发器
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";
// 当数据类型为文本笔记的数据发生变化时,更新对应笔记内容的触发器
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";
// 当删除数据且数据类型为文本笔记时,将对应笔记内容清空的触发器
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";
// 当删除笔记时,删除该笔记关联的所有数据的触发器
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";
// 当删除文件夹时,删除该文件夹下所有笔记的触发器
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";
// 当文件夹被移动到回收站时,将该文件夹下所有笔记也移动到回收站的触发器
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);
}
// 创建笔记表的方法
public void createNoteTable(SQLiteDatabase db) {
db.execSQL(CREATE_NOTE_TABLE_SQL); // 执行创建笔记表的SQL语句
reCreateNoteTableTriggers(db); // 重新创建笔记表相关的触发器
createSystemFolder(db); // 创建系统文件夹
Log.d(TAG, "note table has been created"); // 记录日志,表明笔记表已创建
}
// 重新创建笔记表触发器的方法
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);
}
// 创建系统文件夹的方法
private void createSystemFolder(SQLiteDatabase db) {
ContentValues values = new ContentValues();
// 创建通话记录文件夹
values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
// 创建根文件夹
values.clear();
values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
// 创建临时文件夹
values.clear();
values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
// 创建回收站文件夹
values.clear();
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
db.insert(TABLE.NOTE, null, values);
}
// 创建数据表的方法
public void createDataTable(SQLiteDatabase db) {
db.execSQL(CREATE_DATA_TABLE_SQL); // 执行创建数据表的SQL语句
reCreateDataTableTriggers(db); // 重新创建数据表相关的触发器
db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL); // 执行创建note_id索引的SQL语句
Log.d(TAG, "data table has been created"); // 记录日志,表明数据表已创建
}
// 重新创建数据表触发器的方法
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);
}
// 获取单例实例的方法
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); // 创建数据表
}
// 当数据库版本升级时调用的方法
// 数据库版本升级时调用的方法
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 标记是否需要重新创建触发器
boolean reCreateTriggers = false;
// 标记是否跳过版本2的升级过程因为某些升级包含了从版本2到版本3的部分
boolean skipV2 = false;
// 如果旧版本是1
if (oldVersion == 1) {
// 执行升级到版本2的操作
upgradeToV2(db);
// 标记跳过版本2的升级过程因为此次升级包含了从版本2到版本3的升级
skipV2 = true;
// 旧版本号加1
oldVersion++;
}
// 如果旧版本是2且没有跳过版本2的升级过程
if (oldVersion == 2 &&!skipV2) {
// 执行升级到版本3的操作
upgradeToV3(db);
// 标记需要重新创建触发器
reCreateTriggers = true;
// 旧版本号加1
oldVersion++;
}
// 如果旧版本是3
if (oldVersion == 3) {
// 执行升级到版本4的操作
upgradeToV4(db);
// 旧版本号加1
oldVersion++;
}
// 如果需要重新创建触发器
if (reCreateTriggers) {
// 重新创建笔记表的触发器
reCreateNoteTableTriggers(db);
// 重新创建数据表的触发器
reCreateDataTableTriggers(db);
}
// 如果旧版本号不等于新版本号,说明升级过程出现问题
if (oldVersion!= newVersion) {
// 抛出异常,提示升级失败
throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ " fails");
}
}
// 升级到版本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);
}
// 升级到版本3的具体实现方法
private void upgradeToV3(SQLiteDatabase db) {
// 删除不再使用的触发器
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");
// 向笔记表中添加一个用于存储gtask id的列
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID
+ " TEXT NOT NULL DEFAULT ''");
// 创建一个用于存储回收站信息的系统文件夹
ContentValues values = new ContentValues();
// 设置文件夹的ID为回收站文件夹的ID
values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
// 设置文件夹的类型为系统类型
values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
// 将该文件夹信息插入到笔记表中
db.insert(TABLE.NOTE, null, values);
}