Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API-274] SQL for Map ([API-617], [API-616], [API-431], [API-619], [API-620], [API-432], [API-659], [API-660], [API-661]) #475

Merged
merged 132 commits into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from 117 commits
Commits
Show all changes
132 commits
Select commit Hold shift + click to select a range
5544daf
[WIP]
alexb5dh Jun 24, 2021
121b2ea
Add options validation
alexb5dh Jun 29, 2021
b9d4a2b
Fix `HazelcastClient` construction
alexb5dh Jun 29, 2021
9e3cc9e
`SqlService` implementation update
alexb5dh Jun 30, 2021
e61d1c9
Update FIXME comments
alexb5dh Jul 1, 2021
63a56c0
Implement `SqlResult` enumeration
alexb5dh Jul 1, 2021
355a7dd
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Jul 5, 2021
f331851
Add missing words to ReSharper dictionary
alexb5dh Jul 5, 2021
a87a58c
Implement missing codecs
alexb5dh Jul 5, 2021
e828f89
Remove SQL "reserved" codecs
alexb5dh Jul 6, 2021
6d1c079
Add missing docs, comments & update access modifiers
alexb5dh Jul 6, 2021
ad86650
Check column type for `CreateSqlColumnMetadata`
alexb5dh Jul 7, 2021
9112fda
Fix SQL tests init and cleanup
alexb5dh Jul 7, 2021
41dfe18
Get rid of `if #FALSE` in generated codecs
alexb5dh Jul 8, 2021
7b0ce54
Change `CPSubsystem` and `SqlService` initialization in client
alexb5dh Jul 8, 2021
502c6c4
Fixes
alexb5dh Jul 8, 2021
70ac532
Save error details for `HazelcastSqlException`
alexb5dh Jul 8, 2021
0414394
Formatting settings
alexb5dh Jul 8, 2021
3c07be9
Separate query and command methods, update `SqlResult`
alexb5dh Jul 9, 2021
79941ae
Interface for `SqlQueryResult`
alexb5dh Jul 10, 2021
24f2174
Tests cleanup
alexb5dh Jul 10, 2021
1140e74
Refactor `SqlQueryResult` disposing
alexb5dh Jul 10, 2021
13a9d6a
Update `SqlQueryResult`
alexb5dh Jul 10, 2021
665396f
Tests update
alexb5dh Jul 10, 2021
7ed18bf
Code cleanup
alexb5dh Jul 10, 2021
1a25f20
Summary for `ISqlQueryResult`
alexb5dh Jul 10, 2021
7baa028
Jet engine query test
alexb5dh Jul 10, 2021
bc84609
Naming update
alexb5dh Jul 15, 2021
c30c88a
Make `SqlResultType` internal
alexb5dh Jul 15, 2021
e309d15
Formatting
alexb5dh Jul 15, 2021
2157a6a
`OffsetDateTime` format fixes
alexb5dh Jul 15, 2021
3a6c745
Update date/time decoding tests
alexb5dh Jul 15, 2021
461f863
Cancellation token for `ExecuteCommandAsync`
alexb5dh Jul 15, 2021
d253fda
SQL service summary and simplifying extension method
alexb5dh Jul 21, 2021
062ba57
ReSharper formatting config update
alexb5dh Jul 21, 2021
76c6379
Deserialization tests and small tests fix
alexb5dh Jul 21, 2021
bbb3958
Basic querying examples
alexb5dh Jul 21, 2021
cfb9b3c
`BigDecimal` codec fix and optimization
alexb5dh Jul 21, 2021
58d09f2
FIXME comments for some type mapping issues
alexb5dh Jul 21, 2021
8d0740b
Implement custom date/time types and update tests
alexb5dh Jul 22, 2021
7c9583f
Fix `ByteExtensionsTests`
alexb5dh Jul 23, 2021
aecf29d
Code and typo cleanup
alexb5dh Jul 23, 2021
caf3919
`Write*` methods for SQL date/time types
alexb5dh Jul 25, 2021
86abab9
Merge branch 'master' of https://github.com/hazelcast/hazelcast-cshar…
alexb5dh Jul 26, 2021
ce5c578
Update `HLocalDate` format to use int for Year
alexb5dh Jul 26, 2021
14214fa
Summary update
alexb5dh Jul 27, 2021
9f959b7
Serializers for new date/time types
alexb5dh Jul 27, 2021
310f939
Update tests with parameters serialization
alexb5dh Jul 27, 2021
e71f708
Formatting settings update
alexb5dh Jul 27, 2021
f5d137f
Abstract `SqlResult` class
alexb5dh Jul 31, 2021
61c2d2d
`HBigDecimal` implementation
alexb5dh Aug 2, 2021
6bba07c
SQL data types conversion/parsing tests and fixes
alexb5dh Aug 2, 2021
ddf58f6
More data types tests and fixes
alexb5dh Aug 3, 2021
a084454
`HBigDecimal` default serializer and test update
alexb5dh Aug 3, 2021
c4241fc
Separate class for SQL command execution result
alexb5dh Aug 3, 2021
5b89af9
Make `SqlService` methods non-async
alexb5dh Aug 3, 2021
89b0538
Interface fix
alexb5dh Aug 4, 2021
679854e
Add using statements to basic queries example
alexb5dh Aug 4, 2021
b2716f2
Organize tests and fix Jet test
alexb5dh Aug 4, 2021
b95fefa
Fixes
alexb5dh Aug 5, 2021
65f1db5
Tests cleanup
alexb5dh Aug 5, 2021
876066b
More tests
alexb5dh Aug 5, 2021
ec97084
Update, Delete Jet tests
alexb5dh Aug 5, 2021
9917dc8
Cancellation example
alexb5dh Aug 5, 2021
c676c92
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Aug 5, 2021
2c51b31
Summary fix
alexb5dh Aug 5, 2021
b561f94
Add missing `using`s in tests
alexb5dh Aug 6, 2021
16b7d2f
Test `IPortable` fields query
alexb5dh Aug 6, 2021
58ceff8
Support for lowercase T in `HLocalDateTime` string
alexb5dh Aug 6, 2021
5b418bd
[WIP] Documentation
alexb5dh Aug 6, 2021
68cb52b
Documentation fixes
alexb5dh Aug 9, 2021
f21e51c
Add ToC
alexb5dh Aug 9, 2021
c1bd7eb
Format tweaks
alexb5dh Aug 9, 2021
22e2e34
More details on querying
alexb5dh Aug 9, 2021
9bf8ee7
Code cleanup
alexb5dh Aug 9, 2021
709d3a2
Summary update
alexb5dh Aug 9, 2021
5f8f937
Switch to `GetConnectionForSql`
alexb5dh Aug 11, 2021
afabd5e
Fix missed lock for `GetConnectionForSql`
alexb5dh Aug 12, 2021
7a29c41
Add new types for SQL
alexb5dh Aug 16, 2021
51b8a09
Fix and more cases for `ByteExtensionsTests`
alexb5dh Aug 16, 2021
9a1d0ec
Fix and more cases for `ByteExtensionsTests`
alexb5dh Aug 16, 2021
540d5e9
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Aug 19, 2021
40f9232
Merge remote-tracking branch 'hazelcast/master' into feature/sql-types
alexb5dh Aug 19, 2021
04231e7
Switch to hazelcast-all package
alexb5dh Aug 19, 2021
e654281
Update RC version to 0.8
alexb5dh Aug 19, 2021
80a9cd3
Merge branch 'feature/hazelcast-all-package' into feature/sql-support
alexb5dh Aug 19, 2021
f1a0948
Update server to 5.0-SNAPSHOT in hz script
alexb5dh Aug 19, 2021
762534c
Move jet-enabled config to resource files
alexb5dh Aug 19, 2021
9149f1f
Merge remote-tracking branch 'hazelcast/master' into feature/sql-types
alexb5dh Aug 19, 2021
c7133cc
`MemberVersion.ToString` fix
alexb5dh Aug 19, 2021
17d9703
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Aug 19, 2021
f389a4b
Merge remote-tracking branch 'hazelcast/master' into feature/sql-types
alexb5dh Aug 19, 2021
c92c6aa
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Aug 19, 2021
ad7450c
Implement `GetConnectionForSql`
alexb5dh Aug 20, 2021
b9ea5a0
Tests for `GetConnectionForSql` in "dummy" mode
alexb5dh Aug 20, 2021
82590cb
Tests for `FindMemberOfLargerSameVersionGroup`
alexb5dh Aug 20, 2021
79aa067
Move new types to `Models` namespaces instead of `Sql`
alexb5dh Aug 20, 2021
2697878
Merge remote-tracking branch 'hazelcast/master' into feature/sql-types
alexb5dh Aug 22, 2021
5f7b752
Merge branch 'feature/sql-connection' into feature/sql-support
alexb5dh Aug 22, 2021
5604e08
Merge branch 'feature/sql-types' into feature/sql-support
alexb5dh Aug 22, 2021
31b2baf
Add missing copyright
alexb5dh Aug 22, 2021
3b33604
Merge fixes
alexb5dh Aug 22, 2021
ab4241d
PR fixes
alexb5dh Aug 23, 2021
427f3fe
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Aug 23, 2021
8590817
Move jet_enabled config to Tests project
alexb5dh Aug 24, 2021
80d89af
Update client-protocol version
alexb5dh Aug 24, 2021
30764d1
Remove synchronous `EnumerateOnce`
alexb5dh Aug 24, 2021
ba8e4bc
`SqlQueryResult` changes
alexb5dh Aug 24, 2021
1776f6c
Changes to SQL-connection methods
alexb5dh Aug 24, 2021
fa6dfec
Warning fix
alexb5dh Aug 25, 2021
bb7da81
Tests tweaks
alexb5dh Aug 25, 2021
e711099
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Aug 25, 2021
4add8a9
Tests cleanup
alexb5dh Aug 25, 2021
cc2cbb0
Remove `EnumerateOnceAsync`, implement `IAsyncEnumerable` directly
alexb5dh Aug 25, 2021
eecaad0
Update query cancellation example
alexb5dh Aug 25, 2021
81d6e1c
Remove public `IAsyncEnumerator` implementation
alexb5dh Aug 25, 2021
a3bde31
Cleanup
alexb5dh Aug 25, 2021
1b8e49c
Add missing `CfAwait` calls
alexb5dh Aug 25, 2021
90beda3
Add example for LINQ over `ISqlQueryResult`
alexb5dh Aug 25, 2021
7401bb2
Test for cancellation via `ToListAsync` token
alexb5dh Aug 25, 2021
9f3e40d
Update documentation
alexb5dh Aug 25, 2021
4729535
Fix failing tests ?!
zpqrtbnk Aug 27, 2021
8f6e673
Add tests for async
zpqrtbnk Aug 30, 2021
59991cb
Experiment with the SQL API
zpqrtbnk Aug 30, 2021
c69bda9
Catch TaskCancelledException not OperationCancelledException
zpqrtbnk Aug 31, 2021
3c52680
Fix hz script for 5.0
zpqrtbnk Aug 31, 2021
2ade2d3
Code cleanup
alexb5dh Sep 1, 2021
0fc0091
Docs update
alexb5dh Sep 1, 2021
c34a938
Extension methods with cancellation
alexb5dh Sep 1, 2021
cfe08e6
Merge remote-tracking branch 'hazelcast/master' into feature/sql-support
alexb5dh Sep 2, 2021
2c1ead1
Merge branch 'master' into feature/sql-support
alexb5dh Sep 2, 2021
c33e82b
Tests fix
alexb5dh Sep 2, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Hazelcast.Net.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_EXTENDS_COLON/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CN/@EntryIndexedValue">CN</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CP/@EntryIndexedValue">CP</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=438E8320080FDC46904A18FD18FF4DCD/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=438E8320080FDC46904A18FD18FF4DCD/Color/@EntryValue">207, 157, 50</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/Todo/TodoPatterns/=438E8320080FDC46904A18FD18FF4DCD/MatchComments/@EntryValue">True</s:Boolean>
Expand All @@ -13,6 +22,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=endianness/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=expirations/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=multicast/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=nano/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=partitioner/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=retryable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hzconsole/@EntryIndexedValue">True</s:Boolean>
Expand Down
358 changes: 358 additions & 0 deletions doc/dev/doc/sql.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,358 @@
# SQL <!-- omit in toc -->

