def search_contracts(gsins=[], keywords=[]): """Search for matching contracts.""" # Make the SQL condition fragments (ugly, again) conditions = [] conditions.append(" or ".join(["gsin like '{}%'".format(esc(gsin)) for gsin in gsins if gsin])) conditions.append( " or ".join( [ "contract in (select contract from ContractSearch where match(lemma) against('{}'))".format( esc(keyword) ) for keyword in keywords if keyword ] ) ) condition_fragment = " and ".join(["({})".format(condition) for condition in conditions if condition]) if not condition_fragment: condition_fragment = "true" # Make the SQL query string query = CONTRACT_QUERY_TEMPLATE.format(conditions=condition_fragment) # Post-processing for each result row def post_contract(cursor, row): data = sql_row_to_dict(cursor, row) data["gsins"] = [data["gsin"]] del data["gsin"] id = re.sub(r"[^A-Z0-9-]", "-", data["contract"]) data["url_en"] = "https://buyandsell.gc.ca/procurement-data/contract-history/{}".format(id) data["url_fr"] = "https://achatsetventes.gc.ca/donnees-sur-l-approvisionnement/contrats-octroyes/{}".format(id) return data # Execute the query connection = bas.connect(config) with connection.cursor() as cursor: cursor.execute(query) result = cursor.fetchall() return [post_contract(cursor, row) for row in result]
def search_tenders(gsins=[], delivery=[], opportunity=[], keywords=[]): """Search for matching tenders.""" # Make the SQL condition fragments (a bit of ugly here) conditions = [] conditions.append(" or ".join(["gsin like '{}%'".format(esc(gsin)) for gsin in gsins if gsin])) conditions.append(" or ".join(["region_delivery='{}'".format(esc(region)) for region in delivery if region])) conditions.append(" or ".join(["region_opportunity='{}'".format(esc(region)) for region in opportunity if region])) conditions.append( " or ".join( [ "tender in (select tender from TenderSearch where match(lemma) against('{}'))".format(esc(keyword)) for keyword in keywords if keyword ] ) ) condition_fragment = " and ".join(["({})".format(condition) for condition in conditions if condition]) if not condition_fragment: condition_fragment = "true" # Make the SQL query string query = TENDER_QUERY_TEMPLATE.format(conditions=condition_fragment) # Post-processing for each result row def post_tender(cursor, row): data = sql_row_to_dict(cursor, row) # Generate URLs to BAS id = re.sub(r"[^A-Z0-9-]", "", data["tender"]) data["url_en"] = "https://buyandsell.gc.ca/procurement-data/tender-notice/{}".format(id) data["url_fr"] = "https://achatsetventes.gc.ca/donnees-sur-l-approvisionnement/appels-d-offres/{}".format(id) return data # Execute the query connection = bas.connect(config) with connection.cursor() as cursor: cursor.execute(query) result = cursor.fetchall() return [post_tender(cursor, row) for row in result]
'buyer_en = values(buyer_en),', 'buyer_fr = values(buyer_fr),', 'gsin = values(gsin)' )) INSERT_FULLTEXT_QUERY = ' '.join(( 'insert into ContractSearch(contract, lemma, lang)', 'values (%s, %s, %s)' )) # # Load the contracts # with open(sys.argv[1], 'r', encoding='utf-8-sig') as input: contracts = ContractList(input) connection = bas.connect(config) with connection.cursor() as cursor: today = str(datetime.date.today()) cursor.execute('delete from Contracts') cursor.execute('delete from ContractSearch') for counter, contract in enumerate(contracts): if (counter + 1) % 5000 == 0: print("{}...".format(counter+1)) if contract['date-expires'] > today: result = cursor.execute(INSERT_CONTRACT_QUERY, ( contract['contract'], contract['title_en'], contract['title_fr'], contract['date-awarded'], contract['date-expires'], contract['value'],
def esc(s): """SQL escape a string.""" return bas.connect(config).escape_string(s)