source>release>applicationservice>servermodel
This commit is contained in:
parent
a092b597f8
commit
f7a97cf575
|
@ -27,7 +27,7 @@ parameters:
|
||||||
|
|
||||||
response:
|
response:
|
||||||
type: ApplicationService
|
type: ApplicationService
|
||||||
description: Informations sur le modèle de serveur créé.
|
description: Informations sur le service applicatif créé.
|
||||||
|
|
||||||
errors:
|
errors:
|
||||||
- uri: servermodel.create.error.database_not_available
|
- uri: servermodel.create.error.database_not_available
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
uri: applicationservice.dataset.updated
|
uri: applicationservice.dataset.updated
|
||||||
|
|
||||||
description: |
|
description: |
|
||||||
Initialise la table pour les services applicatifs.
|
Les services applicatifs sont mis à jour.
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
public: true
|
public: true
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
release_path:
|
source_name:
|
||||||
type: String
|
type: String
|
||||||
shortarg: s
|
shortarg: s
|
||||||
description: Nom de la source.
|
description: Nom de la source.
|
||||||
release_id:
|
release_distribution:
|
||||||
type: Number
|
type: String
|
||||||
shortarg: r
|
shortarg: r
|
||||||
description: Nom de la version.
|
description: Distribution de la source.
|
||||||
|
|
||||||
response:
|
response:
|
||||||
type: ReturnStatus
|
type: ReturnStatus
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
---
|
||||||
|
uri: applicationservice.get_by_id
|
||||||
|
|
||||||
|
description: |
|
||||||
|
Retourne un service applicatif suivant l'identifiant.
|
||||||
|
|
||||||
|
pattern: rpc
|
||||||
|
|
||||||
|
public: true
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
applicationservice_id:
|
||||||
|
type: Number
|
||||||
|
shortarg: i
|
||||||
|
description: |
|
||||||
|
ID du service applicatif à créer.
|
||||||
|
|
||||||
|
response:
|
||||||
|
type: ApplicationService
|
||||||
|
description: Informations sur le service applicatif créé.
|
||||||
|
|
||||||
|
errors:
|
||||||
|
- uri: servermodel.create.error.database_not_available
|
||||||
|
- uri: servermodel.create.error.duplicate_servermodel
|
||||||
|
- uri: servermodel.create.error.invalid_parentservermodel_id
|
||||||
|
- uri: servermodel.create.error.invalid_source_id
|
||||||
|
- uri: servermodel.create.error.unknown_parentservermodel_id
|
||||||
|
- uri: servermodel.create.error.unknown_source_id
|
||||||
|
- uri: servermodel.create.error.servermodelname_not_provided
|
||||||
|
|
||||||
|
related:
|
||||||
|
- servermodel.list
|
||||||
|
- servermodel.describe
|
||||||
|
- servermodel.update
|
||||||
|
- servermodel.delete
|
||||||
|
- servermodel.event
|
|
@ -6,7 +6,7 @@ description: |
|
||||||
|
|
||||||
pattern: rpc
|
pattern: rpc
|
||||||
|
|
||||||
public: false
|
public: true
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
source_id:
|
source_id:
|
||||||
|
@ -18,6 +18,11 @@ parameters:
|
||||||
shortarg: n
|
shortarg: n
|
||||||
description: |
|
description: |
|
||||||
Nom de la version.
|
Nom de la version.
|
||||||
|
release_distribution:
|
||||||
|
type: String
|
||||||
|
shortarg: d
|
||||||
|
description: |
|
||||||
|
Distribution de la version.
|
||||||
|
|
||||||
response:
|
response:
|
||||||
type: 'Release'
|
type: 'Release'
|
||||||
|
|
|
@ -12,7 +12,7 @@ properties:
|
||||||
applicationservice_description:
|
applicationservice_description:
|
||||||
type: string
|
type: string
|
||||||
description: Description du service applicatif.
|
description: Description du service applicatif.
|
||||||
release_id:
|
applicationservice_release_id:
|
||||||
type: number
|
type: number
|
||||||
ref: Version.ReleaseId
|
ref: Version.ReleaseId
|
||||||
description: Version du service applicatif.
|
description: Version du service applicatif.
|
||||||
|
@ -23,8 +23,6 @@ properties:
|
||||||
description: Liste des services applicatifs déclarés en dépendance de ce service applicatif.
|
description: Liste des services applicatifs déclarés en dépendance de ce service applicatif.
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- servermodelid
|
- applicationservice_id
|
||||||
- servermodelname
|
- applicationservice_name
|
||||||
- servermodeldescription
|
- applicationservice_release_id
|
||||||
- servermodelsubreleaseid
|
|
||||||
- subreleasename
|
|
||||||
|
|
|
@ -9,6 +9,9 @@ properties:
|
||||||
release_name:
|
release_name:
|
||||||
type: string
|
type: string
|
||||||
description: Le nom de la version.
|
description: Le nom de la version.
|
||||||
|
release_distribution:
|
||||||
|
type: string
|
||||||
|
description: Le nom de la distribution de la version.
|
||||||
source_url:
|
source_url:
|
||||||
type: string
|
type: string
|
||||||
description: URL de la source.
|
description: URL de la source.
|
||||||
|
@ -19,6 +22,7 @@ properties:
|
||||||
required:
|
required:
|
||||||
- release_id
|
- release_id
|
||||||
- release_name
|
- release_name
|
||||||
|
- release_distribution
|
||||||
- source_name
|
- source_name
|
||||||
- source_url
|
- source_url
|
||||||
|
|
||||||
|
|
|
@ -84,4 +84,7 @@ async def main():
|
||||||
async with connection.transaction():
|
async with connection.transaction():
|
||||||
returns = await connection.execute(VERSION_INIT)
|
returns = await connection.execute(VERSION_INIT)
|
||||||
|
|
||||||
asyncio.run(main())
|
if __name__ == '__main__':
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
loop.run_until_complete(main())
|
||||||
|
# asyncio.run(main())
|
||||||
|
|
|
@ -12,6 +12,9 @@ from ...context import Context
|
||||||
from ...utils import _
|
from ...utils import _
|
||||||
|
|
||||||
class Risotto(Controller):
|
class Risotto(Controller):
|
||||||
|
def __init__(self):
|
||||||
|
self.source_root_path = get_config().get('source').get('root_path')
|
||||||
|
|
||||||
async def _applicationservice_create(self,
|
async def _applicationservice_create(self,
|
||||||
risotto_context: Context,
|
risotto_context: Context,
|
||||||
applicationservice_name: str,
|
applicationservice_name: str,
|
||||||
|
@ -26,6 +29,7 @@ class Risotto(Controller):
|
||||||
release_id)
|
release_id)
|
||||||
return {'applicationservice_name': applicationservice_name,
|
return {'applicationservice_name': applicationservice_name,
|
||||||
'applicationservice_description': applicationservice_description,
|
'applicationservice_description': applicationservice_description,
|
||||||
|
'applicationservice_release_id': release_id,
|
||||||
'applicationservice_id': applicationservice_id}
|
'applicationservice_id': applicationservice_id}
|
||||||
|
|
||||||
@register('v1.applicationservice.create', None, database=True)
|
@register('v1.applicationservice.create', None, database=True)
|
||||||
|
@ -41,10 +45,21 @@ class Risotto(Controller):
|
||||||
|
|
||||||
@register('v1.applicationservice.dataset.updated', None, database=True)
|
@register('v1.applicationservice.dataset.updated', None, database=True)
|
||||||
async def applicationservice_update(self,
|
async def applicationservice_update(self,
|
||||||
risotto_context,
|
risotto_context: Context,
|
||||||
release_path: str,
|
source_name: str,
|
||||||
release_id: int) -> Dict:
|
release_distribution: str) -> Dict:
|
||||||
applicationservice_path = join(release_path, 'applicationservice')
|
source = await self.call('v1.source.describe',
|
||||||
|
risotto_context,
|
||||||
|
source_name=source_name)
|
||||||
|
release = await self.call('v1.source.release.get_by_distribution',
|
||||||
|
risotto_context,
|
||||||
|
source_id=source['source_id'],
|
||||||
|
release_distribution=release_distribution)
|
||||||
|
applicationservice_path = join(self.source_root_path,
|
||||||
|
source_name,
|
||||||
|
release['release_name'],
|
||||||
|
'applicationservice')
|
||||||
|
release_id = release['release_id']
|
||||||
for service in listdir(applicationservice_path):
|
for service in listdir(applicationservice_path):
|
||||||
try:
|
try:
|
||||||
applicationservice_description_path = join(applicationservice_path,
|
applicationservice_description_path = join(applicationservice_path,
|
||||||
|
@ -68,3 +83,20 @@ class Risotto(Controller):
|
||||||
raise ExecutionError(_(f"Error while injecting application service {applicationservice_description['name']} in database: {err}"))
|
raise ExecutionError(_(f"Error while injecting application service {applicationservice_description['name']} in database: {err}"))
|
||||||
return {'retcode': 0,
|
return {'retcode': 0,
|
||||||
'returns': _('Application Services successfully loaded')}
|
'returns': _('Application Services successfully loaded')}
|
||||||
|
|
||||||
|
@register('v1.applicationservice.get_by_id', None, database=True)
|
||||||
|
async def applicationservice_get_by_id(self,
|
||||||
|
risotto_context: Context,
|
||||||
|
applicationservice_id: int) -> Dict:
|
||||||
|
applicationservice_query = """
|
||||||
|
SELECT ApplicationServiceId as applicationservice_id, ApplicationServiceName as applicationservice_name, ApplicationServiceDependencies as applicationservice_dependencies, ApplicationServiceReleaseId as applicationservice_release_id
|
||||||
|
FROM applicationservice
|
||||||
|
WHERE applicationserviceid=$1"""
|
||||||
|
applicationservice = await risotto_context.connection.fetchrow(applicationservice_query,
|
||||||
|
applicationservice_id)
|
||||||
|
if applicationservice is None:
|
||||||
|
raise Exception(_(f'unknown service with ID {applicationservice_id}'))
|
||||||
|
applicationservice = dict(applicationservice)
|
||||||
|
if applicationservice['applicationservice_dependencies'] is None:
|
||||||
|
applicationservice['applicationservice_dependencies'] = []
|
||||||
|
return applicationservice
|
||||||
|
|
|
@ -29,13 +29,15 @@ class Risotto(Controller):
|
||||||
internal_release = await self.call('v1.source.release.create',
|
internal_release = await self.call('v1.source.release.create',
|
||||||
risotto_context,
|
risotto_context,
|
||||||
source_id=internal_source['source_id'],
|
source_id=internal_source['source_id'],
|
||||||
release_name='none')
|
release_name='none',
|
||||||
|
release_distribution='stable')
|
||||||
self.internal_release_id = internal_release['release_id']
|
self.internal_release_id = internal_release['release_id']
|
||||||
|
|
||||||
async def servermodel_gen_schema(self,
|
async def servermodel_gen_schema(self,
|
||||||
risotto_context: Context,
|
risotto_context: Context,
|
||||||
servermodel_id: int,
|
servermodel_id: int,
|
||||||
applicationservice_id: int) -> None:
|
applicationservice_id: int,
|
||||||
|
release_cache: Dict) -> None:
|
||||||
dependencies = await self.get_applicationservices(risotto_context,
|
dependencies = await self.get_applicationservices(risotto_context,
|
||||||
applicationservice_id)
|
applicationservice_id)
|
||||||
if release_cache is None:
|
if release_cache is None:
|
||||||
|
@ -45,10 +47,11 @@ class Risotto(Controller):
|
||||||
applicationservice_name, as_release_id = applicationservice_infos
|
applicationservice_name, as_release_id = applicationservice_infos
|
||||||
if as_release_id not in release_cache:
|
if as_release_id not in release_cache:
|
||||||
release_cache[as_release_id] = await self.call('v1.source.release.get_by_id',
|
release_cache[as_release_id] = await self.call('v1.source.release.get_by_id',
|
||||||
|
risotto_context,
|
||||||
release_id=as_release_id)
|
release_id=as_release_id)
|
||||||
dict_paths.append(join(self.source_root_path,
|
dict_paths.append(join(self.source_root_path,
|
||||||
release_cache[as_release_id]['source_name'],
|
release_cache[as_release_id]['source_name'],
|
||||||
release_cache[as_release_id]['release_distribution'],
|
release_cache[as_release_id]['release_name'],
|
||||||
'applicationservice',
|
'applicationservice',
|
||||||
applicationservice_name,
|
applicationservice_name,
|
||||||
'dictionaries'))
|
'dictionaries'))
|
||||||
|
@ -85,9 +88,10 @@ class Risotto(Controller):
|
||||||
servermodel_parents_id,
|
servermodel_parents_id,
|
||||||
release_id,
|
release_id,
|
||||||
applicationservice_id)
|
applicationservice_id)
|
||||||
self.servermodel_gen_schema(risotto_context,
|
await self.servermodel_gen_schema(risotto_context,
|
||||||
servermodel_id,
|
servermodel_id,
|
||||||
applicationservice_id)
|
applicationservice_id,
|
||||||
|
release_cache)
|
||||||
return {'servermodel_name': servermodel_name,
|
return {'servermodel_name': servermodel_name,
|
||||||
'servermodel_description': servermodel_description,
|
'servermodel_description': servermodel_description,
|
||||||
'servermodel_parents_id': servermodel_parents_id,
|
'servermodel_parents_id': servermodel_parents_id,
|
||||||
|
@ -120,12 +124,6 @@ class Risotto(Controller):
|
||||||
risotto_context: Context,
|
risotto_context: Context,
|
||||||
source_name: str,
|
source_name: str,
|
||||||
release_distribution: int):
|
release_distribution: int):
|
||||||
servermodel_path = join(self.source_root_path,
|
|
||||||
source_name,
|
|
||||||
release_distribution,
|
|
||||||
'servermodel')
|
|
||||||
servermodels = {}
|
|
||||||
# for dependencies reason load all servermodels
|
|
||||||
source = await self.call('v1.source.describe',
|
source = await self.call('v1.source.describe',
|
||||||
risotto_context,
|
risotto_context,
|
||||||
source_name=source_name)
|
source_name=source_name)
|
||||||
|
@ -134,6 +132,11 @@ class Risotto(Controller):
|
||||||
source_id=source['source_id'],
|
source_id=source['source_id'],
|
||||||
release_distribution=release_distribution)
|
release_distribution=release_distribution)
|
||||||
release_id = release['release_id']
|
release_id = release['release_id']
|
||||||
|
servermodel_path = join(self.source_root_path,
|
||||||
|
source_name,
|
||||||
|
release['release_name'],
|
||||||
|
'servermodel')
|
||||||
|
servermodels = {}
|
||||||
for servermodel in listdir(servermodel_path):
|
for servermodel in listdir(servermodel_path):
|
||||||
if not servermodel.endswith('.yml'):
|
if not servermodel.endswith('.yml'):
|
||||||
continue
|
continue
|
||||||
|
@ -195,30 +198,26 @@ class Risotto(Controller):
|
||||||
return [dict(r) for r in servermodels]
|
return [dict(r) for r in servermodels]
|
||||||
|
|
||||||
async def _parse_depends(self,
|
async def _parse_depends(self,
|
||||||
risotto_context,
|
risotto_context: Context,
|
||||||
applicationservice_id: int,
|
applicationservice_id: int,
|
||||||
or_depends: list,
|
or_depends: list,
|
||||||
ids: list) -> None:
|
ids: list) -> None:
|
||||||
applicationservice_query = """
|
applicationservice = await self.call('v1.applicationservice.get_by_id',
|
||||||
SELECT ApplicationServiceName, ApplicationServiceDependencies, ApplicationServiceReleaseId
|
risotto_context,
|
||||||
FROM applicationservice
|
applicationservice_id=applicationservice_id)
|
||||||
WHERE applicationserviceid=$1"""
|
ids[applicationservice_id] = (applicationservice['applicationservice_name'],
|
||||||
applicationservice = await risotto_context.connection.fetchval(servermodel_update,
|
applicationservice['applicationservice_release_id'])
|
||||||
applicationservice_id)
|
for depend in applicationservice['applicationservice_dependencies']:
|
||||||
ids[applicationservice_id] = (applicationserverice['ApplicationServiceName'],
|
if isinstance(depend, dict):
|
||||||
applicationserverice['ApplicationServiceReleaseId'])
|
or_depends.append(depend['or'])
|
||||||
if applicationserverice['ApplicationServiceDependencies']:
|
elif depend not in ids:
|
||||||
for depend in pplicationserverice['ApplicationServiceDependencies']:
|
await self._parse_depends(risotto_context,
|
||||||
if isinstance(depend, dict):
|
depend,
|
||||||
or_depends.append(depend['or'])
|
or_depends,
|
||||||
elif depend not in ids:
|
ids)
|
||||||
await self._parse_depends(risotto_context,
|
|
||||||
depend,
|
|
||||||
or_depends,
|
|
||||||
ids)
|
|
||||||
|
|
||||||
async def _parse_or_depends(self,
|
async def _parse_or_depends(self,
|
||||||
risotto_context,
|
risotto_context: Context,
|
||||||
or_depends: list,
|
or_depends: list,
|
||||||
ids: list) -> None:
|
ids: list) -> None:
|
||||||
new_or_depends = []
|
new_or_depends = []
|
||||||
|
@ -236,12 +235,12 @@ class Risotto(Controller):
|
||||||
ids)
|
ids)
|
||||||
|
|
||||||
async def get_applicationservices(self,
|
async def get_applicationservices(self,
|
||||||
risotto_context,
|
risotto_context: Context,
|
||||||
applicationservice_id: int) -> list:
|
applicationservice_id: int) -> list:
|
||||||
"""Return consolidated dependencies or raise.
|
"""Return consolidated dependencies or raise.
|
||||||
"""
|
"""
|
||||||
or_depends = []
|
or_depends = []
|
||||||
ids = []
|
ids = {}
|
||||||
await self._parse_depends(risotto_context,
|
await self._parse_depends(risotto_context,
|
||||||
applicationservice_id,
|
applicationservice_id,
|
||||||
or_depends,
|
or_depends,
|
||||||
|
|
|
@ -54,7 +54,7 @@ class Risotto(Controller):
|
||||||
source = await risotto_context.connection.fetchrow(source_get,
|
source = await risotto_context.connection.fetchrow(source_get,
|
||||||
source_name)
|
source_name)
|
||||||
if not source:
|
if not source:
|
||||||
raise Exception(f'unknown source with name {source_name}')
|
raise Exception(_(f'unknown source with name {source_name}'))
|
||||||
return dict(source)
|
return dict(source)
|
||||||
|
|
||||||
@register('v1.source.list', None, database=True)
|
@register('v1.source.list', None, database=True)
|
||||||
|
@ -85,12 +85,13 @@ class Risotto(Controller):
|
||||||
async def source_release_create(self,
|
async def source_release_create(self,
|
||||||
risotto_context: Context,
|
risotto_context: Context,
|
||||||
source_id: int,
|
source_id: int,
|
||||||
release_name: str) -> Dict:
|
release_name: str,
|
||||||
|
release_distribution: str) -> Dict:
|
||||||
source_get = """SELECT SourceId as source_id, SourceName as source_name, SourceURL as source_url
|
source_get = """SELECT SourceId as source_id, SourceName as source_name, SourceURL as source_url
|
||||||
FROM Source
|
FROM Source
|
||||||
WHERE SourceId = $1
|
WHERE SourceId = $1
|
||||||
"""
|
"""
|
||||||
release_upsert = """INSERT INTO Release(ReleaseName, ReleaseSourceId) VALUES ($1, $2)
|
release_upsert = """INSERT INTO Release(ReleaseName, ReleaseSourceId, ReleaseDistribution) VALUES ($1, $2, $3)
|
||||||
ON CONFLICT (ReleaseName, ReleaseSourceId) DO UPDATE SET ReleaseName = $1
|
ON CONFLICT (ReleaseName, ReleaseSourceId) DO UPDATE SET ReleaseName = $1
|
||||||
RETURNING ReleaseId
|
RETURNING ReleaseId
|
||||||
"""
|
"""
|
||||||
|
@ -98,16 +99,18 @@ class Risotto(Controller):
|
||||||
source_id))
|
source_id))
|
||||||
release_id = await risotto_context.connection.fetchval(release_upsert,
|
release_id = await risotto_context.connection.fetchval(release_upsert,
|
||||||
release_name,
|
release_name,
|
||||||
source_id)
|
source_id,
|
||||||
|
release_distribution)
|
||||||
del source['source_id']
|
del source['source_id']
|
||||||
source['release_id'] = release_id
|
source['release_id'] = release_id
|
||||||
source['release_name'] = release_name
|
source['release_name'] = release_name
|
||||||
|
source['release_distribution'] = release_distribution
|
||||||
return source
|
return source
|
||||||
|
|
||||||
@register('v1.source.release.list', None, database=True)
|
@register('v1.source.release.list', None, database=True)
|
||||||
async def release_list(self,
|
async def release_list(self,
|
||||||
risotto_context):
|
risotto_context):
|
||||||
release_query = """SELECT ReleaseId as release_id, SourceName as source_name, SourceURL as source_url, ReleaseName as release_name
|
release_query = """SELECT ReleaseId as release_id, SourceName as source_name, SourceURL as source_url, ReleaseName as release_name, ReleaseDistribution as release_distribution
|
||||||
FROM Release, Source
|
FROM Release, Source
|
||||||
WHERE Source.SourceId=Release.ReleaseSourceId"""
|
WHERE Source.SourceId=Release.ReleaseSourceId"""
|
||||||
result = await risotto_context.connection.fetch(release_query)
|
result = await risotto_context.connection.fetch(release_query)
|
||||||
|
@ -117,11 +120,13 @@ class Risotto(Controller):
|
||||||
async def release_get_by_id(self,
|
async def release_get_by_id(self,
|
||||||
risotto_context: Context,
|
risotto_context: Context,
|
||||||
release_id: int) -> Dict:
|
release_id: int) -> Dict:
|
||||||
release_query = """SELECT ReleaseId as release_id, SourceName as source_name, SourceURL as source_url, ReleaseName as release_name
|
release_query = """SELECT ReleaseId as release_id, SourceName as source_name, SourceURL as source_url, ReleaseName as release_name, ReleaseDistribution as release_distribution
|
||||||
FROM Release, Source
|
FROM Release, Source
|
||||||
WHERE Release.ReleaseId = $1"""
|
WHERE Release.ReleaseId = $1 AND Source.SourceId = Release.ReleaseSourceId"""
|
||||||
result = await risotto_context.connection.fetchrow(release_query,
|
result = await risotto_context.connection.fetchrow(release_query,
|
||||||
release_id)
|
release_id)
|
||||||
|
if not result:
|
||||||
|
raise Exception(_(f'unknown release id {release_id}'))
|
||||||
return dict(result)
|
return dict(result)
|
||||||
|
|
||||||
@register('v1.source.release.get_by_distribution', None, database=True)
|
@register('v1.source.release.get_by_distribution', None, database=True)
|
||||||
|
@ -129,12 +134,12 @@ class Risotto(Controller):
|
||||||
risotto_context: Context,
|
risotto_context: Context,
|
||||||
source_id: int,
|
source_id: int,
|
||||||
release_distribution: str) -> Dict:
|
release_distribution: str) -> Dict:
|
||||||
release_query = """SELECT ReleaseId as release_id, SourceName as source_name, SourceURL as source_url, ReleaseName as release_name
|
release_query = """SELECT ReleaseId as release_id, SourceName as source_name, SourceURL as source_url, ReleaseName as release_name, ReleaseDistribution as release_distribution
|
||||||
FROM Release, Source
|
FROM Release, Source
|
||||||
WHERE Source.SourceId = $1 AND Release.ReleaseName = $2"""
|
WHERE Release.ReleaseSourceId = $1 AND Release.ReleaseDistribution = $2 AND Source.SourceId = Release.ReleaseSourceId"""
|
||||||
result = await risotto_context.connection.fetchrow(release_query,
|
result = await risotto_context.connection.fetchrow(release_query,
|
||||||
source_id,
|
source_id,
|
||||||
release_distribution)
|
release_distribution)
|
||||||
if not result:
|
if not result:
|
||||||
raise Exception(f'unknown distribution {release_distribution} with source {source_id}')
|
raise Exception(_(f'unknown distribution {release_distribution} with source {source_id}'))
|
||||||
return dict(result)
|
return dict(result)
|
||||||
|
|
Loading…
Reference in New Issue