extract_table_names.py 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. #!/usr/bin/env python
  2. # pylint: disable=C,R,W
  3. #
  4. # Copyright (C) 2016 Andi Albrecht, albrecht.andi@gmail.com
  5. #
  6. # This example is part of python-sqlparse and is released under
  7. # the BSD License: http://www.opensource.org/licenses/bsd-license.php
  8. #
  9. # This example illustrates how to extract table names from nested
  10. # SELECT statements.
  11. #
  12. # See:
  13. # http://groups.google.com/group/sqlparse/browse_thread/thread/b0bd9a022e9d4895
  14. import sqlparse
  15. from sqlparse.sql import Identifier, IdentifierList
  16. from sqlparse.tokens import DML, Keyword
  17. def is_subselect(parsed):
  18. if not parsed.is_group():
  19. return False
  20. for item in parsed.tokens:
  21. if item.ttype is DML and item.value.upper() == 'SELECT':
  22. return True
  23. return False
  24. def extract_from_part(parsed):
  25. from_seen = False
  26. for item in parsed.tokens:
  27. if from_seen:
  28. if is_subselect(item):
  29. for x in extract_from_part(item):
  30. yield x
  31. elif item.ttype is Keyword:
  32. raise StopIteration
  33. else:
  34. yield item
  35. elif item.ttype is Keyword and item.value.upper() == 'FROM':
  36. from_seen = True
  37. def extract_table_identifiers(token_stream):
  38. for item in token_stream:
  39. if isinstance(item, IdentifierList):
  40. for identifier in item.get_identifiers():
  41. yield identifier.get_name()
  42. elif isinstance(item, Identifier):
  43. yield item.get_name()
  44. # It's a bug to check for Keyword here, but in the example
  45. # above some tables names are identified as keywords...
  46. elif item.ttype is Keyword:
  47. yield item.value
  48. # TODO(bkyryliuk): add logic to support joins and unions.
  49. def extract_tables(sql):
  50. stream = extract_from_part(sqlparse.parse(sql)[0])
  51. return list(extract_table_identifiers(stream))