cocluto v1.06
- fixed bug in SshAccessedMysqlDb which didn't handle the fields with is_autoinc_index properly - fixed bug in SshAccessedMysqlDb which failed when a field description contained double quotes - improved SshAccessedMysqlDb.query(), which now displays the error message on failure - fixed bug in SshAccessedMysqlDb.table_exists,which failed when the table didn't exist. work related to [https://bugzilla.ipr.univ-rennes.fr/show_bug.cgi?id=3958]
This commit is contained in:
		
							parent
							
								
									fbf565fd8a
								
							
						
					
					
						commit
						e5ced9e8bb
					
				| 
						 | 
				
			
			@ -73,7 +73,7 @@ class ISqlDatabaseBackend(object):
 | 
			
		|||
        pass
 | 
			
		||||
 | 
			
		||||
    @abc.abstractmethod
 | 
			
		||||
    def query(self, sql_query: SqlQuery):
 | 
			
		||||
    def query(self, sql_query: SqlQuery) -> List[str]:
 | 
			
		||||
        """
 | 
			
		||||
        :param str sql_query: the sql query to perform
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +131,7 @@ class RemoteMysqlDb(ISqlDatabaseBackend):
 | 
			
		|||
        self._conn = MySQLdb.connect(self._db_server_fqdn, self._db_user, '', self._db_name)
 | 
			
		||||
        assert self._conn
 | 
			
		||||
 | 
			
		||||
    def query(self, sql_query):
 | 
			
		||||
    def query(self, sql_query) -> List[str]:
 | 
			
		||||
        """
 | 
			
		||||
        :param str sql_query: the sql query to perform
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -177,23 +177,26 @@ class SshAccessedMysqlDb(ISqlDatabaseBackend):
 | 
			
		|||
        self._db_name = db_name
 | 
			
		||||
        self.ssh_user = ssh_user
 | 
			
		||||
 | 
			
		||||
    def query(self, sql_query: SqlQuery):
 | 
			
		||||
    def query(self, sql_query: SqlQuery) -> List[str]:
 | 
			
		||||
        """
 | 
			
		||||
        :param str sql_query: the sql query to perform
 | 
			
		||||
        """
 | 
			
		||||
        escaped_sql_command = sql_query.replace('`', r'\\\`')
 | 
			
		||||
        escaped_sql_command = sql_query.replace('`', r'\\\`').replace('"', r'\\\"')
 | 
			
		||||
        command = f'ssh "{self.ssh_user}@{self._db_server_fqdn}" "echo \\"use {self._db_name}; {escaped_sql_command}\\" | mysql --defaults-group-suffix={self._db_user}"'
 | 
			
		||||
        completed_process = subprocess.run(command, shell=True, check=True, capture_output=True)
 | 
			
		||||
        completed_process = subprocess.run(command, shell=True, check=False, capture_output=True)
 | 
			
		||||
        if completed_process.returncode != 0:
 | 
			
		||||
            logging.error(completed_process.stderr.decode(encoding='utf-8'))
 | 
			
		||||
            assert False
 | 
			
		||||
        rows = completed_process.stdout.decode('utf-8').split('\n')
 | 
			
		||||
        return rows
 | 
			
		||||
 | 
			
		||||
    def table_exists(self, table_name: str) -> bool:
 | 
			
		||||
        rows = self.query(f"SHOW TABLES LIKE '{table_name}';")
 | 
			
		||||
        assert re.match(r'^Tables_in_', rows[0]), f'unexpected value for the 1st line : {rows[0]}. (the 1st line is expected to contain something like "Tables_in_test_iprbenchs (dummy)")'
 | 
			
		||||
        logging.debug('len(rows) = %d', len(rows))
 | 
			
		||||
        logging.debug('rows = %s', str(rows))
 | 
			
		||||
        assert len(rows) <= 3, f'Unexpected case: more than one ({len(rows) - 2}) tables match the table name {table_name}.'
 | 
			
		||||
        if len(rows) >= 3:
 | 
			
		||||
            assert re.match(r'^Tables_in_', rows[0]), f'unexpected value for the 1st line : {rows[0]}. (the 1st line is expected to contain something like "Tables_in_test_iprbenchs (dummy)")'
 | 
			
		||||
            assert rows[1] == table_name
 | 
			
		||||
        return len(rows) == 3
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -210,7 +213,7 @@ class SshAccessedMysqlDb(ISqlDatabaseBackend):
 | 
			
		|||
            }[field.field_type]
 | 
			
		||||
            if field.is_autoinc_index:
 | 
			
		||||
                assert field.field_type == SqlTableField.Type.FIELD_TYPE_INT
 | 
			
		||||
                sql_field_type = 'INTEGER PRIMARY KEY'
 | 
			
		||||
                sql_field_type = 'INTEGER PRIMARY KEY AUTO_INCREMENT'
 | 
			
		||||
            fields_sql_description = self.get_field_directive(field.name, sql_field_type, field.description)
 | 
			
		||||
            fields_sql_descriptions.append(fields_sql_description)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -228,7 +231,7 @@ class SshAccessedMysqlDb(ISqlDatabaseBackend):
 | 
			
		|||
    def dump(self, sql_file_path: Path):
 | 
			
		||||
        # mysqldump -u root --quote-names --opt --single-transaction --quick $db >
 | 
			
		||||
        command = f'ssh "{self.ssh_user}@{self._db_server_fqdn}" "mysqldump --defaults-group-suffix={self._db_user}" {self._db_name} > {sql_file_path}'
 | 
			
		||||
        _ = subprocess.run(command, shell=True, check=True, capture_output=True)
 | 
			
		||||
        _ = subprocess.run(command, shell=True, check=False, capture_output=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SqliteDb(ISqlDatabaseBackend):
 | 
			
		||||
| 
						 | 
				
			
			@ -262,7 +265,7 @@ class SqliteDb(ISqlDatabaseBackend):
 | 
			
		|||
 | 
			
		||||
        _ = self.query('PRAGMA encoding="UTF-8";')
 | 
			
		||||
 | 
			
		||||
    def query(self, sql_query):
 | 
			
		||||
    def query(self, sql_query) -> List[str]:
 | 
			
		||||
        """
 | 
			
		||||
        :param str sql_query: the sql query to perform
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								setup.py
								
								
								
								
							
							
						
						
									
										2
									
								
								setup.py
								
								
								
								
							| 
						 | 
				
			
			@ -2,7 +2,7 @@ from setuptools import setup
 | 
			
		|||
 | 
			
		||||
setup(
 | 
			
		||||
    name='cocluto',
 | 
			
		||||
    version=1.05,
 | 
			
		||||
    version=1.06,
 | 
			
		||||
    description='compute cluster utility tools',
 | 
			
		||||
    url='https://git.ipr.univ-rennes1.fr/graffy/cocluto',
 | 
			
		||||
    author='Guillaume Raffy',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,35 +10,29 @@ def stringify(value: Any):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
def test_sql_backend(sql_backend: ISqlDatabaseBackend):
 | 
			
		||||
    table_name = 'dummy'
 | 
			
		||||
    table_name = 'colutotestmamul1'
 | 
			
		||||
    fields = [
 | 
			
		||||
        SqlTableField('family_name', SqlTableField.Type.FIELD_TYPE_STRING, 'family name'),
 | 
			
		||||
        SqlTableField('birth_area_code', SqlTableField.Type.FIELD_TYPE_INT, 'the number encoding the birth department'),
 | 
			
		||||
        SqlTableField('height', SqlTableField.Type.FIELD_TYPE_FLOAT, 'height (in meters)'),
 | 
			
		||||
        SqlTableField('birth_date', SqlTableField.Type.FIELD_TYPE_TIME, 'birth date')
 | 
			
		||||
        SqlTableField('measure_id', SqlTableField.Type.FIELD_TYPE_INT, 'unique identifier of the measurement', is_autoinc_index=True),
 | 
			
		||||
        SqlTableField('measurement_time', SqlTableField.Type.FIELD_TYPE_TIME, 'the time (and date) at which this measurment has been made'),
 | 
			
		||||
        SqlTableField('cpu_model', SqlTableField.Type.FIELD_TYPE_STRING, 'The exact model of the cpu running the benchmark eg "Intel(R) Core(TM) i5-8350U CPU @ 1.70GHz"'),
 | 
			
		||||
        SqlTableField('duration', SqlTableField.Type.FIELD_TYPE_FLOAT, 'the duration of the benchmark (in seconds)'),
 | 
			
		||||
    ]
 | 
			
		||||
    if sql_backend.table_exists(table_name):
 | 
			
		||||
        sql_backend.delete_table(table_name)
 | 
			
		||||
    sql_backend.create_table(table_name, fields)
 | 
			
		||||
    persons = [
 | 
			
		||||
    measurements = [
 | 
			
		||||
        {
 | 
			
		||||
            'family_name': 'Dupont',
 | 
			
		||||
            'birth_area_code': 35,
 | 
			
		||||
            'height': 1.75,
 | 
			
		||||
            'birth_date': '1950-11-12 01:23:45'
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            'family_name': 'Dupond',
 | 
			
		||||
            'birth_area_code': 44,
 | 
			
		||||
            'height': 1.74,
 | 
			
		||||
            'birth_date': '1951+12-13 12:34:50'
 | 
			
		||||
            'measurement_time': '1951+12-13 12:34:50',
 | 
			
		||||
            'cpu_model': 'Intel(R) Core(TM) i5-8350U CPU @ 1.70GHz',
 | 
			
		||||
            'duration': 0.42
 | 
			
		||||
        }
 | 
			
		||||
    ]
 | 
			
		||||
    for person in persons:
 | 
			
		||||
        sql_query = f'insert into {table_name}({", ".join([field.name for field in fields])}) values({", ".join([stringify(person[field.name]) for field in fields])});'
 | 
			
		||||
    for measurement in measurements:
 | 
			
		||||
        sql_query = f'insert into {table_name}({", ".join([field.name for field in fields if not field.is_autoinc_index])}) values({", ".join([stringify(measurement[field.name]) for field in fields if not field.is_autoinc_index])});'
 | 
			
		||||
        logging.debug('sql_query = %s', sql_query)
 | 
			
		||||
        sql_backend.query(sql_query)
 | 
			
		||||
    sql_backend.dump(Path('/tmp/toto.sql'))
 | 
			
		||||
    sql_backend.delete_table(table_name)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SimpadbTestCase(unittest.TestCase):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue