[25.2.1] - 2025-05-27

CLI

- `picodata admin` in \lua mode no longer requires a delimiter for executing commands.
- allow only the full format for address command-line arguments
  - allow `HOST:PORT`,
  - disallow `HOST` or `:PORT`,
  - this is technically a breaking change.
- provide a more detailed message for address binding errors
- set permissions of admin socket file to 0660 by default.
- `picodata expel` no longer requires the `--cluster-name` parameter; it is now marked as deprecated and will be removed in the future major release (version 26).

Pgproto

- Do not allow connections without ssl when ssl is enabled on the server.
  - In previous versions `pg.ssl = true` meant "allow clients to connect either plaintext or via SSL",
  - Now it more strict: "only allow clients to connect via SSL".
  - This is technically a breaking change.

- The WAIT APPLIED GLOBALLY option now waits for all instances rather than just replicaset masters.

Plugin API

- Plugin RPC requests will now be executed locally whenever possible. Previously
  the behavior was inverted - we preferred remote execution, which was counter
  productive.

- Plugin RPC context has new named field "call_was_local" which is set to `true`
  when the call is made locally (without network access). Note that in the
  opposite case "call_was_local" may be unset, so the absence of this fields
  should be interpreted as a non local call.

ACL

- For all users with role `public` the privileges to `read` system tables `_pico_instance` and `_pico_peer_address` are now granted.

- Forbid the granting of DROP privileges on system tables.

Type system

- Improved type checking now catches more errors earlier with clearer error messages.
  Valid queries should note no difference.

  Example with `SELECT 1 = false`:

  Old behavior:
  ```sql
  picodata> select 1 = false;
  ---
  - null
  - 'sbroad: failed to create tarantool: Tarantool(BoxError { code: 171, message: Some("Type
    mismatch: can not convert boolean(FALSE) to number"), error_type: Some("ClientError"),
    errno: None, file: Some("./src/box/sql/mem.c"), line: Some(2784), fields: {}, cause:
    None })'
  ...
  ```

  New behavior:
  ```sql
  picodata> select 1 = false;
  ---
  - null
  - 'sbroad: could not resolve operator overload for =(usigned, bool)'
  ...
  ```

  Some queries with parameters or subqueries that previously worked might
  now require explicit type casts. For instance, `select 1 + (select $1)`
  now leads to "could not resolve operator overload for +(unsigned, unknown)"
  error, that can be fixed with explicit type cast: `select 1 + (select $1)::int`

- Sbroad now infers parameter types from query context, allowing to
  prepare statements in pgproto without explicit type specification,
  which is a quite common case.

  For iproto nothing actually changes, because parameter types are
  inferred from the actual parameter values.

  For example, query `SELECT * FROM t WHERE a = $1` used to fail in
  pgproto with "could not determine datatype for parameter $1" error,
  if parameter type wasn't specified by the client. Now the
  parameter type is inferred from the context to the type of column `a`.

  In addition, parameter types can be inferred from the column types
  when inserting values. For instance, in `INSERT INTO t (int_col) VALUES ($1)`
  or `UPDATE t SET int_col = $1` query, parameter type will be inferred to
  the type of the column (int).

  Note that there are 2 methods to fix inference errors:
   1) Explicitly provide parameter type on protocol level.
   2) Explicitly provide parameter type by using CAST.

  Limitations:

   - `SELECT $1`
   Works in PostgreSQL, fails in sbroad, because there is no context
   for type inference. Such queries require parameter type defaulting rules.

   - `SELECT 1 UNION SELECT $1`
   Parameter type could be inferred from the left select statement,
   like PostgreSQL does, but this is not implemented yet.

- SQL type system supports parameter type defaulting to text, allowing
  to handle parameterized queries with context for parameter types
  inference. For instance, `SELECT $1` used to result in
  "could not infer data type of parameter $1" error.
  Now the parameter type will be defaulted to text, making the query valid.

- SQL now can coerce string literals to more suitable type according to
  the context where they are used. For instance, string literal will be
  automatically coerced to a datetime value when it's being inserted in a
  column of type datetime. If a string doesn't represent a valid value of
  the inferred type, the result will be a parsing error.

  Query examples:
   - `SELECT 1 + '1'` is the same as `SELECT 1 + 1`
   - `INSERT INTO t (datetime_col) VALUES ('2023-07-07T12:34:56Z')` is the
     same as `INSERT INTO t (datetime_col) VALUES ('2023-07-07T12:34:56Z'::datetime)`

Observability

- Added picodata metrics in prometheus format to the `/metrics` endpoint. Metrics allow to monitor SQL, RPC, CAS, Raft, instance and governor states. List of metrics:
  - pico_governor_changes_total
  - pico_sql_query_total
  - pico_sql_query_errors_total
  - pico_sql_query_duration
  - pico_rpc_request_total
  - pico_rpc_request_errors_total
  - pico_rpc_request_duration
  - pico_cas_records_total
  - pico_cas_errors_total
  - pico_cas_ops_duration
  - pico_instance_state
  - pico_raft_applied_index
  - pico_raft_commit_index
  - pico_raft_term
  - pico_raft_state
  - pico_raft_leader_id

Fixes

- Display correct value for "can_vote" property in webUI

- Disallow DDL creation operations in a heterogeneous cluster. A cluster is considered
  heterogeneous if any instance differs from another by major or minor version.

- Changed `picodata status` output format to more minimalistic and unix-stylished.

- Fixed panic when dropping system user pico_service.

- PostgreSQL protocol initialization now happens at the stage of instance becoming online,
  preventing possible problems in UX.

- User creation or altering in SQL with a password and LDAP authentication method has been forbidden.

- `.proc_before_online`'s PostgreSQL protocol initialization stage will be
  skipped if it was already initialized before, making this RPC idempotent.

- `--pg-listen` parameter is now checked at bootstrap (`postjoin`) stage, so
  it is not possible anymore to bind a busy port when instance is offline.

- Provide the client with a detailed error message when using LDAP for authentication and the LDAP server is unavailable.

- Fixed secondary indexes not working after raft log compaction.

- Fixed a bug where replication master switchover would sometimes fail.

- No longer dumps backtrace files by default. Logs error if dump failed.

- compare_and_swap in plugins now implicitly calls wait_index and validates term of the applied record
  to exclude situations when election caused different entry to become applied at expected index.
  With new behavior users of the API do not need to take that into account.

- Fixed an issue where an instance cannot join after we expelled another instance.

- `ALTER PLUGIN MIGRATE TO` command's timeout option is now handled more accurately.

- Fixed a bug where a timeout during `ALTER PLUGIN MIGRATE` command would make it
  impossible to run migrations on the current instance.

- Fixed a bug where _pico_service_route was incorrectly loaded into the topology cache.

RPC API

- `.proc_before_online` is a successor to `.proc_enable_all_plugins` due to added
  step of initialization of a PostgreSQL protocol at it's call: see "deprecation".

Deprecation

- `.proc_enable_all_plugins` will be deprecated in the next major release.
- `cluster_name` parameter from `.proc_expel` RPC call will be deprecated in the next major release.

SQL

- SQL supports `TRUNCATE` operation.
- SQL supports `ALTER TABLE t ADD COLUMN` operation.
- SQL supports `ALTER TABLE old_table_name RENAME TO new_table_name` operation.
- SQL supports volatile scalar functions: `instance_uuid`.

Configuration

- Minimal supported Rust version has been bumped from `1.76.0` to `1.85`.

- Allow to configure `boot_timeout` parameter per-instance in config file (7200 sec by default) for auto-shutdown.