Repository: diesel-rs/diesel
File: diesel/src/sqlite/expression/functions.rs (Rust)

Code before:
    ///     .get_result::<Option<bool>>(connection)?;
    /// assert_eq!(Some(false), result);
    ///
    /// // JSON5 valid with JSON5 flag (flag = 6)
    /// let result = diesel::select(json_valid_with_flags::<Text, _, _>(r#"{x:35}"#, 6))
    ///     .get_result::<Option<bool>>(connection)?;
    /// assert_eq!(Some(true), result);
    ///
    /// // Invalid JSON
    /// let result = diesel::select(json_valid_with_flags::<Text, _, _>(r#"{"x":35"#, 1))
    ///     .get_result::<Option<bool>>(connection)?;
    /// assert_eq!(Some(false), result);
    ///
    /// // NULL input returns NULL
    /// let result = diesel::select(json_valid_with_flags::<Nullable<Text>, _, _>(None::<&str>, 1))
    ///     .get_result::<Option<bool>>(connection)?;
    /// assert_eq!(None, result);
    ///
    /// # Ok(())
    /// # }
    /// ```
    #[sql_name = "json_valid"]
    #[cfg(feature = "sqlite")]
    fn json_valid_with_flags<X: TextOrNullableTextOrBinaryOrNullableBinary + SingleValue>(
        x: X,
        flags: Integer,
    ) -> Nullable<Bool>;

    /// The json_type(X) function returns the "type" of the outermost element of X.
    /// The "type" returned by json_type() is one of the following SQL text values:
    /// 'null', 'true', 'false', 'integer', 'real', 'text', 'array', or 'object'.
    ///
    /// This function requires at least SQLite 3.38 or newer
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     #[cfg(feature = "serde_json")]
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # #[cfg(feature = "serde_json")]
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::dsl::{sql, json_type};
    /// #     use serde_json::{json, Value};
    /// #     use diesel::sql_types::{Text, Json, Jsonb, Nullable};
    /// #     let connection = &mut establish_connection();
    /// #     assert_version!(connection, 3, 38, 0);

Review comment (suggestion):
I think I would prefer a more strictly typed approach here. That means:

1. Define a new SQL type in https://github.com/diesel-rs/diesel/blob/main/diesel/src/sqlite/types/mod.rs. That should use `#[diesel(sqlite_type(name = "Integer"))`
2. Define an enum with all the variants listed above (marked as `#[non_exhaustive]`
3. Implement `ToSql<YourNewSqlType, Sqlite>` for that enum + derive `AsExpression` for it.
4. Use this new defined sql type here in place of `Integer`

Code after:
    /// let result = diesel::select(json_valid_with_flags::<Text, _, _>(r#"{x:35}"#, JsonValidFlag::Rfc8259Json))
    ///     .get_result::<bool>(connection)?;
    /// assert_eq!(false, result);
    ///
    /// // JSON5 valid with JSON5 flag
    /// let result = diesel::select(json_valid_with_flags::<Text, _, _>(r#"{x:35}"#, JsonValidFlag::Json5OrJsonb))
    ///     .get_result::<bool>(connection)?;
    /// assert_eq!(true, result);
    ///
    /// // Invalid JSON
    /// let result = diesel::select(json_valid_with_flags::<Text, _, _>(r#"{"x":35"#, JsonValidFlag::Rfc8259Json))
    ///     .get_result::<bool>(connection)?;
    /// assert_eq!(false, result);
    ///
    /// // NULL input returns NULL
    /// let result = diesel::select(json_valid_with_flags::<Nullable<Text>, _, _>(None::<&str>, JsonValidFlag::Rfc8259Json))
    ///     .get_result::<Option<bool>>(connection)?;
    /// assert_eq!(None, result);
    ///
    /// # Ok(())
    /// # }
    /// ```
    #[sql_name = "json_valid"]
    #[cfg(feature = "sqlite")]
    fn json_valid_with_flags<
        X: TextOrNullableTextOrBinaryOrNullableBinary + SingleValue + MaybeNullableValue<Bool>,
    >(
        x: X,
        flags: crate::sqlite::types::JsonValidFlags,
    ) -> X::Out;

    /// The json_type(X) function returns the "type" of the outermost element of X.
    /// The "type" returned by json_type() is one of the following SQL text values:
    /// 'null', 'true', 'false', 'integer', 'real', 'text', 'array', or 'object'.
    ///
    /// This function requires at least SQLite 3.38 or newer
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     #[cfg(feature = "serde_json")]
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # #[cfg(feature = "serde_json")]
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::dsl::{sql, json_type};
    /// #     use serde_json::{json, Value};