Skip to content

Commit

Permalink
Merge 8710d0d into 122e90c
Browse files Browse the repository at this point in the history
  • Loading branch information
kneth authored Feb 28, 2024
2 parents 122e90c + 8710d0d commit 6d09459
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 28 deletions.
29 changes: 21 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
## vNext (TBD)

NOTE: This version bumps the Realm file format to version 24. It is not possible to downgrade to earlier versions. Older files will automatically be upgraded to the new file format. Files created by Realm JavaScript prior to v6.0.0, might not be upgradeable. Only Realm Studio 15.0.0 or later will be able to open the new file format.


### Deprecations
* None

### Enhancements
* None
* Updated bundled OpenSSL version to 3.2.0 ([realm/realm-core#7303](https://github.com/realm/realm-core/pull/7303))
* Property keypath in RQL can be substituted with value given as argument. Use `$P<i>` in query string. ([realm/realm-core#7033](https://github.com/realm/realm-core/issues/7033))
* You can now use query substitution for the `@type` argument. ([realm/realm-core#7289](https://github.com/realm/realm-core/issues/7289))
* Storage of `Decimal128` properties has been optimized so that the individual values will take up 0 bits (if all nulls), 32 bits, 64 bits or 128 bits depending on what is needed. ([realm/realm-core#6111]https://github.com/realm/realm-core/pull/6111))
* Querying a specific entry in a collection (in particular 'first and 'last') is supported. (PR [#4269](https://github.com/realm/realm-core/issues/4269))
* Index on list of strings property now supported ([realm/realm-core#7142](https://github.com/realm/realm-core/pull/7142))
* You can set the threshold levels for trace output on individual categories. ([realm/realm-core#7004](https://github.com/realm/realm-core/pull/7004))
* Improved performance of RQL queries on a non-linked string property using `>`, `>=`, `<`, `<=` operators and fixed behavior that a null string should be evaluated as less than everything, previously nulls were not matched. ([realm/realm-core#3939](https://github.com/realm/realm-core/issues/3939))

### Fixed
* <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-js/issues/????), since v?.?.?)
* None
* Align dictionaries to Lists and Sets when they get cleared. ([#6205](https://github.com/realm/realm-core/issues/6205), since v10.3.0-rc.1)
* Fixed equality queries on a `Mixed` property with an index possibly returning the wrong result if values of different types happened to have the same StringIndex hash. ([realm/realm-core#6407](https://github.com/realm/realm-core/issues/6407) since v10.5.0-beta.1)
* @count/@size not supported for mixed properties ([realm/realm-core#7280](https://github.com/realm/realm-core/issues/7280), since v10.0.0)
* Fixed queries like `indexed_property == NONE {x}` which mistakenly matched on only `x` instead of not `x`. This only applies when an indexed property with equality (`==`, or `IN`) matches with `NONE` on a list of one item. If the constant list contained more than one value then it was working correctly. ([realm/realm-java#7862](https://github.com/realm/realm-java/issues/7862), since v10.20.0)
* Uploading the changesets recovered during an automatic client reset recovery may lead to `Bad server version` errors and a new client reset. ([realm/realm-core#7279](https://github.com/realm/realm-core/issues/7279), since v12.5.0)
* Fixed crash in full text index using prefix search with no matches ([realm/realm-core#7309](https://github.com/realm/realm-core/issues/7309), since v12.2.0)
* Fix a race condition when backing up Realm files before a client reset which could have lead to overwriting an existing file. ([realm/realm-core#7341](https://github.com/realm/realm-core/pull/7341)).

### Compatibility
* React Native >= v0.71.4
* Realm Studio v14.0.0.
* File format: generates Realms with format v23 (reads and upgrades file format v5 or later for non-synced Realm, upgrades file format v10 or later for synced Realms).
* Realm Studio v15.0.0.
* File format: generates Realms with format v24 (reads and upgrades file format v10 or later).

### Internal
<!-- * Either mention core version or upgrade -->
<!-- * Using Realm Core vX.Y.Z -->
<!-- * Upgraded Realm Core from vX.Y.Z to vA.B.C -->
* Upgraded Realm Core from v13.26.0 to v14.0.1. ([#6499](https://github.com/realm/realm-js/issues/6499))

## 12.6.1 (2024-02-26)

Expand Down
12 changes: 6 additions & 6 deletions integration-tests/tests/src/tests/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ describe("Queries", () => {
["Unsupported comparison between type", "boolCol == 0"],
["Unsupported comparison between type", "boolCol == 1"],
["Unsupported comparison between type", "boolCol == 'not a bool'"],
["Unsupported comparison between type", "boolCol == $0", "not a bool"],
["Cannot compare argument $0 with value", "boolCol == $0", "not a bool"],
["Unsupported comparison operator", "boolCol BEGINSWITH true"],
["Unsupported comparison operator", "boolCol CONTAINS true"],
["Unsupported comparison operator", "boolCol ENDSWITH true"],
Expand Down Expand Up @@ -363,7 +363,7 @@ describe("Queries", () => {
expectQueryException(this.realm, NullableTypesObject, [
["Unsupported comparison between type", "dateCol == 'not a date'"],
["Unsupported comparison between type", "dateCol == 1"],
["Unsupported comparison between type", "dateCol == $0", 1],
["Cannot compare argument $0 with value", "dateCol == $0", 1],
]);
});
});
Expand Down Expand Up @@ -401,7 +401,7 @@ describe("Queries", () => {
expectQueryException(this.realm, NullableTypesObject, [
["Unsupported comparison between type", "intCol == false"],
["Cannot convert", "intCol == 'not an int'"],
["Unsupported comparison between type", "intCol == $0", "not an int"],
["Cannot convert", "intCol == $0", "not an int"],
["Unsupported comparison operator", "intCol BEGINSWITH 1"],
["Unsupported comparison operator", "intCol CONTAINS 1"],
["Unsupported comparison operator", "intCol ENDSWITH 1"],
Expand Down Expand Up @@ -446,7 +446,7 @@ describe("Queries", () => {
expectQueryException(this.realm, NullableTypesObject, [
["Unsupported comparison between type", "floatCol == false"],
["Cannot convert", "floatCol == 'not a float'"],
["Unsupported comparison between type", "floatCol == $0", "not a float"],
["Cannot convert", "floatCol == $0", "not a float"],
["Unsupported comparison operator", "floatCol BEGINSWITH 1"],
["Unsupported comparison operator", "floatCol CONTAINS 1"],
["Unsupported comparison operator", "floatCol ENDSWITH 1"],
Expand Down Expand Up @@ -492,7 +492,7 @@ describe("Queries", () => {
expectQueryException(this.realm, NullableTypesObject, [
["Unsupported comparison between type", "doubleCol == false"],
["Cannot convert", "doubleCol == 'not a double'"],
["Unsupported comparison between type", "doubleCol == $0", "not a double"],
["Cannot convert", "doubleCol == $0", "not a double"],
["Unsupported comparison operator", "doubleCol BEGINSWITH 1"],
["Unsupported comparison operator", "doubleCol CONTAINS 1"],
["Unsupported comparison operator", "doubleCol ENDSWITH 1"],
Expand Down Expand Up @@ -557,7 +557,7 @@ describe("Queries", () => {
expectQueryException(this.realm, NullableTypesObject, [
["Unsupported comparison between type", "stringCol == true"],
["Unsupported comparison between type", "stringCol == 123"],
["Unsupported comparison operator", "stringCol CONTAINS $0", 1],
["Cannot compare argument $0 with value", "stringCol CONTAINS $0", 1],
]);
});
});
Expand Down
6 changes: 5 additions & 1 deletion packages/realm/bindgen/js_opt_in_spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,14 @@ classes:
- feed_buffer
- make_ssl_verify_callback

LogCategoryRef:
methods:
- set_default_level_threshold
- get_category

Logger:
methods:
- set_default_logger
- set_default_level_threshold

ConstTableRef:
methods:
Expand Down
2 changes: 1 addition & 1 deletion packages/realm/bindgen/src/templates/jsi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,7 @@ export function generate({ rawSpec, spec, file: makeFile }: TemplateContext): vo
extern "C" {
void realm_jsi_invalidate_caches() {
// Clear the default logger, to prevent it from holding on to a pointer that was released
realm::util::Logger::set_default_level_threshold(realm::util::Logger::Level::off);
realm::util::LogCategory::get_category(realm::util::LogCategory::realm.get_name()).set_default_level_threshold(realm::util::Logger::Level::off);
realm::util::Logger::set_default_logger(nullptr);
// Close all cached Realms
realm::_impl::RealmCoordinator::clear_all_caches();
Expand Down
2 changes: 1 addition & 1 deletion packages/realm/bindgen/vendor/realm-core
Submodule realm-core updated 448 files
144 changes: 143 additions & 1 deletion packages/realm/src/Logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,137 @@ import { assert, binding } from "./internal";

export type LogLevel = "all" | "trace" | "debug" | "detail" | "info" | "warn" | "error" | "fatal" | "off";

/**
* Log levels used by Realm
*/
export enum NumericLogLevel {
/**
* Same as 'Trace' but with even more output.
*/
All = 0,
/**
* A version of 'Debug' that allows for very high volume
* output.
*/
Trace = 1,
/**
* Reveal information that can aid debugging, no longer paying
* attention to efficiency.
*/
Debug = 2,
/**
* Same as 'Info', but prioritize completeness over minimalism.
*/
Detail = 3,
/**
* Reveal information about what is going on, but in a
* minimalistic fashion to avoid general overhead from logging
* and to keep volume down.
*/
Info = 4,
/**
* Be silent unless when there is an error or a warning.
*/
Warn = 5,
/**
* Be silent unless when there is an error.
*/
Error = 6,
/**
* Be silent unless when an error is fatal.
*/
Fatal = 7,
/**
* Be silent.
*/
Off = 8,
}

/**
* The category to receive log messages for. The {@link LogLevel} will
* always be set for a specific category. Setting the log level on one
* category, will automatically set the log level for any subcategory.
* @note
* When debugging, you might not need log messages from everything. To narrow
* this scope, log events can be grouped by category.
*/
export enum LogCategory {
/**
* Include logs from all categories. Subcategories are {@link LogCategory.Storage},
* {@link LogCategory.Sync}, {@link LogCategory.App}, and {@link LogCategory.SDK}.
*/
Realm = "Realm",
/**
* Log database mutations and query operations.
* Subcategories are {@link LogCategory.Transaction}, {@link LogCategory.Object},
* {@link LogCategory.Query}, and {@link LogCategory.Notification}.
*/
Storage = "Realm.Storage",
/**
* Log when creating, advancing, and committing transactions.
*/
Transaction = "Realm.Storage.Transaction",
/**
* Log query operations.
*/
Query = "Realm.Storage.Query",
/**
* Log database mutations.
*/
Object = "Realm.Storage.Object",
/**
* Log notifications of changes to the database.
*/
Notification = "Realm.Storage.Notification",
/**
* Log activity related to Atlas Device Sync.
* Subcategories are {@link LogCategory.Client} and {@link LogCategory.Server}.
*/
Sync = "Realm.Sync",
/**
* Log activity related to Atlas Device Sync client operations.
* Subcategories are {@link LogCategory.Session}, {@link LogCategory.Changeset},
* {@link LogCategory.Network}, and {@link LogCategory.Reset}.
*/
Client = "Realm.Sync.Client",
/**
* Log connection level activity.
*/
Session = "Realm.Sync.Client.Session",
/**
* Log when receiving, uploading, and integrating changesets.
*/
Changeset = "Realm.Sync.Client.Changeset",
/**
* Log low level network activity.
*/
Network = "Realm.Sync.Client.Network",
/**
* Log client reset operations.
*/
Reset = "Realm.Sync.Client.Reset",
/**
* Log activity related to Atlas Device Sync server operations.
*/
Server = "Realm.Sync.Server",
/**
* Log activity at the Atlas App level.
*/
App = "Realm.App",
/**
* Log activity at the SDK level.
*/
SDK = "Realm.SDK",
}

/**
* Type for `Realm.setLogLevel`
*/
export type LogArgs = {
level: LogLevel;
category?: LogCategory;
};

/**
* A callback passed to `Realm.App.Sync.setLogger` when instrumenting the Atlas Device Sync client with a custom logger.
* @param level - The level of the log entry between 0 and 8 inclusively.
Expand All @@ -40,7 +159,30 @@ export enum NumericLogLevel {
*/
export type Logger = (level: NumericLogLevel, message: string) => void;

export type LoggerCallback = (level: LogLevel, message: string) => void;
/**
* A callback passed to `Realm.setLogger`.
*
* @param level - The level of the log entry.
* @param message - The message of the log entry.
* @since 12.0.0
* @deprecated Will be removed in v13.0.0
*/
export type LoggerCallback1 = (level: LogLevel, message: string) => void;
export type LoggerCallbackArgs = {
category: LogCategory;
level: LogLevel;
message: string;
};
/**
* A callback passed to `Realm.setLogger`. Arguments are passed as a POJO.
*
* @param category - The category (origin) of the log entry.
* @param level - The level of the log entry.
* @param message - The message of the log entry.
* @since
*/
export type LoggerCallback2 = (args: LoggerCallbackArgs) => void;
export type LoggerCallback = LoggerCallback1 | LoggerCallback2;

/** @internal */
export function toBindingLoggerLevel(arg: LogLevel): binding.LoggerLevel {
Expand Down
69 changes: 62 additions & 7 deletions packages/realm/src/Realm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ import {
INTERNAL,
InitialSubscriptions,
List,
LogArgs,
LogCategory,
LogLevel,
LoggerCallback,
LoggerCallback1,
LoggerCallback2,
MigrationCallback,
ObjectSchema,
ProgressRealmPromise,
Expand Down Expand Up @@ -109,24 +113,75 @@ export class Realm {
/**
* Sets the log level.
* @param level - The log level to be used by the logger. The default value is `info`.
* @param category - The category/component to set the log level for. If omitted, log level is set for all known categories.
* @note The log level can be changed during the lifetime of the application.
* @since 12.0.0
* @example
* Realm.setLogLevel({ category: LogCategory.Realm, level: "all" });
*/
static setLogLevel(level: LogLevel) {
const bindingLoggerLevel = toBindingLoggerLevel(level);
binding.Logger.setDefaultLevelThreshold(bindingLoggerLevel);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
static setLogLevel(_: LogLevel | LogArgs) {
// It is not possible to overload a static function: https://github.com/microsoft/TypeScript/issues/18945

const setLevel = (category: LogCategory, level: LogLevel) => {
assert(Object.values(LogCategory).includes(category));
const ref = binding.LogCategoryRef;
const c = ref.getCategory(category);
c.setDefaultLevelThreshold(toBindingLoggerLevel(level));
};

// FIXME: don't use `arguments` but find a proper type
if (arguments.length === 1) {
// eslint-disable-next-line prefer-rest-params
const arg = arguments[0];
if (arg.level) {
const level = arg.level as LogLevel;
if (arg.category) {
const category = arg.category as LogCategory;
setLevel(category, level);
} else {
Object.values(LogCategory).forEach((category) => {
setLevel(category, level);
});
}
} else {
const level = arg as LogLevel;
Object.values(LogCategory).forEach((category) => {
setLevel(category, level);
});
}
} else {
throw new Error(`Wrong number of arguments - expected 1, got ${arguments.length}`);
}
}

/**
* Sets the logger callback.
* @param loggerCallback - The callback invoked by the logger. The default callback uses `console.log`, `console.warn` and `console.error`, depending on the level of the message.
* @note The logger callback needs to be setup before opening the first realm.
* @note The logger callback needs to be setup before opening the first Realm.
* @since 12.0.0
* @example
* Realm.setLogger(({ category, level, message }) => {
* console.log(`[${category} - ${level}] ${message}`);
* });
*/
static setLogger(loggerCallback: LoggerCallback) {
const logger = binding.Helpers.makeLogger((level, message) => {
loggerCallback(fromBindingLoggerLevelToLogLevel(level), message);
});
let logger: binding.Logger;

// This is a hack to check which of the two logger callbacks which are used
// It only works as the two callback type have different number of arguments, and it will
// probably produce odd error messages if the logger is set by `setLogger((...args) => console.log(args))`.
if (loggerCallback.length === 2) {
const cb = loggerCallback as LoggerCallback1;
logger = binding.Helpers.makeLogger((_category, level, message) => {
cb(fromBindingLoggerLevelToLogLevel(level), message);
});
} else {
const cb = loggerCallback as LoggerCallback2;
logger = binding.Helpers.makeLogger((category, level, message) => {
cb({ category: category as LogCategory, level: fromBindingLoggerLevelToLogLevel(level), message });
});
}
binding.Logger.setDefaultLogger(logger);
}

Expand Down
Loading

0 comments on commit 6d09459

Please sign in to comment.