Skip to content

Commit 7dbf8d6

Browse files
committed
refactor: implement parseBucketUrl() in baseDriver
1 parent 2e47147 commit 7dbf8d6

File tree

2 files changed

+58
-19
lines changed

2 files changed

+58
-19
lines changed

packages/cubejs-base-driver/src/BaseDriver.ts

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,21 @@ export type GoogleStorageClientConfig = {
9595
credentials: any,
9696
};
9797

98+
export type ParsedBucketUrl = {
99+
/**
100+
* may be 's3', 'wasbs', 'gs', 'azure', etc
101+
*/
102+
schema?: string;
103+
bucketName: string;
104+
/**
105+
* prefix/path without leading and trailing / or empty string if not presented
106+
*/
107+
path: string;
108+
username?: string;
109+
password?: string;
110+
original: string;
111+
};
112+
98113
const sortByKeys = (unordered: any) => {
99114
const ordered: any = {};
100115

@@ -188,7 +203,7 @@ export abstract class BaseDriver implements DriverInterface {
188203
/**
189204
* Class constructor.
190205
*/
191-
public constructor(_options: {
206+
protected constructor(_options: {
192207
/**
193208
* Time to wait for a response from a connection after validation
194209
* request before determining it as not valid. Default - 10000 ms.
@@ -695,6 +710,44 @@ export abstract class BaseDriver implements DriverInterface {
695710
query.query = `SELECT * FROM (${query.query}) AS t LIMIT ${query.limit}`;
696711
}
697712

713+
/**
714+
* Returns parsed bucket structure.
715+
* Supported variants:
716+
* s3://my-bucket-name/prefix/longer/
717+
* s3://my-bucket-name
718+
* my-bucket-name/some-path
719+
* my-bucket-name
720+
*
721+
*/
722+
protected parseBucketUrl(input: string | null | undefined): ParsedBucketUrl {
723+
const original = input?.trim() || '';
724+
725+
if (!original) {
726+
return {
727+
bucketName: '',
728+
path: '',
729+
original,
730+
};
731+
}
732+
733+
const hasSchema = /^[a-zA-Z][a-zA-Z0-9+\-.]*:\/\//.test(original);
734+
const normalized = hasSchema ? original : `schema://${original}`;
735+
736+
const url = new URL(normalized);
737+
738+
const path = url.pathname.replace(/^\/+|\/+$/g, '');
739+
const schema = url.protocol.replace(/:$/, '');
740+
741+
return {
742+
schema: schema || undefined,
743+
bucketName: url.hostname,
744+
path,
745+
username: url.username || undefined,
746+
password: url.password || undefined,
747+
original,
748+
};
749+
}
750+
698751
/**
699752
* Returns an array of signed AWS S3 URLs of the unloaded csv files.
700753
*/

packages/cubejs-clickhouse-driver/src/ClickHouseDriver.ts

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -584,33 +584,19 @@ export class ClickHouseDriver extends BaseDriver implements DriverInterface {
584584
);
585585
}
586586

587-
/**
588-
* Returns clean S3 bucket name and prefix path ending with / (if set)
589-
*/
590-
private parseS3Path(input: string): { bucket: string; prefix: string | null } {
591-
let trimmed = input.startsWith('s3://') ? input.slice(5) : input;
592-
trimmed = trimmed.endsWith('/') ? trimmed.slice(0, -1) : trimmed;
593-
const parts = trimmed.split('/');
594-
const bucket = parts[0];
595-
const prefixParts = parts.slice(1);
596-
const prefix = prefixParts.length > 0 ? `${prefixParts.join('/')}/` : null;
597-
598-
return { bucket, prefix };
599-
}
600-
601587
public async unloadFromQuery(sql: string, params: unknown[], _options: UnloadOptions): Promise<DownloadTableCSVData> {
602588
if (!this.config.exportBucket) {
603589
throw new Error('Unload is not configured');
604590
}
605591

606592
const types = await this.queryColumnTypes(`(${sql})`, params);
607-
const { bucket, prefix } = this.parseS3Path(this.config.exportBucket.bucketName);
608-
const exportPrefix = prefix ? `${prefix}${uuidv4()}` : uuidv4();
593+
const { bucketName, path } = this.parseBucketUrl(this.config.exportBucket.bucketName);
594+
const exportPrefix = path ? `${path}/${uuidv4()}` : uuidv4();
609595

610596
const formattedQuery = sqlstring.format(`
611597
INSERT INTO FUNCTION
612598
s3(
613-
'https://${bucket}.s3.${this.config.exportBucket.region}.amazonaws.com/${exportPrefix}/export.csv.gz',
599+
'https://${bucketName}.s3.${this.config.exportBucket.region}.amazonaws.com/${exportPrefix}/export.csv.gz',
614600
'${this.config.exportBucket.keyId}',
615601
'${this.config.exportBucket.secretKey}',
616602
'CSV'
@@ -628,7 +614,7 @@ export class ClickHouseDriver extends BaseDriver implements DriverInterface {
628614
},
629615
region: this.config.exportBucket.region,
630616
},
631-
bucket,
617+
bucketName,
632618
exportPrefix,
633619
);
634620

0 commit comments

Comments
 (0)