- %def>
-
- <% form_elements.append(literal_row) %>
-% endif
+<%
+ form_elements = [table_row]
+ self.append_elements(form_elements) %>
-${parent.upload_form(form_elements)}
+${self.upload_form(form_elements)}
diff --git a/src/pgwui_upload/views/upload.py b/src/pgwui_upload/views/upload.py
index 99408a5..bf2b900 100644
--- a/src/pgwui_upload/views/upload.py
+++ b/src/pgwui_upload/views/upload.py
@@ -32,21 +32,19 @@ from __future__ import division
from pyramid.view import view_config
import logging
-import markupsafe
-import psycopg2.errorcodes
-from psycopg2 import ProgrammingError
from pgwui_common.view import auth_base_view
from pgwui_core.core import (
UploadEngine,
DataLineProcessor,
UploadDoubleTableForm,
- TabularFileUploadHandler,
UploadData,
- doublequote,
escape_eol,
is_checked,
)
+from pgwui_upload_core.views.upload import (
+ BaseTableUploadHandler,
+)
from pgwui_upload import exceptions as upload_ex
@@ -74,7 +72,7 @@ class SaveLine(DataLineProcessor):
self.cur.execute(self.insert_stmt, udl.tuples)
-class TableUploadHandler(TabularFileUploadHandler):
+class TableUploadHandler(BaseTableUploadHandler):
'''
Attributes:
request A pyramid request instance
@@ -109,77 +107,15 @@ class TableUploadHandler(TabularFileUploadHandler):
A list of PGWUIError instances
'''
uf = self.uf
- errors = super(TableUploadHandler, self).val_input()
+ errors = super().val_input()
qualified_table = uf['table']
if qualified_table == '':
errors.append(upload_ex.NoTableError(
'No table or view name supplied'))
- self.double_validator(errors)
-
return errors
- def write(self, result, errors):
- '''Add double upload key into form.'''
- response = super(TableUploadHandler, self).write(result, errors)
- self.write_double_key(response)
- return response
-
- def resolve_table(self, qualified_table):
- '''Return (schema, table) tuple of table name, or raise exception
- if not resolvable.
- '''
- try:
- self.cur.execute(
- ('SELECT nspname, relname'
- ' FROM pg_class'
- ' JOIN pg_namespace'
- ' ON (pg_namespace.oid = pg_class.relnamespace)'
- ' WHERE pg_class.oid = %s::REGCLASS::OID'),
- (qualified_table,))
- except ProgrammingError as err:
- pgcode = err.pgcode
- if pgcode == psycopg2.errorcodes.INVALID_SCHEMA_NAME:
- raise upload_ex.MissingSchemaError(
- 'No such schema',
- err.diag.message_primary,)
- elif pgcode == psycopg2.errorcodes.UNDEFINED_TABLE:
- raise upload_ex.MissingTableError(
- 'No such table or view',
- err.diag.message_primary,
- ('
Hint: Check spelling or try qualifying the'
- ' table name with a schema name
'))
- else:
- raise
- return self.cur.fetchone()
-
- def good_table(self, schema, table):
- '''Is the supplied table or view insertable?
- '''
- sql = ('SELECT 1 FROM information_schema.tables'
- ' WHERE tables.table_name = %s'
- ' AND tables.table_schema = %s'
- " AND (tables.is_insertable_into = 'YES'"
- # Unfortunatly, as of 9.2, the information_schema
- # tables.is_insertable_into does not reflect whether
- # there's an insert trigger on the table.
- " OR tables.table_type = 'VIEW')")
- self.cur.execute(sql, (table, schema))
- return self.cur.fetchone() is not None
-
- def quote_columns(self):
- '''Return boolean -- whether to take column names literally
- '''
- settings = self.request.registry.settings
- quoter_setting = settings['pgwui'].get('literal_column_headings')
- if quoter_setting == 'on':
- return True
- elif quoter_setting == 'ask':
- return self.uf['literal_col_headings']
- else:
- return False
-
def factory(self, ue):
'''Make a db loader function from an UploadEngine.
@@ -191,72 +127,13 @@ class TableUploadHandler(TabularFileUploadHandler):
self.ue = ue
self.cur = ue.cur
- data = ue.data
qualified_table = self.uf['table']
quotecols = self.quote_columns()
- if quotecols:
- column_quoter = doublequote
- else:
- def column_quoter(x):
- return x
-
- schema, table = self.resolve_table(qualified_table)
-
- if not self.good_table(schema, table):
- raise upload_ex.CannotInsertError(
- 'Cannot insert into supplied table or view',
- ('({0}) is either is a view'
- ' that cannot be inserted into'
- ' or you do not have the necessary'
- ' permissions to the table or view').format(
- markupsafe.escape(qualified_table)))
-
- column_sql = ('SELECT 1 FROM information_schema.columns'
- ' WHERE columns.table_name = %s'
- ' AND columns.table_schema = %s')
- if quotecols:
- column_sql += ' AND columns.column_name = %s'
- else:
- column_sql += ' AND columns.column_name = lower(%s::name)'
-
- insert_stmt = 'INSERT INTO {0} ('.format(doublequote(qualified_table))
- value_string = ''
- col_sep = ''
- bad_cols = []
- for col_name in data.headers.tuples:
- # Check that colum name exists
- self.cur.execute(column_sql, (table, schema, col_name))
- if self.cur.fetchone() is None:
- bad_cols.append(col_name)
- else:
- # Add column to sql statement
- insert_stmt += col_sep + column_quoter(col_name)
- value_string += col_sep + '%s'
- col_sep = ', '
-
- if bad_cols:
- if quotecols:
- detail = ('
The following columns are not in the ({0})'
- ' table, or the supplied column names do not match'
- " the character case of the table's columns,"
- ' or you do not have permission to access'
- ' the columns:
')
- else:
- detail = ('
The following columns are not in the ({0})'
- ' table, or the table has column names containing'
- ' upper case characters, or you do not have'
- ' permission to access the columns:
')
- detail = detail.format(markupsafe.escape(qualified_table))
-
- for bad_col in bad_cols:
- detail += '