Exemplo n.º 1
0
    def _test_dataConversion_aggregate(self):
        # Run the data conversion on the same data and look for expected records
        log.debug("Run the conversion process...")
        convOptions = ConversionOptions()
        convOptions.startDate = TEST_START_DATE
        convOptions.aggregate = True
        self.converter.convertSourceItems(convOptions)

        # Just query back for the same data, de-normalizing the data back to a general table
        testQuery = \
            """
            select 
                pi.external_id as pi_external_id,
                pi.patient_id,
                pi.encounter_id,
                cic.description as cic_description,
                ci.external_id as ci_external_id,
                ci.name,
                ci.description as ci_description,
                pi.item_date
            from
                %s.patient_item as pi,
                %s.clinical_item as ci,
                %s.clinical_item_category as cic
            where
                pi.clinical_item_id = ci.clinical_item_id and
                ci.clinical_item_category_id = cic.clinical_item_category_id and
                cic.source_table = '%s'
            order by
                pi.external_id desc, ci.external_id desc
            """ % (TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_SOURCE_TABLE)
        expectedData = \
            []
        actualData = DBUtil.execute(testQuery)
        self.assertEqualTable(expectedData, actualData)
Exemplo n.º 2
0
    def convertSourceItems(self, convOptions, conn=None):
        """Primary run function to process the contents of the raw source
        table and convert them into equivalent patient_item, clinical_item, and clinical_item_category entries.
        Should look for redundancies after the fact to catch repeated conversions.

        startDate - If provided, only return items whose ordering_date is on or after that date.
        endDate - If provided, only return items whose ordering_date is before that date.
        """
        log.info("Conversion for items dated %s to %s" %
                 (convOptions.startDate, convOptions.endDate))
        progress = ProgressDots()

        extConn = conn is not None
        if not extConn:
            conn = self.connFactory.connection()

        try:
            # Next round for medications directly from order_med table not addressed in medmix  TODO (nodir) seems like an unrelated comment?
            category = self.categoryFromSourceItem(conn)
            for sourceItem in self.querySourceItems(convOptions):
                log.debug('sourceItem: {}'.format(sourceItem))
                self.convertSourceItem(category, sourceItem, conn=conn)
                progress.Update()

        finally:
            conn.close()

        progress.PrintStatus()
    def generate_test_and_expected_data(self, test_data_size, aggregate):
        for curr_row in range(test_data_size):
            patient_id = 'JC' + format(curr_row, '06')
            test_data_row = self.generate_test_data_row(curr_row, self.starrUtil.random_period(), patient_id)
            self.test_data.append(test_data_row)
            self.generate_expected_data_rows(test_data_row, self.expected_data, aggregate)

        # pi.external_id desc (ci.external_id is always None, so not included here)
        self.expected_data.sort(key=lambda tup: (-tup[0]))

        log.debug('test_data: {}'.format(self.test_data))
        log.debug('expected_data: {}'.format(self.expected_data))
Exemplo n.º 4
0
    def test_dataConversion(self):
        # Run the data conversion on the same data and look for expected records
        log.debug("Run the conversion process...")
        convOptions = ConversionOptions()
        convOptions.startDate = TEST_START_DATE
        #self.converter.convertSourceItems(convOptions)
        tempDir = '/tmp'
        self.converter.convertAndUpload(convOptions,
                                        tempDir=tempDir,
                                        datasetId=TEST_DEST_DATASET)

        # Just query back for the same data, de-normalizing the data back to a general table
        testQuery = \
            """
            select
                pi.external_id as pi_external_id,
                pi.patient_id,
                pi.encounter_id,
                cic.description as cic_description,
                ci.external_id as ci_external_id,
                ci.name,
                ci.description as ci_description,
                pi.item_date
            from
                %s.patient_item as pi,
                %s.clinical_item as ci,
                %s.clinical_item_category as cic
            where
                pi.clinical_item_id = ci.clinical_item_id and
                ci.clinical_item_category_id = cic.clinical_item_category_id and
                cic.source_table = '%s'
            order by
                pi.external_id desc, ci.external_id desc
            """ % (TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_SOURCE_TABLE)

        self.starrUtil.dumpClinicalTablesToCsv(tempDir)
        self.starrUtil.uploadClinicalTablesCsvToBQ(tempDir, TEST_DEST_DATASET)
        self.starrUtil.removeClinicalTablesCsv(tempDir)
        self.starrUtil.removeClinicalTablesAddedLines(TEST_SOURCE_TABLE)

        expectedData = STARRExpectedData().treatmentteam_expected

        bqCursor = self.bqConn.cursor()
        bqCursor.execute(testQuery)
        actualData = [row.values() for row in bqCursor.fetchall()]
        #print('actual data %s' % actualData)
        self.assertEqualTable(expectedData, actualData)
Exemplo n.º 5
0
    def querySourceItems(self, convOptions):
        """Query the database for list of all source clinical items (medications, etc.)
        and yield the results one at a time.  If startDate provided, only return items whose
        occurrence date is on or after that date.
        """
        # TODO need to figure out how to pass date to query in BQ using SQLQuery object
        query = "SELECT {} FROM {}".format(', '.join(self.HEADERS),
                                           SOURCE_TABLE)

        if convOptions.startDate is not None:
            query += ' WHERE trtmnt_tm_begin_dt_jittered >= @startDate '
        if convOptions.endDate is not None:
            query += ' WHERE ' if convOptions.startDate is None else 'AND'
            query += ' trtmnt_tm_begin_dt_jittered < @endDate'

        query += ' ORDER BY trtmnt_tm_begin_dt_jittered'
        query += ';'

        query_params = [
            bigquery.ScalarQueryParameter(
                'startDate',
                'TIMESTAMP',
                convOptions.startDate,
            ),
            bigquery.ScalarQueryParameter(
                'endDate',
                'TIMESTAMP',
                convOptions.endDate,
            )
        ]

        query_job = self.bqClient.queryBQ(str(query),
                                          query_params=query_params,
                                          location='US',
                                          batch_mode=False,
                                          verbose=True)

        for row in query_job:  # API request - fetches results
            rowModel = RowItemModel(list(row.values()), self.HEADERS)
            log.debug("rowModel: {}".format(rowModel))
            yield self.normalizeRowModel(
                rowModel, convOptions
            )  # Yield one row worth of data at a time to avoid having to keep the whole result set in memory
    def test_batchDataConversion(self):
        # Run the data conversion on the same data and look for expected records
        log.debug(
            "Run the batch conversion process, and upload to test dataset in BigQuery..."
        )
        self.converter.convertItemsByBatch(self.pat_id_csv,
                                           10,
                                           datasetId=TEST_DEST_DATASET,
                                           startBatch=4)

        # Just query back for the same data, de-normalizing the data back to a general table
        testQuery = \
            """
            select 
                pi.external_id as pi_external_id,
                pi.patient_id,
                pi.encounter_id,
                cic.description as cic_description,
                ci.external_id as ci_external_id,
                ci.name,
                ci.description as ci_description,
                pi.item_date
            from
                %s.patient_item as pi,
                %s.clinical_item as ci,
                %s.clinical_item_category as cic
            where
                pi.clinical_item_id = ci.clinical_item_id and
                ci.clinical_item_category_id = cic.clinical_item_category_id and
                cic.source_table = '%s'
            order by
                pi.patient_id desc, ci.name
            """ % (TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_SOURCE_TABLE)

        expectedData = STARRExpectedData().demographics_expected

        bqCursor = self.bqConn.cursor()
        bqCursor.execute(testQuery)
        actualData = [row.values() for row in bqCursor.fetchall()]
        #print('actual data %s' % actualData)
        self.assertEqualTable(expectedData, actualData)
    def test_dataConversion(self, name, aggregation):
        log.info("Generating test source data")
        self.generate_test_and_expected_data(self.TEST_DATA_SIZE,
                                             aggregate=aggregation)
        self.starrUtil.dump_test_data_to_csv(self.converter.HEADERS,
                                             self.test_data,
                                             self.test_data_csv)
        self.starrUtil.upload_csv_to_bigquery(
            'starr_datalake2018', 'treatment_team', TEST_DEST_DATASET,
            'starr_treatment_team', self.test_data_csv, self.converter.HEADERS)

        log.debug("Run the conversion process...")
        conv_options = STARRTreatmentTeamConversion.ConversionOptions()
        conv_options.aggregate = aggregation
        temp_dir = tempfile.gettempdir()
        self.converter.convertAndUpload(conv_options,
                                        tempDir=temp_dir,
                                        targetDatasetId=TEST_DEST_DATASET)

        # Just query back for the same data, de-normalizing the data back to a general table
        test_query = \
            """
            select
                pi.external_id as pi_external_id,
                pi.patient_id,
                pi.encounter_id,
                cic.description as cic_description,
                ci.external_id as ci_external_id,
                ci.name,
                ci.description as ci_description,
                pi.item_date,
                pi.item_date_utc
            from
                %s.patient_item as pi,
                %s.clinical_item as ci,
                %s.clinical_item_category as cic
            where
                pi.clinical_item_id = ci.clinical_item_id and
                ci.clinical_item_category_id = cic.clinical_item_category_id and
                cic.source_table = '%s'
            order by
                pi.external_id desc, ci.external_id desc
            """ % (TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_SOURCE_TABLE)

        bq_cursor = self.bqConn.cursor()
        bq_cursor.execute(test_query)
        actual_data = [row.values() for row in bq_cursor.fetchall()]
        log.debug('actual data: {}'.format(actual_data))
        log.debug('expected data: {}'.format(self.expected_data))
        self.assertEqualTable(self.expected_data, actual_data)
Exemplo n.º 8
0
    def querySourceItems(self,
                         startDate=None,
                         endDate=None,
                         progress=None,
                         conn=None):
        """Query the database for list of all source clinical items (orders, etc.)
        and yield the results one at a time.  If startDate provided, only return items whose order_time is on or after that date.
        Ignore entries with instantiated_time not null, as those represent child orders spawned from an original order,
        whereas we are more interested in the decision making to enter the original order.
        """
        extConn = conn is not None
        if not extConn:
            conn = self.connFactory.connection()

        # Column headers to query for that map to respective fields in analysis table
        queryHeaders = [
            "op.order_proc_id_coded", "jc_uid", "op.pat_enc_csn_id_coded",
            "op.order_type", "op.proc_id", "op.proc_code", "description",
            "order_time_jittered", "order_time_jittered_utc", "ordering_mode",
            "protocol_id", "protocol_name", "ss_section_id", "ss_section_name",
            "ss_sg_key", "ss_sg_name"
        ]
        headers = [
            "order_proc_id_coded", "jc_uid", "pat_enc_csn_id_coded",
            "order_type", "proc_id", "proc_code", "description",
            "order_time_jittered", "order_time_jittered_utc", "ordering_mode",
            "protocol_id", "protocol_name", "ss_section_id", "ss_section_name",
            "ss_sg_key", "ss_sg_name"
        ]

        # TODO original query - need to figure out how to pass date to query in BQ using SQLQuery object
        # query = SQLQuery()
        # for header in queryHeaders:
        #     query.addSelect(header)
        # query.addFrom("stride_order_proc as op left outer join stride_orderset_order_proc as os on op.order_proc_id = os.order_proc_id")
        # query.addWhere("order_time is not null")    # Rare cases of "comment" orders with no date/time associated
        # query.addWhere("instantiated_time is null")
        # query.addWhere("(stand_interval is null or stand_interval not like '%%PRN')")   # Ignore PRN orders to simplify somewhat
        # if startDate is not None:
        #     query.addWhereOp("order_time", ">=", startDate)
        # if endDate is not None:
        #     query.addWhereOp("order_time", "<", endDate)

        query = "SELECT {} FROM {} as op left outer join {} as os on op.order_proc_id_coded = os.order_proc_id_coded" \
            .format(', '.join(queryHeaders), SOURCE_TABLE, ORDERSET_TABLE)

        query += " where order_time_jittered is not null"  # Rare cases of "comment" orders with no date/time associated
        query += " and (stand_interval is NULL or stand_interval not like '%PRN')"  # Ignore PRN orders to simplify somewhat
        if startDate is not None:
            query += " and order_time_jittered >= @startDate"
        if endDate is not None:
            query += " and order_time_jittered < @endDate"
        query += " order by order_time_jittered"
        # query += " order by op.order_proc_id_coded, jc_uid, op.pat_enc_csn_id_coded, op.proc_id"
        query += ';'

        query_params = [
            bigquery.ScalarQueryParameter(
                'startDate',
                'DATETIME',
                startDate,
            ),
            bigquery.ScalarQueryParameter(
                'endDate',
                'DATETIME',
                endDate,
            )
        ]

        # TODO Query to get an estimate of how long the process will be
        # if progress is not None:
        #     progress.total = DBUtil.execute(query.totalQuery(), conn=conn)[0][0]

        query_job = self.bqClient.queryBQ(query,
                                          query_params=query_params,
                                          verbose=True)

        for row in query_job:  # API request - fetches results
            rowModel = RowItemModel(list(row.values()), headers)
            log.debug("rowModel: {}".format(rowModel))
            yield rowModel  # Yield one row worth of data at a time to avoid having to keep the whole result set in memory

        if not extConn:
            conn.close()
