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

tweak(adminPanel): RN-1273: Map overlay relations by code #5646

Merged
merged 44 commits into from
Jun 20, 2024

Conversation

jaskfla
Copy link
Contributor

@jaskfla jaskfla commented May 17, 2024

Issue RN-1273: Map overlay group relation id to code

Changes

  • Adds child_code to MapOverlayGroupRelation at the model level
  • Adds Child code column to Map overlay group relations page in Admin Panel

Model changes based largely off #4270, which was closed without merging Not anymore

@jaskfla jaskfla changed the title RN-1273: Map overlay relations by code tweak(adminPanel): RN-1273: Map overlay relations by code May 17, 2024
@jaskfla jaskfla marked this pull request as ready for review May 30, 2024 01:34
Comment on lines 696 to 725
function getColSelector(connection, inputColStr) {
const jsonOperatorPattern = /->>?/g;
if (!jsonOperatorPattern.test(inputColStr)) return inputColStr;
if (jsonOperatorPattern.test(inputColStr)) {
const params = inputColStr.split(jsonOperatorPattern);
const allButFirst = params.slice(1);
const lastIndexOfLookupAsText = inputColStr.lastIndexOf('->>');
const lastIndexOfLookupAsJson = inputColStr.lastIndexOf('->');
const selector = lastIndexOfLookupAsText >= lastIndexOfLookupAsJson ? '#>>' : '#>';

// Turn `config->item->>colour` into `config #>> '{item,colour}'`
// For some reason, Knex fails when we try to convert it to `config->'item'->>'colour'`
return connection.raw(`?? ${selector} '{${allButFirst.map(() => '??').join(',')}}'`, params);
}

const params = inputColStr.split(jsonOperatorPattern);
const allButFirst = params.slice(1);
const lastIndexOfLookupAsText = inputColStr.lastIndexOf('->>');
const lastIndexOfLookupAsJson = inputColStr.lastIndexOf('->');
const selector = lastIndexOfLookupAsText >= lastIndexOfLookupAsJson ? '#>>' : '#>';
/**
* Special handling of COALESCE() - one of the {@link supportedFunctions} - to treat its arguments
* as identifiers individually rather than trying to treat ‘COALESCE(foo, bar)’ as a single
* identifier.
*/
const coalescePattern = /^COALESCE\(.+\)$/;
if (coalescePattern.test(inputColStr)) {
const [, argsString] = inputColStr.match(/^COALESCE\((.+)\)$/);
const bindings = argsString.split(',').map(arg => arg.trim());
const identifiers = bindings.map(() => '??');

return connection.raw(`COALESCE(${identifiers})`, bindings);
}

// Turn `config->item->>colour` into `config #>> '{item,colour}'`
// For some reason, Knex fails when we try to convert it to `config->'item'->>'colour'`
return connection.raw(`?? ${selector} '{${allButFirst.map(() => '??').join(',')}}'`, params);
return inputColStr;
}
Copy link
Contributor Author

@jaskfla jaskfla May 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two notes:

  1. This implementation assumes we never have a column selector which both calls COALESCE() and uses JSON selectors. If that happens, this algorithm fails. Is this a concern?
  2. Should I make it iterate through supportedFunctions to handle any function in that array?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Ah that's fine I think
  2. Probably worth it I think! Would make this functionality a lot more future proof if we want to make more use of db functions. If you're happy to 🙏

Copy link
Contributor Author

@jaskfla jaskfla Jun 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, it occurs to me that, given some supportedFunction, it would be difficult to know whether to treat its arguments as ? values or ?? identifiers

I could just build in an assumption and always use ??, but this would silently break any attempt to use a function that takes, say, a number. For example, if we have ROUND(foo, 2) Knex would complain that there’s no column called "2". As far as I can tell, we would need to hard-code it to do ROUND(??, ?)

I can’t think of a clean way about this, so have left some comments about why COALESCE gets special handling, and that this might extend to future supported functions too. Would be thrilled if you can think of something obvious I’ve missed, but going to go ahead as-is for now

@rohan-bes rohan-bes force-pushed the rn-1273-overlay-relations-by-code branch 2 times, most recently from 139b415 to 2809015 Compare June 14, 2024 05:13
@rohan-bes rohan-bes force-pushed the rn-1273-overlay-relations-by-code branch from 2809015 to 8920597 Compare June 14, 2024 05:22
Copy link
Collaborator

@rohan-bes rohan-bes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome stuff @jaskfla 🎉

This issue is definitely one of those things that looks super easy on the surface, but is deceptively tricky. Thanks for pushing through with it and really happy with the end result (I feel like it tidies up and makes a few things more consistent with the CRUDHandler
and DatabaseModel behaviour)

Just a comment to ask if we can loop over the supported functions when sanitizing the WHERE clause identifier, but pre-approving

Comment on lines 696 to 725
function getColSelector(connection, inputColStr) {
const jsonOperatorPattern = /->>?/g;
if (!jsonOperatorPattern.test(inputColStr)) return inputColStr;
if (jsonOperatorPattern.test(inputColStr)) {
const params = inputColStr.split(jsonOperatorPattern);
const allButFirst = params.slice(1);
const lastIndexOfLookupAsText = inputColStr.lastIndexOf('->>');
const lastIndexOfLookupAsJson = inputColStr.lastIndexOf('->');
const selector = lastIndexOfLookupAsText >= lastIndexOfLookupAsJson ? '#>>' : '#>';

// Turn `config->item->>colour` into `config #>> '{item,colour}'`
// For some reason, Knex fails when we try to convert it to `config->'item'->>'colour'`
return connection.raw(`?? ${selector} '{${allButFirst.map(() => '??').join(',')}}'`, params);
}

const params = inputColStr.split(jsonOperatorPattern);
const allButFirst = params.slice(1);
const lastIndexOfLookupAsText = inputColStr.lastIndexOf('->>');
const lastIndexOfLookupAsJson = inputColStr.lastIndexOf('->');
const selector = lastIndexOfLookupAsText >= lastIndexOfLookupAsJson ? '#>>' : '#>';
/**
* Special handling of COALESCE() - one of the {@link supportedFunctions} - to treat its arguments
* as identifiers individually rather than trying to treat ‘COALESCE(foo, bar)’ as a single
* identifier.
*/
const coalescePattern = /^COALESCE\(.+\)$/;
if (coalescePattern.test(inputColStr)) {
const [, argsString] = inputColStr.match(/^COALESCE\((.+)\)$/);
const bindings = argsString.split(',').map(arg => arg.trim());
const identifiers = bindings.map(() => '??');

return connection.raw(`COALESCE(${identifiers})`, bindings);
}

// Turn `config->item->>colour` into `config #>> '{item,colour}'`
// For some reason, Knex fails when we try to convert it to `config->'item'->>'colour'`
return connection.raw(`?? ${selector} '{${allButFirst.map(() => '??').join(',')}}'`, params);
return inputColStr;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Ah that's fine I think
  2. Probably worth it I think! Would make this functionality a lot more future proof if we want to make more use of db functions. If you're happy to 🙏

@jaskfla jaskfla merged commit 18b4128 into dev Jun 20, 2024
44 checks passed
@jaskfla jaskfla deleted the rn-1273-overlay-relations-by-code branch June 20, 2024 02:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants