agenthink 0.1.18__py3-none-any.whl → 0.1.19__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
agenthink/connection.py CHANGED
@@ -20,15 +20,6 @@ import logging
20
20
  import re
21
21
  dotenv.load_dotenv()
22
22
 
23
- # Create and configure logger
24
- # logging.basicConfig(
25
- # filename="datastore_library.log",
26
- # format='%(asctime)s %(levelname)s:%(name)s:%(message)s',
27
- # filemode='w'
28
- # )
29
- # logger = logging.getLogger(__name__)
30
- # logger.setLevel(logging.DEBUG)
31
-
32
23
  logger = logging.getLogger(__name__)
33
24
  logger.addHandler(logging.NullHandler())
34
25
 
@@ -223,14 +214,34 @@ class DBConnector:
223
214
  return f"Database: {db_name}, Connection Object: {conn}"
224
215
 
225
216
  def execute_query(self, db_name: str, query: str):
217
+
226
218
  """
227
- Execute a query on the specified database connection.
219
+ Execute a read-only SQL query on a MySQL or MSSQL database.
220
+
221
+ Parameters
222
+ ----------
223
+ db_name : str
224
+ Name of the database connection.
225
+ query : str
226
+ Read-only SQL query to execute (SELECT / WITH / SHOW / DESCRIBE / EXPLAIN).
227
+
228
+ Returns
229
+ -------
230
+ Any or None
231
+ Query results if successful, otherwise None.
232
+
233
+ Notes
234
+ -----
235
+ - Only read-only queries are allowed and enforced by prefix checks.
236
+ - Write or mutating queries are blocked.
237
+ - Errors are logged and cursors are safely closed.
238
+ - Behavior may differ slightly between MySQL and MSSQL drivers.
228
239
  """
240
+
229
241
  if db_name not in self.connection_object_dict:
230
242
  logger.error("No connection found for database: %s", db_name)
231
243
  return None
232
244
 
233
-
234
245
  database_dict = self.connection_object_dict[db_name]
235
246
  database_type = database_dict.get("database_type")
236
247
  database_connection = database_dict.get("connection_object")
@@ -252,19 +263,18 @@ class DBConnector:
252
263
  return None
253
264
 
254
265
  if database_type == "mysql":
255
- # try:
256
- cursor = database_connection.cursor()
257
- cursor.execute(query)
258
- results = cursor.fetchall()
259
- logger.info("Executed query on MySQL database '%s': %s", db_name, query)
260
- # return f"{results}"
261
- return f"{cursor}, {results}"
262
- # except Exception as e:
263
- # logger.exception("Failed to execute query on MySQL database '%s': %s", db_name, e)
264
- # return None
265
- # finally:
266
- # if cursor:
267
- # cursor.close()
266
+ try:
267
+ cursor = database_connection.cursor()
268
+ cursor.execute(query)
269
+ results = cursor.fetchall()
270
+ logger.info("Executed query on MySQL database '%s': %s", db_name, query)
271
+ return f"{results}"
272
+ except Exception as e:
273
+ logger.exception("Failed to execute query on MySQL database '%s': %s", db_name, e)
274
+ return None
275
+ finally:
276
+ if cursor:
277
+ cursor.close()
268
278
  elif database_type == "mssql":
269
279
  try:
270
280
  cursor = database_connection.cursor()
@@ -283,6 +293,108 @@ class DBConnector:
283
293
  else:
284
294
  logger.error("Unsupported database type '%s' for database '%s'", database_type, db_name)
285
295
  return None