Exemplo n.º 9
0
    def test_data_conversion(self):
        log.info("Generating test source data")

        self.generate_test_and_expected_data(self.TEST_DATA_SIZE)

        # upload proc_orderset
        self.starrUtil.dump_test_data_to_csv(self.PROC_ORDERSET_HEADER,
                                             self.orderset_data,
                                             self.orderset_data_csv)
        self.starrUtil.upload_csv_to_bigquery('starr_datalake2018',
                                              'proc_orderset',
                                              TEST_DEST_DATASET,
                                              'starr_proc_orderset',
                                              self.orderset_data_csv,
                                              self.PROC_ORDERSET_HEADER)

        # upload order_proc
        self.starrUtil.dump_test_data_to_csv(self.ORDER_PROC_HEADER,
                                             self.test_data,
                                             self.test_data_csv)
        self.starrUtil.upload_csv_to_bigquery('starr_datalake2018',
                                              'order_proc', TEST_DEST_DATASET,
                                              'starr_order_proc',
                                              self.test_data_csv,
                                              self.ORDER_PROC_HEADER)

        log.debug("Run the conversion process...")
        # temp_dir = tempfile.gettempdir()
        # self.converter.convertAndUpload(tempDir=temp_dir, target_dataset_id=TEST_DEST_DATASET, removeCsvs=True)
        self.converter.main(["test_order_proc"])

        # Just query back for the same data, de-normalizing the data back to a general table
        test_query = \
            """
            select
                pi.external_id as pi_external_id,
                pi.patient_id,
                pi.encounter_id,
                cic.description as cic_description,
                ci.external_id as ci_external_id,
                ci.name,
                ci.description as ci_description,
                pi.item_date,
                pi.item_date_utc
            from
                {}.patient_item as pi,
                {}.clinical_item as ci,
                {}.clinical_item_category as cic
            where
                pi.clinical_item_id = ci.clinical_item_id and
                ci.clinical_item_category_id = cic.clinical_item_category_id and
                cic.source_table = '{}'
            order by
                pi.external_id desc, pi.patient_id, pi.encounter_id, ci.external_id desc
            """.format(TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_SOURCE_TABLE)

        bq_cursor = self.bqConn.cursor()
        bq_cursor.execute(test_query)
        # remove timezone info in pi.item_date from coming from bigquery - we're storing datetime without timezone
        actual_data = [
            row.values()[:7] + (
                row.values()[7].replace(tzinfo=None),
                row.values()[8],
            ) for row in bq_cursor.fetchall()
        ]

        log.debug('actual data: {}'.format(actual_data))
        log.debug('expected data: {}'.format(self.expected_data))
        self.assertEqualTable(self.expected_data, actual_data)

        # Query for orderset links
        test_orderset_query = \
            """
            select
                pi.external_id as pi_external_id,
                ci.external_id as ci_external_id,
                cic.description as cic_description,
                ci.name as ci_name,
                ci.description,
                ic.external_id,
                ic.name,
                ic.section,
                ic.subgroup
            from
                {}.patient_item as pi,
                {}.clinical_item as ci,
                {}.clinical_item_category as cic,
                {}.patient_item_collection_link as picl,
                {}.item_collection_item as ici,
                {}.item_collection as ic
            where
                pi.clinical_item_id = ci.clinical_item_id and
                ci.clinical_item_category_id = cic.clinical_item_category_id and
                cic.source_table = '{}' and
                pi.patient_item_id = picl.patient_item_id and
                picl.item_collection_item_id = ici.item_collection_item_id and
                ici.item_collection_id = ic.item_collection_id
            order by
                pi.external_id, ci.external_id, cic.description, ci.name, ci.description
            """.format(TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_DEST_DATASET, TEST_DEST_DATASET,
                       TEST_DEST_DATASET, TEST_SOURCE_TABLE)

        bq_cursor.execute(test_orderset_query)
        actual_orderset_data = [row.values() for row in bq_cursor.fetchall()]

        log.debug('actual orderset data: {}'.format(actual_orderset_data))
        log.debug('expected orderset data: {}'.format(
            self.expected_orderset_data))
        self.assertEqualTable(self.expected_orderset_data,
                              actual_orderset_data)
Exemplo n.º 10
0
    def querySourceItems(self,
                         rxcuiDataByMedId,
                         convOptions,
                         progress=None,
                         conn=None):
        """Query the database for list of all source clinical items (medications, etc.)
        and yield the results one at a time.  If startDate provided, only return items whose
        order_time_jittered is on or after that date.
        """
        # Column headers to query for that map to respective fields in analysis table
        queryHeaders = [
            "med.order_med_id_coded", "jc_uid", "med.pat_enc_csn_id_coded",
            "med.medication_id", "med.med_description", "order_time_jittered",
            "order_time_jittered_utc", "med_route", "number_of_times",
            "protocol_id", "protocol_name", "ss_section_id", "ss_section_name",
            "ss_sg_key", "ss_sg_name", "ordering_mode"
        ]

        headers = [
            "order_med_id_coded", "jc_uid", "pat_enc_csn_id_coded",
            "medication_id", "med_description", "order_time_jittered",
            "order_time_jittered_utc", "med_route", "number_of_times",
            "protocol_id", "protocol_name", "ss_section_id", "ss_section_name",
            "ss_sg_key", "ss_sg_name", "ordering_mode"
        ]

        # TODO original query - need to figure out how to pass date to query in BQ using SQLQuery object
        # query = SQLQuery()
        # for header in queryHeaders:
        #     query.addSelect(header)
        # query.addFrom("stride_order_med as med left outer join stride_orderset_order_med as os on med.order_med_id = os.order_med_id")  # Grab order set links if they exist
        # query.addWhere("med.medication_id <> %s" % TEMPLATE_MEDICATION_ID)
        # query.addWhere("freq_name not like '%%PRN'")    # Ignore PRN orders
        # if convOptions.startDate is not None:
        #     query.addWhereOp("ordering_date",">=", convOptions.startDate)
        # if convOptions.endDate is not None:
        #     query.addWhereOp("ordering_date","<", convOptions.endDate)

        query = "SELECT {} FROM {} as med left outer join {} as os on med.order_med_id_coded = os.order_med_id_coded".format(
            ', '.join(queryHeaders), SOURCE_TABLE, ORDERSET_TABLE)

        # TODO only 20 records with medication_id = TEMPLATE_MEDICATION_ID (whereas stride has 67041 such rows)
        query += " where med.medication_id <> {}".format(
            TEMPLATE_MEDICATION_ID)
        query += " and (freq_name is NULL or freq_name not like '%PRN')"  # Ignore PRN orders
        if convOptions.startDate is not None:
            query += " and order_time_jittered >= @startDate"
        if convOptions.endDate is not None:
            query += " and order_time_jittered < @endDate"
        query += " order by order_time_jittered, med.order_med_id_coded, jc_uid, med.pat_enc_csn_id_coded, med.medication_id"
        query += ';'

        query_params = [
            bigquery.ScalarQueryParameter(
                'startDate',
                'DATETIME',
                convOptions.startDate,
            ),
            bigquery.ScalarQueryParameter(
                'endDate',
                'DATETIME',
                convOptions.endDate,
            )
        ]

        # TODO Query to get an estimate of how long the process will be
        # if progress is not None:
        #     progress.total = DBUtil.execute(query.totalQuery(), conn=conn)[0][0]

        query_job = self.bqClient.queryBQ(query,
                                          query_params=query_params,
                                          verbose=True)

        for row in query_job:  # API request - fetches results
            rowModel = RowItemModel(row.values(), headers)
            log.debug("rowModel: {}".format(rowModel))
            for normalizedModel in self.normalizeMedData(
                    rxcuiDataByMedId, rowModel, convOptions):
                yield normalizedModel  # Yield one row worth of data at a time to avoid having to keep the whole result set in memory
    def querySourceItems(self, patientIds=None, progress=None, debug=False):
        """Query the database for list of all patient demographics
        and yield the results one at a time.  If patientIds provided, only return items
        matching those IDs.
        """
        # Column headers to query for that map to respective fields in analysis table
        headers = ["rit_uid", "birth_date_jittered", "gender", "death_date_jittered", "canonical_race",
                   "canonical_ethnicity"]

        '''
        query = SQLQuery()
        for header in headers:
            query.addSelect( header )
        query.addFrom(SOURCE_TABLE + " as dem")
        if patientIds is not None:
            query.addWhereIn("dem.rit_uid", patientIds)
        '''

        query = '''
                SELECT rit_uid,birth_date_jittered,gender,death_date_jittered,canonical_race,canonical_ethnicity
                FROM %s as dem
                WHERE dem.rit_uid IN UNNEST(@pat_ids)
                ORDER BY rit_uid;
                ''' % SOURCE_TABLE

        query_params = [
            bigquery.ArrayQueryParameter('pat_ids', 'STRING', patientIds)
        ]

        if debug:
            print(query)
            print(query_params)

        query_job = self.bqClient.queryBQ(str(query), query_params=query_params, location='US', batch_mode=False,
                                          verbose=True)

        previous_rit_uid = None
        rows_fetched = 0
        for row in query_job:  # API request - fetches results
            rows_fetched += 1
            # Row values can be accessed by field name or index
            # assert row[0] == row.name == row["name"]
            rowModel = RowItemModel(row.values(), headers)

            # skip this record if we already processed this rit_uid
            if rowModel["rit_uid"] == previous_rit_uid:
                continue

            if rowModel["birth_date_jittered"] is None:
                # Blank values, doesn't make sense.  Skip it
                log.warning(rowModel)
            else:
                # Record birth at resolution of year
                rowModel["itemDate"] = datetime(rowModel["birth_date_jittered"].year, 1, 1)
                rowModel["name"] = "Birth"
                rowModel["description"] = "Birth Year"
                yield rowModel

                # Record another at resolution of decade
                decade = (rowModel["birth_date_jittered"].year / 10) * 10
                rowModel["itemDate"] = datetime(rowModel["birth_date_jittered"].year, 1, 1)
                rowModel["name"] = "Birth%ds" % decade
                rowModel["description"] = "Birth Decade %ds" % decade
                yield rowModel

                # Summarize race and ethnicity information into single field of interest
                raceEthnicity = self.summarizeRaceEthnicity(rowModel["canonical_race"], rowModel["canonical_ethnicity"])
                rowModel["itemDate"] = datetime(rowModel["birth_date_jittered"].year, 1, 1)
                rowModel["name"] = "Race" + (raceEthnicity.translate(None, " ()-/"))  # Strip off punctuation
                rowModel["description"] = "Race/Ethnicity: %s" % raceEthnicity
                yield rowModel

                gender = rowModel["gender"].title()
                rowModel["name"] = gender
                rowModel["description"] = "%s Gender" % gender
                yield rowModel

                if rowModel["death_date_jittered"] is not None:
                    rowModel["name"] = "Death"
                    rowModel["description"] = "Death Date"
                    rowModel["itemDate"] = rowModel["death_date_jittered"]
                    yield rowModel

            previous_rit_uid = rowModel["rit_uid"]

            progress.Update()

        log.debug("fetched {} rows".format(rows_fetched))
