mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
fix: SQLite simple-enum column parsing (#10550)
This commit is contained in:
parent
a4900ae15f
commit
696e688d00
@ -1453,20 +1453,10 @@ export abstract class AbstractSqliteQueryRunner
|
||||
}
|
||||
|
||||
if (tableColumn.type === "varchar") {
|
||||
// Check if this is an enum
|
||||
const enumMatch = sql.match(
|
||||
new RegExp(
|
||||
'"(' +
|
||||
tableColumn.name +
|
||||
")\" varchar CHECK\\s*\\(\\s*\"\\1\"\\s+IN\\s*\\(('[^']+'(?:\\s*,\\s*'[^']+')+)\\s*\\)\\s*\\)",
|
||||
),
|
||||
tableColumn.enum = OrmUtils.parseSqlCheckExpression(
|
||||
sql,
|
||||
tableColumn.name,
|
||||
)
|
||||
if (enumMatch) {
|
||||
// This is an enum
|
||||
tableColumn.enum = enumMatch[2]
|
||||
.substr(1, enumMatch[2].length - 2)
|
||||
.split("','")
|
||||
}
|
||||
}
|
||||
|
||||
// parse datatype and attempt to retrieve length, precision and scale
|
||||
|
||||
@ -340,6 +340,81 @@ export class OrmUtils {
|
||||
return !haveSharedObjects
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the CHECK constraint on the specified column and returns
|
||||
* all values allowed by the constraint or undefined if the constraint
|
||||
* is not present.
|
||||
*/
|
||||
static parseSqlCheckExpression(
|
||||
sql: string,
|
||||
columnName: string,
|
||||
): string[] | undefined {
|
||||
const enumMatch = sql.match(
|
||||
new RegExp(
|
||||
`"${columnName}" varchar CHECK\\s*\\(\\s*"${columnName}"\\s+IN\\s*`,
|
||||
),
|
||||
)
|
||||
|
||||
if (enumMatch && enumMatch.index) {
|
||||
const afterMatch = sql.substring(
|
||||
enumMatch.index + enumMatch[0].length,
|
||||
)
|
||||
|
||||
// This is an enum
|
||||
// all enum values stored as a comma separated list
|
||||
const chars = afterMatch
|
||||
|
||||
/**
|
||||
* * When outside quotes: empty string
|
||||
* * When inside single quotes: `'`
|
||||
*/
|
||||
let currentQuotes = ""
|
||||
let nextValue = ""
|
||||
const enumValues: string[] = []
|
||||
for (let idx = 0; idx < chars.length; idx++) {
|
||||
const char = chars[idx]
|
||||
switch (char) {
|
||||
case ",":
|
||||
if (currentQuotes == "") {
|
||||
enumValues.push(nextValue)
|
||||
nextValue = ""
|
||||
} else {
|
||||
nextValue += char
|
||||
}
|
||||
break
|
||||
case "'":
|
||||
if (currentQuotes == char) {
|
||||
const isNextCharQuote = chars[idx + 1] === char
|
||||
if (isNextCharQuote) {
|
||||
// double quote in sql should be treated as a
|
||||
// single quote that's part of the quoted string
|
||||
nextValue += char
|
||||
idx += 1 // skip that next quote
|
||||
} else {
|
||||
currentQuotes = ""
|
||||
}
|
||||
} else {
|
||||
currentQuotes = char
|
||||
}
|
||||
break
|
||||
case ")":
|
||||
if (currentQuotes == "") {
|
||||
enumValues.push(nextValue)
|
||||
return enumValues
|
||||
} else {
|
||||
nextValue += char
|
||||
}
|
||||
break
|
||||
default:
|
||||
if (currentQuotes != "") {
|
||||
nextValue += char
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Private methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
75
test/unit/orm-utils.ts
Normal file
75
test/unit/orm-utils.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import { OrmUtils } from "../../src/util/OrmUtils"
|
||||
import { expect } from "chai"
|
||||
|
||||
describe(`orm-utils`, () => {
|
||||
describe("parseSqlCheckExpression", () => {
|
||||
it("parses a simple CHECK constraint", () => {
|
||||
// Spaces between CHECK values
|
||||
expect(
|
||||
OrmUtils.parseSqlCheckExpression(
|
||||
`CREATE TABLE "foo_table" (
|
||||
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
"col" varchar CHECK("col" IN ('FOO', 'BAR', 'BAZ')) NOT NULL,
|
||||
"some_other_col" integer NOT NULL
|
||||
);`,
|
||||
"col",
|
||||
),
|
||||
).to.have.same.members(["FOO", "BAR", "BAZ"])
|
||||
|
||||
// No spaces between CHECK values
|
||||
expect(
|
||||
OrmUtils.parseSqlCheckExpression(
|
||||
`CREATE TABLE "foo_table" (
|
||||
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
"col" varchar CHECK("col" IN ('FOO','BAR','BAZ')) NOT NULL,
|
||||
"some_other_col" integer NOT NULL
|
||||
);`,
|
||||
"col",
|
||||
),
|
||||
).to.have.same.members(["FOO", "BAR", "BAZ"])
|
||||
})
|
||||
|
||||
it("returns undefined when the column doesn't have a CHECK", () => {
|
||||
expect(
|
||||
OrmUtils.parseSqlCheckExpression(
|
||||
`CREATE TABLE "foo_table" (
|
||||
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
"col" varchar NOT NULL,
|
||||
"some_other_col" integer NOT NULL
|
||||
);`,
|
||||
"col",
|
||||
),
|
||||
).to.equal(undefined)
|
||||
})
|
||||
|
||||
it("parses a CHECK constraint with values containing special characters", () => {
|
||||
expect(
|
||||
OrmUtils.parseSqlCheckExpression(
|
||||
`CREATE TABLE "foo_table" (
|
||||
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
"col" varchar CHECK("col" IN (
|
||||
'a,b',
|
||||
',c,',
|
||||
'd''d',
|
||||
'''e''',
|
||||
'f'',''f',
|
||||
''')',
|
||||
')'''
|
||||
)
|
||||
) NOT NULL,
|
||||
"some_other_col" integer NOT NULL
|
||||
);`,
|
||||
"col",
|
||||
),
|
||||
).to.have.same.members([
|
||||
"a,b",
|
||||
",c,",
|
||||
"d'd",
|
||||
"'e'",
|
||||
"f','f",
|
||||
"')",
|
||||
")'",
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user