Example #1
0
    def get(self, request, schema, table):
        """
        Returns a dictionary that describes the DDL-make-up of this table.
        Fields are:

        * name : Name of the table,
        * schema: Name of the schema,
        * columns : as specified in :meth:`api.actions.describe_columns`
        * indexes : as specified in :meth:`api.actions.describe_indexes`
        * constraints: as specified in
                    :meth:`api.actions.describe_constraints`

        :param request:
        :return:
        """

        schema, table = actions.get_table_name(schema, table, restrict_schemas=False)

        return JsonResponse(
            {
                "schema": schema,
                "name": table,
                "columns": actions.describe_columns(schema, table),
                "indexed": actions.describe_indexes(schema, table),
                "constraints": actions.describe_constraints(schema, table),
            }
        )
Example #2
0
    def get(self, request, schema, table):
        # get the columns id from the schema and the table
        columns = [(c, c) for c in describe_columns(schema, table).keys()]
        formset = GraphViewForm(columns=columns)

        return render(request, 'dataedit/tablegraph_form.html',
                      {'formset': formset})
Example #3
0
 def get(self, request, schema, table, column=None):
     schema, table = actions.get_table_name(schema, table, restrict_schemas=False)
     response = actions.describe_columns(schema, table)
     if column:
         try:
             response = response[column]
         except KeyError:
             raise actions.APIError('The column specified is not part of '
                                    'this table.')
     return JsonResponse(response)
Example #4
0
    def get(self, request, schema, table, maptype):
        columns = [(c, c) for c in describe_columns(schema, table).keys()]
        if maptype == "latlon":
            form = LatLonViewForm(columns=columns)
        elif maptype == "geom":
            form = GeomViewForm(columns=columns)
        else:
            raise Http404

        return render(request, 'dataedit/tablemap_form.html', {'form': form})
Example #5
0
    def post(self, request, schema, table, maptype):
        columns = [(c, c) for c in describe_columns(schema, table).keys()]
        if maptype == "latlon":
            form = LatLonViewForm(request.POST, columns=columns)
            options = dict(lat=request.POST.get('lat'),
                           lon=request.POST.get('lon'))
        elif maptype == "geom":
            form = GeomViewForm(request.POST, columns=columns)
            options = dict(geom=request.POST.get('geom'))
        else:
            raise Http404

        form.schema = schema
        form.table = table
        form.options = options
        if form.is_valid():
            view_id = form.save(commit=True)
            return redirect(
                "/dataedit/view/{schema}/{table}?view={view_id}".format(
                    schema=schema, table=table, view_id=view_id))
        else:
            return self.get(request, schema, table)
Example #6
0
def change_requests(schema, table):
    """
    Loads the dataedit admin interface
    :param request:
    :return:
    """
    # I want to display old and new data, if different.

    display_message = None
    api_columns = dba.get_column_changes(reviewed=False,
                                         schema=schema,
                                         table=table)
    api_constraints = dba.get_constraints_changes(reviewed=False,
                                                  schema=schema,
                                                  table=table)

    # print(api_columns)
    # print(api_constraints)

    cache = dict()
    data = dict()

    data['api_columns'] = {}
    data['api_constraints'] = {}

    keyword_whitelist = [
        'column_name', 'c_table', 'c_schema', 'reviewed', 'changed', 'id'
    ]

    old_description = dba.describe_columns(schema, table)

    for change in api_columns:

        name = change['column_name']
        id = change['id']

        # Identifing over 'new'.
        if change.get('new_name') is not None:
            change['column_name'] = change['new_name']

        old_cd = old_description.get(name)

        data['api_columns'][id] = {}
        data['api_columns'][id]['old'] = {}

        if old_cd is not None:
            old = api.parser.parse_scolumnd_from_columnd(
                schema, table, name, old_description.get(name))

            for key in list(change):
                value = change[key]
                if key not in keyword_whitelist and (value is None
                                                     or value == old[key]):
                    old.pop(key)
                    change.pop(key)
            data['api_columns'][id]['old'] = old
        else:
            data['api_columns'][id]['old']['c_schema'] = schema
            data['api_columns'][id]['old']['c_table'] = table
            data['api_columns'][id]['old']['column_name'] = name

        data['api_columns'][id]['new'] = change

    for i in range(len(api_constraints)):
        value = api_constraints[i]
        id = value.get('id')
        if value.get('reference_table') is None or value.get(
                'reference_column') is None:
            value.pop('reference_table')
            value.pop('reference_column')

        data['api_constraints'][id] = value

    display_style = [
        'c_schema', 'c_table', 'column_name', 'not_null', 'data_type',
        'reference_table', 'constraint_parameter', 'reference_column',
        'action', 'constraint_type', 'constraint_name'
    ]

    return {
        'data': data,
        'display_items': display_style,
        'display_message': display_message
    }
