Skip to content
Merged

Dev #174

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
16 changes: 9 additions & 7 deletions py-src/data_formulator/data_loader/mysql_data_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def list_params() -> bool:
{"name": "user", "type": "string", "required": True, "default": "root", "description": ""},
{"name": "password", "type": "string", "required": False, "default": "", "description": "leave blank for no password"},
{"name": "host", "type": "string", "required": True, "default": "localhost", "description": ""},
{"name": "port", "type": "int", "required": False, "default": 3306, "description": "MySQL server port (default 3306)"},
{"name": "database", "type": "string", "required": True, "default": "mysql", "description": ""}
]
return params_list
Expand All @@ -25,23 +26,24 @@ def auth_instructions() -> str:

1. Local MySQL Setup:
- Ensure MySQL server is running on your machine
- Default connection: host='localhost', user='root'
- Default connection: host='localhost', user='root', port=3306
- If you haven't set a root password, leave password field empty

2. Remote MySQL Connection:
- Obtain host address, username, and password from your database administrator
- Obtain host address, port, username, and password from your database administrator
- Ensure the MySQL server allows remote connections
- Check that your IP is whitelisted in MySQL's user permissions

3. Common Connection Parameters:
- user: Your MySQL username (default: 'root')
- password: Your MySQL password (leave empty if no password set)
- host: MySQL server address (default: 'localhost')
- port: MySQL server port (default: 3306)
- database: Target database name to connect to

4. Troubleshooting:
- Verify MySQL service is running: `brew services list` (macOS) or `sudo systemctl status mysql` (Linux)
- Test connection: `mysql -u [username] -p -h [host] [database]`
- Test connection: `mysql -u [username] -p -h [host] -P [port] [database]`
"""

def __init__(self, params: Dict[str, Any], duck_db_conn: duckdb.DuckDBPyConnection):
Expand All @@ -52,17 +54,17 @@ def __init__(self, params: Dict[str, Any], duck_db_conn: duckdb.DuckDBPyConnecti
self.duck_db_conn.install_extension("mysql")
self.duck_db_conn.load_extension("mysql")

attatch_string = ""
attach_string = ""
for key, value in self.params.items():
if value:
attatch_string += f"{key}={value} "
if value is not None and value != "":
attach_string += f"{key}={value} "

# Detach existing mysqldb connection if it exists
try:
self.duck_db_conn.execute("DETACH mysqldb;")
except:
pass # Ignore if mysqldb doesn't exist # Register MySQL connection
self.duck_db_conn.execute(f"ATTACH '{attatch_string}' AS mysqldb (TYPE mysql);")
self.duck_db_conn.execute(f"ATTACH '{attach_string}' AS mysqldb (TYPE mysql);")

def list_tables(self, table_filter: str = None):
tables_df = self.duck_db_conn.execute(f"""
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "data_formulator"
version = "0.2.1.4"
version = "0.2.1.5"

