Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for query filtering on array based properties #167

Open
pavelhoral opened this issue Feb 2, 2024 · 1 comment
Open

Add support for query filtering on array based properties #167

pavelhoral opened this issue Feb 2, 2024 · 1 comment

Comments

@pavelhoral
Copy link
Member

Our current data layer does not support query filters on array properties. For example the filter tags eq 'hello' should be able to match object { "tags": ["hello", "world"] }. This behavior is defined in wrensec-commons.

It is not that obvious such feature is necessary in Wren:IDM. That is why I am creating this GitHub issue to open the discussion.

@pavelhoral
Copy link
Member Author

Of course one of the main issues here is to actually come up with a way to generate database schema and SQL queries that would not bomb the performance while not introducing unnecessary complexity. I have played with few ideas in PostgreSQL before abandoning it... nevertheless here is my script that can provide a starting point in a potential future attempts:

-- Create basic schema for property objects
CREATE TABLE objects (
  id BIGINT NOT NULL PRIMARY KEY,
  type_id INTEGER NOT NULL,
  objectid VARCHAR(255) NOT NULL,
  CONSTRAINT idx_objects UNIQUE (type_id, objectid)
);

CREATE TABLE props (
  id BIGINT NOT NULL,
  propkey VARCHAR(255) NOT NULL,
  proptype VARCHAR(32),
  propvalue VARCHAR(65535),
  CONSTRAINT fk_objects FOREIGN KEY (id) REFERENCES objects (id) ON DELETE CASCADE ON UPDATE NO ACTION
);
CREATE INDEX idx_prop_id ON props (id);
CREATE INDEX idx_prop_values ON props (propkey, propvalue);


-- Fill in few objects
INSERT INTO objects VALUES (1, 1, 'test');
INSERT INTO props VALUES
(1, '/foo', 'java.lang.String', 'FOOBAR'),
(1, '/bar/0', 'java.lang.String', 'first'),
(1, '/bar/1', 'java.lang.String', 'second'),
(1, '/bar/2', 'java.lang.String', 'third'),
(1, '/bar/4', 'java.lang.String', 'second'),
(1, '/baz/x', 'java.lang.String', 'tic'),
(1, '/baz/y', 'java.lang.String', 'tac'),
(1, '/baz/z', 'java.lang.String', 'toe');

-- Fill in a lot of random stuff so that we are not testing empty tables
INSERT INTO objects (SELECT generate_series(1,100000), 1, md5(random()::text));
INSERT INTO props (SELECT generate_series(1,100000), '/bar/0', 'java.lang.String', md5(random()::text));
INSERT INTO props (SELECT generate_series(1,100000), '/bar/1', 'java.lang.String', md5(random()::text));
INSERT INTO props (SELECT generate_series(1,100000), '/bar/2', 'java.lang.String', md5(random()::text));
INSERT INTO props (SELECT generate_series(1,100000), '/bar/3', 'java.lang.String', md5(random()::text));
INSERT INTO props (SELECT generate_series(1,100000), '/bar/4', 'java.lang.String', md5(random()::text));
INSERT INTO props (SELECT generate_series(1,100000), '/bar/5', 'java.lang.String', md5(random()::text));
INSERT INTO props (SELECT generate_series(1,100000), '/bar/6', 'java.lang.String', md5(random()::text));
INSERT INTO props (SELECT generate_series(1,100000), '/bar/7', 'java.lang.String', md5(random()::text));
INSERT INTO props (SELECT generate_series(1,100000), '/bar/8', 'java.lang.String', md5(random()::text));
INSERT INTO props (SELECT generate_series(1,100000), '/bar/9', 'java.lang.String', md5(random()::text));
INSERT INTO props (SELECT generate_series(1,100000), '/bar/10', 'java.lang.String', md5(random()::text));

-- This will produce duplicated result (this is what current data layer generates)
EXPLAIN ANALYZE SELECT obj.* FROM objects obj
LEFT JOIN props p1 ON p1.id = obj.id AND p1.propkey LIKE '/bar/%'
WHERE p1.proptype = 'java.lang.String' AND p1.propvalue LIKE 'sec%'
ORDER BY obj.objectid;

-- This works, but is not what current data layer generates
EXPLAIN ANALYZE SELECT obj.* FROM objects obj
WHERE 
  id IN (
    SELECT id FROM props prop WHERE prop.propkey LIKE '/bar/%' AND 
    prop.proptype = 'java.lang.String' AND prop.propvalue LIKE 'sec%'
  )
ORDER BY obj.objectid;

DROP TABLE props;
DROP TABLE objects;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant