nodes: 0, module; 1, function_definition; 2, function_name:find_column; 3, parameters; 4, block; 5, identifier:self; 6, identifier:search; 7, default_parameter; 8, expression_statement; 9, if_statement; 10, expression_statement; 11, for_statement; 12, return_statement; 13, identifier:data_type; 14, None; 15, comment:"""
          Aggresively search through your database's schema for a column.
  
          Parameters
          -----------
          search: str
             glob pattern for what you're looking for
          data_type: str, list
             (optional) specify which data type(s) you want to return
  
          Examples
          ----------
          >>> from db import DemoDB
          >>> db = DemoDB()
          >>> len(db.find_column("Name").columns)
          5
          >>> len(db.find_column("*Id").columns)
          20
          >>> len(db.find_column("*Address*").columns)
          3
          >>> len(db.find_column("*Address*", data_type="NVARCHAR(70)").columns)
          3
          >>> len(db.find_column("*e*", data_type=["NVARCHAR(70)", "INTEGER"]).columns)
          17
  
          -= Should sort in some way for all those doctests to be viable...
          -= if not, there's always a random issue where rows are not in the same order, making doctest fail.
          db.find_column("Name") # returns all columns named "Name"
          +-----------+-------------+---------------+
          | Table     | Column Name | Type          |
          +-----------+-------------+---------------+
          | Artist    |     Name    | NVARCHAR(120) |
          | Genre     |     Name    | NVARCHAR(120) |
          | MediaType |     Name    | NVARCHAR(120) |
          | Playlist  |     Name    | NVARCHAR(120) |
          | Track     |     Name    | NVARCHAR(200) |
          +-----------+-------------+---------------+
          db.find_column("*Id") # returns all columns ending w/ Id
          +---------------+---------------+---------+
          | Table         |  Column Name  | Type    |
          +---------------+---------------+---------+
          | Album         |    AlbumId    | INTEGER |
          | Album         |    ArtistId   | INTEGER |
          | Artist        |    ArtistId   | INTEGER |
          | Customer      |  SupportRepId | INTEGER |
          | Customer      |   CustomerId  | INTEGER |
          | Employee      |   EmployeeId  | INTEGER |
          | Genre         |    GenreId    | INTEGER |
          | Invoice       |   InvoiceId   | INTEGER |
          | Invoice       |   CustomerId  | INTEGER |
          | InvoiceLine   |    TrackId    | INTEGER |
          | InvoiceLine   | InvoiceLineId | INTEGER |
          | InvoiceLine   |   InvoiceId   | INTEGER |
          | MediaType     |  MediaTypeId  | INTEGER |
          | Playlist      |   PlaylistId  | INTEGER |
          | PlaylistTrack |    TrackId    | INTEGER |
          | PlaylistTrack |   PlaylistId  | INTEGER |
          | Track         |    TrackId    | INTEGER |
          | Track         |    AlbumId    | INTEGER |
          | Track         |  MediaTypeId  | INTEGER |
          | Track         |    GenreId    | INTEGER |
          +---------------+---------------+---------+
          db.find_column("*Address*") # returns all columns containing Address
          +----------+----------------+--------------+
          | Table    |  Column Name   | Type         |
          +----------+----------------+--------------+
          | Customer |    Address     | NVARCHAR(70) |
          | Employee |    Address     | NVARCHAR(70) |
          | Invoice  | BillingAddress | NVARCHAR(70) |
          +----------+----------------+--------------+
          db.find_column("*Address*", data_type="NVARCHAR(70)") # returns all columns containing Address that are varchars
          +----------+----------------+--------------+
          | Table    |  Column Name   | Type         |
          +----------+----------------+--------------+
          | Customer |    Address     | NVARCHAR(70) |
          | Employee |    Address     | NVARCHAR(70) |
          | Invoice  | BillingAddress | NVARCHAR(70) |
          +----------+----------------+--------------+
          db.find_column("*e*", data_type=["NVARCHAR(70)", "INTEGER"]) # returns all columns have an "e" and are NVARCHAR(70)S or INTEGERS
          +-------------+----------------+--------------+
          | Table       |  Column Name   | Type         |
          +-------------+----------------+--------------+
          | Customer    |    Address     | NVARCHAR(70) |
          | Customer    |  SupportRepId  | INTEGER      |
          | Customer    |   CustomerId   | INTEGER      |
          | Employee    |   ReportsTo    | INTEGER      |
          | Employee    |   EmployeeId   | INTEGER      |
          | Employee    |    Address     | NVARCHAR(70) |
          | Genre       |    GenreId     | INTEGER      |
          | Invoice     |   InvoiceId    | INTEGER      |
          | Invoice     |   CustomerId   | INTEGER      |
          | Invoice     | BillingAddress | NVARCHAR(70) |
          | InvoiceLine | InvoiceLineId  | INTEGER      |
          | InvoiceLine |   InvoiceId    | INTEGER      |
          | MediaType   |  MediaTypeId   | INTEGER      |
          | Track       |  MediaTypeId   | INTEGER      |
          | Track       |  Milliseconds  | INTEGER      |
          | Track       |    GenreId     | INTEGER      |
          | Track       |     Bytes      | INTEGER      |
          +-------------+----------------+--------------+
          """; 16, call; 17, block; 18, assignment; 19, identifier:table; 20, attribute; 21, block; 22, call; 23, identifier:isinstance; 24, argument_list; 25, expression_statement; 26, identifier:cols; 27, list; 28, identifier:self; 29, identifier:tables; 30, for_statement; 31, identifier:ColumnSet; 32, argument_list; 33, identifier:data_type; 34, identifier:str; 35, assignment; 36, identifier:col; 37, call; 38, block; 39, identifier:cols; 40, identifier:data_type; 41, list; 42, identifier:vars; 43, argument_list; 44, if_statement; 45, identifier:data_type; 46, identifier:table; 47, call; 48, block; 49, attribute; 50, argument_list; 51, if_statement; 52, if_statement; 53, attribute; 54, identifier:fnmatch; 55, identifier:col; 56, identifier:search; 57, boolean_operator; 58, block; 59, call; 60, block; 61, identifier:glob; 62, identifier:fnmatch; 63, boolean_operator; 64, comparison_operator:getattr(table, col).type not in data_type; 65, continue_statement; 66, identifier:isinstance; 67, argument_list; 68, expression_statement; 69, identifier:data_type; 70, call; 71, attribute; 72, identifier:data_type; 73, call; 74, identifier:Column; 75, call; 76, identifier:isinstance; 77, argument_list; 78, call; 79, identifier:type; 80, identifier:getattr; 81, argument_list; 82, attribute; 83, argument_list; 84, call; 85, identifier:Column; 86, identifier:getattr; 87, argument_list; 88, identifier:table; 89, identifier:col; 90, identifier:cols; 91, identifier:append; 92, call; 93, identifier:getattr; 94, argument_list; 95, identifier:table; 96, identifier:col; 97, identifier:getattr; 98, argument_list; 99, identifier:table; 100, identifier:col; 101, identifier:table; 102, identifier:col
code: def find_column(self, search, data_type=None):
          """
          Aggresively search through your database's schema for a column.
  
          Parameters
          -----------
          search: str
             glob pattern for what you're looking for
          data_type: str, list
             (optional) specify which data type(s) you want to return
  
          Examples
          ----------
          >>> from db import DemoDB
          >>> db = DemoDB()
          >>> len(db.find_column("Name").columns)
          5
          >>> len(db.find_column("*Id").columns)
          20
          >>> len(db.find_column("*Address*").columns)
          3
          >>> len(db.find_column("*Address*", data_type="NVARCHAR(70)").columns)
          3
          >>> len(db.find_column("*e*", data_type=["NVARCHAR(70)", "INTEGER"]).columns)
          17
  
          -= Should sort in some way for all those doctests to be viable...
          -= if not, there's always a random issue where rows are not in the same order, making doctest fail.
          db.find_column("Name") # returns all columns named "Name"
          +-----------+-------------+---------------+
          | Table     | Column Name | Type          |
          +-----------+-------------+---------------+
          | Artist    |     Name    | NVARCHAR(120) |
          | Genre     |     Name    | NVARCHAR(120) |
          | MediaType |     Name    | NVARCHAR(120) |
          | Playlist  |     Name    | NVARCHAR(120) |
          | Track     |     Name    | NVARCHAR(200) |
          +-----------+-------------+---------------+
          db.find_column("*Id") # returns all columns ending w/ Id
          +---------------+---------------+---------+
          | Table         |  Column Name  | Type    |
          +---------------+---------------+---------+
          | Album         |    AlbumId    | INTEGER |
          | Album         |    ArtistId   | INTEGER |
          | Artist        |    ArtistId   | INTEGER |
          | Customer      |  SupportRepId | INTEGER |
          | Customer      |   CustomerId  | INTEGER |
          | Employee      |   EmployeeId  | INTEGER |
          | Genre         |    GenreId    | INTEGER |
          | Invoice       |   InvoiceId   | INTEGER |
          | Invoice       |   CustomerId  | INTEGER |
          | InvoiceLine   |    TrackId    | INTEGER |
          | InvoiceLine   | InvoiceLineId | INTEGER |
          | InvoiceLine   |   InvoiceId   | INTEGER |
          | MediaType     |  MediaTypeId  | INTEGER |
          | Playlist      |   PlaylistId  | INTEGER |
          | PlaylistTrack |    TrackId    | INTEGER |
          | PlaylistTrack |   PlaylistId  | INTEGER |
          | Track         |    TrackId    | INTEGER |
          | Track         |    AlbumId    | INTEGER |
          | Track         |  MediaTypeId  | INTEGER |
          | Track         |    GenreId    | INTEGER |
          +---------------+---------------+---------+
          db.find_column("*Address*") # returns all columns containing Address
          +----------+----------------+--------------+
          | Table    |  Column Name   | Type         |
          +----------+----------------+--------------+
          | Customer |    Address     | NVARCHAR(70) |
          | Employee |    Address     | NVARCHAR(70) |
          | Invoice  | BillingAddress | NVARCHAR(70) |
          +----------+----------------+--------------+
          db.find_column("*Address*", data_type="NVARCHAR(70)") # returns all columns containing Address that are varchars
          +----------+----------------+--------------+
          | Table    |  Column Name   | Type         |
          +----------+----------------+--------------+
          | Customer |    Address     | NVARCHAR(70) |
          | Employee |    Address     | NVARCHAR(70) |
          | Invoice  | BillingAddress | NVARCHAR(70) |
          +----------+----------------+--------------+
          db.find_column("*e*", data_type=["NVARCHAR(70)", "INTEGER"]) # returns all columns have an "e" and are NVARCHAR(70)S or INTEGERS
          +-------------+----------------+--------------+
          | Table       |  Column Name   | Type         |
          +-------------+----------------+--------------+
          | Customer    |    Address     | NVARCHAR(70) |
          | Customer    |  SupportRepId  | INTEGER      |
          | Customer    |   CustomerId   | INTEGER      |
          | Employee    |   ReportsTo    | INTEGER      |
          | Employee    |   EmployeeId   | INTEGER      |
          | Employee    |    Address     | NVARCHAR(70) |
          | Genre       |    GenreId     | INTEGER      |
          | Invoice     |   InvoiceId    | INTEGER      |
          | Invoice     |   CustomerId   | INTEGER      |
          | Invoice     | BillingAddress | NVARCHAR(70) |
          | InvoiceLine | InvoiceLineId  | INTEGER      |
          | InvoiceLine |   InvoiceId    | INTEGER      |
          | MediaType   |  MediaTypeId   | INTEGER      |
          | Track       |  MediaTypeId   | INTEGER      |
          | Track       |  Milliseconds  | INTEGER      |
          | Track       |    GenreId     | INTEGER      |
          | Track       |     Bytes      | INTEGER      |
          +-------------+----------------+--------------+
          """
          if isinstance(data_type, str):
              data_type = [data_type]
          cols = []
          for table in self.tables:
              for col in vars(table):
                  if glob.fnmatch.fnmatch(col, search):
                      if data_type and isinstance(getattr(table, col), Column) and getattr(table, col).type not in data_type:
                          continue
                      if isinstance(getattr(table, col), Column):
                          cols.append(getattr(table, col))
          return ColumnSet(cols)