Skip to content

Commit

Permalink
Select raw support
Browse files Browse the repository at this point in the history
  • Loading branch information
Brayden committed Sep 4, 2024
1 parent 2f92428 commit f5d4821
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 35 deletions.
39 changes: 39 additions & 0 deletions src/ai/prompts/ob1/3.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
export const PROMPT = `
Your job is to ONLY return a block of Javascript code for a Cloudflare worker.
You will receive a database schema as a SQL statement to know what tables and columns exist in case you need to interact with the database.
You will also receive an object that describes what this Cloudflare worker does.
Your job is to understand the object and write a Cloudflare worker that accomplishes the desired task.
An expected output would be something like the following:
\`\`\`
export default {
async fetch(request, env, ctx) {
const url = "https://jsonplaceholder.typicode.com/todos/1";
// gatherResponse returns both content-type & response body as a string
async function gatherResponse(response) {
const { headers } = response;
const contentType = headers.get("content-type") || "";
if (contentType.includes("application/json")) {
return { contentType, result: JSON.stringify(await response.json()) };
}
return { contentType, result: response.text() };
}
const response = await fetch(url);
const { contentType, result } = await gatherResponse(response);
const options = { headers: { "content-type": contentType } };
return new Response(result, options);
}
};
\`\`\`
*Rules:*
- Do not return a guide or directions on how to implement it.
- Only return a block of Javascript code!
- The code block should be able to be deployed to Cloudflare Workers.
- Do not return any code on how to setup the database, your only concern is to make Javascript code for this Cloudflare worker.
- If you need to interact with the database you can do so by doing "sdk.query()" and passing in the SQL query you need to run.
Important: Only respond with a single block of Javascript code, nothing else.
`
5 changes: 3 additions & 2 deletions src/ai/providers/cloudflare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ export class CloudflareAi implements AiProvider {

constructor(_?: { model: string, apiKey: string }) {
if (!_) return;
this.model = _.model;
this.apiKey = _.apiKey;

if (_.model) this.model = _.model;
if (_.apiKey) this.apiKey = _.apiKey;
}

async startConversation(systemPrompt: string, message: string): Promise<OperationResponse> {
Expand Down
10 changes: 10 additions & 0 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export interface QueryBuilder {
asClass?: any
groupBy?: string

selectRawValue?: string

// General operation values, such as when renaming tables referencing the old and new name
originalValue?: string
newValue?: string
Expand All @@ -49,6 +51,8 @@ export interface OuterbaseType {
selectFrom: (
columnsArray: { schema?: string; table: string; columns: string[] }[]
) => OuterbaseType
selectRaw: (statement: string) => OuterbaseType

insert: (data: { [key: string]: any }) => OuterbaseType
update: (data: { [key: string]: any }) => OuterbaseType
deleteFrom: (table: string) => OuterbaseType
Expand Down Expand Up @@ -112,6 +116,12 @@ export function Outerbase(connection: Connection): OuterbaseType {

return this
},
selectRaw(statement) {
this.queryBuilder.action = QueryBuilderAction.SELECT
this.queryBuilder.selectRawValue = statement

return this
},
where(condition) {
// Check if `condition` is an array of conditions
if (Array.isArray(condition)) {
Expand Down
3 changes: 0 additions & 3 deletions src/query-builder/dialects/bigquery.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import { QueryBuilder } from 'src/client';
import { Query } from 'src/query';
import { QueryType } from 'src/query-params';
import { AbstractDialect } from '../index';

export class BigQueryDialect extends AbstractDialect {
Expand Down
3 changes: 0 additions & 3 deletions src/query-builder/dialects/duckdb.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import { QueryBuilder } from 'src/client';
import { Query } from 'src/query';
import { QueryType } from 'src/query-params';
import { AbstractDialect } from '../index';

export class DuckDbDialect extends AbstractDialect {
Expand Down
10 changes: 2 additions & 8 deletions src/query-builder/dialects/mysql.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import { AbstractDialect, ColumnDataType } from '../index';
import { QueryBuilder } from '../../client';
import { QueryType } from '../../query-params';

export class MySQLDialect extends AbstractDialect {
mapDataType(dataType: ColumnDataType): string {
switch (dataType.toLowerCase()) {
case ColumnDataType.STRING:
return 'VARCHAR(255)'; // MySQL specific VARCHAR length
return 'VARCHAR(255)';
case ColumnDataType.BOOLEAN:
return 'TINYINT(1)'; // MySQL uses TINYINT for boolean
return 'TINYINT(1)';
default:
return super.mapDataType(dataType);
}
}

// select(builder: QueryBuilder, type: QueryType): string {
// return `SELECT MYSQL`
// }
}
92 changes: 73 additions & 19 deletions src/query-builder/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ interface Dialect {
dropTable(builder: QueryBuilder, type: QueryType, query: Query): Query;
renameTable(builder: QueryBuilder, type: QueryType, query: Query): Query;

// Column operations
// addColumn?: (name: string, table: string, schema?: string) => Promise<OperationResponse>
// dropColumn?: (name: string, table: string, schema?: string) => Promise<OperationResponse>
// renameColumn?: (name: string, original: string, table: string, schema?: string) => Promise<OperationResponse>
// updateColumn?: (name: string, column: TableColumn, table: string, schema?: string) => Promise<OperationResponse>

// // // Index operations
// createIndex?: (index: TableIndex, table: string, schema?: string) => Promise<OperationResponse>
// dropIndex?: (name: string, table: string, schema?: string) => Promise<OperationResponse>
// renameIndex?: (name: string, original: string, table: string, schema?: string) => Promise<OperationResponse>

// // // Schema operations
// createSchema?: (name: string) => Promise<OperationResponse>
// dropSchema?: (name: string) => Promise<OperationResponse>

equals(a: any, b: string): string;
equalsNumber(a: any, b: any): string;
equalsColumn(a: any, b: any): string;
Expand Down Expand Up @@ -49,21 +64,6 @@ interface Dialect {
notBetweenNumbers(a: any, b: any, c: any): string;
ascending(a: any): string;
descending(a: any): string;

// Column operations
// addColumn?: (name: string, table: string, schema?: string) => Promise<OperationResponse>
// dropColumn?: (name: string, table: string, schema?: string) => Promise<OperationResponse>
// renameColumn?: (name: string, original: string, table: string, schema?: string) => Promise<OperationResponse>
// updateColumn?: (name: string, column: TableColumn, table: string, schema?: string) => Promise<OperationResponse>

// // Index operations
// createIndex?: (index: TableIndex, table: string, schema?: string) => Promise<OperationResponse>
// dropIndex?: (name: string, table: string, schema?: string) => Promise<OperationResponse>
// renameIndex?: (name: string, original: string, table: string, schema?: string) => Promise<OperationResponse>

// // Schema operations
// createSchema?: (name: string) => Promise<OperationResponse>
// dropSchema?: (name: string) => Promise<OperationResponse>
}

export enum ColumnDataType {
Expand All @@ -79,26 +79,53 @@ export enum ColumnDataType {
}

export abstract class AbstractDialect implements Dialect {
/**
* WORK IN PROGRESS!
* This code is not used anywhere in the SDK at the moment. It is a work in progress to add support for SQL functions
* in the query builder. The idea is to allow users to use SQL functions in their queries, and the query builder will
* automatically format the query to use the correct SQL function for the specific database dialect.
*
* The `sqlFunctions` object is a map of SQL function names to their implementations. The `getFunction` method is used
* to get the implementation of a specific SQL function. The `addFunction` method is used to add a new SQL function
* to the `sqlFunctions` object.
*/
protected sqlFunctions: { [key: string]: (...args: string[]) => string } = {
now: () => 'NOW()',
concat: (...args: string[]) => `CONCAT(${args.join(', ')})`,
coalesce: (...args: string[]) => `COALESCE(${args.join(', ')})`,
abs: (value: string) => `ABS(${value})`,
};

/**
* Retrieves the implementation of the SQL function with the given name.
*
* @param funcName
* @returns Returns the implementation of the SQL function with the given name.
*/
getFunction(funcName: string): (...args: string[]) => string {
if (this.sqlFunctions[funcName]) {
return this.sqlFunctions[funcName];
}
throw new Error(`SQL function '${funcName}' not supported in this dialect.`);
}

// Allow specific dialects to add or override functions
/**
* Adds a new SQL function to the `sqlFunctions` object. If a function with the same name already exists, it will be
* overwritten with the new implementation.
*
* @param funcName
* @param implementation
*/
protected addFunction(funcName: string, implementation: (...args: string[]) => string) {
this.sqlFunctions[funcName] = implementation;
}

// Maps generic data types to database-specific data types
/**
* Maps the data type from the SDK to the equivalent data type for the specific database dialect.
*
* @param dataType
* @returns Returns the equivalent data type for the specific database dialect.
*/
mapDataType(dataType: ColumnDataType | string): string {
switch (dataType) {
case ColumnDataType.STRING:
Expand All @@ -114,6 +141,11 @@ export abstract class AbstractDialect implements Dialect {
}
}

/**
* Words that are reserved in the query language and may require special character wrapping to prevent
* collisions with the database engine executing the query. Each dialect may need to override this property
* with the reserved keywords for the specific database engine.
*/
reservedKeywords: string[] = [
'ADD',
'ALL',
Expand Down Expand Up @@ -178,7 +210,13 @@ export abstract class AbstractDialect implements Dialect {
];

/**
* Formats the schema and table names according to the specific database dialect.
* Formats how the schema and table name should be used in the SELECT statement.
*
* @why When implementing support for BigQuery, the SELECT statement takes only a table name, where the FROM
* statement takes the schema and table name. It also requires both the schema and name to be wrapped in
* backticks together, and not separately. This method allows for formatting the schema and table name in a way
* that is compatible with the specific database dialect.
* See also - `formatFromSchemaAndTable`
* @param schema The schema name (optional).
* @param table The table name.
* @returns The formatted schema and table combination.
Expand All @@ -190,6 +228,18 @@ export abstract class AbstractDialect implements Dialect {
return table;
}

/**
* Formats how the schema and table name should be used in the FROM statement.
*
* @why When implementing support for BigQuery, the FROM statement takes a fully qualified schema and table name,
* where the SELECT statement only takes the table name. It also requires both the schema and name to be wrapped
* in backticks together, and not separately. This method allows for formatting the schema and table name in a way
* that is compatible with the specific database dialect.
* See also - `formatSchemaAndTable`
* @param schema
* @param table
* @returns The formatted schema and table combination.
*/
formatFromSchemaAndTable(schema: string | undefined, table: string): string {
if (schema) {
return `"${schema}".${table}`;
Expand Down Expand Up @@ -226,7 +276,11 @@ export abstract class AbstractDialect implements Dialect {
}
})

query.query = `SELECT ${selectColumns} FROM ${fromTable}`
query.query = `SELECT
${selectColumns}
${builder.selectRawValue ? builder.selectRawValue : ''}
FROM ${fromTable}
`

if (joinClauses) {
query.query += ` ${joinClauses}`
Expand Down

0 comments on commit f5d4821

Please sign in to comment.