Exceptable

1,050 views

Published on

Exceptable - Useful database stored procedure exceptions in your application layer.

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,050
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Exceptable

  1. 1. Exceptable Tuesday, October 20, 2009
  2. 2. Exception Propagation, in PostgreSQL and Python Aurynn Shaw, Commandprompt, Inc. PostgreSQL Conference West, 2009 Tuesday, October 20, 2009
  3. 3. Background • Large, enterprise Python + Pylons application • Simpycity ORM utilizes significant stored procedures • Strong procedural interfaces Tuesday, October 20, 2009
  4. 4. Stored Procedures are Rare • Most people don’t use Stored Procedures. Tuesday, October 20, 2009
  5. 5. The Present System Wherein • A Database Query • A Stored Procedure • Or, A Database Query • Exceptions Galore Tuesday, October 20, 2009
  6. 6. A Database Query • The App queries the Database Tuesday, October 20, 2009
  7. 7. A Database Query • The App queries the Database • Any variety of query Tuesday, October 20, 2009
  8. 8. A Database Query >>> c.Raw("SELECT * FROM auth_only")() Traceback (most recent call last): ... <SNIP> ... psycopg2.ProgrammingError: permission denied for relation auth_only Tuesday, October 20, 2009
  9. 9. A Database Query • The App queries the Database • Any variety of query • Or A Stored Procedure Tuesday, October 20, 2009
  10. 10. Or a Stored Procedure CREATE OR REPLACE FUNCTION except_test() RETURNS VOID AS $$ BEGIN RAISE EXCEPTION 'Test!'; END; $$ LANGUAGE PLPGSQL; >>> c.Function("except_test")() Traceback (most recent call last): ... <SNIP> ... psycopg2.InternalError: Test! Tuesday, October 20, 2009
  11. 11. Beget an Exception • Stored procedures raise InternalErrors • Every procedural exception becomes this • Permissions violations raise ProgrammingErrors • I haven’t tested if this is all PG exceptions. Tuesday, October 20, 2009
  12. 12. Seriously? • This is what we have to work with? Tuesday, October 20, 2009
  13. 13. Why this is Important Wherein • Why? • Defining your APIs • Separation of Concerns • Procedural Spaghetti Tuesday, October 20, 2009
  14. 14. Why? • Limited information to propagate upwards • Stored Procedures are Harder to use • Permissions violations are difficult to detect Tuesday, October 20, 2009
  15. 15. API Undefined • Exceptions are part of your API Tuesday, October 20, 2009
  16. 16. API Undefined • Exceptions are part of your API • Easily overlooked Tuesday, October 20, 2009
  17. 17. API Undefined • Exceptions are part of your API • Easily overlooked • Delineations will make life easier Tuesday, October 20, 2009
  18. 18. Separation of Concerns • The Database is for Database Logic Tuesday, October 20, 2009
  19. 19. Separation of Concerns • The Database is for Database Logic • Harder to write Data Logic Tuesday, October 20, 2009
  20. 20. Spaghetti Early version of our app didn’t have Exceptable - we were left catching InternalErrors and guessing at what • InternalErrors everywhere the error was, based on timing. Tuesday, October 20, 2009
  21. 21. Spaghetti • InternalErrors everywhere • Insufficiency of Information Tuesday, October 20, 2009
  22. 22. Spaghetti • InternalErrors everywhere • Insufficiency of Information • Considerable Repeated Code Tuesday, October 20, 2009
  23. 23. A Saving Grace • Violating Procedure Signatures -> Python DataError Tuesday, October 20, 2009
  24. 24. A Better Deal Wherein • Database API • Easy Python implementation • Universality • Exceptable Tuesday, October 20, 2009
  25. 25. Database API • Easier to define an API Tuesday, October 20, 2009
  26. 26. Database API • Easier to define an API • The DB becomes part of that API Tuesday, October 20, 2009
  27. 27. Database API • Easier to define an API • The DB becomes part of that API • Simple Stored Procedure interface Tuesday, October 20, 2009
  28. 28. Database API • Easier to define an API • The DB becomes part of that API • Simple Stored Procedure interface • Easily declare new Exceptions Tuesday, October 20, 2009
  29. 29. Wonderfully Python • A Simple Decorator Tuesday, October 20, 2009
  30. 30. Simply Decorated from exceptable.exceptable import Except base = Except() @base def db_function(): pass Tuesday, October 20, 2009
  31. 31. Wonderfully Python • A Simple Decorator • Catches and re-emits Exceptions • The core of Exceptable • Easy to Integrate - 2 lines, in Simpycity Tuesday, October 20, 2009
  32. 32. Universality • Exceptable Procedures never change • DB logic doesn’t change • Application support is Easy Tuesday, October 20, 2009
  33. 33. Exceptable • More Pythonic Database Access • Better exceptions means better app flow Tuesday, October 20, 2009
  34. 34. Example Code Wherein • The DB Library • The Application Implementation • Catching Permissions Violations • PostgreSQL 8.4 Tuesday, October 20, 2009
  35. 35. To Start, CREATE TABLE exceptions ( name text primary key, description text not null, parent text references exceptions(name) ); INSERT INTO exceptions VALUES ('Exception', 'Base exception',NULL); INSERT INTO exceptions VALUES ('NotFoundException', 'Could not find specified record', 'Exception'); Tuesday, October 20, 2009
  36. 36. Which leads to CREATE OR REPLACE FUNCTION not_found ( in_reason TEXT ) RETURNS VOID as $body$ SELECT exceptaple.raise( 'NotFoundException', $1 ); $body$ LANGUAGE SQL; Tuesday, October 20, 2009
  37. 37. Application Level • Easy to Query the Exception tables Tuesday, October 20, 2009
  38. 38. Application Level • Easy to Query the Exception tables • Easy to set up a new library • Python took 50 lines Tuesday, October 20, 2009
  39. 39. Our Python Example • The Exceptable decorator is easy to set up • Designed for DB-API integration Tuesday, October 20, 2009
  40. 40. In the Application base = Except(InternalError, { 'Exception': Exception, 'NotFoundException': NotFoundError, }) Tuesday, October 20, 2009
  41. 41. Our Python Example • The Exceptable decorator is easy to set up • Designed for DB-API integration • User-defined Tuesday, October 20, 2009
  42. 42. User Definitions base = Except(InternalError, { 'PermissionError': PermissionError, 'UnknownUser': UnknownUserError, 'NotFoundException': NotFoundError, }) Tuesday, October 20, 2009
  43. 43. Our Python Example • The Exceptable decorator is easy to set up • Designed for DB-API integration • User-defined, and soon, table introspection Tuesday, October 20, 2009
  44. 44. base is a decorator @base def db_api(query): con = db.connect(conn_string) cur = con.cursor() return cur(query) Tuesday, October 20, 2009
  45. 45. Which leads to try: rs = db_api(‘select * from test_api()’) except NotFoundError, e: # A hah! A usable error! pass Tuesday, October 20, 2009
  46. 46. As Opposed To try: rs = db_api(‘select * from test_api()’) except InternalError, e: if “NotFoundException” in str(e): raise NotFoundError(str(e)) elif “PermissionsError” in str(e): raise PermissionsError(str(e)) Tuesday, October 20, 2009
  47. 47. Our Python Example • The Exceptable decorator is easy to set up • Designed for DB-API integration • User-defined, and soon, table introspection • Existing decorators can be expanded easily Tuesday, October 20, 2009
  48. 48. Grow, my Pretties! class NotNullError(BaseException): pass class SCE(BaseException): pass base.add({ ‘NotNullException’: NotNullError, ‘SufficientCoffeeException’: SCE }) Tuesday, October 20, 2009
  49. 49. Permission Denied • Exceptable.py also wraps the base permission denied • DB permissions violations work at the app level Tuesday, October 20, 2009
  50. 50. Vertically Challenged a = c.Function(‘test_auth’); try: result = a() except PermissionDenied, e: abort(403) except NoSuchUser, e: abort(401) Tuesday, October 20, 2009
  51. 51. AND THUS Questions? Tuesday, October 20, 2009
  52. 52. Get It! https://projects.commandprompt.com/ public/exceptable/ Tuesday, October 20, 2009
  53. 53. THANK YOU! Tuesday, October 20, 2009

×