def post(self, request, schema, table): table_obj = actions._get_table(schema=schema, table=table) raw_input = request.data metadata, error = actions.try_parse_metadata(raw_input) if metadata is not None: compiler = JSONCompiler() table_obj.comment = json.dumps(compiler.visit(metadata)) cursor = actions.load_cursor_from_context(request.data) # Surprisingly, SQLAlchemy does not seem to escape comment strings # properly. Certain strings cause errors database errors. # This MAY be a security issue. Therefore, we do not use # SQLAlchemy's compiler here but do it manually. sql = "COMMENT ON TABLE {schema}.{table} IS %s".format( schema=table_obj.schema, table=table_obj.name) cursor.execute(sql, (table_obj.comment, )) return JsonResponse(raw_input) else: raise APIError(error)
def wrapper(*args, **kwargs): artificial_connection = 'connection_id' not in args[1].data fetch_all = 'cursor_id' not in args[1].data if fetch_all: # django_restframework passes different data dictionaries depending # on the request type: PUT -> Mutable, POST -> Immutable # Thus, we have to replace the data dictionary by one we can mutate. if hasattr(args[1].data, '_mutable'): args[1].data._mutable = True context = {} context['user'] = args[1].user if not artificial_connection: context['connection_id'] = args[1].data['connection_id'] else: context.update(actions.open_raw_connection({}, context)) args[1].data['connection_id'] = context['connection_id'] if 'cursor_id' in args[1].data: context['cursor_id'] = args[1].data['cursor_id'] else: context.update(actions.open_cursor({}, context)) args[1].data['cursor_id'] = context['cursor_id'] try: result = f(*args, **kwargs) if fetch_all: cursor = actions.load_cursor_from_context(context) session = actions.load_session_from_context(context) if not result: result = {} if cursor.description: result['description'] = cursor.description result['rowcount'] = cursor.rowcount result['data'] = (list( map(actions._translate_fetched_cell, row)) for row in cursor.fetchall()) if artificial_connection: session.connection.commit() finally: if fetch_all: actions.close_cursor({}, context) if artificial_connection: actions.close_raw_connection({}, context) return result
def wrapper(*args, **kwargs): artificial_connection = "connection_id" not in args[1].data fetch_all = "cursor_id" not in args[1].data triggered_close = False if fetch_all: # django_restframework passes different data dictionaries depending # on the request type: PUT -> Mutable, POST -> Immutable # Thus, we have to replace the data dictionary by one we can mutate. if hasattr(args[1].data, "_mutable"): args[1].data._mutable = True context = {} context["user"] = args[1].user if not artificial_connection: context["connection_id"] = args[1].data["connection_id"] else: context.update(actions.open_raw_connection({}, context)) args[1].data["connection_id"] = context["connection_id"] if "cursor_id" in args[1].data: context["cursor_id"] = args[1].data["cursor_id"] else: context.update(actions.open_cursor({}, context, named=named)) args[1].data["cursor_id"] = context["cursor_id"] try: result = f(*args, **kwargs) if fetch_all: cursor = actions.load_cursor_from_context(context) session = actions.load_session_from_context(context) if not result: result = {} # Initial server-side cursors do not contain any description before # the first row is fetched. Therefore, we have to try to fetch the # first one - if successful, we a description if not, nothing is returned. # But: After the last row the cursor will 'forget' its description. # Therefore we have to fetch the remaining data later. # Set of triggers after all the data was fetched. The cursor must not be closed earlier! triggers = [actions.close_cursor, actions.close_raw_connection, session.connection.commit] trigger_args = [({}, context), ({}, context), tuple()] first = None if not named or cursor.statusmessage: try: first = cursor.fetchone() except psycopg2.ProgrammingError as e: if not e.args or e.args[0] != "no results to fetch": raise e except psycopg2.errors.InvalidCursorName as e: print(e) if first: first = map(actions._translate_fetched_cell, first) if cursor.description: description = [ [ col.name, col.type_code, col.display_size, col.internal_size, col.precision, col.scale, col.null_ok, ] for col in cursor.description ] result["data"] = (x for x in itertools.chain([first],transform_results(cursor, triggers, trigger_args))) result["description"] = description result["context"] = context result["rowcount"] = cursor.rowcount triggered_close = True if not triggered_close and artificial_connection: session.connection.commit() finally: if not triggered_close: if fetch_all and not artificial_connection: actions.close_cursor({}, context) if artificial_connection: actions.close_raw_connection({}, context) return result