Skip to content

Commit f929f6d

Browse files
committed
like_pattern
1 parent 957475a commit f929f6d

File tree

2 files changed

+17
-7
lines changed

2 files changed

+17
-7
lines changed

lib/bencher_schema/src/model/project/mod.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl QueryProject {
155155
};
156156
// The choice was either to relax the schema constraint to allow duplicate project names
157157
// or to append a number to the project name to ensure uniqueness.
158-
let name = Self::unique_name(context, &query_organization, project_name).await?;
158+
let name = Self::unique_name(log, context, &query_organization, project_name).await?;
159159
let insert_project =
160160
InsertProject::new(query_organization.id, name, project_slug, None, None);
161161
if let Some(auth_user) = auth_user {
@@ -177,6 +177,7 @@ impl QueryProject {
177177
}
178178

179179
async fn unique_name(
180+
log: &Logger,
180181
context: &ApiContext,
181182
query_organization: &QueryOrganization,
182183
project_name: ResourceName,
@@ -191,20 +192,24 @@ impl QueryProject {
191192
const ELLIPSES_LEN: usize = 3;
192193
// The max length for a `usize` is 20 characters,
193194
// so we don't have to worry about the number suffix being too long.
194-
project_name
195+
let name = project_name
195196
.as_ref()
196197
.chars()
197198
.take(max_name_len - ELLIPSES_LEN)
198199
.chain(".".repeat(ELLIPSES_LEN).chars())
199-
.collect::<String>()
200+
.collect::<String>();
201+
slog::debug!(log, "Truncated project name: {name}");
202+
name
200203
} else {
201204
project_name.to_string()
202205
};
203206

204-
// Escape the project name for use in a regex pattern
205-
let escaped_name = regex::escape(&name_str);
207+
// Escape the project name for use in a LIKE pattern
208+
// https://www.sqlite.org/lang_expr.html#the_like_glob_regexp_match_and_extract_operators
209+
let escaped_name = name_str.replace('%', r"\%").replace('_', r"\_");
206210
// Create a regex pattern to match the original project name or any subsequent projects with the same name
207-
let pattern = format!(r"^{escaped_name} \(\d+\)$");
211+
let pattern = format!(r"{escaped_name} (%)");
212+
slog::debug!(log, "LIKE pattern: {pattern}");
208213

209214
let Ok(highest_name) = schema::project::table
210215
.filter(schema::project::organization_id.eq(query_organization.id))
@@ -218,10 +223,12 @@ impl QueryProject {
218223
.first::<ResourceName>(conn_lock!(context))
219224
else {
220225
// The project name is already unique
226+
slog::debug!(log, "Project name is unique: {project_name}");
221227
return Ok(project_name);
222228
};
223229

224230
let next_number = if highest_name == project_name {
231+
slog::debug!(log, "First project name duplicate: {highest_name}");
225232
1
226233
} else if let Some(caps) = UNIQUE_SUFFIX.captures(highest_name.as_ref()) {
227234
let last_number: usize = caps
@@ -234,6 +241,7 @@ impl QueryProject {
234241
highest_name,
235242
)
236243
})?;
244+
slog::debug!(log, "Multiple project name duplicates: {last_number}");
237245
last_number + 1
238246
} else {
239247
return Err(issue_error(
@@ -244,6 +252,7 @@ impl QueryProject {
244252
};
245253

246254
let name_with_suffix = format!("{name_str} ({next_number})");
255+
slog::debug!(log, "Unique project name: {name_with_suffix}");
247256
name_with_suffix.parse().map_err(|e| {
248257
issue_error(
249258
"Failed to create new project name",

tasks/test_api/src/task/test/seed_test.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1402,7 +1402,8 @@ impl SeedTest {
14021402
);
14031403
assert_eq!(
14041404
json.project.slug.as_ref().len(),
1405-
REPO_NAME.len() + 1 + 7 + 1 + 13
1405+
REPO_NAME.len() + 1 + 7 + 1 + 13,
1406+
"{json:?}"
14061407
);
14071408
assert_eq!(json.project.claimed, None);
14081409
anonymous_project.replace(json.project);

0 commit comments

Comments
 (0)