Projects

Talks & Writings

Posts

reading: one’s place by ハルミチヒロ

A short story included in Rakuen le Paradis issue 38. The editors describe it thus:

オトナ女性二人と少女の過去・現在・未来。

Translated:

The past, present, and future of two women and a girl.

Basically, Miya has basically had two mothers ever since she was young, going with her mother to her mother’s friend Koyomi for meals. And now a teenager, Miya realizes what Koyomi feels for her mother may be more than just friendship.

The author, Harumi Chihiro, is quite good at these little dramas. Some other excellent choices from her include 彼岸 (Higan, or “Nirvana”) and カノン (Canon).

java: binding parameter values influences the result types you get from JDBC

JDBC lets you get the types of the parameters of a prepared statement, and the types of the result set, without actually executing the statement. That also works when you have bind parameters. But in this SQL statement, what are the types of the result set columns?

SELECT ?

The parameter could be literally anything! Even in this statement:

SELECT ? + 1

the types of the parameter and the result are arguably ambiguous (what if the parameter is NUMERIC? or DOUBLE PRECISION?).

It turns out the PostgreSQL JDBC driver, at least, just makes its best guess:

jshell> import java.sql.Connection;

jshell> import java.sql.DriverManager;

jshell> var conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgres?user=postgres&password=password");

jshell> var stmt = conn.prepareStatement("SELECT ?");
stmt ==> SELECT ?

jshell> var meta = stmt.getMetaData();
meta ==> org.postgresql.jdbc.PgResultSetMetaData@25bbf683

jshell> for (int i = 0; i < meta.getColumnCount(); i++) {
   ...>     System.out.println(meta.getColumnTypeName(i + 1));
   ...> }
text

Here you can see that PostgreSQL has just filled in “text” as its best guess as to the type. But of course, if you bound an integer, you’d get back an integer.

If you did have the actual parameter values, could you get the actual types of the result set columns, taking those parameter values into account? It turns out, yes, at least for the PostgreSQL JDBC driver! Just bind them and call getMetaData again:

jshell> stmt.setInt(1, 42);

jshell> meta = stmt.getMetaData();
meta ==> org.postgresql.jdbc.PgResultSetMetaData@401e7803

jshell> for (int i = 0; i < meta.getColumnCount(); i++) {
   ...>     System.out.println(meta.getColumnTypeName(i + 1));
   ...> }
int4

japanese: バタ臭い

A fairly hilarious discovery today while reading アリスとテレスのまぼろし工場: one way to call something “Western” is to describe it as batakusai (バタ臭い), literally “reeking of butter”. See Jisho or Kotobank.

To wit:

もともとゲームが好きだった正宗は、あるRPGのバタくさいイラストレーターの絵に衝撃をうけ、真似て描くうち絵が好きになっていたのだ。

python: "Expression of type '(enum)' cannot be assigned to declared type 'Literal[(enum member)]'"

mypy’s stubgen generates something like this for enums:

import enum
from typing import ClassVar


class StatusCode(enum.IntEnum):
    ALREADY_EXISTS: ClassVar[StatusCode] = ...

But pyright will complain:

error: Expression of type "StatusCode" cannot be assigned to declared type "Literal[StatusCode.ALREADY_EXISTS]"
    "StatusCode" cannot be assigned to type "Literal[StatusCode.ALREADY_EXISTS]" (reportGeneralTypeIssues)

The solution is to just delete the annotation. pyright will infer the right type, as you can see with reveal_type():

import enum


class StatusCode(enum.IntEnum):
    ALREADY_EXISTS = ...

reveal_type(AdbcStatusCode.ALREADY_EXISTS)
# information: Type of "StatusCode.ALREADY_EXISTS" is "Literal[StatusCode.ALREADY_EXISTS]"

c++: clang-tidy complains it can’t find common headers (especially under conda/conda-forge)

clang-tidy might complain it can’t find headers that it should be able to find as a matter of course:

c/driver/postgresql/connection.h:20:10: error: 'cstdint' file not found [clang-diagnostic-error]
#include <cstdint>
         ^~~~~~~~~

It turns out that clang-tidy needs to be able to resolve where the compiler looks for these standard headers, and if the compiler used is a symlink, it won’t find them. Details are in llvm/llvm-project#46804.

To fix it, use a compile_commands.json (e.g. for CMake, set CMAKE_EXPORT_COMPILE_COMMANDS=ON) and make sure that CC and CXX point to the actual compilers, not a symlink:

export CC=$(readlink -f ${CC:-$(which cc)})
export CXX=$(readlink -f ${CXX:-$(which cxx)})

cmake ...