def _execute_sql(node: Node, output: Repository) -> ProvenanceLine: # Calculate the hash of the layer we are trying to create. # Since we handle the "input" hashing in the import step, we don't need to care about the sources here. # Later on, we could enhance the caching and base the hash of the command on the hashes of objects that # definitely go there as sources. if node.expr_name == "sql_file": node_contents = extract_nodes(node, ["non_newline"])[0].text logging.info("Loading the SQL commands from %s" % node_contents) with open(node_contents, "r") as file: # Possibly use a different method to calculate the image hash for commands originating from # SQL files instead? # Don't "canonicalize" it here to get rid of whitespace, just hash the whole file. sql_command = file.read() else: # Support singleline and multiple SQL commands between braces nodes = extract_nodes(node, ["non_newline"]) if not nodes: nodes = extract_nodes(node, ["non_curly_brace"]) sql_command = nodes[0].text.replace("\\{", "{").replace("\\}", "}").replace( "\\\\", "\\") # Prepare the SQL by rewriting outside image references into LQ schemas # Canonicalize the SQL command by formatting it. image_mapper = ImageMapper(output.object_engine) sql_rewritten, sql_canonical = prepare_splitfile_sql( sql_command, image_mapper) output_head = output.head_strict.image_hash target_hash = _combine_hashes( [output_head, sha256(sql_canonical.encode("utf-8")).hexdigest()]) def _calc(): logging.info("Executing SQL...") try: image_mapper.setup_lq_mounts() output.object_engine.commit() sql_to_run = get_singleton(CONFIG, "SG_LQ_TUNING") + sql_rewritten logging.debug("Running rewritten SQL %s against %s", sql_to_run, output) output.run_sql(sql_to_run) finally: image_mapper.teardown_lq_mounts() output.commit(target_hash, comment=sql_command) _checkout_or_calculate_layer(output, target_hash, _calc) provenance: ProvenanceLine = {"type": "SQL", "sql": sql_canonical} provenance.update(image_mapper.get_provenance_data()) return provenance
def test_rewrite(source, rewritten, canonical): assert prepare_splitfile_sql(source, _mapper) == (rewritten, canonical)
def fails_on_both(sql): with pytest.raises(UnsupportedSQLError) as e: prepare_splitfile_sql(sql, dummy_mapper) with pytest.raises(UnsupportedSQLError) as e: validate_import_sql(sql)
def succeeds_on_sql_fails_on_import(sql): prepare_splitfile_sql(sql, dummy_mapper) with pytest.raises(UnsupportedSQLError) as e: validate_import_sql(sql)
def succeeds_on_both(sql): prepare_splitfile_sql(sql, dummy_mapper) validate_import_sql(sql)