296
+
297
+ def display_tables(self,db_name:str):
298
+ """
299
+ Retrieve a list of user tables from a MySQL or MSSQL database.
300
+
301
+ Parameters
302
+ ----------
303
+ db_name : str
304
+ Name of the database connection.
305
+
306
+ Returns
307
+ -------
308
+ list[str] or None
309
+ List of table names if successful, otherwise None.
310
+
311
+ Notes
312
+ -----
313
+ - Uses `SHOW TABLES` for MySQL.
314
+ - Uses `INFORMATION_SCHEMA.TABLES` for MSSQL.
315
+ - Errors are logged and not raised.
316
+ """
317
+ database_dict = self.connection_object_dict[db_name]
318
+ database_type = database_dict.get("database_type")
319
+ database_connection = database_dict.get("connection_object")
320
+ if database_type == "mysql":
321
+ try:
322
+ cursor = database_connection.cursor()
323
+ cursor.execute("SHOW TABLES")
324
+ tables = cursor.fetchall()
325
+ table_list = [table[0] for table in tables]
326
+ return table_list
327
+ except Exception as e:
328
+ logger.exception("Failed to retrieve tables from MySQL database '%s': %s", db_name, e)
329
+ return None
330
+
331
+ if database_type == "mssql":
332
+ try:
333
+ cursor = database_connection.cursor()
334
+ cursor.execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'")
335
+ tables = cursor.fetchall()
336
+ table_list = [table[0] for table in tables]
337
+ return table_list
338
+ except Exception as e:
339
+ logger.exception("Failed to retrieve tables from MSSQL database '%s': %s", db_name, e)
340
+ return None
341
+
342
+
343
+ def insert_data(self,db_name:str,table_name:str,data:dict):
344
+ """
345
+ Insert a single row into a MySQL or MSSQL table.
346
+
347
+ Parameters
348
+ ----------
349
+ db_name : str
350
+ Name of the database connection.
351
+ table_name : str
352
+ Target table name (must be trusted).
353
+ data : dict
354
+ Column-to-value mapping for the row to insert.
355
+
356
+ Notes
357
+ -----
358
+ - Uses `%s` placeholders for MySQL and `?` for MSSQL.
359
+ - Commits the transaction on success and logs the result.
360
+ - Table and column names are not parameterized and must be validated.
361
+ """
362
+ database_dict = self.connection_object_dict[db_name]
363
+ database_type = database_dict.get("database_type")
364
+ database_connection = database_dict.get("connection_object")
365
+ columns = ', '.join(data.keys())
366
+ placeholders = ', '.join(['%s'] * len(data))
367
+ values = tuple(data.values())
368
+ if database_type == "mysql":
369
+ try:
370
+ cursor = database_connection.cursor()
371
+ sql = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"
372
+ cursor.execute(sql, values)
373
+ database_connection.commit()
374
+ cursor.close()
375
+ logger.info("Data inserted into MySQL database '%s', table '%s'", db_name, table_name)
376
+ except Exception as e:
377
+ logger.exception("Failed to insert data into MySQL database '%s', table '%s': %s", db_name, table_name, e)
378
+ if database_type == "mssql":
379
+ try:
380
+ cursor = database_connection.cursor()
381
+ columns_sql = ", ".join(f"[{c}]" for c in data.keys())
382
+ placeholders = ", ".join("?" for _ in data)
383
+ values = tuple(data.values())
384
+
385
+ sql = f"INSERT INTO [{table_name}] ({columns_sql}) VALUES ({placeholders})"
386
+
387
+ cursor.execute(sql, values)
388
+ database_connection.commit()
389
+
390
+ logger.info(
391
+ "Data inserted into MSSQL database '%s', table '%s'",
392
+ db_name,
393
+ table_name
394
+ )
395
+ cursor.close()
396
+ except Exception as e:
397
+ logger.exception("Insert failed for %s database '%s', table '%s'", database_type, db_name, table_name)
286
398
 
287
399
  def _debugging_function(self):
288
400
  prefix = f"{self._workflow_id}/{self._user_id}/"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agenthink
3
- Version: 0.1.18
3
+ Version: 0.1.19
4
4
  Summary: A unified agent framework for connecting workflows, databases, and agents
5
5
  Author: Ritobroto
6
6
  Requires-Python: >=3.10
@@ -0,0 +1,8 @@
1
+ agenthink/__init__.py,sha256=6oUldrZgE76j8OhwsQgVY5vdaPTDFyChOljske-so8U,78
2
+ agenthink/connection.py,sha256=ZWWXsn1RiylzgOyL_-TQEuYYxNEMpqqAF0_HFedBoH4,17648
3
+ agenthink/models.py,sha256=PhXEMmfU31MTt1IwXxXV9DVPl5PLroQFHjRgRDs8iTo,251
4
+ agenthink/utils.py,sha256=r5o74RbenFhQ7E3N7naoLJ-fYEe9otz0nkcvwKHDTaU,911
5
+ agenthink-0.1.19.dist-info/METADATA,sha256=-DF_4vTTRb6FF1T7rEGFnSGDYYOWfAHe2r3pplPy7-o,1722
6
+ agenthink-0.1.19.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
+ agenthink-0.1.19.dist-info/top_level.txt,sha256=rYw4Lx2uqOzbGCSoJEaikme7vS9NvgbVMc26QUIZoZM,10
8
+ agenthink-0.1.19.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- agenthink/__init__.py,sha256=6oUldrZgE76j8OhwsQgVY5vdaPTDFyChOljske-so8U,78
2
- agenthink/connection.py,sha256=ngnRP-5qrIssl8Xeib0aD9yHUuDiC0WWaQcKRax6mfc,13108
3
- agenthink/models.py,sha256=PhXEMmfU31MTt1IwXxXV9DVPl5PLroQFHjRgRDs8iTo,251
4
- agenthink/utils.py,sha256=r5o74RbenFhQ7E3N7naoLJ-fYEe9otz0nkcvwKHDTaU,911
5
- agenthink-0.1.18.dist-info/METADATA,sha256=Qj9Eg1TtdoE5JpU8zXgdFhnmy0caMtHq601rj1kXKJk,1722
6
- agenthink-0.1.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
- agenthink-0.1.18.dist-info/top_level.txt,sha256=rYw4Lx2uqOzbGCSoJEaikme7vS9NvgbVMc26QUIZoZM,10
8
- agenthink-0.1.18.dist-info/RECORD,,