Another Nix Success Story
source link: https://maxdeviant.com/shards/2021/another-nix-success-story/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Another Nix Success Story
Yesterday I found myself in a position where I needed to know the dependency graph of tables within a Postgres database.
I figured that someone else had written a program to solve this problem, and some quick Google-fu revealed that I was correct.
I happened upon this post that contained a Python script that generated the dependency graph I was looking for and dumped it to Graphviz DOT. Beautiful!
Here's the script:
from optparse import OptionParser, OptionGroup
import psycopg2
import sys
def writedeps(cursor, tbl):
sql = """SELECT
tc.constraint_name, tc.table_name, kcu.column_name,
ccu.table_name AS foreign_table_name,
ccu.column_name AS foreign_column_name
FROM
information_schema.table_constraints AS tc
JOIN information_schema.key_column_usage AS kcu ON
tc.constraint_name = kcu.constraint_name
JOIN information_schema.constraint_column_usage AS ccu ON
ccu.constraint_name = tc.constraint_name
WHERE constraint_type = 'FOREIGN KEY' AND tc.table_name = '%s'"""
cursor.execute(sql % tbl)
for row in cursor.fetchall():
constraint, table, column, foreign_table, foreign_column = row
print '"%s" -> "%s" [label="%s"];' % (tbl, foreign_table, constraint)
def get_tables(cursor):
cursor.execute("SELECT tablename FROM pg_tables WHERE schemaname='public'")
for row in cursor.fetchall():
yield row[0]
def main():
parser = OptionParser()
group = OptionGroup(parser, "Database Options")
group.add_option("--dbname", action="store", dest="dbname",
help="The database name.")
group.add_option("--dbhost", action="store", dest="dbhost",
default="localhost", help="The database host.")
group.add_option("--dbuser", action="store", dest="dbuser",
help="The database username.")
group.add_option("--dbpass", action="store", dest="dbpass",
help="The database password.")
parser.add_option_group(group)
(options, args) = parser.parse_args()
if not options.dbname:
print "Please supply a database name, see --help for more info."
sys.exit(1)
try:
conn = psycopg2.connect("dbname='%s' user='%s' host='%s' password='%s'"
% (options.dbname, options.dbuser, options.dbhost, options.dbpass))
except psycopg2.OperationalError, e:
print "Failed to connect to database,",
print "perhaps you need to supply auth details:\n %s" % str(e)
print "Use --help for more info."
sys.exit(1)
cursor = conn.cursor()
print "Digraph F {\n"
print 'ranksep=1.0; size="18.5, 15.5"; rankdir=LR;'
for i in get_tables(cursor):
writedeps(cursor, i)
print "}"
sys.exit(0)
if __name__ == "__main__":
main()
It was herein that I discovered two problems:
- The script depends on
psycopg2
, which means I need to muck about with Python dependency management - I can tell from the
print
statements that the script is written in Python 2, and my work Macbook has Python 3
My immediate thought was to use Nix to solve this. I grabbed a shell.nix
template from the Packaging/Python
section of the NixOS wiki and added the psycopg2
dependency along with graphviz
:
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "pip-env";
buildInputs = [
+ graphviz
+
# System requirements.
readline
# Python requirements (enough to get a virtualenv going).
python27Full
python27Packages.virtualenv
python27Packages.pip
+ python27Packages.psycopg2
];
src = null;
shellHook = ''
# Allow the use of wheels.
SOURCE_DATE_EPOCH=$(date +%s)
# Augment the dynamic linker path
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${R}/lib/R/lib:$ {readline}/lib
'';
}
I was then able to drop into a nix-shell
and run the script:
python database_dependency_order.py --dbname <NAME> --dbhost <HOST> --dbuser <USER> --dbpass <PASSWORD> | dot -Tpng > deps.png
Easy as Py Nix.
Recommend
-
36
I just cleared my OCAJP certification for Java SE 8 with an 88 percent score. Thanks to my friends for sharing good study materials for my success. I have been a passionate learner of Java since my first year of...
-
6
This procedure does not guarantee anything and should be considered approximate. However this should be fairly enough for someone familiar with Apache environments. Ruby environment We install Ruby via apt-get s...
-
6
The Crazy Story Behind Calm’s Success Everyone knows @calm Not as many know how @tewy made his first million and proved his product/marketing genius while waking up a nation of young e...
-
6
Starting UpFresh Off IPO, Upstart’s CEO Shares Why the Startup Isn’t a Typical Success StoryLast week,
-
14
Bill Gates Success Story > CEOWORLD magazineBill Gates is a man who, with an idea born in a garage, managed to conquer the whole world. In this article, you will find out how he managed to become one of the richest people in the world...
-
6
Transcript Beckwith: I'm Monica Beckwith, a Java champion. I work in optimizing the JVM at Microsoft. I'm going to talk about our journey with enabling Java on Windows and ARM64 systems. Outline I'm...
-
4
Background UK companies are required to make a quarterly report of VAT amount calculations to HRMC. Since the introduction of ‘Making Tax Digital for VAT’, VAT-registered businesses with a taxable turnover above the...
-
5
GraphQL: A success story for PayPal CheckoutFrom graphql.orgAt PayPal, we recently introduced GraphQL to our technology stack.If you haven’t heard of
-
10
FinTech 4 Pillars of Your Fintech Development Outsourcing Success
-
3
CEO SpotlightProfile: Prem Baniya — The Surreal Story of Life, Success, and StrugglePrem Baniya, a vocal powerhouse who hails from Nepal changed...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK