Skip to content
Merged
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
119 changes: 109 additions & 10 deletions Backend/postgres_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
manages server data queries
"""
import psycopg2
import psycopg2.extras
from psycopg2 import sql
from config import load_config


# important do not store password when dealing with real database
# might want to consider SQL injection down the line
# gets all systems from the database
Expand Down Expand Up @@ -53,6 +55,9 @@ def rows_to_dicts(self, cursor, rows):
return None

def try_query(self, sql_query, params=None, fetch="all"):
if not self.is_connection_active():
self.connect()

result = None
cur = None

Expand Down Expand Up @@ -147,19 +152,66 @@ def get_system(self, function_id):
def get_filtered_systems(self, filters):
where_sql, params = self.build_where_text(filters)
stats = self.get_statistics(where_sql, params)

query = sql.SQL("""
SELECT f.function_id, sigma_one, sigma_two, ordinal, degree,
(original_model).coeffs, f.base_field_label
SELECT f.function_id, f.sigma_one, f.sigma_two, f.ordinal, f.degree,
(f.original_model).coeffs, f.base_field_label
FROM functions_dim_1_nf f
JOIN rational_preperiodic_dim_1_nf r ON f.function_id = r.function_id
JOIN graphs_dim_1_nf g ON g.graph_id = r.graph_id
{}
""").format(where_sql)

rows = self.try_query(query, params, fetch='all')
return rows, stats
result = []

if rows:
mon_dict = {}
for row in rows:
try:
d = int(row[4])
coeffs = row[5]
field_label = row[6]
func_id = row[0]
except (KeyError, TypeError):
d = int(row['degree'])
coeffs = row['coeffs']
field_label = row['base_field_label']
func_id = row['function_id']

if d not in mon_dict:
mon = []
for i in range(d+1):
if i == 0: mon.append('x^'+str(d))
elif i == d: mon.append('y^'+str(d))
else:
term = 'x' if (d-i) == 1 else 'x^'+str(d-i)
term += 'y' if i == 1 else 'y^'+str(i)
mon.append(term)
mon_dict[d] = mon
else:
mon = mon_dict[d]

poly = '['
for j in range(2):
first_term = True
for i in range(d+1):
val = str(coeffs[j][i])
if val != '0':
if val[0] != '-' and not first_term:
poly += '+'
if val == '1': poly += mon[i]
elif val == '-1': poly += '-' + mon[i]
else: poly += val + mon[i]
first_term = False
if j == 0: poly += ' : '
poly += ']'

label = self.construct_label(row)
result.append([label, '1', d, poly, field_label, func_id])

return result, stats

# gets a subset of the systems identified by the labels
# input should be json list
def get_selected_systems(self, labels):
if not labels:
return []
Expand All @@ -178,17 +230,21 @@ def get_selected_systems(self, labels):

def get_statistics(self, where_sql, params):
query = sql.SQL("""
SELECT COUNT(*) as total_count,
AVG(degree) as avg_degree
SELECT count(*)
FROM functions_dim_1_nf f
JOIN rational_preperiodic_dim_1_nf r ON f.function_id = r.function_id
JOIN graphs_dim_1_nf g ON g.graph_id = r.graph_id
{}
""").format(where_sql)
result = self.try_query(query, params, fetch="one")

result = self.try_query(query, params, fetch='one')

if result:
return result
return {'total_count': 0, 'avg_degree': 0}
try:
return result[0]
except KeyError:
return result['count']
return 0

def get_family(self, family_id):
# We grab all family data
Expand Down Expand Up @@ -280,3 +336,46 @@ def build_where_text(self, filters):
where_fragment = sql.SQL(" WHERE ") + sql.SQL(" AND ").join(conditions)

return where_fragment, params
# for fil, values in filters.items():
# if fil == 'family_id':
# # Exact match for family_id (numeric)
# conditions.append(f'family_id = {int(values)}')

# elif fil == 'name':
# # Text search with ILIKE for partial matching
# conditions.append(
# f"name ILIKE '%' || TRIM('{values}') || '%'"
# )

# elif fil == 'degree':
# # Array of degrees: degree IN (2, 3)
# if isinstance(values, list) and len(values) > 0:
# conditions.append(
# 'degree IN (' + ', '.join(str(e) for e in values) + ')'
# )
# else:
# # Single value
# conditions.append(f'degree = {int(values)}')

# elif fil == 'dimension':
# # families_dim_1_nf only contains dimension 1 objects
# dims = values if isinstance(values, list) else [values]
# dims = [int(d) for d in dims]
# if 1 not in dims:
# # Requested dimension is not present in this table
# conditions.append('1 = 0')

# elif fil == 'is_polynomial':
# # Same style as system filter: IN (...)
# conditions.append(
# 'is_polynomial IN (' + ', '.join(str(v) for v in values) + ')'
# )

# elif fil == 'base_field_label':
# # Partial match, case-insensitive
# conditions.append(
# f"base_field_label ILIKE '%' || TRIM('{values}') || '%'"
# )

# filter_text += ' AND '.join(conditions)
# return filter_text
2 changes: 1 addition & 1 deletion Frontend/src/api/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const get_families = () => api.get("/get_all_families");
export const get_family = (familyId) => api.post("/get_family", { id: familyId });

// dreyes: used to filter families based on the filters selected in the UI
export const get_filtered_families = (filters) => api.post("/get_filtered_families", filters);
export const get_filtered_families = (filters) => api.post("/get_filtered_familes", filters);

export const get_rational_periodic_data = (functionId) =>
api.post("/get_rational_periodic_data", { function_id: functionId });
Expand Down
Loading