Exemplo n.º 12
0
    def _test_dataConversion(self):
        # Run the data conversion on the same data and look for expected records
        log.debug("Run the conversion process...")
        self.converter.convertSourceItems(self.patientIds)

        # Just query back for the same data, de-normalizing the data back to a general table
        testQuery = \
            """
            select 
                pi.external_id,
                pi.patient_id,
                pi.encounter_id,
                cic.description,
                ci.external_id,
                ci.name,
                ci.description,
                pi.item_date
            from
                patient_item as pi,
                clinical_item as ci,
                clinical_item_category as cic
            where
                pi.clinical_item_id = ci.clinical_item_id and
                ci.clinical_item_category_id = cic.clinical_item_category_id and
                cic.source_table = '%s'
            order by
                pi.patient_id desc, ci.name
            """ % TEST_SOURCE_TABLE

        expectedData = \
            [
                [None, 15437801L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1963, 1, 1, 0, 0)],
                [None, 15437801L, None, 'Demographics', None, 'Birth1960s', 'Birth Decade 1960s',
                 datetime(1963, 1, 1, 0, 0)],
                [None, 15437801L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1963, 1, 1, 0, 0)],
                [None, 15437801L, None, 'Demographics', None, 'RaceOther', 'Race/Ethnicity: Other',
                 datetime(1963, 1, 1, 0, 0)],
                [None, 15350146L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2007, 1, 1, 0, 0)],
                [None, 15350146L, None, 'Demographics', None, 'Birth2000s', 'Birth Decade 2000s',
                 datetime(2007, 1, 1, 0, 0)],
                [None, 15350146L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(2007, 1, 1, 0, 0)],
                [None, 15350146L, None, 'Demographics', None, 'RaceAsian', 'Race/Ethnicity: Asian',
                 datetime(2007, 1, 1, 0, 0)],
                [None, 15246036L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2008, 1, 1, 0, 0)],
                [None, 15246036L, None, 'Demographics', None, 'Birth2000s', 'Birth Decade 2000s',
                 datetime(2008, 1, 1, 0, 0)],
                [None, 15246036L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(2008, 1, 1, 0, 0)],
                [None, 15246036L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(2008, 1, 1, 0, 0)],
                [None, 15221085L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1929, 1, 1, 0, 0)],
                [None, 15221085L, None, 'Demographics', None, 'Birth1920s', 'Birth Decade 1920s',
                 datetime(1929, 1, 1, 0, 0)],
                [None, 15221085L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1929, 1, 1, 0, 0)],
                [None, 15221085L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1929, 1, 1, 0, 0)],
                [None, 15220610L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1991, 1, 1, 0, 0)],
                [None, 15220610L, None, 'Demographics', None, 'Birth1990s', 'Birth Decade 1990s',
                 datetime(1991, 1, 1, 0, 0)],
                [None, 15220610L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1991, 1, 1, 0, 0)],
                [None, 15220610L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1991, 1, 1, 0, 0)],
                [None, 15177469L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1945, 1, 1, 0, 0)],
                [None, 15177469L, None, 'Demographics', None, 'Birth1940s', 'Birth Decade 1940s',
                 datetime(1945, 1, 1, 0, 0)],
                [None, 15177469L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1945, 1, 1, 0, 0)],
                [None, 15177469L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1945, 1, 1, 0, 0)],
                [None, 15156104L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1958, 1, 1, 0, 0)],
                [None, 15156104L, None, 'Demographics', None, 'Birth1950s', 'Birth Decade 1950s',
                 datetime(1958, 1, 1, 0, 0)],
                [None, 15156104L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1958, 1, 1, 0, 0)],
                [None, 15156104L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1958, 1, 1, 0, 0)],
                [None, 15107009L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1955, 1, 1, 0, 0)],
                [None, 15107009L, None, 'Demographics', None, 'Birth1950s', 'Birth Decade 1950s',
                 datetime(1955, 1, 1, 0, 0)],
                [None, 15107009L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1955, 1, 1, 0, 0)],
                [None, 15107009L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1955, 1, 1, 0, 0)],
                [None, 15097860L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1997, 1, 1, 0, 0)],
                [None, 15097860L, None, 'Demographics', None, 'Birth1990s', 'Birth Decade 1990s',
                 datetime(1997, 1, 1, 0, 0)],
                [None, 15097860L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1997, 1, 1, 0, 0)],
                [None, 15097860L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1997, 1, 1, 0, 0)],
                [None, 15072385L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2003, 1, 1, 0, 0)],
                [None, 15072385L, None, 'Demographics', None, 'Birth2000s', 'Birth Decade 2000s',
                 datetime(2003, 1, 1, 0, 0)],
                [None, 15072385L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(2003, 1, 1, 0, 0)],
                [None, 15072385L, None, 'Demographics', None, 'RaceUnknown', 'Race/Ethnicity: Unknown',
                 datetime(2003, 1, 1, 0, 0)],
                [None, 15050031L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1981, 1, 1, 0, 0)],
                [None, 15050031L, None, 'Demographics', None, 'Birth1980s', 'Birth Decade 1980s',
                 datetime(1981, 1, 1, 0, 0)],
                [None, 15050031L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1981, 1, 1, 0, 0)],
                [None, 15050031L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1981, 1, 1, 0, 0)],
                [None, 14984898L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1950, 1, 1, 0, 0)],
                [None, 14984898L, None, 'Demographics', None, 'Birth1950s', 'Birth Decade 1950s',
                 datetime(1950, 1, 1, 0, 0)],
                [None, 14984898L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1950, 1, 1, 0, 0)],
                [None, 14984898L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1950, 1, 1, 0, 0)],
                [None, 14936429L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1932, 1, 1, 0, 0)],
                [None, 14936429L, None, 'Demographics', None, 'Birth1930s', 'Birth Decade 1930s',
                 datetime(1932, 1, 1, 0, 0)],
                [None, 14936429L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1932, 1, 1, 0, 0)],
                [None, 14936429L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1932, 1, 1, 0, 0)],
                [None, 14901937L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1960, 1, 1, 0, 0)],
                [None, 14901937L, None, 'Demographics', None, 'Birth1960s', 'Birth Decade 1960s',
                 datetime(1960, 1, 1, 0, 0)],
                [None, 14901937L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1960, 1, 1, 0, 0)],
                [None, 14901937L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1960, 1, 1, 0, 0)],
                [None, 14891388L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2014, 1, 1, 0, 0)],
                [None, 14891388L, None, 'Demographics', None, 'Birth2010s', 'Birth Decade 2010s',
                 datetime(2014, 1, 1, 0, 0)],
                [None, 14891388L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(2014, 1, 1, 0, 0)],
                [None, 14891388L, None, 'Demographics', None, 'RaceUnknown', 'Race/Ethnicity: Unknown',
                 datetime(2014, 1, 1, 0, 0)],
                [None, 14770355L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1950, 1, 1, 0, 0)],
                [None, 14770355L, None, 'Demographics', None, 'Birth1950s', 'Birth Decade 1950s',
                 datetime(1950, 1, 1, 0, 0)],
                [None, 14770355L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1950, 1, 1, 0, 0)],
                [None, 14770355L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1950, 1, 1, 0, 0)],
                [None, 14719178L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2011, 1, 1, 0, 0)],
                [None, 14719178L, None, 'Demographics', None, 'Birth2010s', 'Birth Decade 2010s',
                 datetime(2011, 1, 1, 0, 0)],
                [None, 14719178L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(2011, 1, 1, 0, 0)],
                [None, 14719178L, None, 'Demographics', None, 'RaceUnknown', 'Race/Ethnicity: Unknown',
                 datetime(2011, 1, 1, 0, 0)],
                [None, 14701588L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1949, 1, 1, 0, 0)],
                [None, 14701588L, None, 'Demographics', None, 'Birth1940s', 'Birth Decade 1940s',
                 datetime(1949, 1, 1, 0, 0)],
                [None, 14701588L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1949, 1, 1, 0, 0)],
                [None, 14701588L, None, 'Demographics', None, 'RaceOther', 'Race/Ethnicity: Other',
                 datetime(1949, 1, 1, 0, 0)],
                [None, 14540276L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2018, 1, 1, 0, 0)],
                [None, 14540276L, None, 'Demographics', None, 'Birth2010s', 'Birth Decade 2010s',
                 datetime(2018, 1, 1, 0, 0)],
                [None, 14540276L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(2018, 1, 1, 0, 0)],
                [None, 14540276L, None, 'Demographics', None, 'RaceUnknown', 'Race/Ethnicity: Unknown',
                 datetime(2018, 1, 1, 0, 0)],
                [None, 14398846L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1959, 1, 1, 0, 0)],
                [None, 14398846L, None, 'Demographics', None, 'Birth1950s', 'Birth Decade 1950s',
                 datetime(1959, 1, 1, 0, 0)],
                [None, 14398846L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1959, 1, 1, 0, 0)],
                [None, 14398846L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1959, 1, 1, 0, 0)],
                [None, 14389220L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1992, 1, 1, 0, 0)],
                [None, 14389220L, None, 'Demographics', None, 'Birth1990s', 'Birth Decade 1990s',
                 datetime(1992, 1, 1, 0, 0)],
                [None, 14389220L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1992, 1, 1, 0, 0)],
                [None, 14389220L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1992, 1, 1, 0, 0)],
                [None, 14358325L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1956, 1, 1, 0, 0)],
                [None, 14358325L, None, 'Demographics', None, 'Birth1950s', 'Birth Decade 1950s',
                 datetime(1956, 1, 1, 0, 0)],
                [None, 14358325L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1956, 1, 1, 0, 0)],
                [None, 14358325L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1956, 1, 1, 0, 0)],
                [None, 14354559L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1954, 1, 1, 0, 0)],
                [None, 14354559L, None, 'Demographics', None, 'Birth1950s', 'Birth Decade 1950s',
                 datetime(1954, 1, 1, 0, 0)],
                [None, 14354559L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1954, 1, 1, 0, 0)],
                [None, 14354559L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1954, 1, 1, 0, 0)],
                [None, 14325830L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1942, 1, 1, 0, 0)],
                [None, 14325830L, None, 'Demographics', None, 'Birth1940s', 'Birth Decade 1940s',
                 datetime(1942, 1, 1, 0, 0)],
                [None, 14325830L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1942, 1, 1, 0, 0)],
                [None, 14325830L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1942, 1, 1, 0, 0)],
                [None, 14284725L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2015, 1, 1, 0, 0)],
                [None, 14284725L, None, 'Demographics', None, 'Birth2010s', 'Birth Decade 2010s',
                 datetime(2015, 1, 1, 0, 0)],
                [None, 14284725L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(2015, 1, 1, 0, 0)],
                [None, 14284725L, None, 'Demographics', None, 'RaceUnknown', 'Race/Ethnicity: Unknown',
                 datetime(2015, 1, 1, 0, 0)],
                [None, 14283443L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2007, 1, 1, 0, 0)],
                [None, 14283443L, None, 'Demographics', None, 'Birth2000s', 'Birth Decade 2000s',
                 datetime(2007, 1, 1, 0, 0)],
                [None, 14283443L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(2007, 1, 1, 0, 0)],
                [None, 14283443L, None, 'Demographics', None, 'RaceUnknown', 'Race/Ethnicity: Unknown',
                 datetime(2007, 1, 1, 0, 0)],
                [None, 14259737L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1946, 1, 1, 0, 0)],
                [None, 14259737L, None, 'Demographics', None, 'Birth1940s', 'Birth Decade 1940s',
                 datetime(1946, 1, 1, 0, 0)],
                [None, 14259737L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1946, 1, 1, 0, 0)],
                [None, 14259737L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1946, 1, 1, 0, 0)],
                [None, 14259046L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1929, 1, 1, 0, 0)],
                [None, 14259046L, None, 'Demographics', None, 'Birth1920s', 'Birth Decade 1920s',
                 datetime(1929, 1, 1, 0, 0)],
                [None, 14259046L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1929, 1, 1, 0, 0)],
                [None, 14259046L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1929, 1, 1, 0, 0)],
                [None, 14257909L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2018, 1, 1, 0, 0)],
                [None, 14257909L, None, 'Demographics', None, 'Birth2010s', 'Birth Decade 2010s',
                 datetime(2018, 1, 1, 0, 0)],
                [None, 14257909L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(2018, 1, 1, 0, 0)],
                [None, 14257909L, None, 'Demographics', None, 'RaceUnknown', 'Race/Ethnicity: Unknown',
                 datetime(2018, 1, 1, 0, 0)],
                [None, 14088469L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1932, 1, 1, 0, 0)],
                [None, 14088469L, None, 'Demographics', None, 'Birth1930s', 'Birth Decade 1930s',
                 datetime(1932, 1, 1, 0, 0)],
                [None, 14088469L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1932, 1, 1, 0, 0)],
                [None, 14088469L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1932, 1, 1, 0, 0)],
                [None, 14027699L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2015, 1, 1, 0, 0)],
                [None, 14027699L, None, 'Demographics', None, 'Birth2010s', 'Birth Decade 2010s',
                 datetime(2015, 1, 1, 0, 0)],
                [None, 14027699L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(2015, 1, 1, 0, 0)],
                [None, 14027699L, None, 'Demographics', None, 'RaceUnknown', 'Race/Ethnicity: Unknown',
                 datetime(2015, 1, 1, 0, 0)],
                [None, 14020462L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1998, 1, 1, 0, 0)],
                [None, 14020462L, None, 'Demographics', None, 'Birth1990s', 'Birth Decade 1990s',
                 datetime(1998, 1, 1, 0, 0)],
                [None, 14020462L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1998, 1, 1, 0, 0)],
                [None, 14020462L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1998, 1, 1, 0, 0)],
                [None, 14015085L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1974, 1, 1, 0, 0)],
                [None, 14015085L, None, 'Demographics', None, 'Birth1970s', 'Birth Decade 1970s',
                 datetime(1974, 1, 1, 0, 0)],
                [None, 14015085L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1974, 1, 1, 0, 0)],
                [None, 14015085L, None, 'Demographics', None, 'RaceUnknown', 'Race/Ethnicity: Unknown',
                 datetime(1974, 1, 1, 0, 0)],
                [None, 13909424L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2011, 1, 1, 0, 0)],
                [None, 13909424L, None, 'Demographics', None, 'Birth2010s', 'Birth Decade 2010s',
                 datetime(2011, 1, 1, 0, 0)],
                [None, 13909424L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(2011, 1, 1, 0, 0)],
                [None, 13909424L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(2011, 1, 1, 0, 0)],
                [None, 13858359L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1936, 1, 1, 0, 0)],
                [None, 13858359L, None, 'Demographics', None, 'Birth1930s', 'Birth Decade 1930s',
                 datetime(1936, 1, 1, 0, 0)],
                [None, 13858359L, None, 'Demographics', None, 'Death', 'Death Date', datetime(2013, 11, 4, 16, 0)],
                [None, 13858359L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1936, 1, 1, 0, 0)],
                [None, 13858359L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1936, 1, 1, 0, 0)],
                [None, 13834993L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1948, 1, 1, 0, 0)],
                [None, 13834993L, None, 'Demographics', None, 'Birth1940s', 'Birth Decade 1940s',
                 datetime(1948, 1, 1, 0, 0)],
                [None, 13834993L, None, 'Demographics', None, 'Death', 'Death Date', datetime(2016, 1, 19, 16, 0)],
                [None, 13834993L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1948, 1, 1, 0, 0)],
                [None, 13834993L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1948, 1, 1, 0, 0)],
                [None, 13830852L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2011, 1, 1, 0, 0)],
                [None, 13830852L, None, 'Demographics', None, 'Birth2010s', 'Birth Decade 2010s',
                 datetime(2011, 1, 1, 0, 0)],
                [None, 13830852L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(2011, 1, 1, 0, 0)],
                [None, 13830852L, None, 'Demographics', None, 'RaceUnknown', 'Race/Ethnicity: Unknown',
                 datetime(2011, 1, 1, 0, 0)],
                [None, 13744930L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1955, 1, 1, 0, 0)],
                [None, 13744930L, None, 'Demographics', None, 'Birth1950s', 'Birth Decade 1950s',
                 datetime(1955, 1, 1, 0, 0)],
                [None, 13744930L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1955, 1, 1, 0, 0)],
                [None, 13744930L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1955, 1, 1, 0, 0)],
                [None, 13734401L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1994, 1, 1, 0, 0)],
                [None, 13734401L, None, 'Demographics', None, 'Birth1990s', 'Birth Decade 1990s',
                 datetime(1994, 1, 1, 0, 0)],
                [None, 13734401L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1994, 1, 1, 0, 0)],
                [None, 13734401L, None, 'Demographics', None, 'RaceAsian', 'Race/Ethnicity: Asian',
                 datetime(1994, 1, 1, 0, 0)],
                [None, 13652744L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1979, 1, 1, 0, 0)],
                [None, 13652744L, None, 'Demographics', None, 'Birth1970s', 'Birth Decade 1970s',
                 datetime(1979, 1, 1, 0, 0)],
                [None, 13652744L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1979, 1, 1, 0, 0)],
                [None, 13652744L, None, 'Demographics', None, 'RacePacificIslander', 'Race/Ethnicity: Pacific Islander',
                 datetime(1979, 1, 1, 0, 0)],
                [None, 13549039L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1947, 1, 1, 0, 0)],
                [None, 13549039L, None, 'Demographics', None, 'Birth1940s', 'Birth Decade 1940s',
                 datetime(1947, 1, 1, 0, 0)],
                [None, 13549039L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1947, 1, 1, 0, 0)],
                [None, 13549039L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1947, 1, 1, 0, 0)],
                [None, 13546041L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1935, 1, 1, 0, 0)],
                [None, 13546041L, None, 'Demographics', None, 'Birth1930s', 'Birth Decade 1930s',
                 datetime(1935, 1, 1, 0, 0)],
                [None, 13546041L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1935, 1, 1, 0, 0)],
                [None, 13546041L, None, 'Demographics', None, 'RaceOther', 'Race/Ethnicity: Other',
                 datetime(1935, 1, 1, 0, 0)],
                [None, 13513085L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(2002, 1, 1, 0, 0)],
                [None, 13513085L, None, 'Demographics', None, 'Birth2000s', 'Birth Decade 2000s',
                 datetime(2002, 1, 1, 0, 0)],
                [None, 13513085L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(2002, 1, 1, 0, 0)],
                [None, 13513085L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(2002, 1, 1, 0, 0)],
                [None, 13513078L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1952, 1, 1, 0, 0)],
                [None, 13513078L, None, 'Demographics', None, 'Birth1950s', 'Birth Decade 1950s',
                 datetime(1952, 1, 1, 0, 0)],
                [None, 13513078L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1952, 1, 1, 0, 0)],
                [None, 13513078L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1952, 1, 1, 0, 0)],
                [None, 13485728L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1981, 1, 1, 0, 0)],
                [None, 13485728L, None, 'Demographics', None, 'Birth1980s', 'Birth Decade 1980s',
                 datetime(1981, 1, 1, 0, 0)],
                [None, 13485728L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1981, 1, 1, 0, 0)],
                [None, 13485728L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1981, 1, 1, 0, 0)],
                [None, 13484358L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1958, 1, 1, 0, 0)],
                [None, 13484358L, None, 'Demographics', None, 'Birth1950s', 'Birth Decade 1950s',
                 datetime(1958, 1, 1, 0, 0)],
                [None, 13484358L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1958, 1, 1, 0, 0)],
                [None, 13484358L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1958, 1, 1, 0, 0)],
                [None, 13414764L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1929, 1, 1, 0, 0)],
                [None, 13414764L, None, 'Demographics', None, 'Birth1920s', 'Birth Decade 1920s',
                 datetime(1929, 1, 1, 0, 0)],
                [None, 13414764L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1929, 1, 1, 0, 0)],
                [None, 13414764L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1929, 1, 1, 0, 0)],
                [None, 13411182L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1961, 1, 1, 0, 0)],
                [None, 13411182L, None, 'Demographics', None, 'Birth1960s', 'Birth Decade 1960s',
                 datetime(1961, 1, 1, 0, 0)],
                [None, 13411182L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1961, 1, 1, 0, 0)],
                [None, 13411182L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1961, 1, 1, 0, 0)],
                [None, 13406787L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1954, 1, 1, 0, 0)],
                [None, 13406787L, None, 'Demographics', None, 'Birth1950s', 'Birth Decade 1950s',
                 datetime(1954, 1, 1, 0, 0)],
                [None, 13406787L, None, 'Demographics', None, 'Female', 'Female Gender', datetime(1954, 1, 1, 0, 0)],
                [None, 13406787L, None, 'Demographics', None, 'RaceBlack', 'Race/Ethnicity: Black',
                 datetime(1954, 1, 1, 0, 0)],
                [None, 13386163L, None, 'Demographics', None, 'Birth', 'Birth Year', datetime(1983, 1, 1, 0, 0)],
                [None, 13386163L, None, 'Demographics', None, 'Birth1980s', 'Birth Decade 1980s',
                 datetime(1983, 1, 1, 0, 0)],
                [None, 13386163L, None, 'Demographics', None, 'Male', 'Male Gender', datetime(1983, 1, 1, 0, 0)],
                [None, 13386163L, None, 'Demographics', None, 'RaceWhiteNonHispanicLatino',
                 'Race/Ethnicity: White (Non-Hispanic/Latino)', datetime(1983, 1, 1, 0, 0)]

            ]

        actualData = DBUtil.execute(testQuery)
        self.assertEqualTable(expectedData, actualData)