From 40e6b6dff32b18d59ddb3c3d6fc7d529119db457 Mon Sep 17 00:00:00 2001 From: Priec Date: Fri, 4 Sep 2026 23:02:44 +0200 Subject: [PATCH] reference a value from other linked table --- common/build.rs | 4 +++ common/proto/table_definition.proto | 24 ++++++++++++----- common/src/proto/descriptor.bin | Bin 247550 -> 247554 bytes common/src/proto/komp_ac.table_definition.rs | 27 ++++++++++++++----- web/src/schema/mod.rs | 1 + 5 files changed, 42 insertions(+), 14 deletions(-) diff --git a/common/build.rs b/common/build.rs index 16a8c4aa..33791b95 100644 --- a/common/build.rs +++ b/common/build.rs @@ -19,6 +19,10 @@ fn main() -> Result<(), Box> { .type_attribute(".komp_ac.search", serde) .type_attribute(".komp_ac.search2", serde) .type_attribute(".komp_ac.table_definition", serde) + .type_attribute( + ".komp_ac.table_definition.ColumnDefinition", + "#[serde(default)]", + ) .type_attribute(".komp_ac.table_script", serde) .type_attribute(".komp_ac.table_structure", serde) .type_attribute(".komp_ac.table_validation", serde) diff --git a/common/proto/table_definition.proto b/common/proto/table_definition.proto index 64d93d15..3e1281e2 100644 --- a/common/proto/table_definition.proto +++ b/common/proto/table_definition.proto @@ -121,9 +121,9 @@ message PostTableDefinitionRequest { // allowed. string table_name = 1; - // The table's columns, including its links and stored linked projections. - // A projection uses field_type FROM(link_column.source_column); its physical - // type and money metadata are inferred from the linked source column. + // The table's columns, including its links and stored linked values. + // A linked value uses ColumnDefinition.linked_value; its physical type and + // money metadata are inferred from the linked source column. repeated ColumnDefinition columns = 3; // Column names to index, matching names declared above. System columns @@ -276,7 +276,7 @@ message AddTableColumnsRequest { string table_name = 2; // New user-defined columns only. Existing columns cannot be changed here. - // Stored linked projections use field_type FROM(link_column.source_column). + // Stored linked values use ColumnDefinition.linked_value. repeated ColumnDefinition columns = 3; // Optional indexes for the new columns only. @@ -359,9 +359,6 @@ message ColumnDefinition { // LINK(table) → BIGINT referencing that table in the same profile, indexed // automatically. A table may hold several links to the same // target as long as the columns are named differently. - // FROM(link.source) → stored, read-only copy of an atomic column reached - // through another column in this definition whose type is - // LINK(...). SQL type and money metadata are inferred. string field_type = 2; // MONEY rounding applied before a value is stored. @@ -381,6 +378,19 @@ message ColumnDefinition { // Enables a Boolean ledger on Boolean columns. ANY means // one true contribution wins; ALL means one false contribution wins. BooleanLedgerOperator boolean_ledger = 7; + + // Defines this named column as a stored, read-only value copied through an + // existing LINK column. field_type and money metadata are inferred from the + // source column and must not be supplied by the caller. + optional LinkedValueDefinition linked_value = 8; +} + +message LinkedValueDefinition { + // Exact display name of a LINK column in the table being defined. + string link_column = 1; + + // Exact display name of an atomic column in the linked table. + string source_column = 2; } enum BooleanLedgerOperator { diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index bd7a59ab734ecaf7dcf4cc97c59876496bb0c954..30145289d992346c18451e2ce6f84ea503dbce16 100644 GIT binary patch delta 15765 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 EFS9>2NdN!< delta 15775 zcmb80d7M?nweQcVU3=4gnn5;m(=?lzW@zT9XjGJts3?l)C3&CEl?D#bvFRq=jb3t- z91tUef{MfTqEVwJIFXB@HY!9-=Q<#Y8cm`Yya5u7O5}+_#ew%-HT2=;@&0)H)xTY9 z{c26Ms&?(em1{eFy{6OBN3-854Gs;?r3cEheOmIR*=?$HZNFR;>&i@h%kcKuzej}~ zI;V6d)+c5rX3L+}$@Ki9#(Y!0zPTx>NzS=w+WASt?CK5mdg*A&tB(?R;`TDuF_4AYFhGbE`aUME#OOiP?i<%cV=9A_H`J^eo zu%^Dbc1}~$FfXae8TNvwPi8ErZA$X>HM8sTP06B~#wOvasb7-RG|sMVZmelsV$E4p zv!t$}W^Pg=1}@AuHPy_|=aPA~`MS9nkzCN&(A;3`p4ZU0u*TSJsOL4*)iqqvluVy; zR&vtV2`4A>7uU|s7wT&3nGadxL1P1^iwS0~iAjA!GiV9sV_fr+Ma(p(rkdl3!cj)SM>? zByzDyR9k>BC6^0yCL0GQmUPUWoYOj^GI4OSO3Fth7q^uUMI+kj7hSW1&N*3i&9%>k zB8lF~-FkZzfGYdu9#j-*Hr8imzLzb(Lmj6`P2ib3oz^Y;(MU>zAl37*c5c$tT+^I) zW@Vv2v!p|=KW1f1DErCkyXl?Xv;7N`OWNm#%2P3Ritbb1`#7`As$X1JHw!K?7Rg9N zJ9q^5l#V?;!t^P~UBnlZAX^b#fl@H`ycBrhY~w#}rUQV=kFB zvaO&-wAGQ+Mh$E1n2IqeGBsRn7gkMOQ-dqr-0^C+&{n*j_n0+woYJI<+iEkvP!?XX zCVffTAZ0^w-G@vPFtx0Q3sROKO)c+D;0qFY6$jG@((xkS)Z9ovXp6jpbXps!f^=FN zse*JGr01Ey1E%YqhcuI&{@rmg~j<b4NpZG42d8?lAjI zinIJU?$k6k)+}kWGo&_Ww$)|`<;=F)456G!ZQc~*RLCO8XBJ$REng8FhqSHYDM)Jn z5^4Ce5}IKR?VM&_pRXI?S^$yEQ_9H|wap8XhI;x~L%nNS(udj_W-jf}E8C-x%yMMX zR@ql-8|pDWndDkIy}=9|JFQ`sEy1kzq=8MPk>1F}vql@E<}}nd(bVZsIluf_RSm4F z;*&+6n;oE#@4#JB)_n>8Gnp9*7};n_dc2AjVRV}Z!X3xsDyz^h# zTSk?=*`jjo;xL=}B5L{ZKeG3A>-3(qI3FtzuKn%n`r9U z=bu|Pw7R;wsyeyo!l@=`11C~y9oV^WBs89scxW7>kGau6MrmYc7_W)$N9pjB)R`kc zQmT`akyw1BPUz_&Djz9&$`6bR=uo=;B-J$XkW!J8p;_ufs$F*vMM(83&n+=3I@X`2 z6HiwEKJrtgykWBGf2vA5I~95%uxq#61x5uYj--1|R@1AG6lbB;=_9J0x07B6jJxDk zOR02F9Dct}XHQhu7QR-hhvSXV`C9cH>>)Z|tEyqF5f!R9S{7t}8f0^2tWt4%SrC>p zq(fO?`pQ5J6For;0tb0W;I0gYRykP)mj|l98_b?>aUYKnULGX4rtf`IP3qDS!IeQtUq-aMkifrLPy3%B9=@dsd1eq7pF{i83 zyLUqHhM=T(ZW^|93NmqYW1wzJuRdLUrw5SH8-rZeTvaZTQL**r^e?BY0jC@e~-2W8!g519Dopl7e##;jvNVtqRK47I^9h}r9pWe~&H2W8#c7{v7T0R=eR z7?_QtI|9{`4w<9|VxWlM5g>eyp_g-^zAK$QNliY5K@-lq0$u9Zc!2y}0qL_A^8ot0 zBr+#E0tD_!|2#>JGX!GaJw^MnCb0JeWu4jx#J+n1O7};OfV6K&r=6)TpDGq8R?LP# z7ble3-Vk)?(MBL?+z|BaUwi=LhG5X(+$D|?{6O0IEOmil3}AfVSVj&zJm}D+jX;+0 z13}jz#RtL=3>%*Nu49B^W4iGyb&+vWL$L8!CuKozET%E5WJzz7G@j`Q(AbooGFhEU z7PBf87;xV5QI+MrDJU&QNf!7fiPA>p7zo4TEt@B+Az4EaLGk#pHpps!Jm7%kIU^_@ z4>)60nL=R2KN+ZJ((Y4Ke+ogO_+*gloIBU>n?=7hoi;^%3l~AqZ!OZ>F0i$jM;<`G zRV+Nq5kUBKx^s&9<~c%;C1g(*qs{{ycsl41JNtMb3PG1%#Ro7x9aQwOl`ECmnqKm4 zHRP;LDg#?Cx?jkr(5aV7>U;mDpR^V@pd)XTY zWQv!AGTYsOD83xTm1YVcQ@kAX>u;v$97nGPnb+MEosoQ1+MI05on?yG0yWy`ftUnn zBLE}7;X1#dx0L0*~!}1w`i$L1{Nb4ut#8@hmo%L@)r-ZquCmYV^S*)b4QPD>LbcCV4-l$- zL2UL&QH5%sxHbmYy2a6ZLFPbu)l@Yi-E^+fh4*A*l1aLWZ+{DvJ^O%Q1==$U5Z1r> zZ4wCU-(;J#stmp#D4XqWX2k%lZ$L9zdV&cW5Y_jCE^^VKb)lR1_JL11h-rcCoUl0a zK~UnE#hDL$%DV~rFi>_8gHQ!}RcX;51|>G-j2dA!Ia#RP4HW=DZ zrKL->dx&|T1QXB5@Xq`6vE^7Oecj~*sZKpSizs-FkkbJ`%VozlJH z=qjCAxXCC9zQycOC741_AstBQFmw0j3(6x9{l1WZ&ZkCoWqcqR0}g4Y%1mBneL zAXeIGl`fB?Yjoy1=UO?E*XR;?=g_)bT)Wm=1cDZ5n-UP&Yjr!DLLjWydW*_s%EB70 zY&iqb1zL-M46o6p)?gsIYjh8}wUlY`X02A^jW-~Q5NI1Nkj-SRE*s)UVOpz)j`9$u zwR-G0DWrn#9Y;6l%+1cZ-iY3yU8CtO&aLy61j0a|H4upGI;kYd6cE~VzL0v0b2s`z z0-*}@s^Z&?Qb?u<8AkU;TS*!!oV!UY^8zLaU7*($=9_e>U5$*QdXsi-sUnV2ow?IF zQ-NfvU0bRUXKvMQ`vAdut1h@yff2q{yVoorw6|*4A1Y+d|Ilv#0HF)C76Hwu+dqJ) z{)cw^M};`EUb{U2geuUk@d{NC=Jncb0t}k2`)`5=PO1$td+OSkC~yBZla z!mg24NJZRUoL1Tr(5p&Yx?N^9@kbcl+l$j8{4?#EaD{10K(8xp>1VpcRxP8b{!F_j zTp^Wrhqmv(*e@q~pjVai{2jW)UPUk}P52JYT?CZ~PxN!0`Gw70D9-&{hh`HF1IgXp zS`Cy^6T~2}uZM*AZry)?EDc5(yr(!Q$pM-Zn+zg*kM2|HWDCH1i^8G{^um(6d#$k2 zed1_?&iu;NRv#ocNQ0B**hlQU&*=%mZJ@0WAhP#qch&?FvHP?=78a0Z^nR_X%rXLz zIG|n1K&bB5+ycrX0~+DZCJ+Llx?c|&>a4)r2b?nuN(lfxlT_XVMJAc{0bS^9kFrQZ z^?(Zu%Ag1R$_J5FpzUKobRX2QUHL#G?6#0TGVMd!ZHOQXy%kc34{7%%(TDy6)kE67 zN+1o@L)yGbNLUfx=$9Qtl2wW1ChgurDkWJD zYkNOd&_HOxwn%{pKg@fqi8v72hjoXJCd8EzwMYE20-*}D76Hv@sol?ks6OIXRizZu zW*<@zA>B;>u`vasyV=JSi0)?JO)CXG>gx-{v_L3B@5#JMB! z2YP2s{2$XCv8BEcM)xtzd#03irNsYnt?YUQS?H&g_&=`QT_mHZKCZcow5qt*;%l)| zMOXp!L6yGHBDHAx55rKkXjh9ss9Jn2R;qTf-r~1O5V}BbMLSft_-&F=RJZtTvQm}A z`Uzi)Aglm-D@sE8&lA2F8HVZ!UyDGfp76C;sY>U$<3FL3Kd)*Sfo$Yn1LAN6+faZ{4!(i|DidFw$3+?Qi@V z06`11v_NEkL6yLrP$|$wks>|$o18AfN3^S1cLe;8A zR&%|mbP`9;>&(09!T+VcRY(wgUYFRjX(IN$z~>&L2Esm|wGW8w3%ay}ABFSoetOtJ;Mq`B6WM!{&7weynhZjWJLqwHRa60u^3uS<}H zo=SSq4qr@+V$=>Do6C5Zr3LNK_A(xb?8{n>bJOy%RG^u)AfxEMtShViFuE`6F=L%W z2*2XnS7Ht$K%WumIj{IaWE9m`eEUkI=j<#dQ+f{29_txIb*HXq=d&qIXQyQIVv`Y? z&THv;|EeyWm?(OTeyx~GX)&)!$=E1Li+N3oe@oVA(qn$l?oxh#Hhp5U8k3e@s(w5^ zQPN#_?k$(@@_S$Fj6(8zzMSWFTN2vKuJp-E)!X9|CCy}4(Qs)dyR`e{!YG=%blf#J z)67mY*_}Q=OU;;^C}}0Ti`kb}vb&fvX(hXLY|nrQ!?RmgRObGLCDJdB_UO##I=!?; zUD%}`l6&N&`CX>yCu?M1+FGM79>?Es?(?<*k=&=-*^>?s&V6!%d^CAKpb5iW>%*^ov(h_huqbkOM(YT3|FSz z7jVhU-*B!BT?Bzht_)pi0O4F2x~q%<;^(T+y~%=51zK}}X4D;vfvBzud6AugH3Q>l zO_;ec%$83{CYcZ2=4Wi_I}5l;9*E+a(7n1RhJY7nsl%8;RT|&E-bMxFhCIv-8Yg!addN-xh=F; zYlD!yIdm5ygCr=o_{f9s3}_nx5ZPNocZC3i^%jY|sogd1Q5DF8x^1#b$19r zbkoq?Aql+`Y=86?`p(E07k6$ zVF9ALK6JYi(8!XSUrHqpj-xxn%rB^&G@HJC2nV(Z0=~v%ZgC;R0}qblM^{HobJA>YWxYQ#}hd>j)SLm-QiWv?0tqNmFhrcX&u1Nk6+oMHAhP%QtOH@aPqHrMJVczj-)9a)=1v9M)PbS8-#Y{}(#|0u zRQHQRvXcyvB6u*pp_yX^f1~)IPaF`%2YupzC_X4_>V8Sw&^X!@W*#ST>s{gw)T`Bn zq3CQ1xtbP3hl-C6`^16Z2in8|k$u=F4ha9lK5;{3@<;q~2cZh|s^Zflez`M>>LYE- zeW*CKIdoS|AmRhG;Q>Om*@p)R)#lKhI)G4Z4!L=f@C+67SbEMPbzyxwJS`g}8r z?z3W%EXrZxN^82jQBAMsZzgT^t^iSN^;;eg#a6%N4HNWRzk7pF1=>siQT=V`jXz68^z~}bIR8JoG%PUQGCu9#_%|LG0g0A;Tw+Ri=q1rJY2%J z-4_N3R-iQpi0pP>7(iIJx9tPN#m|>Q_YDJtF3=vGfM(Qf{6KVH@=+Kr;oIS(074b$ zrxoHIJ_?MYx+5eCvOIgL^<7`l)p4{Z z%)A%=i#^&@Bf2MapGT@Cqq{C4?OwmhRg2^MIN79kUe3;KU*LF% z%s!4V>5j|Qspbe&Eg|@8=Vp7;^{+k%K%?t|P%S~&?~@3^TA&RA z5Y_#@o`F&T`+Zv+6-V!fng8wTY80aH`yh;xAbjBK3Ir|C)&>yS4}4t#vFHO|R-+^c zA9{;Gr~?P7@iQp%`j6kpgtvx_wKk;P*g!PlQ&Nx~e{f9pxgU|)q5CYApJ0Szn{f9px zkCq4?_7Mc33bYXfqI%dz5QyqwAHmUrzWJ#SArM`lH(5gXsf17>$SBgEhD1#gEleG$oG9qc%;67obt%x#f(pP`1s=ACta7DzY0l6I-D`u@q+y6w(7{}jGu8LfYfJm;2 z+=~wo%2g3ZVEH}PSh3~W^v0j46AS!};r$7|1jm%q*(&OUjx+rr)WSiAE zB(IBjW0Q?%oEUR`j`9ZQ^YTfpO+s9gT?+w(+jUs&z@os0eLiXKQT5BPsC>aAZ(LW zBtK0x4`A3P48N3Lx5^V9w6^qKp^~ieLi$SUu@ur-S|fh0;whxJv__m5AvN)=~Js!dD?ZAnsKIR z%5@?G_Q$&B0aV+g((*Pcxl-I7@tyonJ|N7#Gt#}wcVyFkE4UE-^(wW^I3^$S7%7s; zo#M`jJ3Q~0+$!#rn!U)`#qIj*>Eo-_d4@o4*Iz%DK1o%fsU|ye$^OQ%1ai&(MpRnaW`SI^zY+BtkbB9y!&UoR>2uep|2j?lmmBuCj;#>6 zV}C2+3#Io#ZrR_GC3~thL5ldDNWYi9c&!>&0f#B$ccS*abL-{6XP!tQznk`4qt>0} zF!Q_{MeX^Ka;X<#rgx(bosWIQT<=OD%xWV-Xm5I8jhg9*q@?%$Pa-Mmy%E1EFLFzt z*&A`C-PA@zUGGmg@G_Wmf!9it_+y+10eIQ9`l`y=j3wgoN&d}a8!Wx{o; zC3`MJN8Ui6Z9J!BAK&TE!-R%cEAVh~Fek{*PoAx5+ABobfH>ed805BaXGD+NyMD7ZS aQ6n4Muj4?NjzlZ|ZJlcQw{^kl@&5;LM06(r diff --git a/common/src/proto/komp_ac.table_definition.rs b/common/src/proto/komp_ac.table_definition.rs index 1770d8c6..cde3e16f 100644 --- a/common/src/proto/komp_ac.table_definition.rs +++ b/common/src/proto/komp_ac.table_definition.rs @@ -25,9 +25,9 @@ pub struct PostTableDefinitionRequest { /// allowed. #[prost(string, tag = "1")] pub table_name: ::prost::alloc::string::String, - /// The table's columns, including its links and stored linked projections. - /// A projection uses field_type FROM(link_column.source_column); its physical - /// type and money metadata are inferred from the linked source column. + /// The table's columns, including its links and stored linked values. + /// A linked value uses ColumnDefinition.linked_value; its physical type and + /// money metadata are inferred from the linked source column. #[prost(message, repeated, tag = "3")] pub columns: ::prost::alloc::vec::Vec, /// Column names to index, matching names declared above. System columns @@ -201,7 +201,7 @@ pub struct AddTableColumnsRequest { #[prost(string, tag = "2")] pub table_name: ::prost::alloc::string::String, /// New user-defined columns only. Existing columns cannot be changed here. - /// Stored linked projections use field_type FROM(link_column.source_column). + /// Stored linked values use ColumnDefinition.linked_value. #[prost(message, repeated, tag = "3")] pub columns: ::prost::alloc::vec::Vec, /// Optional indexes for the new columns only. @@ -255,6 +255,7 @@ pub struct PutTableDefinitionResponse { } /// Describes one user-defined column for a table. #[derive(serde::Serialize, serde::Deserialize)] +#[serde(default)] #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct ColumnDefinition { /// Public display name for this column; the physical column uses a stable @@ -292,9 +293,6 @@ pub struct ColumnDefinition { /// LINK(table) → BIGINT referencing that table in the same profile, indexed /// automatically. A table may hold several links to the same /// target as long as the columns are named differently. - /// FROM(link.source) → stored, read-only copy of an atomic column reached - /// through another column in this definition whose type is - /// LINK(...). SQL type and money metadata are inferred. #[prost(string, tag = "2")] pub field_type: ::prost::alloc::string::String, /// MONEY rounding applied before a value is stored. @@ -316,6 +314,21 @@ pub struct ColumnDefinition { #[prost(enumeration = "BooleanLedgerOperator", tag = "7")] #[serde(default, alias = "boolean_ledger_operator")] pub boolean_ledger: i32, + /// Defines this named column as a stored, read-only value copied through an + /// existing LINK column. field_type and money metadata are inferred from the + /// source column and must not be supplied by the caller. + #[prost(message, optional, tag = "8")] + pub linked_value: ::core::option::Option, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct LinkedValueDefinition { + /// Exact display name of a LINK column in the table being defined. + #[prost(string, tag = "1")] + pub link_column: ::prost::alloc::string::String, + /// Exact display name of an atomic column in the linked table. + #[prost(string, tag = "2")] + pub source_column: ::prost::alloc::string::String, } /// Response after table creation (success + DDL preview). #[derive(serde::Serialize, serde::Deserialize)] diff --git a/web/src/schema/mod.rs b/web/src/schema/mod.rs index 17498bd2..b81fba26 100644 --- a/web/src/schema/mod.rs +++ b/web/src/schema/mod.rs @@ -1273,6 +1273,7 @@ pub(crate) fn proto_columns(columns: &[ColumnDefinition]) -> Vec