Skip to content

Commit

Permalink
Handle property and dependency values of type BLOB in ListBundles. (#744
Browse files Browse the repository at this point in the history
)

Per https://www.sqlite.org/datatype3.html#type_affinity:

> In order to maximize compatibility between SQLite and other database
> engines, and so that the example above will work on SQLite as it
> does on other SQL database engines, SQLite supports the concept of
> "type affinity" on columns. The type affinity of a column is the
> recommended type for data stored in that column. The important idea
> here is that the type is recommended, not required. Any column can
> still store any type of data. It is just that some columns, given
> the choice, will prefer to use one storage class over another. The
> preferred storage class for a column is called its "affinity".

Even though the properties and dependencies tables are created with
column affinity TEXT on both their "type" and "value" columns, SQLite
does not require values stored in those columns to have that type.

The query backing the registry.ListBundles API recently began using
the json_object function from the json1 SQLite
extension (https://www.sqlite.org/json1.html#jobj), which does not
support arguments of type BLOB. The docs state:

> If any argument to json_object() is a BLOB then an error is thrown.

But it seems that no error is actually being returned. Instead, the
result set it empty. This may be an issue with the SQLite driver? It
seems to produce an error in sqlite3's interactive mode.

Signed-off-by: Ben Luddy <bluddy@redhat.com>
  • Loading branch information
benluddy committed Aug 5, 2021
1 parent ff2c921 commit c2fc1fd
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
4 changes: 2 additions & 2 deletions pkg/sqlite/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -991,12 +991,12 @@ tip (depth) AS (
GROUP BY all_entry.operatorbundle_name, all_entry.package_name, all_entry.channel_name
),
merged_properties (bundle_name, merged) AS (
SELECT operatorbundle_name, json_group_array(json_object('type', properties.type, 'value', properties.value))
SELECT operatorbundle_name, json_group_array(json_object('type', CAST(properties.type AS TEXT), 'value', CAST(properties.value AS TEXT)))
FROM properties
GROUP BY operatorbundle_name
),
merged_dependencies (bundle_name, merged) AS (
SELECT operatorbundle_name, json_group_array(json_object('type', dependencies.type, 'value', CAST(dependencies.value AS TEXT)))
SELECT operatorbundle_name, json_group_array(json_object('type', CAST(dependencies.type AS TEXT), 'value', CAST(dependencies.value AS TEXT)))
FROM dependencies
GROUP BY operatorbundle_name
)
Expand Down
31 changes: 31 additions & 0 deletions pkg/sqlite/query_sql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,37 @@ func TestListBundlesQuery(t *testing.T) {
require.False(rows.Next())
},
},
{
Name: "properties and depdendencies columns may be stored as sqlite type blob",
OmitManfests: true,
Setup: func(t *testing.T, db *sql.DB) {
for _, stmt := range []string{
`insert into package (name, default_channel) values ("package", "channel")`,
`insert into channel (name, package_name, head_operatorbundle_name) values ("channel", "package", "bundle")`,
`insert into operatorbundle (name, bundle) values ("bundle-a", "{}")`,
`insert into channel_entry (package_name, channel_name, operatorbundle_name, entry_id, depth) values ("package", "channel", "bundle-a", 1, 0)`,
`insert into properties (type, value, operatorbundle_name) values (CAST("blob_ptype" AS BLOB), CAST("blob_pvalue" AS BLOB), "bundle-a")`,
`insert into dependencies (type, value, operatorbundle_name) values (CAST("blob_dtype" AS BLOB), CAST("blob_dvalue" AS BLOB), "bundle-a")`,
} {
if _, err := db.Exec(stmt); err != nil {
t.Fatalf("unexpected error executing setup statements: %v", err)
}
}

},
Expect: func(t *testing.T, rows *sql.Rows) {
require := require.New(t)
require.True(rows.Next())
var (
props, deps sql.NullString
c interface{}
)
require.NoError(rows.Scan(&c, &c, &c, &c, &c, &c, &c, &c, &c, &c, &deps, &props))
require.Equal(sql.NullString{Valid: true, String: `[{"type":"blob_ptype","value":"blob_pvalue"}]`}, props)
require.Equal(sql.NullString{Valid: true, String: `[{"type":"blob_dtype","value":"blob_dvalue"}]`}, deps)
require.False(rows.Next())
},
},
{
Name: "manifests not omitted with bundlepath",
OmitManfests: true,
Expand Down

0 comments on commit c2fc1fd

Please sign in to comment.