mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-07-01 18:52:20 +08:00
parent
a00dcb78cb
commit
b6d83503c3
@ -40,6 +40,25 @@ describe('uuid field', () => {
|
||||
expect(item['uuid']).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
|
||||
});
|
||||
|
||||
it('should filter uuid field', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
fields: [{ type: 'uuid', name: 'uuid' }],
|
||||
});
|
||||
|
||||
await Test.sync();
|
||||
|
||||
const item1 = await Test.model.create();
|
||||
|
||||
const result = await Test.repository.find({
|
||||
filter: {
|
||||
uuid: { $includes: [item1['uuid']] },
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should set autofill attribute', async () => {
|
||||
const Test = db.collection({
|
||||
name: 'tests',
|
||||
|
@ -7,13 +7,75 @@
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { Op } from 'sequelize';
|
||||
import { Op, cast, where, col, Sequelize } from 'sequelize';
|
||||
import { isPg } from './utils';
|
||||
|
||||
function escapeLike(value: string) {
|
||||
return value.replace(/[_%]/g, '\\$&');
|
||||
}
|
||||
|
||||
const getFieldName = (ctx) => {
|
||||
const fullNameSplit = ctx.fullName.split('.');
|
||||
const fieldName = ctx.fieldName;
|
||||
let columnName = fieldName;
|
||||
const associationPath = [];
|
||||
if (fullNameSplit.length > 1) {
|
||||
for (let i = 0; i < fullNameSplit.length - 1; i++) {
|
||||
associationPath.push(fullNameSplit[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const getModelFromAssociationPath = () => {
|
||||
let model = ctx.model;
|
||||
for (const association of associationPath) {
|
||||
model = model.associations[association].target;
|
||||
}
|
||||
|
||||
return model;
|
||||
};
|
||||
|
||||
const model = getModelFromAssociationPath();
|
||||
|
||||
let columnPrefix = model.name;
|
||||
|
||||
if (model.rawAttributes[fieldName]) {
|
||||
columnName = model.rawAttributes[fieldName].field || fieldName;
|
||||
}
|
||||
|
||||
if (associationPath.length > 0) {
|
||||
const association = associationPath.join('->');
|
||||
columnPrefix = association;
|
||||
}
|
||||
|
||||
columnName = `${columnPrefix}.${columnName}`;
|
||||
return columnName;
|
||||
};
|
||||
|
||||
// Helper function to handle field casting for PostgreSQL
|
||||
function getFieldExpression(value, ctx, operator) {
|
||||
if (isPg(ctx)) {
|
||||
const fieldName = getFieldName(ctx);
|
||||
const queryInterface = ctx.db.sequelize.getQueryInterface();
|
||||
const quotedField = queryInterface.quoteIdentifiers(fieldName);
|
||||
|
||||
return Sequelize.literal(`CAST(${quotedField} AS TEXT) ${operator} ${ctx.db.sequelize.escape(value)}`);
|
||||
}
|
||||
|
||||
// For MySQL and other databases, return the operator directly
|
||||
const op =
|
||||
operator === 'LIKE'
|
||||
? Op.like
|
||||
: operator === 'NOT LIKE'
|
||||
? Op.notLike
|
||||
: operator === 'ILIKE'
|
||||
? Op.like
|
||||
: operator === 'NOT ILIKE'
|
||||
? Op.notLike
|
||||
: Op.like;
|
||||
|
||||
return { [op]: value };
|
||||
}
|
||||
|
||||
export default {
|
||||
$includes(value, ctx) {
|
||||
if (value === null) {
|
||||
@ -22,18 +84,16 @@ export default {
|
||||
};
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
const conditions = value.map((item) => ({
|
||||
[isPg(ctx) ? Op.iLike : Op.like]: `%${escapeLike(item)}%`,
|
||||
}));
|
||||
const conditions = value.map((item) =>
|
||||
getFieldExpression(`%${escapeLike(item)}%`, ctx, isPg(ctx) ? 'ILIKE' : 'LIKE'),
|
||||
);
|
||||
|
||||
return {
|
||||
[Op.or]: conditions,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
[isPg(ctx) ? Op.iLike : Op.like]: `%${escapeLike(value)}%`,
|
||||
};
|
||||
return getFieldExpression(`%${escapeLike(value)}%`, ctx, isPg(ctx) ? 'ILIKE' : 'LIKE');
|
||||
},
|
||||
|
||||
$notIncludes(value, ctx) {
|
||||
@ -43,81 +103,71 @@ export default {
|
||||
};
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
const conditions = value.map((item) => ({
|
||||
[isPg(ctx) ? Op.notILike : Op.notLike]: `%${escapeLike(item)}%`,
|
||||
}));
|
||||
const conditions = value.map((item) =>
|
||||
getFieldExpression(`%${escapeLike(item)}%`, ctx, isPg(ctx) ? 'NOT ILIKE' : 'NOT LIKE'),
|
||||
);
|
||||
|
||||
return {
|
||||
[Op.and]: conditions,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
[isPg(ctx) ? Op.notILike : Op.notLike]: `%${escapeLike(value)}%`,
|
||||
};
|
||||
return getFieldExpression(`%${escapeLike(value)}%`, ctx, isPg(ctx) ? 'NOT ILIKE' : 'NOT LIKE');
|
||||
},
|
||||
|
||||
$startsWith(value, ctx) {
|
||||
if (Array.isArray(value)) {
|
||||
const conditions = value.map((item) => ({
|
||||
[isPg(ctx) ? Op.iLike : Op.like]: `${escapeLike(item)}%`,
|
||||
}));
|
||||
const conditions = value.map((item) =>
|
||||
getFieldExpression(`${escapeLike(item)}%`, ctx, isPg(ctx) ? 'ILIKE' : 'LIKE'),
|
||||
);
|
||||
|
||||
return {
|
||||
[Op.or]: conditions,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
[isPg(ctx) ? Op.iLike : Op.like]: `${escapeLike(value)}%`,
|
||||
};
|
||||
return getFieldExpression(`${escapeLike(value)}%`, ctx, isPg(ctx) ? 'ILIKE' : 'LIKE');
|
||||
},
|
||||
|
||||
$notStartsWith(value, ctx) {
|
||||
if (Array.isArray(value)) {
|
||||
const conditions = value.map((item) => ({
|
||||
[isPg(ctx) ? Op.notILike : Op.notLike]: `${escapeLike(item)}%`,
|
||||
}));
|
||||
const conditions = value.map((item) =>
|
||||
getFieldExpression(`${escapeLike(item)}%`, ctx, isPg(ctx) ? 'NOT ILIKE' : 'NOT LIKE'),
|
||||
);
|
||||
|
||||
return {
|
||||
[Op.and]: conditions,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
[isPg(ctx) ? Op.notILike : Op.notLike]: `${escapeLike(value)}%`,
|
||||
};
|
||||
return getFieldExpression(`${escapeLike(value)}%`, ctx, isPg(ctx) ? 'NOT ILIKE' : 'NOT LIKE');
|
||||
},
|
||||
|
||||
$endWith(value, ctx) {
|
||||
if (Array.isArray(value)) {
|
||||
const conditions = value.map((item) => ({
|
||||
[isPg(ctx) ? Op.iLike : Op.like]: `%${escapeLike(item)}`,
|
||||
}));
|
||||
const conditions = value.map((item) =>
|
||||
getFieldExpression(`%${escapeLike(item)}`, ctx, isPg(ctx) ? 'ILIKE' : 'LIKE'),
|
||||
);
|
||||
|
||||
return {
|
||||
[Op.or]: conditions,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
[isPg(ctx) ? Op.iLike : Op.like]: `%${escapeLike(value)}`,
|
||||
};
|
||||
return getFieldExpression(`%${escapeLike(value)}`, ctx, isPg(ctx) ? 'ILIKE' : 'LIKE');
|
||||
},
|
||||
|
||||
$notEndWith(value, ctx) {
|
||||
if (Array.isArray(value)) {
|
||||
const conditions = value.map((item) => ({
|
||||
[isPg(ctx) ? Op.notILike : Op.notLike]: `%${escapeLike(item)}`,
|
||||
}));
|
||||
const conditions = value.map((item) =>
|
||||
getFieldExpression(`%${escapeLike(item)}`, ctx, isPg(ctx) ? 'NOT ILIKE' : 'NOT LIKE'),
|
||||
);
|
||||
|
||||
return {
|
||||
[Op.and]: conditions,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
[isPg(ctx) ? Op.notILike : Op.notLike]: `%${escapeLike(value)}`,
|
||||
};
|
||||
return getFieldExpression(`%${escapeLike(value)}`, ctx, isPg(ctx) ? 'NOT ILIKE' : 'NOT LIKE');
|
||||
},
|
||||
} as Record<string, any>;
|
||||
|
Loading…
x
Reference in New Issue
Block a user