# 注解查询

这些示例使用现有只读关系。字段含义见[表参考](schema.zh.md)。递归或大规模 join 前先用谓词收窄范围。

## 查找含嵌套注解值的 owner

展开值前先按注解类型过滤。下面查找路由表注解中嵌套值为 `/aio` 的 owner。

```sql
WITH owners AS (
    SELECT DISTINCT file_id, annotation_off, owner
    FROM annotation_elements_resolved
    WHERE annotation = 'Lcom/example/RouteTable;'
)
SELECT DISTINCT a.file_id, a.owner
FROM owners a
JOIN annotation_elements e
  ON e.file_id = a.file_id AND e.annotation_off = a.annotation_off
JOIN dex_files d ON d.file_id = e.file_id
JOIN strings s
  ON s.string_pool_id = d.string_pool_id AND s.string_idx = e.value_index
WHERE e.depth > 0 AND e.value_kind = 'string' AND s.value = '/aio';
```

## 解析元素值

`value_kind` 指定值的类型域。整数和布尔值读取 `value_i64`，浮点读取 `value_f64`，字符串、类型和成员通过 `value_index` 关联。本例解析 file 0 中第一个非空注解；修改 `selected` 可指定目标注解。将筛选放入查询中，可以限制 join 的范围。

```sql
WITH selected AS (
    SELECT file_id, annotation_off
    FROM annotations
    WHERE file_id = 0 AND element_count > 0
    ORDER BY annotation_off LIMIT 1
)
SELECT e.file_id, e.annotation_off, e.value_off,
       ns.value AS name, e.value_kind, e.value_i64, e.value_f64,
       vs.value AS string_value, vt.descriptor AS type_value,
       vf.descriptor AS field_value, vm.descriptor AS method_value
FROM annotation_elements e
JOIN selected a ON a.file_id = e.file_id AND a.annotation_off = e.annotation_off
JOIN dex_files d ON d.file_id = e.file_id
LEFT JOIN strings ns
  ON ns.string_pool_id = d.string_pool_id AND ns.string_idx = e.name_idx
LEFT JOIN strings vs
  ON e.value_kind = 'string'
 AND vs.string_pool_id = d.string_pool_id AND vs.string_idx = e.value_index
LEFT JOIN types vt
  ON e.value_kind IN ('type', 'annotation')
 AND vt.file_id = e.file_id AND vt.type_idx = e.value_index
LEFT JOIN fields vf
  ON e.value_kind IN ('field', 'enum')
 AND vf.file_id = e.file_id AND vf.field_idx = e.value_index
LEFT JOIN methods vm
  ON e.value_kind = 'method'
 AND vm.file_id = e.file_id AND vm.method_idx = e.value_index;
```

## 遍历注解节点

深度和字节范围包含关系可以识别直接子节点。下面的遍历生成点分路径及所属注解偏移。`selected` CTE 选取 file 0 中第一个非空注解；起始项和递归 join 都只使用它的节点。可替换为所需的 `(file_id, annotation_off)`。

```sql
WITH RECURSIVE selected AS (
    SELECT file_id, annotation_off
    FROM annotations
    WHERE file_id = 0 AND element_count > 0
    ORDER BY annotation_off LIMIT 1
), elements AS (
    SELECT e.* FROM annotation_elements e
    JOIN selected a ON a.file_id = e.file_id AND a.annotation_off = e.annotation_off
), tree(file_id, annotation_off, value_off, value_end_off, depth, path, group_id) AS (
  SELECT file_id, annotation_off, value_off, value_end_off, depth,
         CAST(ordinal AS TEXT), annotation_off
  FROM elements WHERE depth = 0
  UNION ALL
  SELECT c.file_id, c.annotation_off, c.value_off, c.value_end_off, c.depth,
         t.path || '.' || CAST(c.ordinal AS TEXT),
         CASE p.value_kind WHEN 'annotation' THEN p.value_off ELSE t.group_id END
  FROM tree t
  JOIN elements p
    ON p.file_id = t.file_id AND p.annotation_off = t.annotation_off
   AND p.value_off = t.value_off
  JOIN elements c
    ON c.file_id = t.file_id AND c.annotation_off = t.annotation_off
   AND c.depth = t.depth + 1
   AND c.value_off > t.value_off AND c.value_end_off <= t.value_end_off
)
SELECT t.file_id, t.annotation_off, t.path, t.group_id, n.value_index AS nested_type_idx
FROM tree t
LEFT JOIN elements n
  ON n.file_id = t.file_id AND n.annotation_off = t.annotation_off
 AND n.value_off = t.group_id AND t.group_id <> t.annotation_off;
```

---

Copyright (c) 2026 LSPosed Developers。本文档采用 [MIT 许可证](../license.md)。
