/test/orm/test_of_type.py

https://github.com/sqlalchemy/sqlalchemy · Python · 1248 lines · 1190 code · 54 blank · 4 comment · 0 complexity · 4fce4518e1a308f6e524c2d7aa430d7d MD5 · raw file

  1. from sqlalchemy import and_
  2. from sqlalchemy import exc as sa_exc
  3. from sqlalchemy import ForeignKey
  4. from sqlalchemy import Integer
  5. from sqlalchemy import String
  6. from sqlalchemy import testing
  7. from sqlalchemy.orm import aliased
  8. from sqlalchemy.orm import contains_eager
  9. from sqlalchemy.orm import joinedload
  10. from sqlalchemy.orm import relationship
  11. from sqlalchemy.orm import Session
  12. from sqlalchemy.orm import subqueryload
  13. from sqlalchemy.orm import with_polymorphic
  14. from sqlalchemy.testing import assert_raises_message
  15. from sqlalchemy.testing import eq_
  16. from sqlalchemy.testing import fixtures
  17. from sqlalchemy.testing.assertsql import CompiledSQL
  18. from sqlalchemy.testing.entities import ComparableEntity
  19. from sqlalchemy.testing.schema import Column
  20. from .inheritance._poly_fixtures import _PolymorphicAliasedJoins
  21. from .inheritance._poly_fixtures import _PolymorphicJoins
  22. from .inheritance._poly_fixtures import _PolymorphicPolymorphic
  23. from .inheritance._poly_fixtures import _PolymorphicUnions
  24. from .inheritance._poly_fixtures import Boss
  25. from .inheritance._poly_fixtures import Company
  26. from .inheritance._poly_fixtures import Engineer
  27. from .inheritance._poly_fixtures import Machine
  28. from .inheritance._poly_fixtures import Manager
  29. from .inheritance._poly_fixtures import Person
  30. class _PolymorphicTestBase(object):
  31. __dialect__ = "default"
  32. def test_any_one(self):
  33. sess = Session()
  34. any_ = Company.employees.of_type(Engineer).any(
  35. Engineer.primary_language == "cobol"
  36. )
  37. eq_(sess.query(Company).filter(any_).one(), self.c2)
  38. def test_any_two(self):
  39. sess = Session()
  40. calias = aliased(Company)
  41. any_ = calias.employees.of_type(Engineer).any(
  42. Engineer.primary_language == "cobol"
  43. )
  44. eq_(sess.query(calias).filter(any_).one(), self.c2)
  45. def test_any_three(self):
  46. sess = Session()
  47. any_ = Company.employees.of_type(Boss).any(Boss.golf_swing == "fore")
  48. eq_(sess.query(Company).filter(any_).one(), self.c1)
  49. def test_any_four(self):
  50. sess = Session()
  51. any_ = Company.employees.of_type(Manager).any(
  52. Manager.manager_name == "pointy"
  53. )
  54. eq_(sess.query(Company).filter(any_).one(), self.c1)
  55. def test_any_five(self):
  56. sess = Session()
  57. any_ = Company.employees.of_type(Engineer).any(
  58. and_(Engineer.primary_language == "cobol")
  59. )
  60. eq_(sess.query(Company).filter(any_).one(), self.c2)
  61. def test_join_to_subclass_one(self):
  62. sess = Session()
  63. eq_(
  64. sess.query(Company)
  65. .join(Company.employees.of_type(Engineer))
  66. .filter(Engineer.primary_language == "java")
  67. .all(),
  68. [self.c1],
  69. )
  70. def test_join_to_subclass_two(self):
  71. sess = Session()
  72. eq_(
  73. sess.query(Company)
  74. .join(Company.employees.of_type(Engineer), "machines")
  75. .filter(Machine.name.ilike("%thinkpad%"))
  76. .all(),
  77. [self.c1],
  78. )
  79. def test_join_to_subclass_three(self):
  80. sess = Session()
  81. eq_(
  82. sess.query(Company, Engineer)
  83. .join(Company.employees.of_type(Engineer))
  84. .filter(Engineer.primary_language == "java")
  85. .count(),
  86. 1,
  87. )
  88. def test_join_to_subclass_four(self):
  89. sess = Session()
  90. # test [ticket:2093]
  91. eq_(
  92. sess.query(Company.company_id, Engineer)
  93. .join(Company.employees.of_type(Engineer))
  94. .filter(Engineer.primary_language == "java")
  95. .count(),
  96. 1,
  97. )
  98. def test_join_to_subclass_five(self):
  99. sess = Session()
  100. eq_(
  101. sess.query(Company)
  102. .join(Company.employees.of_type(Engineer))
  103. .filter(Engineer.primary_language == "java")
  104. .count(),
  105. 1,
  106. )
  107. def test_with_polymorphic_join_compile_one(self):
  108. sess = Session()
  109. self.assert_compile(
  110. sess.query(Company).join(
  111. Company.employees.of_type(
  112. with_polymorphic(
  113. Person, [Engineer, Manager], aliased=True, flat=True
  114. )
  115. )
  116. ),
  117. "SELECT companies.company_id AS companies_company_id, "
  118. "companies.name AS companies_name FROM companies "
  119. "JOIN %s" % (self._polymorphic_join_target([Engineer, Manager])),
  120. )
  121. def test_with_polymorphic_join_exec_contains_eager_one(self):
  122. sess = Session()
  123. def go():
  124. wp = with_polymorphic(
  125. Person, [Engineer, Manager], aliased=True, flat=True
  126. )
  127. eq_(
  128. sess.query(Company)
  129. .join(Company.employees.of_type(wp))
  130. .order_by(Company.company_id, wp.person_id)
  131. .options(contains_eager(Company.employees.of_type(wp)))
  132. .all(),
  133. [self.c1, self.c2],
  134. )
  135. self.assert_sql_count(testing.db, go, 1)
  136. @testing.combinations(
  137. # this form is not expected to work in all cases, ultimately
  138. # the "alias" parameter should be deprecated entirely
  139. # lambda Company, wp: contains_eager(Company.employees, alias=wp),
  140. lambda Company, wp: contains_eager(Company.employees.of_type(wp)),
  141. lambda Company, wp: contains_eager(
  142. Company.employees.of_type(wp), alias=wp
  143. ),
  144. )
  145. def test_with_polymorphic_join_exec_contains_eager_two(
  146. self, contains_eager_option
  147. ):
  148. sess = Session()
  149. wp = with_polymorphic(Person, [Engineer, Manager], aliased=True)
  150. contains_eager_option = testing.resolve_lambda(
  151. contains_eager_option, Company=Company, wp=wp
  152. )
  153. q = (
  154. sess.query(Company)
  155. .join(Company.employees.of_type(wp))
  156. .order_by(Company.company_id, wp.person_id)
  157. .options(contains_eager_option)
  158. )
  159. def go():
  160. eq_(q.all(), [self.c1, self.c2])
  161. self.assert_sql_count(testing.db, go, 1)
  162. self.assert_compile(
  163. q,
  164. self._test_with_polymorphic_join_exec_contains_eager_two_result(),
  165. )
  166. def test_with_polymorphic_any(self):
  167. sess = Session()
  168. wp = with_polymorphic(Person, [Engineer], aliased=True)
  169. eq_(
  170. sess.query(Company.company_id)
  171. .filter(
  172. Company.employees.of_type(wp).any(
  173. wp.Engineer.primary_language == "java"
  174. )
  175. )
  176. .all(),
  177. [(1,)],
  178. )
  179. def test_subqueryload_implicit_withpoly(self):
  180. sess = Session()
  181. def go():
  182. eq_(
  183. sess.query(Company)
  184. .filter_by(company_id=1)
  185. .options(subqueryload(Company.employees.of_type(Engineer)))
  186. .all(),
  187. [self._company_with_emps_fixture()[0]],
  188. )
  189. self.assert_sql_count(testing.db, go, 4)
  190. def test_joinedload_implicit_withpoly(self):
  191. sess = Session()
  192. def go():
  193. eq_(
  194. sess.query(Company)
  195. .filter_by(company_id=1)
  196. .options(joinedload(Company.employees.of_type(Engineer)))
  197. .all(),
  198. [self._company_with_emps_fixture()[0]],
  199. )
  200. self.assert_sql_count(testing.db, go, 3)
  201. def test_subqueryload_explicit_withpoly(self):
  202. sess = Session()
  203. def go():
  204. target = with_polymorphic(Person, Engineer)
  205. eq_(
  206. sess.query(Company)
  207. .filter_by(company_id=1)
  208. .options(subqueryload(Company.employees.of_type(target)))
  209. .all(),
  210. [self._company_with_emps_fixture()[0]],
  211. )
  212. self.assert_sql_count(testing.db, go, 4)
  213. def test_joinedload_explicit_withpoly(self):
  214. sess = Session()
  215. def go():
  216. target = with_polymorphic(Person, Engineer, flat=True)
  217. eq_(
  218. sess.query(Company)
  219. .filter_by(company_id=1)
  220. .options(joinedload(Company.employees.of_type(target)))
  221. .all(),
  222. [self._company_with_emps_fixture()[0]],
  223. )
  224. self.assert_sql_count(testing.db, go, 3)
  225. def test_joinedload_stacked_of_type(self):
  226. sess = Session()
  227. def go():
  228. eq_(
  229. sess.query(Company)
  230. .filter_by(company_id=1)
  231. .options(
  232. joinedload(Company.employees.of_type(Manager)),
  233. joinedload(Company.employees.of_type(Engineer)),
  234. )
  235. .all(),
  236. [self._company_with_emps_fixture()[0]],
  237. )
  238. self.assert_sql_count(testing.db, go, 2)
  239. class PolymorphicPolymorphicTest(
  240. _PolymorphicTestBase, _PolymorphicPolymorphic
  241. ):
  242. def _polymorphic_join_target(self, cls):
  243. return (
  244. "(people AS people_1 LEFT OUTER JOIN engineers AS engineers_1 "
  245. "ON people_1.person_id = engineers_1.person_id "
  246. "LEFT OUTER JOIN managers AS managers_1 "
  247. "ON people_1.person_id = managers_1.person_id) "
  248. "ON companies.company_id = people_1.company_id"
  249. )
  250. def _test_with_polymorphic_join_exec_contains_eager_two_result(self):
  251. return (
  252. "SELECT anon_1.people_person_id AS anon_1_people_person_id, "
  253. "anon_1.people_company_id AS anon_1_people_company_id, "
  254. "anon_1.people_name AS anon_1_people_name, "
  255. "anon_1.people_type AS anon_1_people_type, "
  256. "anon_1.engineers_person_id AS anon_1_engineers_person_id, "
  257. "anon_1.engineers_status AS anon_1_engineers_status, "
  258. "anon_1.engineers_engineer_name "
  259. "AS anon_1_engineers_engineer_name, "
  260. "anon_1.engineers_primary_language "
  261. "AS anon_1_engineers_primary_language, anon_1.managers_person_id "
  262. "AS anon_1_managers_person_id, anon_1.managers_status "
  263. "AS anon_1_managers_status, anon_1.managers_manager_name "
  264. "AS anon_1_managers_manager_name, companies.company_id "
  265. "AS companies_company_id, companies.name AS companies_name "
  266. "FROM companies JOIN (SELECT people.person_id AS "
  267. "people_person_id, people.company_id AS people_company_id, "
  268. "people.name AS people_name, people.type AS people_type, "
  269. "engineers.person_id AS engineers_person_id, engineers.status "
  270. "AS engineers_status, engineers.engineer_name "
  271. "AS engineers_engineer_name, engineers.primary_language "
  272. "AS engineers_primary_language, managers.person_id "
  273. "AS managers_person_id, managers.status AS managers_status, "
  274. "managers.manager_name AS managers_manager_name FROM people "
  275. "LEFT OUTER JOIN engineers ON people.person_id = "
  276. "engineers.person_id LEFT OUTER JOIN managers "
  277. "ON people.person_id = managers.person_id) AS anon_1 "
  278. "ON companies.company_id = anon_1.people_company_id "
  279. "ORDER BY companies.company_id, anon_1.people_person_id"
  280. )
  281. class PolymorphicUnionsTest(_PolymorphicTestBase, _PolymorphicUnions):
  282. def _polymorphic_join_target(self, cls):
  283. return (
  284. "(SELECT engineers.person_id AS person_id, people.company_id "
  285. "AS company_id, people.name AS name, people.type AS type, "
  286. "engineers.status AS status, "
  287. "engineers.engineer_name AS engineer_name, "
  288. "engineers.primary_language AS primary_language, "
  289. "CAST(NULL AS VARCHAR(50)) AS manager_name FROM people "
  290. "JOIN engineers ON people.person_id = engineers.person_id "
  291. "UNION ALL SELECT managers.person_id AS person_id, "
  292. "people.company_id AS company_id, people.name AS name, "
  293. "people.type AS type, managers.status AS status, "
  294. "CAST(NULL AS VARCHAR(50)) AS engineer_name, "
  295. "CAST(NULL AS VARCHAR(50)) AS primary_language, "
  296. "managers.manager_name AS manager_name FROM people "
  297. "JOIN managers ON people.person_id = managers.person_id) "
  298. "AS pjoin_1 ON companies.company_id = pjoin_1.company_id"
  299. )
  300. def _test_with_polymorphic_join_exec_contains_eager_two_result(self):
  301. return (
  302. "SELECT pjoin_1.person_id AS pjoin_1_person_id, "
  303. "pjoin_1.company_id AS pjoin_1_company_id, pjoin_1.name AS "
  304. "pjoin_1_name, pjoin_1.type AS pjoin_1_type, pjoin_1.status "
  305. "AS pjoin_1_status, pjoin_1.engineer_name AS "
  306. "pjoin_1_engineer_name, pjoin_1.primary_language AS "
  307. "pjoin_1_primary_language, pjoin_1.manager_name AS "
  308. "pjoin_1_manager_name, companies.company_id AS "
  309. "companies_company_id, companies.name AS companies_name "
  310. "FROM companies JOIN (SELECT engineers.person_id AS "
  311. "person_id, people.company_id AS company_id, people.name AS name, "
  312. "people.type AS type, engineers.status AS status, "
  313. "engineers.engineer_name AS engineer_name, "
  314. "engineers.primary_language AS primary_language, "
  315. "CAST(NULL AS VARCHAR(50)) AS manager_name FROM people "
  316. "JOIN engineers ON people.person_id = engineers.person_id "
  317. "UNION ALL SELECT managers.person_id AS person_id, "
  318. "people.company_id AS company_id, people.name AS name, "
  319. "people.type AS type, managers.status AS status, "
  320. "CAST(NULL AS VARCHAR(50)) AS engineer_name, "
  321. "CAST(NULL AS VARCHAR(50)) AS primary_language, "
  322. "managers.manager_name AS manager_name FROM people "
  323. "JOIN managers ON people.person_id = managers.person_id) AS "
  324. "pjoin_1 ON companies.company_id = pjoin_1.company_id "
  325. "ORDER BY companies.company_id, pjoin_1.person_id"
  326. )
  327. class PolymorphicAliasedJoinsTest(
  328. _PolymorphicTestBase, _PolymorphicAliasedJoins
  329. ):
  330. def _polymorphic_join_target(self, cls):
  331. return (
  332. "(SELECT people.person_id AS people_person_id, "
  333. "people.company_id AS people_company_id, "
  334. "people.name AS people_name, people.type AS people_type, "
  335. "engineers.person_id AS engineers_person_id, "
  336. "engineers.status AS engineers_status, "
  337. "engineers.engineer_name AS engineers_engineer_name, "
  338. "engineers.primary_language AS engineers_primary_language, "
  339. "managers.person_id AS managers_person_id, "
  340. "managers.status AS managers_status, "
  341. "managers.manager_name AS managers_manager_name "
  342. "FROM people LEFT OUTER JOIN engineers "
  343. "ON people.person_id = engineers.person_id "
  344. "LEFT OUTER JOIN managers "
  345. "ON people.person_id = managers.person_id) AS pjoin_1 "
  346. "ON companies.company_id = pjoin_1.people_company_id"
  347. )
  348. def _test_with_polymorphic_join_exec_contains_eager_two_result(self):
  349. return (
  350. "SELECT pjoin_1.people_person_id AS pjoin_1_people_person_id, "
  351. "pjoin_1.people_company_id AS pjoin_1_people_company_id, "
  352. "pjoin_1.people_name AS pjoin_1_people_name, pjoin_1.people_type "
  353. "AS pjoin_1_people_type, pjoin_1.engineers_person_id AS "
  354. "pjoin_1_engineers_person_id, pjoin_1.engineers_status AS "
  355. "pjoin_1_engineers_status, pjoin_1.engineers_engineer_name "
  356. "AS pjoin_1_engineers_engineer_name, "
  357. "pjoin_1.engineers_primary_language AS "
  358. "pjoin_1_engineers_primary_language, pjoin_1.managers_person_id "
  359. "AS pjoin_1_managers_person_id, pjoin_1.managers_status "
  360. "AS pjoin_1_managers_status, pjoin_1.managers_manager_name "
  361. "AS pjoin_1_managers_manager_name, companies.company_id "
  362. "AS companies_company_id, companies.name AS companies_name "
  363. "FROM companies JOIN (SELECT people.person_id AS "
  364. "people_person_id, people.company_id AS people_company_id, "
  365. "people.name AS people_name, people.type AS people_type, "
  366. "engineers.person_id AS engineers_person_id, engineers.status "
  367. "AS engineers_status, engineers.engineer_name AS "
  368. "engineers_engineer_name, engineers.primary_language "
  369. "AS engineers_primary_language, managers.person_id AS "
  370. "managers_person_id, managers.status AS managers_status, "
  371. "managers.manager_name AS managers_manager_name FROM people "
  372. "LEFT OUTER JOIN engineers ON people.person_id = "
  373. "engineers.person_id LEFT OUTER JOIN managers "
  374. "ON people.person_id = managers.person_id) AS pjoin_1 "
  375. "ON companies.company_id = pjoin_1.people_company_id "
  376. "ORDER BY companies.company_id, pjoin_1.people_person_id"
  377. )
  378. class PolymorphicJoinsTest(_PolymorphicTestBase, _PolymorphicJoins):
  379. def _polymorphic_join_target(self, cls):
  380. return (
  381. "(people AS people_1 LEFT OUTER JOIN engineers "
  382. "AS engineers_1 ON people_1.person_id = engineers_1.person_id "
  383. "LEFT OUTER JOIN managers AS managers_1 "
  384. "ON people_1.person_id = managers_1.person_id) "
  385. "ON companies.company_id = people_1.company_id"
  386. )
  387. def _test_with_polymorphic_join_exec_contains_eager_two_result(self):
  388. return (
  389. "SELECT anon_1.people_person_id AS anon_1_people_person_id, "
  390. "anon_1.people_company_id AS anon_1_people_company_id, "
  391. "anon_1.people_name AS anon_1_people_name, "
  392. "anon_1.people_type AS anon_1_people_type, "
  393. "anon_1.engineers_person_id AS anon_1_engineers_person_id, "
  394. "anon_1.engineers_status AS anon_1_engineers_status, "
  395. "anon_1.engineers_engineer_name "
  396. "AS anon_1_engineers_engineer_name, "
  397. "anon_1.engineers_primary_language "
  398. "AS anon_1_engineers_primary_language, anon_1.managers_person_id "
  399. "AS anon_1_managers_person_id, anon_1.managers_status "
  400. "AS anon_1_managers_status, anon_1.managers_manager_name "
  401. "AS anon_1_managers_manager_name, companies.company_id "
  402. "AS companies_company_id, companies.name AS companies_name "
  403. "FROM companies JOIN (SELECT people.person_id AS "
  404. "people_person_id, people.company_id AS people_company_id, "
  405. "people.name AS people_name, people.type AS people_type, "
  406. "engineers.person_id AS engineers_person_id, engineers.status "
  407. "AS engineers_status, engineers.engineer_name "
  408. "AS engineers_engineer_name, engineers.primary_language "
  409. "AS engineers_primary_language, managers.person_id "
  410. "AS managers_person_id, managers.status AS managers_status, "
  411. "managers.manager_name AS managers_manager_name FROM people "
  412. "LEFT OUTER JOIN engineers ON people.person_id = "
  413. "engineers.person_id LEFT OUTER JOIN managers "
  414. "ON people.person_id = managers.person_id) AS anon_1 "
  415. "ON companies.company_id = anon_1.people_company_id "
  416. "ORDER BY companies.company_id, anon_1.people_person_id"
  417. )
  418. def test_joinedload_explicit_with_unaliased_poly_compile(self):
  419. sess = Session()
  420. target = with_polymorphic(Person, Engineer)
  421. q = (
  422. sess.query(Company)
  423. .filter_by(company_id=1)
  424. .options(joinedload(Company.employees.of_type(target)))
  425. )
  426. assert_raises_message(
  427. sa_exc.InvalidRequestError,
  428. "Detected unaliased columns when generating joined load.",
  429. q._compile_context,
  430. )
  431. def test_joinedload_explicit_with_flataliased_poly_compile(self):
  432. sess = Session()
  433. target = with_polymorphic(Person, Engineer, flat=True)
  434. q = (
  435. sess.query(Company)
  436. .filter_by(company_id=1)
  437. .options(joinedload(Company.employees.of_type(target)))
  438. )
  439. self.assert_compile(
  440. q,
  441. "SELECT companies.company_id AS companies_company_id, "
  442. "companies.name AS companies_name, "
  443. "people_1.person_id AS people_1_person_id, "
  444. "people_1.company_id AS people_1_company_id, "
  445. "people_1.name AS people_1_name, people_1.type AS people_1_type, "
  446. "engineers_1.person_id AS engineers_1_person_id, "
  447. "engineers_1.status AS engineers_1_status, "
  448. "engineers_1.engineer_name AS engineers_1_engineer_name, "
  449. "engineers_1.primary_language AS engineers_1_primary_language "
  450. "FROM companies LEFT OUTER JOIN (people AS people_1 "
  451. "LEFT OUTER JOIN engineers AS engineers_1 "
  452. "ON people_1.person_id = engineers_1.person_id "
  453. "LEFT OUTER JOIN managers AS managers_1 "
  454. "ON people_1.person_id = managers_1.person_id) "
  455. "ON companies.company_id = people_1.company_id "
  456. "WHERE companies.company_id = :company_id_1 "
  457. "ORDER BY people_1.person_id",
  458. )
  459. class SubclassRelationshipTest(
  460. testing.AssertsCompiledSQL, fixtures.DeclarativeMappedTest
  461. ):
  462. """There's overlap here vs. the ones above."""
  463. run_setup_classes = "once"
  464. run_setup_mappers = "once"
  465. run_inserts = "once"
  466. run_deletes = None
  467. __dialect__ = "default"
  468. @classmethod
  469. def setup_classes(cls):
  470. Base = cls.DeclarativeBasic
  471. class Job(ComparableEntity, Base):
  472. __tablename__ = "job"
  473. id = Column(
  474. Integer, primary_key=True, test_needs_autoincrement=True
  475. )
  476. type = Column(String(10))
  477. widget_id = Column(ForeignKey("widget.id"))
  478. widget = relationship("Widget")
  479. container_id = Column(Integer, ForeignKey("data_container.id"))
  480. __mapper_args__ = {"polymorphic_on": type}
  481. class SubJob(Job):
  482. __tablename__ = "subjob"
  483. id = Column(Integer, ForeignKey("job.id"), primary_key=True)
  484. attr = Column(String(10))
  485. __mapper_args__ = {"polymorphic_identity": "sub"}
  486. class ParentThing(ComparableEntity, Base):
  487. __tablename__ = "parent"
  488. id = Column(
  489. Integer, primary_key=True, test_needs_autoincrement=True
  490. )
  491. container_id = Column(Integer, ForeignKey("data_container.id"))
  492. container = relationship("DataContainer")
  493. class DataContainer(ComparableEntity, Base):
  494. __tablename__ = "data_container"
  495. id = Column(
  496. Integer, primary_key=True, test_needs_autoincrement=True
  497. )
  498. name = Column(String(10))
  499. jobs = relationship(Job, order_by=Job.id)
  500. class Widget(ComparableEntity, Base):
  501. __tablename__ = "widget"
  502. id = Column(
  503. Integer, primary_key=True, test_needs_autoincrement=True
  504. )
  505. name = Column(String(10))
  506. @classmethod
  507. def insert_data(cls, connection):
  508. s = Session(connection)
  509. s.add_all(cls._fixture())
  510. s.commit()
  511. @classmethod
  512. def _fixture(cls):
  513. ParentThing, DataContainer, SubJob, Widget = (
  514. cls.classes.ParentThing,
  515. cls.classes.DataContainer,
  516. cls.classes.SubJob,
  517. cls.classes.Widget,
  518. )
  519. return [
  520. ParentThing(
  521. container=DataContainer(
  522. name="d1",
  523. jobs=[
  524. SubJob(attr="s1", widget=Widget(name="w1")),
  525. SubJob(attr="s2", widget=Widget(name="w2")),
  526. ],
  527. )
  528. ),
  529. ParentThing(
  530. container=DataContainer(
  531. name="d2",
  532. jobs=[
  533. SubJob(attr="s3", widget=Widget(name="w3")),
  534. SubJob(attr="s4", widget=Widget(name="w4")),
  535. ],
  536. )
  537. ),
  538. ]
  539. @classmethod
  540. def _dc_fixture(cls):
  541. return [p.container for p in cls._fixture()]
  542. def test_contains_eager_wpoly(self):
  543. DataContainer, Job, SubJob = (
  544. self.classes.DataContainer,
  545. self.classes.Job,
  546. self.classes.SubJob,
  547. )
  548. Job_P = with_polymorphic(Job, SubJob, aliased=True)
  549. s = Session(testing.db)
  550. q = (
  551. s.query(DataContainer)
  552. .join(DataContainer.jobs.of_type(Job_P))
  553. .options(contains_eager(DataContainer.jobs.of_type(Job_P)))
  554. )
  555. def go():
  556. eq_(q.all(), self._dc_fixture())
  557. self.assert_sql_count(testing.db, go, 5)
  558. def test_joinedload_wpoly(self):
  559. DataContainer, Job, SubJob = (
  560. self.classes.DataContainer,
  561. self.classes.Job,
  562. self.classes.SubJob,
  563. )
  564. Job_P = with_polymorphic(Job, SubJob, aliased=True)
  565. s = Session(testing.db)
  566. q = s.query(DataContainer).options(
  567. joinedload(DataContainer.jobs.of_type(Job_P))
  568. )
  569. def go():
  570. eq_(q.all(), self._dc_fixture())
  571. self.assert_sql_count(testing.db, go, 5)
  572. def test_joinedload_wsubclass(self):
  573. DataContainer, SubJob = (
  574. self.classes.DataContainer,
  575. self.classes.SubJob,
  576. )
  577. s = Session(testing.db)
  578. q = s.query(DataContainer).options(
  579. joinedload(DataContainer.jobs.of_type(SubJob))
  580. )
  581. def go():
  582. eq_(q.all(), self._dc_fixture())
  583. self.assert_sql_count(testing.db, go, 5)
  584. def test_lazyload(self):
  585. DataContainer = self.classes.DataContainer
  586. s = Session(testing.db)
  587. q = s.query(DataContainer)
  588. def go():
  589. eq_(q.all(), self._dc_fixture())
  590. # SELECT data container
  591. # SELECT job * 2 container rows
  592. # SELECT subjob * 4 rows
  593. # SELECT widget * 4 rows
  594. self.assert_sql_count(testing.db, go, 11)
  595. def test_subquery_wsubclass(self):
  596. DataContainer, SubJob = (
  597. self.classes.DataContainer,
  598. self.classes.SubJob,
  599. )
  600. s = Session(testing.db)
  601. q = s.query(DataContainer).options(
  602. subqueryload(DataContainer.jobs.of_type(SubJob))
  603. )
  604. def go():
  605. eq_(q.all(), self._dc_fixture())
  606. self.assert_sql_count(testing.db, go, 6)
  607. def test_twolevel_subqueryload_wsubclass(self):
  608. ParentThing, DataContainer, SubJob = (
  609. self.classes.ParentThing,
  610. self.classes.DataContainer,
  611. self.classes.SubJob,
  612. )
  613. s = Session(testing.db)
  614. q = s.query(ParentThing).options(
  615. subqueryload(ParentThing.container).subqueryload(
  616. DataContainer.jobs.of_type(SubJob)
  617. )
  618. )
  619. def go():
  620. eq_(q.all(), self._fixture())
  621. self.assert_sql_count(testing.db, go, 7)
  622. def test_twolevel_subqueryload_wsubclass_mapper_term(self):
  623. DataContainer, SubJob = self.classes.DataContainer, self.classes.SubJob
  624. s = Session(testing.db)
  625. sj_alias = aliased(SubJob)
  626. q = s.query(DataContainer).options(
  627. subqueryload(DataContainer.jobs.of_type(sj_alias)).subqueryload(
  628. sj_alias.widget
  629. )
  630. )
  631. def go():
  632. eq_(q.all(), self._dc_fixture())
  633. self.assert_sql_count(testing.db, go, 3)
  634. def test_twolevel_joinedload_wsubclass(self):
  635. ParentThing, DataContainer, SubJob = (
  636. self.classes.ParentThing,
  637. self.classes.DataContainer,
  638. self.classes.SubJob,
  639. )
  640. s = Session(testing.db)
  641. q = s.query(ParentThing).options(
  642. joinedload(ParentThing.container).joinedload(
  643. DataContainer.jobs.of_type(SubJob)
  644. )
  645. )
  646. def go():
  647. eq_(q.all(), self._fixture())
  648. self.assert_sql_count(testing.db, go, 5)
  649. def test_any_wpoly(self):
  650. DataContainer, Job, SubJob = (
  651. self.classes.DataContainer,
  652. self.classes.Job,
  653. self.classes.SubJob,
  654. )
  655. Job_P = with_polymorphic(Job, SubJob, aliased=True, flat=True)
  656. s = Session()
  657. q = (
  658. s.query(Job)
  659. .join(DataContainer.jobs)
  660. .filter(DataContainer.jobs.of_type(Job_P).any(Job_P.id < Job.id))
  661. )
  662. self.assert_compile(
  663. q,
  664. "SELECT job.id AS job_id, job.type AS job_type, "
  665. "job.widget_id AS job_widget_id, "
  666. "job.container_id "
  667. "AS job_container_id "
  668. "FROM data_container "
  669. "JOIN job ON data_container.id = job.container_id "
  670. "WHERE EXISTS (SELECT 1 "
  671. "FROM job AS job_1 LEFT OUTER JOIN subjob AS subjob_1 "
  672. "ON job_1.id = subjob_1.id "
  673. "WHERE data_container.id = job_1.container_id "
  674. "AND job_1.id < job.id)",
  675. )
  676. def test_any_walias(self):
  677. (
  678. DataContainer,
  679. Job,
  680. ) = (self.classes.DataContainer, self.classes.Job)
  681. Job_A = aliased(Job)
  682. s = Session()
  683. q = (
  684. s.query(Job)
  685. .join(DataContainer.jobs)
  686. .filter(
  687. DataContainer.jobs.of_type(Job_A).any(
  688. and_(Job_A.id < Job.id, Job_A.type == "fred")
  689. )
  690. )
  691. )
  692. self.assert_compile(
  693. q,
  694. "SELECT job.id AS job_id, job.type AS job_type, "
  695. "job.widget_id AS job_widget_id, "
  696. "job.container_id AS job_container_id "
  697. "FROM data_container JOIN job "
  698. "ON data_container.id = job.container_id "
  699. "WHERE EXISTS (SELECT 1 "
  700. "FROM job AS job_1 "
  701. "WHERE data_container.id = job_1.container_id "
  702. "AND job_1.id < job.id AND job_1.type = :type_1)",
  703. )
  704. def test_join_wpoly(self):
  705. DataContainer, Job, SubJob = (
  706. self.classes.DataContainer,
  707. self.classes.Job,
  708. self.classes.SubJob,
  709. )
  710. Job_P = with_polymorphic(Job, SubJob)
  711. s = Session()
  712. q = s.query(DataContainer).join(DataContainer.jobs.of_type(Job_P))
  713. self.assert_compile(
  714. q,
  715. "SELECT data_container.id AS data_container_id, "
  716. "data_container.name AS data_container_name "
  717. "FROM data_container JOIN "
  718. "(job LEFT OUTER JOIN subjob "
  719. "ON job.id = subjob.id) "
  720. "ON data_container.id = job.container_id",
  721. )
  722. def test_join_wsubclass(self):
  723. DataContainer, SubJob = (
  724. self.classes.DataContainer,
  725. self.classes.SubJob,
  726. )
  727. s = Session()
  728. q = s.query(DataContainer).join(DataContainer.jobs.of_type(SubJob))
  729. # note the of_type() here renders JOIN for the Job->SubJob.
  730. # this is because it's using the SubJob mapper directly within
  731. # query.join(). When we do joinedload() etc., we're instead
  732. # doing a with_polymorphic(), and there we need the join to be
  733. # outer by default.
  734. self.assert_compile(
  735. q,
  736. "SELECT data_container.id AS data_container_id, "
  737. "data_container.name AS data_container_name "
  738. "FROM data_container JOIN (job JOIN subjob ON job.id = subjob.id) "
  739. "ON data_container.id = job.container_id",
  740. )
  741. def test_join_wpoly_innerjoin(self):
  742. DataContainer, Job, SubJob = (
  743. self.classes.DataContainer,
  744. self.classes.Job,
  745. self.classes.SubJob,
  746. )
  747. Job_P = with_polymorphic(Job, SubJob, innerjoin=True)
  748. s = Session()
  749. q = s.query(DataContainer).join(DataContainer.jobs.of_type(Job_P))
  750. self.assert_compile(
  751. q,
  752. "SELECT data_container.id AS data_container_id, "
  753. "data_container.name AS data_container_name "
  754. "FROM data_container JOIN "
  755. "(job JOIN subjob ON job.id = subjob.id) "
  756. "ON data_container.id = job.container_id",
  757. )
  758. def test_join_walias(self):
  759. (
  760. DataContainer,
  761. Job,
  762. ) = (self.classes.DataContainer, self.classes.Job)
  763. Job_A = aliased(Job)
  764. s = Session()
  765. q = s.query(DataContainer).join(DataContainer.jobs.of_type(Job_A))
  766. self.assert_compile(
  767. q,
  768. "SELECT data_container.id AS data_container_id, "
  769. "data_container.name AS data_container_name "
  770. "FROM data_container JOIN job AS job_1 "
  771. "ON data_container.id = job_1.container_id",
  772. )
  773. def test_join_explicit_wpoly_noalias(self):
  774. DataContainer, Job, SubJob = (
  775. self.classes.DataContainer,
  776. self.classes.Job,
  777. self.classes.SubJob,
  778. )
  779. Job_P = with_polymorphic(Job, SubJob)
  780. s = Session()
  781. q = s.query(DataContainer).join(Job_P, DataContainer.jobs)
  782. self.assert_compile(
  783. q,
  784. "SELECT data_container.id AS data_container_id, "
  785. "data_container.name AS data_container_name "
  786. "FROM data_container JOIN "
  787. "(job LEFT OUTER JOIN subjob "
  788. "ON job.id = subjob.id) "
  789. "ON data_container.id = job.container_id",
  790. )
  791. def test_join_explicit_wpoly_flat(self):
  792. DataContainer, Job, SubJob = (
  793. self.classes.DataContainer,
  794. self.classes.Job,
  795. self.classes.SubJob,
  796. )
  797. Job_P = with_polymorphic(Job, SubJob, flat=True)
  798. s = Session()
  799. q = s.query(DataContainer).join(Job_P, DataContainer.jobs)
  800. self.assert_compile(
  801. q,
  802. "SELECT data_container.id AS data_container_id, "
  803. "data_container.name AS data_container_name "
  804. "FROM data_container JOIN "
  805. "(job AS job_1 LEFT OUTER JOIN subjob AS subjob_1 "
  806. "ON job_1.id = subjob_1.id) "
  807. "ON data_container.id = job_1.container_id",
  808. )
  809. def test_join_explicit_wpoly_full_alias(self):
  810. DataContainer, Job, SubJob = (
  811. self.classes.DataContainer,
  812. self.classes.Job,
  813. self.classes.SubJob,
  814. )
  815. Job_P = with_polymorphic(Job, SubJob, aliased=True)
  816. s = Session()
  817. q = s.query(DataContainer).join(Job_P, DataContainer.jobs)
  818. self.assert_compile(
  819. q,
  820. "SELECT data_container.id AS data_container_id, "
  821. "data_container.name AS data_container_name "
  822. "FROM data_container JOIN "
  823. "(SELECT job.id AS job_id, job.type AS job_type, "
  824. "job.widget_id AS job_widget_id, "
  825. "job.container_id AS job_container_id, "
  826. "subjob.id AS subjob_id, subjob.attr AS subjob_attr "
  827. "FROM job LEFT OUTER JOIN subjob ON job.id = subjob.id) "
  828. "AS anon_1 ON data_container.id = anon_1.job_container_id",
  829. )
  830. class SubclassRelationshipTest2(
  831. testing.AssertsCompiledSQL, fixtures.DeclarativeMappedTest
  832. ):
  833. run_setup_classes = "once"
  834. run_setup_mappers = "once"
  835. run_inserts = "once"
  836. run_deletes = None
  837. __dialect__ = "default"
  838. @classmethod
  839. def setup_classes(cls):
  840. Base = cls.DeclarativeBasic
  841. class A(Base):
  842. __tablename__ = "t_a"
  843. id = Column(
  844. Integer, primary_key=True, test_needs_autoincrement=True
  845. )
  846. class B(Base):
  847. __tablename__ = "t_b"
  848. type = Column(String(2))
  849. __mapper_args__ = {
  850. "polymorphic_identity": "b",
  851. "polymorphic_on": type,
  852. }
  853. id = Column(
  854. Integer, primary_key=True, test_needs_autoincrement=True
  855. )
  856. # Relationship to A
  857. a_id = Column(Integer, ForeignKey("t_a.id"))
  858. a = relationship("A", backref="bs")
  859. class B2(B):
  860. __tablename__ = "t_b2"
  861. __mapper_args__ = {"polymorphic_identity": "b2"}
  862. id = Column(Integer, ForeignKey("t_b.id"), primary_key=True)
  863. class C(Base):
  864. __tablename__ = "t_c"
  865. type = Column(String(2))
  866. __mapper_args__ = {
  867. "polymorphic_identity": "c",
  868. "polymorphic_on": type,
  869. }
  870. id = Column(
  871. Integer, primary_key=True, test_needs_autoincrement=True
  872. )
  873. # Relationship to B
  874. b_id = Column(Integer, ForeignKey("t_b.id"))
  875. b = relationship("B", backref="cs")
  876. class C2(C):
  877. __tablename__ = "t_c2"
  878. __mapper_args__ = {"polymorphic_identity": "c2"}
  879. id = Column(Integer, ForeignKey("t_c.id"), primary_key=True)
  880. class D(Base):
  881. __tablename__ = "t_d"
  882. id = Column(
  883. Integer, primary_key=True, test_needs_autoincrement=True
  884. )
  885. # Relationship to B
  886. c_id = Column(Integer, ForeignKey("t_c.id"))
  887. c = relationship("C", backref="ds")
  888. @classmethod
  889. def insert_data(cls, connection):
  890. s = Session(connection)
  891. s.add_all(cls._fixture())
  892. s.commit()
  893. @classmethod
  894. def _fixture(cls):
  895. A, B, B2, C, C2, D = cls.classes("A", "B", "B2", "C", "C2", "D")
  896. return [A(bs=[B2(cs=[C2(ds=[D()])])]), A(bs=[B2(cs=[C2(ds=[D()])])])]
  897. def test_all_subq_query(self):
  898. A, B, B2, C, C2, D = self.classes("A", "B", "B2", "C", "C2", "D")
  899. session = Session(testing.db)
  900. b_b2 = with_polymorphic(B, [B2], flat=True)
  901. c_c2 = with_polymorphic(C, [C2], flat=True)
  902. q = session.query(A).options(
  903. subqueryload(A.bs.of_type(b_b2))
  904. .subqueryload(b_b2.cs.of_type(c_c2))
  905. .subqueryload(c_c2.ds)
  906. )
  907. self.assert_sql_execution(
  908. testing.db,
  909. q.all,
  910. CompiledSQL("SELECT t_a.id AS t_a_id FROM t_a", {}),
  911. CompiledSQL(
  912. "SELECT t_b_1.type AS t_b_1_type, t_b_1.id AS t_b_1_id, "
  913. "t_b_1.a_id AS t_b_1_a_id, t_b2_1.id AS t_b2_1_id, "
  914. "anon_1.t_a_id AS anon_1_t_a_id FROM "
  915. "(SELECT t_a.id AS t_a_id FROM t_a) AS anon_1 "
  916. "JOIN (t_b AS t_b_1 LEFT OUTER JOIN t_b2 AS t_b2_1 "
  917. "ON t_b_1.id = t_b2_1.id) ON anon_1.t_a_id = t_b_1.a_id",
  918. {},
  919. ),
  920. CompiledSQL(
  921. "SELECT t_c_1.type AS t_c_1_type, t_c_1.id AS t_c_1_id, "
  922. "t_c_1.b_id AS t_c_1_b_id, t_c2_1.id AS t_c2_1_id, "
  923. "t_b_1.id AS t_b_1_id FROM (SELECT t_a.id AS t_a_id FROM t_a) "
  924. "AS anon_1 JOIN (t_b AS t_b_1 LEFT OUTER JOIN t_b2 AS t_b2_1 "
  925. "ON t_b_1.id = t_b2_1.id) ON anon_1.t_a_id = t_b_1.a_id "
  926. "JOIN (t_c AS t_c_1 LEFT OUTER JOIN t_c2 AS t_c2_1 ON "
  927. "t_c_1.id = t_c2_1.id) ON t_b_1.id = t_c_1.b_id",
  928. {},
  929. ),
  930. CompiledSQL(
  931. "SELECT t_d.id AS t_d_id, t_d.c_id AS t_d_c_id, "
  932. "t_c_1.id AS t_c_1_id "
  933. "FROM (SELECT t_a.id AS t_a_id FROM t_a) AS anon_1 "
  934. "JOIN (t_b AS t_b_1 LEFT OUTER JOIN t_b2 AS t_b2_1 "
  935. "ON t_b_1.id = t_b2_1.id) "
  936. "ON anon_1.t_a_id = t_b_1.a_id "
  937. "JOIN (t_c AS t_c_1 LEFT OUTER JOIN t_c2 AS t_c2_1 "
  938. "ON t_c_1.id = t_c2_1.id) "
  939. "ON t_b_1.id = t_c_1.b_id "
  940. "JOIN t_d ON t_c_1.id = t_d.c_id",
  941. {},
  942. ),
  943. )
  944. class SubclassRelationshipTest3(
  945. testing.AssertsCompiledSQL, fixtures.DeclarativeMappedTest
  946. ):
  947. run_setup_classes = "once"
  948. run_setup_mappers = "once"
  949. run_inserts = "once"
  950. run_deletes = None
  951. __dialect__ = "default"
  952. @classmethod
  953. def setup_classes(cls):
  954. Base = cls.DeclarativeBasic
  955. class _A(Base):
  956. __tablename__ = "a"
  957. id = Column(Integer, primary_key=True)
  958. type = Column(String(50), nullable=False)
  959. b = relationship("_B", back_populates="a")
  960. __mapper_args__ = {"polymorphic_on": type}
  961. class _B(Base):
  962. __tablename__ = "b"
  963. id = Column(Integer, primary_key=True)
  964. type = Column(String(50), nullable=False)
  965. a_id = Column(Integer, ForeignKey(_A.id))
  966. a = relationship(_A, back_populates="b")
  967. __mapper_args__ = {"polymorphic_on": type}
  968. class _C(Base):
  969. __tablename__ = "c"
  970. id = Column(Integer, primary_key=True)
  971. type = Column(String(50), nullable=False)
  972. b_id = Column(Integer, ForeignKey(_B.id))
  973. __mapper_args__ = {"polymorphic_on": type}
  974. class A1(_A):
  975. __mapper_args__ = {"polymorphic_identity": "A1"}
  976. class B1(_B):
  977. __mapper_args__ = {"polymorphic_identity": "B1"}
  978. class C1(_C):
  979. __mapper_args__ = {"polymorphic_identity": "C1"}
  980. b1 = relationship(B1, backref="c1")
  981. _query1 = (
  982. "SELECT b.id AS b_id, b.type AS b_type, b.a_id AS b_a_id, "
  983. "c.id AS c_id, c.type AS c_type, c.b_id AS c_b_id, a.id AS a_id, "
  984. "a.type AS a_type "
  985. "FROM a LEFT OUTER JOIN b ON "
  986. "a.id = b.a_id AND b.type IN ([POSTCOMPILE_type_1]) "
  987. "LEFT OUTER JOIN c ON "
  988. "b.id = c.b_id AND c.type IN ([POSTCOMPILE_type_2]) "
  989. "WHERE a.type IN ([POSTCOMPILE_type_3])"
  990. )
  991. _query2 = (
  992. "SELECT bbb.id AS bbb_id, bbb.type AS bbb_type, bbb.a_id AS bbb_a_id, "
  993. "ccc.id AS ccc_id, ccc.type AS ccc_type, ccc.b_id AS ccc_b_id, "
  994. "aaa.id AS aaa_id, aaa.type AS aaa_type "
  995. "FROM a AS aaa LEFT OUTER JOIN b AS bbb "
  996. "ON aaa.id = bbb.a_id AND bbb.type IN ([POSTCOMPILE_type_1]) "
  997. "LEFT OUTER JOIN c AS ccc ON "
  998. "bbb.id = ccc.b_id AND ccc.type IN ([POSTCOMPILE_type_2]) "
  999. "WHERE aaa.type IN ([POSTCOMPILE_type_3])"
  1000. )
  1001. _query3 = (
  1002. "SELECT bbb.id AS bbb_id, bbb.type AS bbb_type, bbb.a_id AS bbb_a_id, "
  1003. "c.id AS c_id, c.type AS c_type, c.b_id AS c_b_id, "
  1004. "aaa.id AS aaa_id, aaa.type AS aaa_type "
  1005. "FROM a AS aaa LEFT OUTER JOIN b AS bbb "
  1006. "ON aaa.id = bbb.a_id AND bbb.type IN ([POSTCOMPILE_type_1]) "
  1007. "LEFT OUTER JOIN c ON "
  1008. "bbb.id = c.b_id AND c.type IN ([POSTCOMPILE_type_2]) "
  1009. "WHERE aaa.type IN ([POSTCOMPILE_type_3])"
  1010. )
  1011. def _test(self, join_of_type, of_type_for_c1, aliased_):
  1012. A1, B1, C1 = self.classes("A1", "B1", "C1")
  1013. if aliased_:
  1014. A1 = aliased(A1, name="aaa")
  1015. B1 = aliased(B1, name="bbb")
  1016. C1 = aliased(C1, name="ccc")
  1017. sess = Session()
  1018. abc = sess.query(A1)
  1019. if join_of_type:
  1020. abc = abc.outerjoin(A1.b.of_type(B1)).options(
  1021. contains_eager(A1.b.of_type(B1))
  1022. )
  1023. if of_type_for_c1:
  1024. abc = abc.outerjoin(B1.c1.of_type(C1)).options(
  1025. contains_eager(A1.b.of_type(B1), B1.c1.of_type(C1))
  1026. )
  1027. else:
  1028. abc = abc.outerjoin(B1.c1).options(
  1029. contains_eager(A1.b.of_type(B1), B1.c1)
  1030. )
  1031. else:
  1032. abc = abc.outerjoin(B1, A1.b).options(
  1033. contains_eager(A1.b.of_type(B1))
  1034. )
  1035. if of_type_for_c1:
  1036. abc = abc.outerjoin(C1, B1.c1).options(
  1037. contains_eager(A1.b.of_type(B1), B1.c1.of_type(C1))
  1038. )
  1039. else:
  1040. abc = abc.outerjoin(B1.c1).options(
  1041. contains_eager(A1.b.of_type(B1), B1.c1)
  1042. )
  1043. if aliased_:
  1044. if of_type_for_c1:
  1045. self.assert_compile(abc, self._query2)
  1046. else:
  1047. self.assert_compile(abc, self._query3)
  1048. else:
  1049. self.assert_compile(abc, self._query1)
  1050. def test_join_of_type_contains_eager_of_type_b1_c1(self):
  1051. self._test(join_of_type=True, of_type_for_c1=True, aliased_=False)
  1052. def test_join_flat_contains_eager_of_type_b1_c1(self):
  1053. self._test(join_of_type=False, of_type_for_c1=True, aliased_=False)
  1054. def test_join_of_type_contains_eager_of_type_b1(self):
  1055. self._test(join_of_type=True, of_type_for_c1=False, aliased_=False)
  1056. def test_join_flat_contains_eager_of_type_b1(self):
  1057. self._test(join_of_type=False, of_type_for_c1=False, aliased_=False)
  1058. def test_aliased_join_of_type_contains_eager_of_type_b1_c1(self):
  1059. self._test(join_of_type=True, of_type_for_c1=True, aliased_=True)
  1060. def test_aliased_join_flat_contains_eager_of_type_b1_c1(self):
  1061. self._test(join_of_type=False, of_type_for_c1=True, aliased_=True)
  1062. def test_aliased_join_of_type_contains_eager_of_type_b1(self):
  1063. self._test(join_of_type=True, of_type_for_c1=False, aliased_=True)
  1064. def test_aliased_join_flat_contains_eager_of_type_b1(self):
  1065. self._test(join_of_type=False, of_type_for_c1=False, aliased_=True)