mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-06-17 22:06:02 +01:00
utils/postgres: Rename postgres_covert to house more general methods
Rename the postgres_covert file to allow for place more general postgres utility functions.
This commit is contained in:
wa
219
wa/utils/postgres.py
Normal file
219
wa/utils/postgres.py
Normal file
@ -0,0 +1,219 @@
|
||||
# Copyright 2018 ARM Limited
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
"""
|
||||
This module contains additional casting and adaptation functions for several
|
||||
different datatypes and metadata types for use with the psycopg2 module. The
|
||||
casting functions will transform Postgresql data types into Python objects, and
|
||||
the adapters the reverse. They are named this way according to the psycopg2
|
||||
conventions.
|
||||
|
||||
For more information about the available adapters and casters in the standard
|
||||
psycopg2 module, please see:
|
||||
|
||||
http://initd.org/psycopg/docs/extensions.html#sql-adaptation-protocol-objects
|
||||
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
try:
|
||||
from psycopg2 import InterfaceError
|
||||
from psycopg2.extensions import AsIs
|
||||
except ImportError:
|
||||
InterfaceError = None
|
||||
AsIs = None
|
||||
|
||||
from wa.utils.types import level
|
||||
|
||||
|
||||
def cast_level(value, cur): # pylint: disable=unused-argument
|
||||
"""Generic Level caster for psycopg2"""
|
||||
if not InterfaceError:
|
||||
raise ImportError('There was a problem importing psycopg2.')
|
||||
if value is None:
|
||||
return None
|
||||
|
||||
m = re.match(r"([^\()]*)\((\d*)\)", value)
|
||||
name = str(m.group(1))
|
||||
number = int(m.group(2))
|
||||
|
||||
if m:
|
||||
return level(name, number)
|
||||
else:
|
||||
raise InterfaceError("Bad level representation: {}".format(value))
|
||||
|
||||
|
||||
def cast_vanilla(value, cur): # pylint: disable=unused-argument
|
||||
"""Vanilla Type caster for psycopg2
|
||||
|
||||
Simply returns the string representation.
|
||||
"""
|
||||
if value is None:
|
||||
return None
|
||||
else:
|
||||
return str(value)
|
||||
|
||||
|
||||
# List functions and classes for adapting
|
||||
|
||||
def adapt_level(a_level):
|
||||
"""Generic Level Adapter for psycopg2"""
|
||||
return "{}({})".format(a_level.name, a_level.value)
|
||||
|
||||
|
||||
class ListOfLevel(object):
|
||||
value = None
|
||||
|
||||
def __init__(self, a_level):
|
||||
self.value = a_level
|
||||
|
||||
def return_original(self):
|
||||
return self.value
|
||||
|
||||
|
||||
def adapt_ListOfX(adapt_X):
|
||||
"""This will create a multi-column adapter for a particular type.
|
||||
|
||||
Note that the type must itself need to be in array form. Therefore
|
||||
this function serves to seaprate out individual lists into multiple
|
||||
big lists.
|
||||
E.g. if the X adapter produces array (a,b,c)
|
||||
then this adapter will take an list of Xs and produce a master array:
|
||||
((a1,a2,a3),(b1,b2,b3),(c1,c2,c3))
|
||||
|
||||
Takes as its argument the adapter for the type which must produce an
|
||||
SQL array string.
|
||||
Note that you should NOT put the AsIs in the adapt_X function.
|
||||
|
||||
The need for this function arises from the fact that we may want to
|
||||
actually handle list-creating types differently if they themselves
|
||||
are in a list, as in the example above, we cannot simply adopt a
|
||||
recursive strategy.
|
||||
|
||||
Note that master_list is the list representing the array. Each element
|
||||
in the list will represent a subarray (column). If there is only one
|
||||
subarray following processing then the outer {} are stripped to give a
|
||||
1 dimensional array.
|
||||
"""
|
||||
def adapter_function(param):
|
||||
if not AsIs:
|
||||
raise ImportError('There was a problem importing psycopg2.')
|
||||
param = param.value
|
||||
result_list = []
|
||||
for element in param: # Where param will be a list of X's
|
||||
result_list.append(adapt_X(element))
|
||||
test_element = result_list[0]
|
||||
num_items = len(test_element.split(","))
|
||||
master_list = []
|
||||
for x in range(num_items):
|
||||
master_list.append("")
|
||||
for element in result_list:
|
||||
element = element.strip("{").strip("}")
|
||||
element = element.split(",")
|
||||
for x in range(num_items):
|
||||
master_list[x] = master_list[x] + element[x] + ","
|
||||
if num_items > 1:
|
||||
master_sql_string = "{"
|
||||
else:
|
||||
master_sql_string = ""
|
||||
for x in range(num_items):
|
||||
# Remove trailing comma
|
||||
master_list[x] = master_list[x].strip(",")
|
||||
master_list[x] = "{" + master_list[x] + "}"
|
||||
master_sql_string = master_sql_string + master_list[x] + ","
|
||||
master_sql_string = master_sql_string.strip(",")
|
||||
if num_items > 1:
|
||||
master_sql_string = master_sql_string + "}"
|
||||
return AsIs("'{}'".format(master_sql_string))
|
||||
return adapter_function
|
||||
|
||||
|
||||
def return_as_is(adapt_X):
|
||||
"""Returns the AsIs appended function of the function passed
|
||||
|
||||
This is useful for adapter functions intended to be used with the
|
||||
adapt_ListOfX function, which must return strings, as it allows them
|
||||
to be standalone adapters.
|
||||
"""
|
||||
if not AsIs:
|
||||
raise ImportError('There was a problem importing psycopg2.')
|
||||
|
||||
def adapter_function(param):
|
||||
return AsIs("'{}'".format(adapt_X(param)))
|
||||
return adapter_function
|
||||
|
||||
|
||||
def adapt_vanilla(param):
|
||||
"""Vanilla adapter: simply returns the string representation"""
|
||||
if not AsIs:
|
||||
raise ImportError('There was a problem importing psycopg2.')
|
||||
return AsIs("'{}'".format(param))
|
||||
|
||||
|
||||
def create_iterable_adapter(array_columns, explicit_iterate=False):
|
||||
"""Create an iterable adapter of a specified dimension
|
||||
|
||||
If explicit_iterate is True, then it will be assumed that the param needs
|
||||
to be iterated upon via param.iteritems(). Otherwise it will simply be
|
||||
iterated vanilla.
|
||||
The value of array_columns will be equal to the number of indexed elements
|
||||
per item in the param iterable. E.g. a list of 3-element-long lists has
|
||||
3 elements per item in the iterable (the master list) and therefore
|
||||
array_columns should be equal to 3.
|
||||
If array_columns is 0, then this indicates that the iterable contains
|
||||
single items.
|
||||
"""
|
||||
if not AsIs:
|
||||
raise ImportError('There was a problem importing psycopg2.')
|
||||
|
||||
def adapt_iterable(param):
|
||||
"""Adapts an iterable object into an SQL array"""
|
||||
final_string = "" # String stores a string representation of the array
|
||||
if param:
|
||||
if array_columns > 1:
|
||||
for index in range(array_columns):
|
||||
array_string = ""
|
||||
for item in param.iteritems():
|
||||
array_string = array_string + str(item[index]) + ","
|
||||
array_string = array_string.strip(",")
|
||||
array_string = "{" + array_string + "}"
|
||||
final_string = final_string + array_string + ","
|
||||
final_string = final_string.strip(",")
|
||||
final_string = "{" + final_string + "}"
|
||||
else:
|
||||
# Simply return each item in the array
|
||||
if explicit_iterate:
|
||||
for item in param.iteritems():
|
||||
final_string = final_string + str(item) + ","
|
||||
else:
|
||||
for item in param:
|
||||
final_string = final_string + str(item) + ","
|
||||
final_string = "{" + final_string + "}"
|
||||
return AsIs("'{}'".format(final_string))
|
||||
return adapt_iterable
|
||||
|
||||
|
||||
# For reference only and future use
|
||||
def adapt_list(param):
|
||||
"""Adapts a list into an array"""
|
||||
if not AsIs:
|
||||
raise ImportError('There was a problem importing psycopg2.')
|
||||
final_string = ""
|
||||
if param:
|
||||
for item in param:
|
||||
final_string = final_string + str(item) + ","
|
||||
final_string = "{" + final_string + "}"
|
||||
return AsIs("'{}'".format(final_string))
|
Reference in New Issue
Block a user