def save_file(db, user_id, path, content, encrypt_func, max_size_bytes):
content = preprocess_incoming_content(<EOL>content,<EOL>encrypt_func,<EOL>max_size_bytes,<EOL>)<EOL>directory, name = split_api_filepath(path)<EOL>with db.begin_nested() as savepoint:<EOL><INDENT>try:<EOL><INDENT>res = db.execute(<EOL>files.insert().values(<EOL>name=name,<EOL>user_id=user_id,<EOL>parent_name=directory,<EOL>content=content,<EOL>)<EOL>)<EOL><DEDENT>except IntegrityError as error:<EOL><INDENT>if is_unique_violation(error):<EOL><INDENT>savepoint.rollback()<EOL>res = db.execute(<EOL>files.update().where(<EOL>_file_where(user_id, path),<EOL>).values(<EOL>content=content,<EOL>created_at=func.now(),<EOL>)<EOL>)<EOL><DEDENT>else:<EOL><INDENT>raise<EOL><DEDENT><DEDENT><DEDENT>return res<EOL>
Save a file.

TODO: Update-then-insert is probably cheaper than insert-then-update.