requires-python = ">=3.9"
authors = [
Expand Down
51 changes: 39 additions & 12 deletions src/app/dfSlice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,19 @@ export interface ModelConfig {
api_version?: string;
}

// Define model slot types
export type ModelSlotType = 'generation' | 'hint';

export interface ModelSlots {
generation?: string; // model id assigned to generation tasks
hint?: string; // model id assigned to hint tasks
}

// Define a type for the slice state
export interface DataFormulatorState {
sessionId: string | undefined;
models: ModelConfig[];
selectedModelId: string | undefined;
modelSlots: ModelSlots;
testedModels: {id: string, status: 'ok' | 'error' | 'testing' | 'unknown', message: string}[];

tables : DictTable[];
Expand Down Expand Up @@ -89,7 +97,7 @@ export interface DataFormulatorState {
const initialState: DataFormulatorState = {
sessionId: undefined,
models: [],
selectedModelId: undefined,
modelSlots: {},
testedModels: [],

tables: [],
Expand Down Expand Up @@ -263,7 +271,7 @@ export const dataFormulatorSlice = createSlice({
// avoid resetting inputted models
// state.oaiModels = state.oaiModels.filter((m: any) => m.endpoint != 'default');

state.selectedModelId = state.models.length > 0 ? state.models[0].id : undefined;
state.modelSlots = {};
state.testedModels = [];

state.tables = [];
Expand All @@ -289,7 +297,7 @@ export const dataFormulatorSlice = createSlice({
let savedState = action.payload;

state.models = savedState.models;
state.selectedModelId = savedState.selectedModelId;
state.modelSlots = savedState.modelSlots || {};
state.testedModels = []; // models should be tested again

//state.table = undefined;
Expand Down Expand Up @@ -318,16 +326,25 @@ export const dataFormulatorSlice = createSlice({
state.config = action.payload;
},
selectModel: (state, action: PayloadAction<string | undefined>) => {
state.selectedModelId = action.payload;
state.modelSlots = { ...state.modelSlots, generation: action.payload };
},
setModelSlot: (state, action: PayloadAction<{slotType: ModelSlotType, modelId: string | undefined}>) => {
state.modelSlots = { ...state.modelSlots, [action.payload.slotType]: action.payload.modelId };
},
setModelSlots: (state, action: PayloadAction<ModelSlots>) => {
state.modelSlots = action.payload;
},
addModel: (state, action: PayloadAction<ModelConfig>) => {
state.models = [...state.models, action.payload];
},
removeModel: (state, action: PayloadAction<string>) => {
state.models = state.models.filter(model => model.id != action.payload);
if (state.selectedModelId == action.payload) {
state.selectedModelId = undefined;
}
// Remove the model from all slots if it's assigned
Object.keys(state.modelSlots).forEach(slotType => {
if (state.modelSlots[slotType as ModelSlotType] === action.payload) {
state.modelSlots[slotType as ModelSlotType] = undefined;
}
});
},
updateModelStatus: (state, action: PayloadAction<{id: string, status: 'ok' | 'error' | 'testing' | 'unknown', message: string}>) => {
let id = action.payload.id;
Expand Down Expand Up @@ -735,16 +752,19 @@ export const dataFormulatorSlice = createSlice({

state.models = [
...defaultModels,
...state.models.filter(e => !defaultModels.map((m: ModelConfig) => m.endpoint).includes(e.endpoint))
...state.models.filter(e => !defaultModels.some((m: ModelConfig) =>
m.endpoint === e.endpoint && m.model === e.model &&
m.api_base === e.api_base && m.api_version === e.api_version
))
];

state.testedModels = [
...defaultModels.map((m: ModelConfig) => {return {id: m.id, status: 'ok'}}) ,
...state.testedModels.filter(t => !defaultModels.map((m: ModelConfig) => m.id).includes(t.id))
]

if (state.selectedModelId == undefined && defaultModels.length > 0) {
state.selectedModelId = defaultModels[0].id;
if (state.modelSlots.generation == undefined && defaultModels.length > 0) {
state.modelSlots.generation = defaultModels[0].id;
}

// console.log("load model complete");
Expand All @@ -769,7 +789,14 @@ export const dataFormulatorSlice = createSlice({

export const dfSelectors = {
getActiveModel: (state: DataFormulatorState) : ModelConfig => {
return state.models.find(m => m.id == state.selectedModelId) || state.models[0];
return state.models.find(m => m.id == state.modelSlots.generation) || state.models[0];
},
getModelBySlot: (state: DataFormulatorState, slotType: ModelSlotType) : ModelConfig | undefined => {
const modelId = state.modelSlots[slotType];
return modelId ? state.models.find(m => m.id === modelId) : undefined;
},
getAllSlotTypes: () : ModelSlotType[] => {
return ['generation', 'hint'];
},
getActiveBaseTableIds: (state: DataFormulatorState) => {
let focusedTableId = state.focusedTableId;
Expand Down
Loading