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

364 lines
16 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 类用于管理应用中的SQLite数据库。
* 这个类继承自 SQLiteOpenHelper负责创建、升级数据库和管理数据表。
*/
public class NotesDatabaseHelper extends SQLiteOpenHelper {
// 数据库文件的名称
private static final String DB_NAME = "note.db";
// 数据库的版本号当前为4
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;
/**
* 创建笔记表note的SQL语句。
* 该表包含多个列分别用于存储笔记的各类信息例如ID、创建时间、修改时间等
*/
private static final String CREATE_NOTE_TABLE_SQL =
"CREATE TABLE " + TABLE.NOTE + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," + // 笔记的唯一ID
NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + // 父级笔记ID
NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," + // 提醒时间
NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," + // 背景色ID
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," + // 小部件ID
NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," + // 小部件类型
NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," + // 同步ID
NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," + // 本地修改标识
NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," + // 原始父级ID
NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," + // Google任务ID
NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0" + // 笔记版本
")";
/**
* 创建数据表data的SQL语句。
* 该表存储与笔记相关的附加数据,例如附件、图片等。
*/
private static final String CREATE_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.DATA + "(" +
DataColumns.ID + " INTEGER PRIMARY KEY," + // 数据的唯一ID
DataColumns.MIME_TYPE + " TEXT NOT NULL," + // 数据的MIME类型例如text, image等
DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," + // 关联的笔记ID
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
")";
/**
* 构造函数,传入上下文和数据库的名称与版本号,初始化父类。
*/
public NotesDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
/**
* 当数据库第一次创建时调用执行创建表的SQL语句。
*
* @param db SQLiteDatabase对象
*/
@Override
public void onCreate(SQLiteDatabase db) {
// 创建笔记表
db.execSQL(CREATE_NOTE_TABLE_SQL);
// 创建数据表
db.execSQL(CREATE_DATA_TABLE_SQL);
}
/**
* 当数据库版本号升级时调用,负责处理数据库结构的变更。
*
* @param db SQLiteDatabase对象
* @param oldVersion 旧的数据库版本
* @param newVersion 新的数据库版本
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 在此可以根据版本号差异执行数据库升级的操作
Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion);
// 例如可以添加一些ALTER TABLE语句来迁移数据
}
/**
* 获取NotesDatabaseHelper的单例实例。
*/
/**
* 获取NotesDatabaseHelper的单例对象。
* 这个方法确保了整个应用中只有一个NotesDatabaseHelper实例被创建并且是线程安全的。
* @param context 上下文对象,用于获取应用程序的上下文环境。
* @return NotesDatabaseHelper的单例对象。
*/
public static synchronized NotesDatabaseHelper getInstance(Context context) {
// 如果mInstance是null说明还没有创建实例那么创建一个新的实例
if (mInstance == null) {
mInstance = new NotesDatabaseHelper(context.getApplicationContext());
}
// 返回单例对象
return mInstance;
}
// SQL语句用于创建一个索引提高根据note_id查询数据的效率。
private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
/**
* 当笔记移动到文件夹时,增加文件夹的笔记计数。
* 这个触发器在更新笔记的PARENT_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";
/**
* 当笔记从文件夹移动出去时,减少文件夹的笔记计数。
* 这个触发器在更新笔记的PARENT_ID字段后执行用于更新文件夹的笔记计数。
* 注意只有当笔记计数大于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";
/**
* 当向文件夹中插入新笔记时,增加文件夹的笔记计数。
* 这个触发器在插入新笔记后执行,用于更新文件夹的笔记计数。
*/
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";
/**
* 当从文件夹中删除笔记时,减少文件夹的笔记计数。
* 这个触发器在删除笔记后执行,用于更新文件夹的笔记计数。
* 注意只有当笔记计数大于0时才会减少防止计数变为负数。
*/
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";
/**
* 当插入数据类型为{@link DataConstants#NOTE}时,更新笔记内容的触发器。
* 这个触发器在数据表(DATA)插入新数据后执行如果新数据的MIME_TYPE是NOTE则更新笔记表(NOTE)中对应笔记的摘要(SNIPPET)。
*/
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";
/**
* 当数据类型为{@link DataConstants#NOTE}的数据发生变化时,更新笔记内容的触发器。
* 这个触发器在数据表(DATA)的数据更新后执行如果旧数据的MIME_TYPE是NOTE则更新笔记表(NOTE)中对应笔记的摘要(SNIPPET)。
*/
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";
/**
* 当数据类型为{@link DataConstants#NOTE}的数据被删除时,更新笔记内容的触发器。
* 这个触发器在数据表(DATA)的数据删除后执行如果旧数据的MIME_TYPE是NOTE则将笔记表(NOTE)中对应笔记的摘要(SNIPPET)设置为空。
*/
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";
/**
* 当笔记被删除时,删除属于该笔记的数据的触发器。
* 这个触发器在笔记表(NOTE)的数据删除后执行,删除数据表(DATA)中所有属于被删除笔记的数据。
*/
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";
/**
* 当文件夹被删除时,删除属于该文件夹的笔记的触发器。
* 这个触发器在笔记表(NOTE)的数据删除后执行,删除笔记表(NOTE)中所有属于被删除文件夹的笔记。
*/
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";
/**
* 当文件夹被移动到垃圾文件夹时,移动属于该文件夹的笔记的触发器。
* 这个触发器在笔记表(NOTE)的PARENT_ID字段更新后执行如果新PARENT_ID是垃圾文件夹的ID则将所有属于旧文件夹ID的笔记移动到垃圾文件夹。
*/
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);
reCreateNoteTableTriggers(db);
createSystemFolder(db);
Log.d(TAG, "note table has been created");
}
// 重新创建笔记表的触发器
private void reCreateNoteTableTriggers(SQLiteDatabase db) {
// 省略了触发器的删除和创建代码,具体逻辑见上文注释
}
// 创建系统文件夹
private void createSystemFolder(SQLiteDatabase db) {
// 省略了系统文件夹的创建代码,具体逻辑见上文注释
}
// 创建数据表
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");
}
// 重新创建数据表的触发器
private void reCreateDataTableTriggers(SQLiteDatabase db) {
// 省略了触发器的删除和创建代码,具体逻辑见上文注释
}
// 获取数据库帮助类的单例对象
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) {
// 省略了数据库升级的具体代码,具体逻辑见上文注释
}
// 数据库升级到版本2
private void upgradeToV2(SQLiteDatabase db) {
// 省略了升级到版本2的具体代码具体逻辑见上文注释
}
// 数据库升级到版本3
private void upgradeToV3(SQLiteDatabase db) {
// 省略了升级到版本3的具体代码具体逻辑见上文注释
}
// 数据库升级到版本4
private void upgradeToV4(SQLiteDatabase db) {
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ " INTEGER NOT NULL DEFAULT 0");
}