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

HCK-9252: keys from secondary indexes #43

Merged
merged 15 commits into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions forward_engineering/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ const {
GENERATING_CONTAINER_SCRIPT,
GENERATING_ENTITY_SCRIPT,
CREATING_A_BUCKET,
} = require('../shared/enums/static-messages');
} = require('../shared/enums/staticMessages');
const {
getCheckBucketExistsMessage,
getCreatingBucketMessage,
getSuccessfullyCreatedBucketMessage,
} = require('../shared/enums/dynamic-messages');
const { HTTP_ERROR_CODES } = require('../shared/enums/http');
} = require('../shared/enums/dynamicMessages');
const { HTTP_ERROR_CODES } = require('../shared/enums/httpCodes');

const { applyScript, logApplyScriptAttempt } = require('./services/applyToInstanceService');
const ForwardEngineeringScriptBuilder = require('./services/forwardEngineeringScriptBuilder');
Expand Down
4 changes: 2 additions & 2 deletions forward_engineering/services/applyToInstanceService.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ const {
SCRIPT_SUCCESSFULLY_APPLIED,
SUCCESSFULLY_APPLIED,
ERROR_HAS_BEEN_THROWN_WHILE_APPLYING_SCRIPT_TO_COUCHBASE_INSTANCE,
} = require('../../shared/enums/static-messages');
} = require('../../shared/enums/staticMessages');
const {
getApplyingScriptPercentMessage,
getRetryAttemptNumberMessage,
getApplyingScriptToBucketWithAttemptNumberMessage,
getApplyingScriptMessage,
} = require('../../shared/enums/dynamic-messages');
} = require('../../shared/enums/dynamicMessages');
const { COUCHBASE_ERROR_CODE } = require('../../shared/constants');

const MAX_APPLY_ATTEMPTS = 5;
Expand Down
29 changes: 21 additions & 8 deletions forward_engineering/services/statements/indexesStatements.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { filter, get, isEmpty } = require('lodash');
const { getIndexKeyIdToKeyNameMap, injectKeysNamesIntoIndexKeys } = require('../../utils/indexes');
const { wrapWithBackticks, getKeySpaceReference, joinStatements } = require('./commonStatements');
const { INDEX_TYPE } = require('../../../shared/enums/n1ql');
const { INDEX_TYPE } = require('../../../shared/enums/indexType');