- [Example: How to Query an IHMap using SQL](#example-how-to-query-an-ihmap-using-sql)
- [Querying IHMap](#querying-ihmap)
- [Map Names](#map-names)
- [Field Names](#field-names)
- [Key and Value Objects](#key-and-value-objects)
- [Key and Value Fields](#key-and-value-fields)
- ["SELECT *" Queries](#select--queries)
- [Special characters in names](#special-characters-in-names)
- [Enumerating query result](#enumerating-query-result)
- [Disposing or cancelling the query](#disposing-or-cancelling-the-query)
- [Data Types](#data-types)
- [Decimal String Format](#decimal-string-format)
- [Date String Format](#date-string-format)
- [Time String Format](#time-string-format)
- [Timestamp String Format](#timestamp-string-format)
- [Timestamp with Timezone String Format](#timestamp-with-timezone-string-format)
- [Casting](#casting)
- [How to Cast](#how-to-cast)
- [Casting Between Types](#casting-between-types)
- [An Example of Implicit Cast](#an-example-of-implicit-cast)
- [An Example of Explicit Cast](#an-example-of-explicit-cast)
- [Important Notes About Comparison and Casting](#important-notes-about-comparison-and-casting)
- [SELECT](#select)
- [Synopsis](#synopsis)
- [Description](#description)
- [Sorting](#sorting)
- [Unsupported Features](#unsupported-features)
- [Expressions](#expressions)
- [Lite Members](#lite-members)
- [More Information](#more-information)

The SQL service provided by Hazelcast .NET client allows you to query data stored in `IHMap` declaratively.

> **WARNING: The SQL feature is currently in beta. The compatibility between versions is not guaranteed. API might change between versions without notice. While in beta, SQL feature is tested against the same version of the IMDG, e.g 5.0-BETA

## Example: How to Query an IHMap using SQL

This SQL query returns map entries whose values are more than 1:

```csharp
await using var map = await client.GetMapAsync<int, string>("MyMap");
await map.SetAllAsync(Enumerable.Range(1, 5).ToDictionary(v => v, v => $"{v}"));

await using var result = client.Sql.ExecuteQuery($"SELECT __key, this FROM {map.Name} WHERE this > 2");

await foreach (var row in result.EnumerateOnceAsync())
Console.WriteLine($"{row.GetKey<int>()}: {row.GetValue<string>()}");
```

## Querying IHMap

The following subsections describe how you can access Hazelcast map objects and perform queries on them.

### Map Names

The SQL service exposes `IHMap` objects as tables in the predefined `partitioned` schema using exact names.
This schema is in the SQL service search path so that you can access the `IHMap` objects with or without the schema name.s

Schema and table names are case-sensitive; you can access the `employee` map, for example, as employee or `partitioned.employee`,
but not as `Employee`:
```sql
SELECT * FROM employee
SELECT * FROM partitioned.employee
```

### Field Names

The SQL service resolves fields accessible from the SQL automatically. The service reads the first local entry pair of the `IHMap` to construct the list of fields. If the `IHMap` does not have local entries on the member where the query is started, then the list of fields cannot be resolved, and an exception is thrown.

Field names are case-sensitive.

#### Key and Value Objects

An `IHMap` entry consists of a key and a value. These are accessible through the `__key` and `this` aliases. The following
query returns the keys and values of all entries in a map:

```sql
SELECT __key, this FROM employee
```

#### Key and Value Fields

You may also access the nested fields of a key or value. The list of exposed fields depends on the serialization format, as described below:

* For [IdentifiedDataSerializable](serialization.md#identifieddataserializable-serialization) objects, you can use public field name or getter names.
See [IMDG docs](https://docs.hazelcast.com/imdg/4.2/sql/querying-imap.html#key-and-value-fields) for more information.
* For [Portable](serialization.md#portable-serialization) objects, the fields written with `IPortableWriter` methods are exposed using their exact names.

> **NOTE: You cannot query JSON fields in SQL. If you want to query JSON, see [Querying with JSON Strings](distributedQuery.md#querying-with-json-strings).**

For example, consider this portable class:

```csharp
public class Employee : IPortable
{
int IPortable.ClassId => 123;
int IPortable.FactoryId => 345;

public int Age { get; set; }
public string Name { get; set; }

public void ReadPortable(IPortableReader reader)
{
Age = reader.ReadInt(nameof(Age));
Name = reader.ReadString(nameof(Name));
}

public void WritePortable(IPortableWriter writer)
{
writer.WriteInt(nameof(Age), Age);
writer.WriteString(nameof(Name), Name);
}
}
```

The SQL service can access the following fields:

| Name | SQL Type |
|--------|-----------|
| name | VARCHAR |
| age | INTEGER |

Together with the key and value objects, you may query the following fields from `IHMap<int, Employee>`:

```sql
SELECT __key, this, Name, Age FROM employee
```

If both the key and value have fields with the same name, then the field of the value is exposed.

#### "SELECT *" Queries

You may use the `SELECT * FROM <table>` syntax to get all the table fields.

The `__key` and `this` fields are returned by the `SELECT *` queries if they do not have nested fields. For `IHMap<number, Employee>`, the following query does not return the `this` field, because the value has nested fields `Name` and `Age`:

```sql
-- Returns __key, Name, Age
SELECT * FROM employee
```

### Special characters in names

If map or field name contains non-alphanumeric characters or starts with a number, you will need to enclose it in double quotes:

```sql
SELECT * FROM "my-map"
SELECT * FROM "2map"
```

### Enumerating query result
`ISqlService.ExecuteQuery` returns `Hazelcast.Sql.ISqlQueryResult` which provides methods to enumerate or cancel the running query:

```csharp
await using var result = client.Sql.ExecuteQuery("SELECT Name, Age FROM employee");
```

It represents one-off stream of rows, implements `IAsyncEnumerator` and can be iterated via `MoveNextAsync()` implementation. Invoking it will either advance row on the last fetched page, or make an asynchronous query for the next one. Below is an example of enumeration via `MoveNextAsync()`:

```csharp
while (await result.MoveNextAsync())
Console.WriteLine(result.Current.GetColumn<string>("Name"));
```

For async enumeration via `IAsyncEnumerable<>` you can call `EnumerateOnceAsync()`:

```csharp
await foreach (var row in result.EnumerateOnceAsync())
Console.WriteLine(row.GetColumn<string>("Name"));
```

Using LINQ over `IAsyncEnumerable` requires installing separate [System.Linq.Async](https://www.nuget.org/packages/System.Linq.Async) package.

Note, that invoking any of these methods after enumeration has started will throw `InvalidOperationException`. Reusing obtained `IAsyncEnumerable<>` instance does not restart enumeration and can lead to unpredictable results.

### Disposing or cancelling the query

Both `ISqlQueryResult` and `ISqlCommandResult` implements `IAsyncDisposable`. Their `DisposeAsync` implementation will make sure to cancel the query and free used server resources.

Because of this, it is recommended to wrap operations with query or command into `await using` statement. This will ensure to send Cancel request in case if query is cancelled client-side or exception is thrown before it is completed or all rows are exhausted:

```csharp
await using (var result = client.Sql.ExecuteQuery("SELECT * FROM MyMap"))
{
//...
}
```

```csharp
await using var result = Client.Sql.ExecuteCommand("INSERT INTO MyMap VALUES (1, 2)");
//...
```

To cancel the query by client-side timeout, user action or other reasons you can invoke `DisposeAsync` any time, even during execution. See `SqlCancellationExample` in *Hazelcast.Net.Examples* project for examples. `ISqlQueryResult.MoveNextAsync()` or `ISqlQueryCommand.Execution` may throw `HazelcastSqlException` if query is cancelled while they are running.

> **NOTE: Currently `HazelcastSqlException` provides no simple way to identify if it was caused by client-side cancellation or other error apart from parsing exception message. This may be improved in future versions.**

## Data Types

The SQL service supports a set of SQL data types represented by `Hazelcast.Sql.SqlColumnType` enum. The table below shows SQL datatype, and corresponding .NET types:

| Column Type | .NET |
|------------------------------|---------------------------------|
| **VARCHAR** | `string` |
| **BOOLEAN** | `bool` |
| **TINYINT** | `byte` |
| **SMALLINT** | `short` |
| **INTEGER** | `int` |
| **BIGINT** | `long` |
| **DECIMAL** | `Hazelcast.Sql.HBigDecimal` |
| **REAL** | `float` |
| **DOUBLE** | `double` |
| **DATE** | `Hazelcast.Sql.HLocalDate` |
| **TIME** | `Hazelcast.Sql.HLocalTime` |
| **TIMESTAMP** | `Hazelcast.Sql.HLocalDateTime` |
| **TIMESTAMP_WITH_TIME_ZONE** | `Hazelcast.Sql.HOffsetDateTime` |
| **OBJECT** | Any class |
| **NULL** | `null` |

All `Hazelcast.Sql.*` types has conversion to and from their closest built-in counterparts. Table below lists possible conversions:

| Hazelcast type | To .NET Type | From .NET Type |
----------------------------------|-------------------|------------------------|
| `Hazelcast.Sql.HBigDecimal` | `decimal`** | `decimal` |
| `Hazelcast.Sql.HLocalDate` | `DateTime`* | `DateTime` |
| `Hazelcast.Sql.HLocalTime` | `TimeSpan` | `TimeSpan`, `DateTime` |
| `Hazelcast.Sql.HLocalDateTime` | `DateTime`* | `DateTime` |
| `Hazelcast.Sql.HOffsetDateTime` | `DateTimeOffset`* | `DateTimeOffset` |
<sup>* - Possible `ArgumentOutOfRangeException` </sup>
<sup>** - Possible `OverflowException` </sup>
|

### Decimal String Format

SQL `DECIMAL` type uses dot as separator.

Examples: `12345`, `123456.789`.

### Date String Format

SQL `DATE` type uses `yyyy-mm-dd` format.

Examples: `2021-07-01`, `1990-12-31`.

### Time String Format

SQL `TIME` uses `HH:mm:ss.SSS` where `HH` is in 24-hour format and, `SSS` represents nanoseconds and can be at most 9 digits long.

Examples: `10:20:30`, `23:59:59.999999999`

### Timestamp String Format

SQL `TIMESTAMP` type uses `yyyy-mm-dd(T|t)HH:mm:ss.SSS` which is the combination of
`DATE` and `TIME` strings. There must be a `T` or `t` letter in between.

Examples: `2021-07-01T10:20:30`, `1990-12-31t23:59:59.999999999`

### Timestamp with Timezone String Format

SQL `TIMESTAMP WITH TIMEZONE` uses `yyyy-mm-dd(T|t)HH:mm:ss.SSS{timezoneString}` which is the combination of `TIMESTAMP` and timezone strings. The timezone string can be one of `Z`, `+hh:mm` or `-hh:mm` where `hh` represents hour-in-day, and `mm` represents minutes-in-hour.
The timezone must be in the range `[-18:00, +18:00]`.

`2021-07-01T10:20:30Z`, `1990-12-31t23:59:59.999999999+11:30`

## Casting

You may need to use casting when sending parameters for certain types. In general, you should try to send a parameter that has the same data type as the related column.

### How to Cast

Casting syntax: `CAST(? AS TYPE)`

Example casting:

```sql
SELECT * FROM someMap WHERE this = CAST(? AS INTEGER)
```

### Casting Between Types

When comparing a column with a parameter, your parameter must be of a compatible type. You can cast string to every SQL type.

### An Example of Implicit Cast
In the example below, Age column is of type `INTEGER`. We pass parameters as shorts (`TINYINT`) and they are automatically casted to `INTEGER` for comparison.

```csharp
await using var result = client.Sql.ExecuteQuery(
$"SELECT Name FROM {map.Name} WHERE Age > ? AND Age < ?",
(short)20, (short)30
);
```

### An Example of Explicit Cast

In the example below, Age column is of type `INTEGER`. We pass parameters as strings (`VARCHAR`) and cast them to `INTEGER` for comparison.

```csharp
await using var result = client.Sql.ExecuteQuery(
$"SELECT Name FROM {map.Name} WHERE Age > CAST(? AS INTEGER) AND Age < CAST(? AS INTEGER)",
"20", "30"
);
```

### Important Notes About Comparison and Casting

* In case of comparison operators (=, <, <>, ...), if one side is `?`, it's assumed to be exactly the other side's type, except that `TINYINT`, `SMALLINT`, `INTEGER` are all converted to `BIGINT`. Note, that reverse is not valid as it may lead to value loss.

* String parameters can be cast to any type. The cast operation may fail though.

* To send a `DECIMAL` type, use `Hazelcast.Sql.HBigDecimal` or an explicit `CAST` from string or other number type.

* To send date and time related types, use corresponding `Hazelcast.Sql.H*` type or a string with an explicit `CAST`.

## SELECT

### Synopsis

```sql
SELECT [ * | expression [ [ AS ] expression_alias ] [, ...] ]
FROM table_name [ [ AS ] table_alias ]
[WHERE condition]
```

### Description

The `SELECT` command retrieves rows from a table. A row is a sequence of expressions defined after the `SELECT` keyword. Expressions may have optional aliases.

`table_name` refers to a single `IHMap` data structure. A table may have an optional alias.

An optional `WHERE` clause defines a condition, that is any expression that evaluates to a result of type boolean. Any row that doesn’t satisfy the condition is eliminated from the result.

### Sorting

You can use the standard SQL clauses ORDER BY, LIMIT, and OFFSET to sort and limit the result set. In order to do so, you need server configuration. See [IMDG docs](https://docs.hazelcast.com/imdg/4.2/sql/select-statement.html#sorting) for more.

### Unsupported Features

The following features are **not supported** and are planned for future releases:

* set operators (`UNION`, `INTERSECT`, `MINUS`)
* subqueries (`SELECT … FROM table WHERE x = (SELECT …)`)

## Expressions

Hazelcast SQL supports logical predicates, `IS` predicates, comparison operators, mathematical functions and operators, string functions, and special functions.
Refer to [IMDG docs](https://docs.hazelcast.com/imdg/4.2/sql/expressions.html) for all possible operations.

## Lite Members

You cannot start SQL queries on lite members. This limitation will be removed in future releases.

## More Information

Please refer to [IMDG SQL docs](https://docs.hazelcast.com/imdg/4.2/sql/distributed-sql.html) for more information.

For basic usage of SQL, see `SqlBasicQueryExample` in *Hazelcast.Net.Examples* project.
2 changes: 1 addition & 1 deletion hz.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ $params = @(
desc = "whether to run enterprise tests";
info = "Running enterprise tests require an enterprise key, which can be supplied either via the HAZELCAST_ENTERPRISE_KEY environment variable, or the build/enterprise.key file."
},
@{ name = "server"; type = [string]; default = "4.1-SNAPSHOT" # -SNAPSHOT to avoid obsolete certs in JARs
@{ name = "server"; type = [string]; default = "5.0-SNAPSHOT" # -SNAPSHOT to avoid obsolete certs in JARs
parm = "<version>";
desc = "the server version when running tests, the remote controller, or a server";
note = "The server <version> must match a released Hazelcast IMDG server version, e.g. 4.0 or 4.1-SNAPSHOT. Server JARs are automatically downloaded."
Expand Down
Loading