54
54
SPARQL_EXPLAIN_MODES , OPENCYPHER_EXPLAIN_MODES , GREMLIN_EXPLAIN_MODES , \
55
55
OPENCYPHER_PLAN_CACHE_MODES , OPENCYPHER_DEFAULT_TIMEOUT , OPENCYPHER_STATUS_STATE_MODES , \
56
56
normalize_service_name , NEPTUNE_DB_SERVICE_NAME , NEPTUNE_ANALYTICS_SERVICE_NAME , GRAPH_PG_INFO_METRICS , \
57
- GREMLIN_PROTOCOL_FORMATS , DEFAULT_HTTP_PROTOCOL , DEFAULT_WS_PROTOCOL , \
58
- GREMLIN_SERIALIZERS_WS , GREMLIN_SERIALIZERS_CLASS_TO_MIME_MAP , normalize_protocol_name , generate_snapshot_name )
57
+ GREMLIN_PROTOCOL_FORMATS , DEFAULT_HTTP_PROTOCOL , DEFAULT_WS_PROTOCOL , GRAPHSONV4_UNTYPED , \
58
+ GREMLIN_SERIALIZERS_WS , get_gremlin_serializer_mime , normalize_protocol_name , generate_snapshot_name )
59
59
from graph_notebook .network import SPARQLNetwork
60
60
from graph_notebook .network .gremlin .GremlinNetwork import parse_pattern_list_str , GremlinNetwork
61
61
from graph_notebook .visualization .rows_and_columns import sparql_get_rows_and_columns , opencypher_get_rows_and_columns
@@ -1091,6 +1091,9 @@ def gremlin(self, line, cell, local_ns: dict = None):
1091
1091
f'If not specified, defaults to the value of the gremlin.connection_protocol field '
1092
1092
f'in %%graph_notebook_config. Please note that this option has no effect on the '
1093
1093
f'Profile and Explain modes, which must use HTTP.' )
1094
+ parser .add_argument ('-qp' , '--query-parameters' , type = str , default = '' ,
1095
+ help = 'Parameter definitions to apply to the query. This option can accept a local variable '
1096
+ 'name, or a string representation of the map.' )
1094
1097
parser .add_argument ('--explain-type' , type = str .lower , default = 'dynamic' ,
1095
1098
help = f'Explain mode to use when using the explain query mode. '
1096
1099
f'Accepted values: { GREMLIN_EXPLAIN_MODES } ' )
@@ -1160,6 +1163,21 @@ def gremlin(self, line, cell, local_ns: dict = None):
1160
1163
logger .debug (f'Arguments { args } ' )
1161
1164
results_df = None
1162
1165
1166
+ query_params = None
1167
+ if args .query_parameters :
1168
+ if args .query_parameters in local_ns :
1169
+ query_params_input = local_ns [args .query_parameters ]
1170
+ else :
1171
+ query_params_input = args .query_parameters
1172
+ if isinstance (query_params_input , dict ):
1173
+ query_params = json .dumps (query_params_input )
1174
+ else :
1175
+ try :
1176
+ query_params_dict = json .loads (query_params_input .replace ("'" , '"' ))
1177
+ query_params = json .dumps (query_params_dict )
1178
+ except Exception as e :
1179
+ print (f"Invalid query parameter input, ignoring." )
1180
+
1163
1181
if args .no_scroll :
1164
1182
gremlin_layout = UNRESTRICTED_LAYOUT
1165
1183
gremlin_scrollY = True
@@ -1184,8 +1202,13 @@ def gremlin(self, line, cell, local_ns: dict = None):
1184
1202
1185
1203
if mode == QueryMode .EXPLAIN :
1186
1204
try :
1205
+ explain_args = {}
1206
+ if args .explain_type :
1207
+ explain_args ['explain.mode' ] = args .explain_type
1208
+ if self .client .is_analytics_domain () and query_params :
1209
+ explain_args ['parameters' ] = query_params
1187
1210
res = self .client .gremlin_explain (cell ,
1188
- args = { 'explain.mode' : args . explain_type } if args . explain_type else {} )
1211
+ args = explain_args )
1189
1212
res .raise_for_status ()
1190
1213
except Exception as e :
1191
1214
if self .client .is_analytics_domain ():
@@ -1219,6 +1242,8 @@ def gremlin(self, line, cell, local_ns: dict = None):
1219
1242
"profile.serializer" : serializer ,
1220
1243
"profile.indexOps" : args .profile_indexOps ,
1221
1244
"profile.debug" : args .profile_debug }
1245
+ if self .client .is_analytics_domain () and query_params :
1246
+ profile_args ['parameters' ] = query_params
1222
1247
try :
1223
1248
profile_misc_args_dict = json .loads (args .profile_misc_args )
1224
1249
profile_args .update (profile_misc_args_dict )
@@ -1269,17 +1294,29 @@ def gremlin(self, line, cell, local_ns: dict = None):
1269
1294
try :
1270
1295
if connection_protocol == DEFAULT_HTTP_PROTOCOL :
1271
1296
using_http = True
1297
+ headers = {}
1272
1298
message_serializer = self .graph_notebook_config .gremlin .message_serializer
1273
- message_serializer_mime = GREMLIN_SERIALIZERS_CLASS_TO_MIME_MAP [message_serializer ]
1274
- query_res_http = self .client .gremlin_http_query (cell , headers = {
1275
- 'Accept' : message_serializer_mime })
1299
+ message_serializer_mime = get_gremlin_serializer_mime (message_serializer , DEFAULT_HTTP_PROTOCOL )
1300
+ if message_serializer_mime != GRAPHSONV4_UNTYPED :
1301
+ headers ['Accept' ] = message_serializer_mime
1302
+ passed_params = query_params if self .client .is_analytics_domain () else None
1303
+ query_res_http = self .client .gremlin_http_query (cell ,
1304
+ headers = headers ,
1305
+ query_params = passed_params )
1276
1306
query_res_http .raise_for_status ()
1277
1307
try :
1278
1308
query_res_http_json = query_res_http .json ()
1279
1309
except JSONDecodeError :
1280
1310
query_res_fixed = repair_json (query_res_http .text )
1281
1311
query_res_http_json = json .loads (query_res_fixed )
1282
- query_res = query_res_http_json ['result' ]['data' ]
1312
+ if 'result' in query_res_http_json :
1313
+ query_res = query_res_http_json ['result' ]['data' ]
1314
+ else :
1315
+ if 'reason' in query_res_http_json :
1316
+ logger .debug ('Query failed with internal error, see response.' )
1317
+ else :
1318
+ logger .debug ('Received unexpected response format, outputting as single entry.' )
1319
+ query_res = [query_res_http_json ]
1283
1320
else :
1284
1321
query_res = self .client .gremlin_query (cell , transport_args = transport_args )
1285
1322
except Exception as e :
@@ -1317,7 +1354,7 @@ def gremlin(self, line, cell, local_ns: dict = None):
1317
1354
ignore_groups = args .ignore_groups ,
1318
1355
using_http = using_http )
1319
1356
1320
- if using_http and 'path()' in cell and query_res :
1357
+ if using_http and 'path()' in cell and query_res and isinstance ( query_res , list ) :
1321
1358
first_path = query_res [0 ]
1322
1359
if isinstance (first_path , dict ) and first_path .keys () == {'labels' , 'objects' }:
1323
1360
query_res_to_path_type = []
@@ -2844,8 +2881,8 @@ def seed(self, line, local_ns: dict = None):
2844
2881
2845
2882
if self .client .is_analytics_domain ():
2846
2883
model_options = SEED_MODEL_OPTIONS_PG
2847
- custom_language_options = SEED_LANGUAGE_OPTIONS_OC
2848
- samples_pg_language_options = SEED_LANGUAGE_OPTIONS_OC
2884
+ custom_language_options = SEED_LANGUAGE_OPTIONS_PG
2885
+ samples_pg_language_options = SEED_LANGUAGE_OPTIONS_PG
2849
2886
else :
2850
2887
model_options = SEED_MODEL_OPTIONS
2851
2888
custom_language_options = SEED_LANGUAGE_OPTIONS
@@ -3121,7 +3158,11 @@ def process_gremlin_query_line(query_line, line_index, q):
3121
3158
logger .debug (f"Skipped blank query at line { line_index + 1 } in seed file { q ['name' ]} " )
3122
3159
return 0
3123
3160
try :
3124
- self .client .gremlin_query (query_line )
3161
+ if self .client .is_neptune_domain () and self .client .is_analytics_domain () and \
3162
+ self .graph_notebook_config .gremlin .connection_protocol == DEFAULT_HTTP_PROTOCOL :
3163
+ self .client .gremlin_http_query (query_line )
3164
+ else :
3165
+ self .client .gremlin_query (query_line )
3125
3166
return 0
3126
3167
except GremlinServerError as gremlinEx :
3127
3168
try :
0 commit comments