package dbutils import ( "fmt" "strings" ) // JSONEach returns JSON_EACH SQLite string expression with // some normalizations for non-json columns. func JSONEach(column string) string { return fmt.Sprintf( `json_each(CASE WHEN json_valid([[%s]]) THEN [[%s]] ELSE json_array([[%s]]) END)`, column, column, column, ) } // JSONArrayLength returns JSON_ARRAY_LENGTH SQLite string expression // with some normalizations for non-json columns. // // It works with both json and non-json column values. // // Returns 0 for empty string or NULL column values. func JSONArrayLength(column string) string { return fmt.Sprintf( `json_array_length(CASE WHEN json_valid([[%s]]) THEN [[%s]] ELSE (CASE WHEN [[%s]] = '' OR [[%s]] IS NULL THEN json_array() ELSE json_array([[%s]]) END) END)`, column, column, column, column, column, ) } // JSONExtract returns a JSON_EXTRACT SQLite string expression with // some normalizations for non-json columns. func JSONExtract(column string, path string) string { // prefix the path with dot if it is not starting with array notation if path != "" && !strings.HasPrefix(path, "[") { path = "." + path } return fmt.Sprintf( // note: the extra object wrapping is needed to workaround the cases where a json_extract is used with non-json columns. "(CASE WHEN json_valid([[%s]]) THEN JSON_EXTRACT([[%s]], '$%s') ELSE JSON_EXTRACT(json_object('pb', [[%s]]), '$.pb%s') END)", column, column, path, column, path, ) }