Example #7
0
def get_column_description(schema, table):
    """Return list of column descriptions:
     [{
        "name": str,
        "data_type": str,
        "is_nullable': bool,
        "is_pk": bool
     }]

    """
    def get_datatype_str(column_def):
        """get single string sql type definition.

        We want the data type definition to be a simple string, e.g. decimal(10, 6) or varchar(128),
        so we need to combine the various fields (type, numeric_precision, numeric_scale, ...)
        """
        # for reverse validation, see also api.parser.parse_type(dt_string)
        dt = column_def['data_type'].lower()
        precisions = None
        if dt.startswith('character'):
            if dt == 'character varying':
                dt = 'varchar'
            else:
                dt = 'char'
            precisions = [column_def['character_maximum_length']]
        elif dt.endswith(' without time zone'):  # this is the default
            dt = dt.replace(' without time zone', '')
        elif re.match('(numeric|decimal)', dt):
            precisions = [
                column_def['numeric_precision'], column_def['numeric_scale']
            ]
        elif dt == 'interval':
            precisions = [column_def['interval_precision']]
        elif re.match('.*int', dt) and re.match(
                'nextval',
                column_def.get('column_default') or ''):
            #dt = dt.replace('int', 'serial')
            pass
        elif dt.startswith('double'):
            dt = 'float'
        if precisions:  # remove None
            precisions = [x for x in precisions if x is not None]
        if precisions:
            dt += '(%s)' % ', '.join(str(x) for x in precisions)
        return dt

    def get_pk_fields(constraints):
        """Get the column names that make up the primary key from the constraints definitions.

        NOTE: Currently, the wizard to create tables only supports single fields primary keys (which is advisable anyways)
        """
        pk_fields = []
        for _name, constraint in constraints.items():
            if constraint.get("constraint_type") == "PRIMARY KEY":
                m = re.match(r"PRIMARY KEY[ ]*\(([^)]+)",
                             constraint.get("definition") or "")
                if m:
                    # "f1, f2" -> ["f1", "f2"]
                    pk_fields = [x.strip() for x in m.groups()[0].split(',')]
        return pk_fields

    _columns = actions.describe_columns(schema, table)
    _constraints = actions.describe_constraints(schema, table)
    pk_fields = get_pk_fields(_constraints)
    # order by ordinal_position
    columns = []
    for name, col in sorted(_columns.items(),
                            key=lambda kv: int(kv[1]['ordinal_position'])):
        columns.append({
            'name': name,
            'data_type': get_datatype_str(col),
            'is_nullable': col['is_nullable'],
            'is_pk': name in pk_fields
        })
    return columns
Example #8
0
def change_requests(schema, table):
    """
    Loads the dataedit admin interface
    :param request:
    :return:
    """
    # I want to display old and new data, if different.

    display_message = None
    api_columns = actions.get_column_changes(reviewed=False,
                                             schema=schema,
                                             table=table)
    api_constraints = actions.get_constraints_changes(reviewed=False,
                                                      schema=schema,
                                                      table=table)

    # print(api_columns)
    # print(api_constraints)

    cache = dict()
    data = dict()

    data["api_columns"] = {}
    data["api_constraints"] = {}

    keyword_whitelist = [
        "column_name",
        "c_table",
        "c_schema",
        "reviewed",
        "changed",
        "id",
    ]

    old_description = actions.describe_columns(schema, table)

    for change in api_columns:

        name = change["column_name"]
        id = change["id"]

        # Identifing over 'new'.
        if change.get("new_name") is not None:
            change["column_name"] = change["new_name"]

        old_cd = old_description.get(name)

        data["api_columns"][id] = {}
        data["api_columns"][id]["old"] = {}

        if old_cd is not None:
            old = api.parser.parse_scolumnd_from_columnd(
                schema, table, name, old_description.get(name))

            for key in list(change):
                value = change[key]
                if key not in keyword_whitelist and (value is None
                                                     or value == old[key]):
                    old.pop(key)
                    change.pop(key)
            data["api_columns"][id]["old"] = old
        else:
            data["api_columns"][id]["old"]["c_schema"] = schema
            data["api_columns"][id]["old"]["c_table"] = table
            data["api_columns"][id]["old"]["column_name"] = name

        data["api_columns"][id]["new"] = change

    for i in range(len(api_constraints)):
        value = api_constraints[i]
        id = value.get("id")
        if (value.get("reference_table") is None
                or value.get("reference_column") is None):
            value.pop("reference_table")
            value.pop("reference_column")

        data["api_constraints"][id] = value

    display_style = [
        "c_schema",
        "c_table",
        "column_name",
        "not_null",
        "data_type",
        "reference_table",
        "constraint_parameter",
        "reference_column",
        "action",
        "constraint_type",
        "constraint_name",
    ]

    return {
        "data": data,
        "display_items": display_style,
        "display_message": display_message,
    }