/**
*
Expand Down Expand Up @@ -85,7 +85,7 @@ const getKeys = index => {
switch (index.indxType) {
case INDEX_TYPE.primary:
return { script: '', canHaveIndex: true };
case INDEX_TYPE.secondary:
case INDEX_TYPE.secondary: {
const keys = index.indxKey?.map(key => ({ ...key, name: wrapWithBackticks(key.name) }));

const keysNames = joinStatements({
Expand All @@ -96,6 +96,7 @@ const getKeys = index => {
});

return { script: `(${keysNames})`, canHaveIndex: Boolean(keysNames.length) };
}
case INDEX_TYPE.array:
return { script: `(${index.arrayExpr})`, canHaveIndex: true };
case INDEX_TYPE.metadata:
Expand Down Expand Up @@ -148,13 +149,19 @@ const getWhereClause = index => {
*/
const getWithClause = index => {
const deferBuild = get(index, 'withOptions.defer_build') ? `"defer_build":true` : '';

const numReplica = !isEmpty(get(index, 'withOptions.num_replica'))
? `"num_replica":${index.withOptions.num_replica}`
: '';
const nodes = get(index, 'withOptions.nodes', []).length
? `"nodes":[${joinStatements({ statements: index.withOptions.nodes.map(node => `"${node.nodeName}"`), separator: ',' })}]`
: '';

const nodeStatement = joinStatements({
statements: index.withOptions?.nodes?.map(node => `"${node.nodeName}"`),
separator: ',',
});
const nodes = get(index, 'withOptions.nodes', []).length ? `"nodes":[${nodeStatement}]` : '';

const hasWithClosure = deferBuild || numReplica || nodes;

const withClosure = joinStatements({ statements: [deferBuild, numReplica, nodes], separator: ',' });

return hasWithClosure ? `WITH{${withClosure}}` : '';
Expand Down Expand Up @@ -190,13 +197,14 @@ const getOrder = order => {
*/
const getPartitionByHashClause = index => {
switch (index.partitionByHash) {
case 'Keys':
case 'Keys': {
const keysNames = joinStatements({
statements: index.partitionByHashKeys.map(key => wrapWithBackticks(key.name)),
separator: ',',
});

return `PARTITION BY HASH(${keysNames})`;
}
case 'Expression':
return `PARTITION BY HASH(${index.partitionByHashExpr})`;
default:
Expand All @@ -209,8 +217,13 @@ const getPartitionByHashClause = index => {
* @param {string} statement
* @returns {string}
*/
const commentStatement = statement =>
`/*\n${joinStatements({ statements: statement.split('\n').map(line => ` * ${line}`), separator: '\n' })}\n */`;
const commentStatement = statement => {
const joinedStatement = joinStatements({
statements: statement.split('\n').map(line => ` * ${line}`),
separator: '\n',
});
return `/*\n${joinedStatement}\n */`;
};

module.exports = {
getIndexesScript,
Expand Down
31 changes: 27 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion reverse_engineering/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ const getDbCollectionsData = async (data, appLogger, callback, app) => {
});

try {
const connectionInfo = data.connectionInfo;
const connectionInfo = data;
const includeEmptyCollection = data.includeEmptyCollection;
const bucketName = data.database;
const collections = data.collectionData.collections;
Expand Down
9 changes: 5 additions & 4 deletions reverse_engineering/helpers/indexHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const restApiHelper = require('./restApiHelper');
const clusterHelper = require('../../shared/helpers/clusterHelper');
const parserHelper = require('./parserHelper');
const { GET_META_REGEXP, GET_PARTITION_HASH_REGEXP, DEFAULT_NAME } = require('../../shared/constants');
const { INDEX_TYPE } = require('../../shared/enums/indexType');

const handleIndex = index => {
const indexData = getHackoladeCompatibleIndex(index);
Expand All @@ -13,21 +14,21 @@ const getHackoladeCompatibleIndex = index => {
if (index.is_primary) {
return {
indxName: index.name,
indxType: 'Primary',
indxType: INDEX_TYPE.primary,
usingGSI: index.using === 'gsi',
};
} else if (checkArrayIndex(index)) {
return {
indxName: index.name,
indxType: 'Array',
indxType: INDEX_TYPE.array,
usingGSI: index.using === 'gsi',
arrayExpr: index.index_key.map(getExpression).join(','),
whereClause: getWhereCondition(index),
};
} else if (checkMetaIndex(index)) {
return {
indxName: index.name,
indxType: 'Metadata',
indxType: INDEX_TYPE.metadata,
metadataExpr: index.index_key.map(getExpression).join(','),
};
} else {
Expand All @@ -36,7 +37,7 @@ const getHackoladeCompatibleIndex = index => {

return {
indxName: index.name,
indxType: 'Secondary',
indxType: INDEX_TYPE.secondary,
usingGSI: index.using === 'gsi',
indxKey: keys,
functionExpr: expression,
Expand Down
38 changes: 35 additions & 3 deletions reverse_engineering/helpers/queryHelper.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const { isEmpty } = require('lodash');
const { NUM_SAMPLE_VALUES } = require('../../shared/constants');
const { INDEX_TYPE } = require('../../shared/enums/indexType');

/**
* @param {{ bucketName: string; scopeName: string; collectionName: string; limit: number }} param0
Expand All @@ -18,11 +20,41 @@ const getSelectBucketDocumentsQuery = ({ bucketName, limit, offset }) => {
};

/**
* @param {{ bucketName: string; scopeName: string; collectionName: string; limit: number; offset: number }} param0
* @param {{ collectionIndexes: object[] }} param0
* @returns {string}
*/
const getSelectCollectionDocumentsQuery = ({ bucketName, scopeName, collectionName, limit, offset }) => {
const query = `SELECT *, META().id AS docid FROM \`${bucketName}\`.\`${scopeName}\`.\`${collectionName}\` AS \`${bucketName}\``;
const getWhereClauseFromIndexes = ({ collectionIndexes }) => {
// primary index allows to `select` the document id without extra WHERE clause
const primaryIndex = collectionIndexes.find(index => index.indxType === INDEX_TYPE.primary);

if (isEmpty(collectionIndexes) || primaryIndex) {
return '';
}

return `WHERE ${collectionIndexes[0].indxKey[0].name} LIKE '%'`;
};

/**
* @param {{
* bucketName: string;
* scopeName: string;
* collectionName: string;
* collectionIndexes: object[];
* limit: number;
* offset: number
* }} param0
* @returns {string}
*/
const getSelectCollectionDocumentsQuery = ({
bucketName,
scopeName,
collectionName,
collectionIndexes,
limit,
offset,
}) => {
const whereClause = getWhereClauseFromIndexes({ collectionIndexes });
const query = `SELECT *, META().id AS docid FROM \`${bucketName}\`.\`${scopeName}\`.\`${collectionName}\` AS \`${bucketName}\` ${whereClause}`;
return getQueryOptions({ query, limit, offset });
};

Expand Down
4 changes: 2 additions & 2 deletions reverse_engineering/helpers/restApiHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ class CouchbaseRestApiService {
Authorization: `Basic ${encodedCredentials}`,
},
};

return hckFetch(uri, options);
const response = await hckFetch(uri, options);
return await response.json();
} catch (error) {
throw new CustomError({
message: error.statusText || error.message,
Expand Down
2 changes: 1 addition & 1 deletion shared/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const COUCHBASE_DEFAULT_KV_CONNECTION_PORT = 11210;
const DISABLED_TOOLTIP = 'Something went wrong. Please, check logs for more details';

const GET_META_REGEXP = /\(meta\(\)\.(.*?)\)/;
const GET_NODES_REGEXP = /"nodes":(\[.*?\])/;
const GET_NODES_REGEXP = /"nodes":(\[.*?])/;
const GET_PARTITION_HASH_REGEXP = /(HASH|hash)\((.*?)\)$/;

/**
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
7 changes: 6 additions & 1 deletion shared/helpers/clusterHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,12 @@ const getDbCollectionData = async ({
logger,
});
const options = { limit, pagination: data.pagination, bucketName, scopeName, collectionName };
const query = queryHelper.getSelectCollectionDocumentsQuery({ bucketName, scopeName, collectionName });
const query = queryHelper.getSelectCollectionDocumentsQuery({
bucketName,
scopeName,
collectionName,
collectionIndexes,
});
const documents = await getPaginatedQuery({ cluster, options, query, logger });
const standardDocument = await getCollectionDocumentByDocumentId({
cluster,
Expand Down
Loading