,并定义类遵循WCTTableCoding协议
- **WCDB_PROPERTY**用于在头文件中声明绑定到数据库表的字段。
- **WCDB_IMPLEMENTATION**,用于在类文件中定义绑定到数据库表的类。同时,该宏内实现了WCTTableCoding。因此,开发者无须添加更多的代码来完成WCTTableCoding的接口
- **WCDB_SYNTHESIZE**,用于在类文件中定义绑定到数据库表的字段。
- **WCDB_PRIMARY**用于定义主键
- **WCDB_PRIMARY_AUTO_INCREMENT** 用于定义自增主键
- **WCDB_INDEX**用于定义索引
- **WCDB_UNIQUE**用于定义唯一约束
- **WCDB_NOT_NULL**用于定义非空约束
## CRUD
得益于ORM的定义,WCDB可以直接进行通过object进行增删改查(CRUD)操作。
- **增**
```objc
//插入
Person *man = [[Person alloc] init];
man.isAutoIncrement = YES;
man.name = @"Hello, WCDB!";
man.age = 12;
return [database insertObject:man into:TABLE_WCDB_NAME];
```
- **删**
```objc
return [database deleteObjectsFromTable:TABLE_WCDB_NAME where:Person.studentId == studentId];
```
- **改**
```objc
Person *person = [[Person alloc] init];
person.name = content;
return [database updateRowsInTable:TABLE_WCDB_NAME onProperties:Person.name withObject:person where:Person.studentId == studentId];
```
- **查**
```objc
NSArray* person = [database getObjectsOfClass:Person.class fromTable:TABLE_WCDB_NAME orderBy:Person.localID.order()];
```
## Transaction
WCDB内可通过两种方式执行Transaction(事务),一是runTransaction:接口
[![dDH3J.md.jpg](https://storage4.cuntuku.com/2018/01/22/dDH3J.md.jpg)](https://cuntuku.com/image/dDH3J)
这种方式要求数据库操作在一个BLOCK内完成,简单易用。
另一种方式则是获取WCTTransaction对象
[![dDEbr.md.jpg](https://storage1.cuntuku.com/2018/01/22/dDEbr.md.jpg)](https://cuntuku.com/image/dDEbr)
WCTTransaction对象可以在类或函数间传递,因此这种方式也更具灵活性。
## WINQ
WINQ(WCDB Integrated Query,音'wink'),即WCDB集成查询,是将自然查询的SQL集成到WCDB框架中的技术,基于C++实现。
- 免去拼接SQL字符串、防注入
- 借助IDE代码提示和编译器语法检查
- 对于一个已绑定ORM的类,可以通过className.propertyName的方式,获得数据库内字段的映射
- WINQ的接口包括但不限于:
- 一元操作符:+、-、!等
- 二元操作符:||、&&、+、-、*、/、|、&、<>、、>=等
- 范围比较:IN、BETWEEN等
- 字符串匹配:LIKE、GLOB、MATCH、REGEXP等
- 聚合函数:AVG、COUNT、MAX、MIN、SUM等
- ...
### 原理
- 初衷,适应WCDB+ORM解决SQL字符串的代码冗余和难以被编译器进行语法检查而造成的错误和时间浪费。SQL字符串太容易被注入
- SQL抽象
- 封装常用操作,覆盖80%的使用场景
- 暴露底层接口,适配剩余20%的特殊情况
- 定义常用操作
- 特殊场景所暴露的底层接口,应该以什么形式存在?
- SELECT、DISTINCT、ALL等等大写字母是keyword,属于SQL的保留字。
- result-column、``table-or-subquery、expr等等小写字母是token。token可以再进一步地展开其构成的语法规则。
- 将固定的keyword,封装为函数名,作为连接。
- 将可以展开的token,封装为类,并在类内实现其不同的组合。
- 在语法规则中,WHERE、LIMIT等都接受expr作为参数。因此,不管SQL多么复杂,StatementSelect也只接受Expr的参数。而其组合的能力,则在Expr类内实现。
## 数据库修复
- 官方的Dump恢复方案
- 遍历sqlite_master表,将未损坏的表和已损坏的前半部分读取出来将dump 出来的SQL语句逐行执行,最终可以得到一个等效的新DB
功率约为30%。
- 第一页就损坏后续无法读取
- 备份恢复方案
- COPY
- 在DB完好的时候执行.dump
- Backup API: SQLite自身提供的一套备份机制,按 Page 为单位复制到新 DB, 支持热备份。
- 最终选择Dump + 压缩,恢复成功率达到72%
- 解析B-tree恢复方案(RepairKit)
- 成功率约为78%
- 不同方案的组合
- RepairKit 尝试恢复最新数据
- 备份恢复 遇到错误填补漏缺
- Dump 最后的尝试
## For Android
- 基本功能
- 基于SQLCipher的数据库加密
- 使用连接池实现并发读写
- 内建 Repair Kit 可用于修复损坏数据
- 针对占用空间大小优化的数据库备份/恢复功能
- 日志输出重定向以及性能跟踪接口
- 内建用于全文搜索的 mmicu FTS3/4 分词器
- 接入与迁移
- WCDB for Android 可通过 Maven 或 AAR 包引用,API 接口与 Android SDK 非常相近, 所以将已有的 App 迁移到 WCDB 是相当容易的。
- [Android 接入与迁移](https://github.com/Tencent/wcdb/wiki/Android%E6%8E%A5%E5%85%A5%E4%B8%8E%E8%BF%81%E7%A7%BB)
- 数据库修复
- [Android 数据库修复](https://github.com/Tencent/wcdb/wiki/Android%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BF%AE%E5%A4%8D)
- 从源码编译
- 你可以使用预编译的依赖库(OpenSSL crypto 和 SQLCipher)来编译 WCDB for Android, 使用 Gradle 或 Android Studio 皆可。Android Studio 请导入 android 目录作为 Root Project。
- 编译 WCDB 需要安装 Android NDK r11c 或以上,并在 android/local.properties 上配置好 SDK 与 NDK 路径。Android Studio 一般会帮你配置好。
- 如果你需要自己编译 OpenSSL 等依赖项,你需要一个 Bash 环境(Windows 可以安装 Cygwin 或 MSys)、target 为本机的 C 编译器(如 GCC)、Perl 5 以及 Tcl。之后执行下面命令即可编译依赖项。
> 参考资料
> [微信移动端数据库组件WCDB系列(一)-iOS基础篇](https://mp.weixin.qq.com/s/1XxcrsR2HKam9ytNk8vmGw)
>[微信移动端数据库组件WCDB系列(二) — 数据库修复三板斧](https://mp.weixin.qq.com/s/Ln7kNOn3zx589ACmn5ESQA)
> [微信移动端数据库组件WCDB系列(三) — WINQ原理篇](https://mp.weixin.qq.com/s/FY2Y9x1_8TcXHDgTRXcTDA)
> [微信移动数据库组件WCDB(四) — Android 特性篇](https://mp.weixin.qq.com/s/NFnYEXSxAaHBqpi7WofSPQ)