Couchbase Lite機能解説：クエリAPI② リテラル、識別子、式

## はじめに

ここでは、Couchbase Lite 3.0の新機能であるクエリAPIについて解説します。

なお、Couchbase Mobileについては、[Couchbase Mobileアプリケーション開発へのロードマップ](https://qiita.com/yoshiyuki_kono/items/6a5bbad1b02196a25417)に記事をまとめている他、（これらの記事を元に構成した）以下の電子書籍を無償で頒布しています。

https://techbookfest.org/product/5074954942939136?productVariantID=5042865933647872

また、Couchbase Mobileは、Couchbase LiteとCouchbase Serverとのデータ同期機能を提供します。Couchbase Serverの存在意義、機能詳細、利用方法等については、拙著[NoSQLドキュメント指向データベースCouchbase Serverファーストステップガイド(インプレスR&D刊)](https://www.amazon.co.jp/-/en/%E6%B2%B3%E9%87%8E-%E6%B3%B0%E5%B9%B8/dp/429560030X/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=1636588872&sr=1-1)や、[NoSQL/JSONデータベースCouchbase Server理解・活用へのロードマップ](https://qiita.com/yoshiyuki_kono/items/4c9cd1115efc5807b49f)にまとめてある記事をご参考ください。

## クエリAPI解説②

### リテラル

次のようなリテラル表現を用いることができます。


#### 数値

下の例のような表現で数値を表すことができます。

```SQL
SELECT value FROM db  WHERE value = 10
SELECT value FROM db  WHERE value = 0
SELECT value FROM db WHERE value = -10
SELECT value FROM db WHERE value = 10.25
SELECT value FROM db WHERE value = 10.25e2
SELECT value FROM db WHERE value = 10.25E2
SELECT value FROM db WHERE value = 10.25E+2
SELECT value FROM db WHERE value = 10.25E-2
```

#### 文字列リテラル

クォートまたはダブルクォートを用いて、文字列を表現します。

```SQL
SELECT firstName, lastName FROM db WHERE middleName = “middle”
SELECT firstName, lastName FROM db WHERE middleName = ‘middle’
```

#### 真偽値

Oracle、MySQL、PostgreSQL同様(SQL ServerやSQLiteとは異なり)、ブーリアン型を扱うことができます。

```SQL
SELECT value FROM db  WHERE value = true
SELECT value FROM db  WHERE value = false
```

#### NULL

`NULL`は、空の値を表します。

JSON仕様には、空の値の表現として、`null`があります。


```SQL
SELECT firstName, lastName FROM db WHERE middleName IS NULL
```

#### MISSING

`MISSING`は、ドキュメントに定義されていない（欠落している)名前と値のペアを表します。


```SQL
SELECT firstName, lastName FROM db WHERE middleName IS MISSING
```

#### 配列

JSON同様の（`[` `]`を用いた）表現で、を配列を表します。


```SQL
SELECT [“a”, “b”, “c”] FROM _
SELECT [ property1, property2, property3] FROM _
```

`IN`句において、複数の値を指定する際に用いられます。

```SQL
SELECT * FROM _ WHERE name IN [“James”, “John”, “Jack”]
```

#### ディクショナリー

JSON同様の（`{` `}` `:`を用いた）表現で、ディクショナリーを表します。


```SQL
SELECT { ‘name’: ‘James’, ‘department’: 10 } FROM db
SELECT { ‘name’: ‘James’, ‘department’: dept } FROM db
SELECT { ‘name’: ‘James’, ‘phones’: [‘650-100-1000’, ‘650-100-2000’] } FROM db
```


### 識別子

データベース名、データベースエイリアス名、プロパティ名、エイリアス名、パラメータ名、関数名、およびFTSインデックス名のような識別子には、以下のような文字を利用することができます。

- アルファベット(`a`~ `z`、`A`~ `Z`)、数字(`0`~ `9`)、`_`（アンダースコア）
- アルファベットの大文字と小文字が区別されます。
- 上記以外の文字（例えば`-`）を使用するには、バッククォート(`)で囲みます。



```SQL
SELECT * FROM `travel-sample` 

SELECT * FROM travel_sample

SELECT * FROM TravelSample
```

### 式

#### プロパティ式

ドキュメント内のプロパティを参照するためにプロパティ式が使用されます。以下のような使い方があります。

- プロパティ式の前にデータソース名またはエイリアスを付けて、その起源を示す（クエリ内で一つのデータソースのみが利用されている場合は省略可能）
- ドット構文を使用して、ネストされたプロパティを参照する
- 配列内の項目を参照するには、角かっこ（`[` `]`）を使った添え字構文を使用する
- すべてのプロパティを表すために、アスタリスク（`*`）文字を使用する（SELECT句の結果リストでのみ使用可能）

以下に例を示します。

```SQL
SELECT db.contact.address.city
  FROM db
  WHERE contact.name = "daniel"

SELECT contact.address.city, contact.phones[0]
  FROM db
  WHERE contact.name = "daniel"

SELECT *
  FROM db
  WHERE contact.name = "daniel"

SELECT db.*
  FROM db
  WHERE contact.name = "daniel"
```

#### 配列式

配列内のアイテムを評価するための独自の構文を持ちます。以下のような構文構造を持ちます。順に説明します。

```SQL
arrayExpression = 
  anyEvery _ variableName 
     _ IN  _ expression 
       _ SATISFIES _ expression 
    END 

anyEvery = anyOrSome AND EVERY | anyOrSome | EVERY

anyOrSome = ANY | SOME
```

配列式は、`ANY/SOME`、または`EVERYANY`で始まり、それぞれが以下に説明するように異なる機能を持ちます。配列式は、`END`で終了します。 

- `ANY/SOME`：配列内の少なくとも1つの項目が式を満たしている場合にTRUEを返します。そうでない場合は、FALSEを返します。`ANY`と`SOME`は交換可能です。

- `EVERY`：配列内のすべての項目が式を満たしている場合はTRUEを返します。そうでない場合は。FALSEを返します。配列が空の場合は、TRUEを返します。

- `ANY/SOME AND EVERY`：配列が値を持ち場合は、`EVERY`と同様ですが、配列が空の場合はFALSEを返します。

- 配列内の各項目を表す、任意の名前の変数を用いることができます（下記例の`v`）
- `IN`キーワードに続いて評価する配列を指定するために
- `SATISFIES`キーワードに続いて、配列内の各項目を評価するための条件を指定します。
- `END`は配列式を終了します。

ALLおよびEvery式の例

```SQL
SELECT name
  FROM db
  WHERE ANY v
          IN contacts
          SATISFIES v.city = ’San Mateo’
        END
```


#### パラメータ式

パラメータ化クエリを利用することができます。一般にパラメータ化クエリは、クエリにランタイムパラメータを用いることによって、SQLインジェクション対策やパフォーマンス改善に役立ちます。

クエリ内にパラメータのプレースホルダーとして、クエリの実行時に指定されるパラメータマップから割り当てられる値を指定します。

クエリ文字列にパラメータ式が用いられているのみ、クエリオブジェクトにパラメータと値のマッピングが渡されない場合には、クエリの実行時にエラーがスローされます。


クエリ文字列内で置換可能なパラメータを指定するには、名前の前に、`$`を付けます。
例えば、以下のようなクエリになります。


```SQL
SELECT name
  FROM db
  WHERE department = $department
```

以下に、プログラミング言語毎のパラメーターの使用例を示します。

```swift:swift
let q = Query(
          query: “SELECT name
                    WHERE department = $department”,
          database: db
        );

q.parameters =
      Parameters().setValue(
        “E001”, forName: "department"); 

let result = try q.execute();
```

クエリは次のように解決されます `SELECT name WHERE department = "E001"`


```java:Java

Database thisDb = argDB;

Query thisQuery =
    thisDb.createQuery(
        "SELECT META().id AS thisId FROM _ WHERE type = $type"); 

thisQuery.parameters =
    Parameters.setString("type", "hotel"); 

return thisQuery.execute().allResults();
```

```KOTLIN:Kotlin
val thisQuery = db.createQuery(
      "SELECT META().id AS id FROM _ WHERE type = \$type") 

thisQuery.parameters = Parameters().setString("type", "hotel") 

return thisQuery.execute().allResults()
```

#### 括弧式

式をグループ化して読みやすくしたり、演算子の優先順位を設定するために、括弧を使用できます。


```SQL
SELECT (value1 + value2) * value3 
  FROM db
```

```SQL
SELECT *
  FROM db
  WHERE ((value1 + value2) * value3) + value4 = 10
```

```SQL
SELECT *
  FROM db
  WHERE (value1 = value2)
     OR (value3 = value4) 
```