def get_schema(self, std_schema: s_schema.FlatSchema) -> s_schema.Schema: assert isinstance(std_schema, s_schema.FlatSchema) return s_schema.ChainedSchema( std_schema, self._current.user_schema, self._current.global_schema, )
def _get_gqlcore( std_schema: s_schema.FlatSchema, user_schema: s_schema.FlatSchema, global_schema: s_schema.FlatSchema, ) -> graphql.GQLCoreSchema: return graphql.GQLCoreSchema( s_schema.ChainedSchema(std_schema, user_schema, global_schema))
async def introspect_user_schema(self, conn): json_data = await conn.parse_execute_json( self._local_intro_query, b'__local_intro_db', dbver=0, use_prep_stmt=True, args=(), ) base_schema = s_schema.ChainedSchema( self._std_schema, s_schema.FlatSchema(), self.get_global_schema(), ) return s_refl.parse_into( base_schema=base_schema, schema=s_schema.FlatSchema(), data=json_data, schema_class_layout=self._schema_class_layout, )
async def _make_stdlib(testmode: bool, global_ids) -> StdlibBits: schema = s_schema.ChainedSchema( s_schema.FlatSchema(), s_schema.FlatSchema(), s_schema.FlatSchema(), ) schema, _ = s_mod.Module.create_in_schema( schema, name=sn.UnqualName('__derived__'), ) current_block = dbops.PLTopBlock() std_texts = [] for modname in s_schema.STD_SOURCES: std_texts.append(s_std.get_std_module_text(modname)) if testmode: std_texts.append(s_std.get_std_module_text(sn.UnqualName('_testmode'))) ddl_text = '\n'.join(std_texts) types: Set[uuid.UUID] = set() std_plans: List[sd.Command] = [] for ddl_cmd in edgeql.parse_block(ddl_text): assert isinstance(ddl_cmd, qlast.DDLCommand) delta_command = s_ddl.delta_from_ddl(ddl_cmd, modaliases={}, schema=schema, stdmode=True) if debug.flags.delta_plan_input: debug.header('Delta Plan Input') debug.dump(delta_command) # Apply and adapt delta, build native delta plan, which # will also update the schema. schema, plan = _process_delta(delta_command, schema) std_plans.append(delta_command) types.update(plan.new_types) plan.generate(current_block) _, schema_version = s_std.make_schema_version(schema) schema, plan = _process_delta(schema_version, schema) std_plans.append(schema_version) plan.generate(current_block) stdglobals = '\n'.join([ f'''CREATE SUPERUSER ROLE {edbdef.EDGEDB_SUPERUSER} {{ SET id := <uuid>'{global_ids[edbdef.EDGEDB_SUPERUSER]}' }};''', ]) schema = await _execute_edgeql_ddl(schema, stdglobals) _, global_schema_version = s_std.make_global_schema_version(schema) schema, plan = _process_delta(global_schema_version, schema) std_plans.append(global_schema_version) plan.generate(current_block) reflection = s_refl.generate_structure(schema) reflschema, reflplan = _process_delta(reflection.intro_schema_delta, schema) assert current_block is not None reflplan.generate(current_block) subblock = current_block.add_block() compiler = edbcompiler.new_compiler( std_schema=schema.get_top_schema(), reflection_schema=reflschema.get_top_schema(), schema_class_layout=reflection.class_layout, # type: ignore ) compilerctx = edbcompiler.new_compiler_context( user_schema=reflschema.get_top_schema(), global_schema=schema.get_global_schema(), bootstrap_mode=True, ) for std_plan in std_plans: compiler._compile_schema_storage_in_delta( ctx=compilerctx, delta=std_plan, block=subblock, ) compilerctx = edbcompiler.new_compiler_context( user_schema=reflschema.get_top_schema(), global_schema=schema.get_global_schema(), bootstrap_mode=True, internal_schema_mode=True, ) compiler._compile_schema_storage_in_delta( ctx=compilerctx, delta=reflection.intro_schema_delta, block=subblock, ) sqltext = current_block.to_string() compilerctx = edbcompiler.new_compiler_context( user_schema=reflschema.get_top_schema(), global_schema=schema.get_global_schema(), schema_reflection_mode=True, output_format=edbcompiler.IoFormat.JSON_ELEMENTS, ) # The introspection query bits are returned in chunks # because it's a large UNION and we currently generate SQL # that is much harder for Posgres to plan as opposed to a # straight flat UNION. sql_intro_local_parts = [] sql_intro_global_parts = [] for intropart in reflection.local_intro_parts: sql_intro_local_parts.append( compile_single_query( intropart, compiler=compiler, compilerctx=compilerctx, ), ) for intropart in reflection.global_intro_parts: sql_intro_global_parts.append( compile_single_query( intropart, compiler=compiler, compilerctx=compilerctx, ), ) local_intro_sql = ' UNION ALL '.join(sql_intro_local_parts) local_intro_sql = f''' WITH intro(c) AS ({local_intro_sql}) SELECT json_agg(intro.c) FROM intro ''' global_intro_sql = ' UNION ALL '.join(sql_intro_global_parts) global_intro_sql = f''' WITH intro(c) AS ({global_intro_sql}) SELECT json_agg(intro.c) FROM intro ''' return StdlibBits( stdschema=schema.get_top_schema(), reflschema=reflschema.get_top_schema(), global_schema=schema.get_global_schema(), sqltext=sqltext, types=types, classlayout=reflection.class_layout, local_intro_query=local_intro_sql, global_intro_query=global_intro_sql, )
def compile_graphql( std_schema: s_schema.FlatSchema, user_schema: s_schema.FlatSchema, global_schema: s_schema.FlatSchema, database_config: Mapping[str, Any], system_config: Mapping[str, Any], gql: str, tokens: Optional[List[Tuple[gql_lexer.TokenKind, int, int, int, int, str]]], substitutions: Optional[Dict[str, Tuple[str, int, int]]], operation_name: str = None, variables: Optional[Mapping[str, object]] = None, ) -> CompiledOperation: if tokens is None: ast = graphql.parse_text(gql) else: ast = graphql.parse_tokens(gql, tokens) gqlcore = _get_gqlcore(std_schema, user_schema, global_schema) op = graphql.translate_ast(gqlcore, ast, variables=variables, substitutions=substitutions, operation_name=operation_name) ir = qlcompiler.compile_ast_to_ir( op.edgeql_ast, schema=s_schema.ChainedSchema( std_schema, user_schema, global_schema, ), options=qlcompiler.CompilerOptions( json_parameters=True, allow_top_level_shape_dml=True, ), ) if ir.cardinality.is_multi(): raise errors.ResultCardinalityMismatchError( f'compiled GrqphQL query has cardinality {ir.cardinality}, ' f'expected ONE') sql_text, argmap = pg_compiler.compile_ir_to_sql( ir, pretty=bool(debug.flags.edgeql_compile), expected_cardinality_one=True, output_format=pg_compiler.OutputFormat.JSON) args: List[Optional[str]] = [None] * len(argmap) for argname, param in argmap.items(): args[param.index - 1] = argname sql_bytes = sql_text.encode() sql_hash = hashlib.sha1(sql_bytes).hexdigest().encode('latin1') return CompiledOperation( sql=sql_bytes, sql_hash=sql_hash, sql_args=args, # type: ignore[arg-type] # XXX: optional bug? cacheable=op.cacheable, cache_deps_vars=op.cache_deps_vars, variables=op.variables_desc, )