mirror of
https://github.com/beekeeper-studio/beekeeper-studio.git
synced 2026-03-13 10:12:54 +08:00
Merge pull request #2853 from beekeeper-studio/rc-51
Rc 51 merge back into master
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "beekeeper-studio",
|
||||
"version": "5.1.4",
|
||||
"version": "5.1.5",
|
||||
"private": true,
|
||||
"description": "An easy-to use SQL query editor and database UI for Mac, Windows, and Linux",
|
||||
"author": {
|
||||
|
||||
@@ -522,7 +522,7 @@ export class DuckDBClient extends BasicDatabaseClient<DuckDBResult> {
|
||||
return rows.map((row) => row.schema_name as string);
|
||||
}
|
||||
|
||||
async getTableReferences(_table: string, _schema: string): Promise<string[]> {
|
||||
async getTableReferences(table: string, schema: string): Promise<string[]> {
|
||||
const { rows } = await this.driverExecuteSingle(`
|
||||
WITH cte AS (
|
||||
SELECT rc.unique_constraint_name AS unique_constraint_name
|
||||
@@ -532,14 +532,14 @@ export class DuckDBClient extends BasicDatabaseClient<DuckDBResult> {
|
||||
JOIN information_schema.table_constraints tc
|
||||
ON rc.constraint_name = tc.constraint_name
|
||||
WHERE tc.constraint_type = 'FOREIGN KEY'
|
||||
AND tc.table_schema = 'main'
|
||||
AND tc.table_name = 'dept_emp'
|
||||
AND tc.table_schema = ?
|
||||
AND tc.table_name = ?
|
||||
)
|
||||
SELECT kc.table_name
|
||||
FROM cte
|
||||
JOIN information_schema.key_column_usage kc
|
||||
ON cte.unique_constraint_name = kc.constraint_name
|
||||
`);
|
||||
`, { params: [schema || await this.defaultSchema(), table] });
|
||||
return rows.map((row) => row.table_name as string);
|
||||
}
|
||||
|
||||
@@ -1062,8 +1062,6 @@ export class DuckDBClient extends BasicDatabaseClient<DuckDBResult> {
|
||||
// took this approach because Typescript wasn't liking the base function could be a null value or a function
|
||||
createUpsertSQL({ name: tableName }: DatabaseEntity, data: {[key: string]: any}[]): string {
|
||||
const [firstObj] = data
|
||||
console.log('~~~ what is that data yo? ~~~')
|
||||
console.log(data)
|
||||
const columns = Object.keys(firstObj)
|
||||
const values = data.map(d => `(${columns.map(c => `'${d[c]}'`).join()})`).join()
|
||||
return `INSERT OR REPLACE \`${tableName}\`, (${columns.map(cpk => `\`${cpk}\``).join(', ')}) VALUES ${values}`.trim()
|
||||
|
||||
@@ -312,7 +312,7 @@ export class SavedConnection extends DbConnectionBase implements IConnection {
|
||||
if(options.find((e) => url.endsWith(e))) {
|
||||
this.connectionType = connectionType as any
|
||||
this.defaultDatabase = url
|
||||
return
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export interface Version {
|
||||
* ```
|
||||
**/
|
||||
export function parseVersion(version: string) {
|
||||
const versionTagRegex = /^(\d+)\.(\d+)\.(\d+)$/;
|
||||
const versionTagRegex = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/;
|
||||
const match = versionTagRegex.exec(version) || [];
|
||||
const [major, minor, patch] = _.tail(match).map((x) => parseInt(x));
|
||||
return { major, minor, patch };
|
||||
@@ -23,9 +23,14 @@ export function parseVersion(version: string) {
|
||||
|
||||
/** Check if version a is less than or equal to version b */
|
||||
export function isVersionLessThanOrEqual(a: Version, b: Version) {
|
||||
if (a.major > b.major) return false;
|
||||
if (a.minor > b.minor) return false;
|
||||
if (a.patch > b.patch) return false;
|
||||
return true;
|
||||
if (a.major > b.major) return false
|
||||
if (a.major === b.major) {
|
||||
if (a.minor > b.minor) return false;
|
||||
if (a.minor === b.minor && a.patch > b.patch) return false
|
||||
return true
|
||||
} else { // a.major < b.major
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import "codemirror/addon/display/autorefresh";
|
||||
import "codemirror/addon/comment/comment";
|
||||
import "codemirror/addon/dialog/dialog";
|
||||
import "codemirror/addon/search/search";
|
||||
@@ -207,6 +208,7 @@ export default {
|
||||
indicatorFolded.innerHTML = `<i class="dropdown-icon material-icons">keyboard_arrow_right</i>`;
|
||||
|
||||
const cm = CodeMirror.fromTextArea(this.$refs.editor, {
|
||||
autoRefresh: true,
|
||||
lineNumbers: this.lineNumbers ?? true,
|
||||
tabSize: 2,
|
||||
theme: "monokai",
|
||||
|
||||
@@ -120,8 +120,10 @@ export const LicenseModule: Module<State, RootState> = {
|
||||
await context.dispatch('sync')
|
||||
},
|
||||
async update(_context, license: TransportLicenseKey) {
|
||||
// This is to allow for dev switching
|
||||
const isDevUpdate = window.platformInfo.isDevelopment && license.email == "fake_email";
|
||||
try {
|
||||
const data = await CloudClient.getLicense(window.platformInfo.cloudUrl, license.email, license.key)
|
||||
const data = isDevUpdate ? license : await CloudClient.getLicense(window.platformInfo.cloudUrl, license.email, license.key)
|
||||
license.validUntil = new Date(data.validUntil)
|
||||
license.supportUntil = new Date(data.supportUntil)
|
||||
license.maxAllowedAppRelease = data.maxAllowedAppRelease
|
||||
|
||||
@@ -140,6 +140,64 @@ function testWith(options: typeof TEST_VERSIONS[number]) {
|
||||
await util.knex.schema.raw("DROP INDEX col_exp_test_idx");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Table References Tests", () => {
|
||||
beforeAll(async () => {
|
||||
// Create parent and child tables with foreign key relationships
|
||||
await util.knex.schema.raw(`
|
||||
CREATE TABLE departments (
|
||||
department_id INT PRIMARY KEY,
|
||||
department_name VARCHAR(100)
|
||||
)
|
||||
`);
|
||||
|
||||
await util.knex.schema.raw(`
|
||||
CREATE TABLE employees (
|
||||
employee_id INT PRIMARY KEY,
|
||||
department_id INT,
|
||||
employee_name VARCHAR(100),
|
||||
FOREIGN KEY (department_id) REFERENCES departments(department_id)
|
||||
)
|
||||
`);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await util.knex.schema.dropTableIfExists("employees");
|
||||
await util.knex.schema.dropTableIfExists("departments");
|
||||
});
|
||||
|
||||
it("should get table references correctly", async () => {
|
||||
// This test may be skipped since it depends on DuckDB's capabilities
|
||||
// The implementation returns empty results if not supported
|
||||
try {
|
||||
const references = await util.connection.getTableReferences("departments", "main");
|
||||
expect(Array.isArray(references)).toBe(true);
|
||||
// Note: DuckDB may not fully support foreign key constraints in a way that
|
||||
// allows listing references, so the actual result may be empty
|
||||
} catch (e) {
|
||||
console.warn("DuckDB getTableReferences test skipped due to DuckDB limitations");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("Upsert SQL Tests", () => {
|
||||
it("should create correct upsert SQL", async () => {
|
||||
const entity = { name: "test_table" };
|
||||
const data = [
|
||||
{ id: 1, name: "Test 1" },
|
||||
{ id: 2, name: "Test 2" }
|
||||
];
|
||||
|
||||
// Access the client directly to test the createUpsertSQL method
|
||||
// @ts-ignore - Accessing private method for testing
|
||||
const sql = util.connection.createUpsertSQL(entity, data);
|
||||
|
||||
expect(sql).toContain("INSERT OR REPLACE");
|
||||
expect(sql).toContain("`test_table`");
|
||||
expect(sql).toContain("`id`, `name`");
|
||||
expect(sql).toContain("('1','Test 1'),('2','Test 2')");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -67,6 +67,11 @@ describe("License", () => {
|
||||
expect(isVersionLessThanOrEqual(v`1.2.1`, v`1.2.3`)).toBe(true);
|
||||
expect(isVersionLessThanOrEqual(v`1.2.3`, v`1.0.0`)).toBe(false);
|
||||
expect(isVersionLessThanOrEqual(v`1.3.2`, v`1.2.3`)).toBe(false);
|
||||
|
||||
expect(isVersionLessThanOrEqual(v`1.99.99`, v`2.2.3`)).toBe(true);
|
||||
expect(isVersionLessThanOrEqual(v`1.1.99`, v`1.2.3`)).toBe(true);
|
||||
expect(isVersionLessThanOrEqual(v`1.1.99-beta.1`, v`1.1.99-beta.2`)).toBe(true);
|
||||
expect(isVersionLessThanOrEqual(v`1.1.99`, v`1.2.0-beta.1`)).toBe(true);
|
||||
});
|
||||
|
||||
describe("License status", () => {
|
||||
@@ -163,5 +168,14 @@ describe("License", () => {
|
||||
condition: ["Expired support date", "App version not allowed"],
|
||||
});
|
||||
})
|
||||
|
||||
// Regression tests for version comparison
|
||||
it("Should properly compare versions", async () => {
|
||||
expect(isVersionLessThanOrEqual(parseVersion("v2.4.6"), parseVersion("v5.7.2"))).toBeTruthy();
|
||||
expect(isVersionLessThanOrEqual(parseVersion("v2.5.1-beta.4"), parseVersion("v5.0.0"))).toBeTruthy();
|
||||
expect(isVersionLessThanOrEqual(parseVersion("v6.3.7"), parseVersion("v4.2.1"))).not.toBeTruthy;
|
||||
expect(isVersionLessThanOrEqual(parseVersion("v3.1.3-beta.4"), parseVersion("v1.8.1"))).not.toBeTruthy();
|
||||
expect(isVersionLessThanOrEqual(parseVersion("v5.0.0"), parseVersion("v5.0.0"))).toBeTruthy();
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user