Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ChangeType } from "@firebaseextensions/firestore-bigquery-change-tracker";
import { FIRESTORE_DEFAULT_DATABASE } from "../src/config";
import { getRowsFromDocs } from "../src/helper";

describe("getRowsFromDocs", () => {
Expand All @@ -20,6 +21,7 @@ describe("getRowsFromDocs", () => {
projectId: "test-project",
sourceCollectionPath: "users",
queryCollectionGroup: false,
firestoreInstanceId: FIRESTORE_DEFAULT_DATABASE,
} as any;

const beforeTimestamp = new Date().toISOString();
Expand Down Expand Up @@ -62,6 +64,7 @@ describe("getRowsFromDocs", () => {
projectId: "test-project",
sourceCollectionPath: "regions/{regionId}/countries/{countryId}/cities",
queryCollectionGroup: false,
firestoreInstanceId: FIRESTORE_DEFAULT_DATABASE,
} as any;

const result = getRowsFromDocs(mockDocs, mockConfig);
Expand Down Expand Up @@ -99,6 +102,7 @@ describe("getRowsFromDocs", () => {
projectId: "test-project",
sourceCollectionPath: "my/{testId}/collection",
queryCollectionGroup: false,
firestoreInstanceId: FIRESTORE_DEFAULT_DATABASE,
} as any;

const result = getRowsFromDocs(mockDocs, mockConfig);
Expand Down Expand Up @@ -153,6 +157,7 @@ describe("getRowsFromDocs", () => {
projectId: "test-project",
sourceCollectionPath: "organizations/{orgId}/users", // Template path
queryCollectionGroup: true,
firestoreInstanceId: FIRESTORE_DEFAULT_DATABASE,
} as any;

const result = getRowsFromDocs(mockDocs, mockConfig);
Expand Down Expand Up @@ -217,6 +222,7 @@ describe("getRowsFromDocs", () => {
projectId: "test-project",
sourceCollectionPath: "my/{coolId}/collection",
queryCollectionGroup: true,
firestoreInstanceId: FIRESTORE_DEFAULT_DATABASE,
} as any;

const myResult = getRowsFromDocs(mockDocs, myConfig);
Expand All @@ -233,6 +239,7 @@ describe("getRowsFromDocs", () => {
projectId: "test-project",
sourceCollectionPath: "my_other/{coolId}/collection",
queryCollectionGroup: true,
firestoreInstanceId: FIRESTORE_DEFAULT_DATABASE,
} as any;

const myOtherResult = getRowsFromDocs(mockDocs, myOtherConfig);
Expand Down Expand Up @@ -291,6 +298,7 @@ describe("getRowsFromDocs", () => {
projectId: "test-project",
sourceCollectionPath: "my_other/{coolId}/collection",
queryCollectionGroup: true,
firestoreInstanceId: FIRESTORE_DEFAULT_DATABASE,
} as any;

const myOtherResult = getRowsFromDocs(mockDocs, myOtherConfig);
Expand All @@ -305,6 +313,7 @@ describe("getRowsFromDocs", () => {
projectId: "test-project",
sourceCollectionPath: "my/{coolId}/collection",
queryCollectionGroup: true,
firestoreInstanceId: FIRESTORE_DEFAULT_DATABASE,
} as any;

const myResult = getRowsFromDocs(mockDocs, myConfig);
Expand All @@ -328,4 +337,67 @@ describe("getRowsFromDocs", () => {
expect(row.documentName).toContain("/my/");
});
});

it("uses non-default Firestore database ID in document_name when specified", () => {
const mockDocs = [
{
id: "doc1",
ref: {
path: "posts/doc1",
},
data: () => ({
title: "Test Post",
}),
},
] as any[];

// Test with non-default database ID
const mockConfig = {
projectId: "test-project",
sourceCollectionPath: "posts",
queryCollectionGroup: false,
firestoreInstanceId: "alpha",
} as any;

const result = getRowsFromDocs(mockDocs, mockConfig);

expect(result).toHaveLength(1);
expect(result[0].documentName).toBe(
"projects/test-project/databases/alpha/documents/posts/doc1"
);
expect(result[0].documentId).toBe("doc1");
});

it("uses non-default Firestore database ID in collection group queries", () => {
const mockDocs = [
{
id: "doc1",
ref: {
path: "organizations/org1/posts/doc1",
},
data: () => ({
title: "Test Post",
}),
},
] as any[];

// Test with non-default database ID and collection group query
const mockConfig = {
projectId: "test-project",
sourceCollectionPath: "organizations/{orgId}/posts",
queryCollectionGroup: true,
firestoreInstanceId: "alpha",
} as any;

const result = getRowsFromDocs(mockDocs, mockConfig);

expect(result).toHaveLength(1);
expect(result[0].documentName).toBe(
"projects/test-project/databases/alpha/documents/organizations/org1/posts/doc1"
);
expect(result[0].documentId).toBe("doc1");
expect(result[0].pathParams).toEqual({
orgId: "org1",
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { runMultiThread } from "../src/run-multi-thread";
import * as admin from "firebase-admin";
import { CliConfig } from "../src/types";
import * as workerpool from "workerpool";
import { FIRESTORE_DEFAULT_DATABASE } from "../src/config";

// Mock Firebase Admin to avoid credential issues
jest.mock("firebase-admin", () => {
Expand Down Expand Up @@ -124,6 +125,7 @@ describe("Multi-threaded Collection Group Bug Reproduction", () => {
useEmulator: false,
rawChangeLogName: "old_data_raw_changelog",
cursorPositionFile: "/tmp/test_cursor_position",
firestoreInstanceId: FIRESTORE_DEFAULT_DATABASE,
};
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { runMultiThread } from "../src/run-multi-thread";
import * as admin from "firebase-admin";
import { CliConfig } from "../src/types";
import * as workerpool from "workerpool";
import { FIRESTORE_DEFAULT_DATABASE } from "../src/config";

// Initialize Firebase Admin (Ensure credentials are set)
if (admin.apps.length === 0) {
Expand Down Expand Up @@ -86,6 +87,7 @@ describe("runMultiThread Partitioning with Firestore", () => {
useEmulator: false,
rawChangeLogName: "testTable_raw_changelog",
cursorPositionFile: "/tmp/test_cursor_position",
firestoreInstanceId: FIRESTORE_DEFAULT_DATABASE,
};
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { runMultiThread } from "../src/run-multi-thread";
import * as workerpool from "workerpool";
import { CliConfig } from "../src/types";
import { cpus } from "os";
import { FIRESTORE_DEFAULT_DATABASE } from "../src/config";

// Mock helper functions
jest.mock("../src/helper", () => ({
Expand Down Expand Up @@ -97,6 +98,7 @@ describe("runMultiThread", () => {
useEmulator: false,
rawChangeLogName: "testTable_raw_changelog",
cursorPositionFile: "/tmp/cursor",
firestoreInstanceId: FIRESTORE_DEFAULT_DATABASE,
};
});

Expand Down
2 changes: 2 additions & 0 deletions firestore-bigquery-export/scripts/import/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import * as inquirer from "inquirer";

import { CliConfig, CliConfigError } from "./types";

export const FIRESTORE_DEFAULT_DATABASE = "(default)";

const BIGQUERY_VALID_CHARACTERS = /^[a-zA-Z0-9_]+$/;
// regex of ^[^/]+(/[^/]+/[^/]+)*$
export const FIRESTORE_VALID_CHARACTERS = new RegExp("^[^/]+(/[^/]+/[^/]+)*$");
Expand Down
6 changes: 2 additions & 4 deletions firestore-bigquery-export/scripts/import/src/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import * as util from "util";

import { resolveWildcardIds } from "./config";

const FIRESTORE_DEFAULT_DATABASE = "(default)";

// TODO: do we need this logic?
export const initializeDataSink = async (
dataSink: FirestoreBigQueryEventHistoryTracker,
Expand Down Expand Up @@ -78,7 +76,7 @@ export function getRowsFromDocs(
rows.push({
timestamp: new Date().toISOString(), // epoch
operation: ChangeType.IMPORT,
documentName: `projects/${config.projectId}/databases/${FIRESTORE_DEFAULT_DATABASE}/documents/${path}`,
documentName: `projects/${config.projectId}/databases/${config.firestoreInstanceId}/documents/${path}`,
documentId: doc.id,
// TODO: fix this type
// @ts-expect-error
Expand All @@ -96,7 +94,7 @@ export function getRowsFromDocs(
return {
timestamp: new Date().toISOString(), // epoch
operation: ChangeType.IMPORT,
documentName: `projects/${config.projectId}/databases/${FIRESTORE_DEFAULT_DATABASE}/documents/${snapshot.ref.path}`,
documentName: `projects/${config.projectId}/databases/${config.firestoreInstanceId}/documents/${snapshot.ref.path}`,
documentId: snapshot.id,
pathParams: resolveWildcardIds(
config.sourceCollectionPath,
Expand Down
Loading