Giter Club home page Giter Club logo

Comments (20)

dvv avatar dvv commented on June 11, 2024 1

Right, I believe we may rely on database sort order -- be it this or that -- the point is to just compact related records, imo.

from lldap.

nitnelave avatar nitnelave commented on June 11, 2024

Hmm, I can't reproduce the panic. Could you post a sql dump of the DB, or send it to me privately on Discord? Don't worry, I won't be able to get the passwords.

from lldap.

dvv avatar dvv commented on June 11, 2024

@nitnelave sorry, no, I don't own it.

Indeed I saw no sorting in migration tool hence user ids come assorted from the source LDAP.
At first I tried to sort them:

--- a/migration-tool/src/main.rs                                                                                                                                      
+++ b/migration-tool/src/main.rs
@@ -23,11 +23,12 @@ fn ask_generic_confirmation(name: &str, message: &str) -> Result<bool> {
 fn get_users_to_add(users: &[User], existing_users: &[String]) -> Result<Option<Vec<User>>> {
     let existing_users = HashSet::<&String>::from_iter(existing_users);
     let num_found_users = users.len();
-    let input_users: Vec<_> = users
+    let mut input_users: Vec<_> = users
         .iter()
         .filter(|u| !existing_users.contains(&u.user_input.id))
         .map(User::clone)
         .collect();
+    input_users.sort_by(|u1, u2| u1.user_input.id.cmp(&u2.user_input.id));
     println!(
         "Found {} users, of which {} new users: [\n  {}\n]",
         num_found_users,

but the error persisted.

Then I commented out the assertion:

--- a/server/src/domain/sql_user_backend_handler.rs
+++ b/server/src/domain/sql_user_backend_handler.rs
@@ -145,11 +145,13 @@ impl UserListerBackendHandler for SqlBackendHandler {
         let mut attributes_iter = attributes.into_iter().peekable();
         use itertools::Itertools; // For take_while_ref
         for user in users.iter_mut() {
+            /*
             assert!(attributes_iter
                 .peek()
                 .map(|u| u.user_id >= user.user.user_id)
                 .unwrap_or(true),
                 "Attributes are not sorted, users are not sorted, or previous user didn't consume all the attributes");
+            */

             user.user.attributes = attributes_iter
                 .take_while_ref(|u| u.user_id == user.user.user_id)

and it worked.

Still I can not use it: I cured symptom but indeed I broke the logic. And I do not understand the logic.

from lldap.

nitnelave avatar nitnelave commented on June 11, 2024

The ordering comes from the SQL query, not the migration: the query is ordered by user id, and so are the attributes. Is there a debug mode in PostgreSQL that prints out the queries? Otherwise, you can run LLDAP with RUST_LOG=debug, I think that should print a lot of things, including the SQL queries used.

As for the logic, we're iterating over the users and the attributes vectors, associating every run of attributes with the same user id with the corresponding user. That relies on both users and attributes to be sorted by user id.

from lldap.

nitnelave avatar nitnelave commented on June 11, 2024

Just to confirm, you used the migration tool provided by LLDAP, correct? Can you confirm that all the user IDs are lowercase in the DB? Something like "SELECT user_id FROM users;" (or select I'd maybe)

from lldap.

dvv avatar dvv commented on June 11, 2024

Yes, exactly.

Lowercased:

lldap=# select user_id from users where user_id != lower(user_id);
 user_id
---------
(0 rows)

from lldap.

dvv avatar dvv commented on June 11, 2024

I see when listing users in web ui:

auth-lldap-1  | 2024-01-30T18:53:58.923828459+00:00  INFO     LDAP session [ 84.5µs | 36.77% / 100.00% ]
auth-lldap-1  | 2024-01-30T18:53:58.923836389+00:00  INFO     ┕━ LDAP request [ 53.4µs | 63.23% ]
auth-lldap-1  | 2024-01-30T18:53:58.923842956+00:00  DEBUG       ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 0, op: SearchRequest(LdapSearchRequest { base: "", scope: Base, alias
es: Never, sizelimit: 0, timelimit: 0, typesonly: false, filter: Present("objectClass"), attrs: ["supportedExtension"] }), ctrl: [] }
auth-lldap-1  | 2024-01-30T18:53:58.923844536+00:00  DEBUG       ┝━ 🐛 [debug]: rootDSE request
auth-lldap-1  | 2024-01-30T18:53:58.923857301+00:00  DEBUG       ┝━ 🐛 [debug]:  | response: SearchResultEntry(LdapSearchResultEntry { dn: "", attributes: [LdapPartialAttribu
te { atype: "objectClass", vals: ["top"] }, LdapPartialAttribute { atype: "vendorName", vals: ["LLDAP"] }, LdapPartialAttribute { atype: "vendorVersion", vals: ["lldap_0.5.1-
alpha"] }, LdapPartialAttribute { atype: "supportedLDAPVersion", vals: ["3"] }, LdapPartialAttribute { atype: "supportedExtension", vals: ["1.3.6.1.4.1.4203.1.11.1"] }, LdapP
artialAttribute { atype: "supportedControl", vals: [] }, LdapPartialAttribute { atype: "supportedFeatures", vals: ["1.3.6.1.4.1.4203.1.5.1"] }, LdapPartialAttribute { atype:
"defaultNamingContext", vals: ["dc=example,dc=com"] }, LdapPartialAttribute { atype: "namingContexts", vals: ["dc=example,dc=com"] }, LdapPartialAttribute { atype: "isGlobalCat
alogReady", vals: ["false"] }] })
auth-lldap-1  | 2024-01-30T18:53:58.923879452+00:00  DEBUG       ┕━ 🐛 [debug]:  | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral
: [] })
auth-lldap-1  | 2024-01-30T18:54:00.764995685+00:00  DEBUG    check_if_token_is_valid [ 81.0µs | 100.00% ]
auth-lldap-1  | 2024-01-30T18:54:00.765075553+00:00  DEBUG    ┕━ 🐛 [debug]:  | return: ValidationResults { user: UserId(CaseInsensitiveString("admin")), permission: Admin }
auth-lldap-1  | thread 'actix-rt|system:0|arbiter:0' panicked at server/src/domain/sql_user_backend_handler.rs:148:13:
auth-lldap-1  | Attributes are not sorted, users are not sorted, or previous user didn't consume all the attributes
auth-lldap-1  | stack backtrace:
auth-lldap-1  |    0: rust_begin_unwind
auth-lldap-1  |              at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/std/src/panicking.rs:597:5
auth-lldap-1  |    1: core::panicking::panic_fmt
auth-lldap-1  |              at /rustc/a28077b28a02b92985b3a3faecf92813155f1ea1/library/core/src/panicking.rs:72:14
auth-lldap-1  |    2: lldap::domain::sql_user_backend_handler::<impl lldap::domain::handler::UserListerBackendHandler for lldap::domain::sql_backend_handler::SqlBackendHandle
r>::list_users::{{closure}}
auth-lldap-1  |    3: <Handler as lldap::infra::access_control::ReadonlyBackendHandler>::list_users::{{closure}}
auth-lldap-1  |    4: <tracing::instrument::Instrumented<T> as core::future::future::Future>::poll
auth-lldap-1  |    5: <lldap::infra::graphql::query::Query<Handler> as juniper::types::async_await::GraphQLValueAsync<__S>>::resolve_field_async::{{closure}}
auth-lldap-1  |    6: juniper::types::async_await::resolve_selection_set_into_async_recursive::{{closure}}
auth-lldap-1  |    7: juniper::types::async_await::GraphQLValueAsync::resolve_async::{{closure}}
auth-lldap-1  |    8: juniper::http::GraphQLRequest<S>::execute::{{closure}}.34508
auth-lldap-1  |    9: actix_web::handler::handler_service::{{closure}}::{{closure}}
auth-lldap-1  |   10: <actix_web::resource::Resource<T> as actix_web::service::HttpServiceFactory>::register::{{closure}}::{{closure}}
auth-lldap-1  |   11: <core::pin::Pin<P> as core::future::future::Future>::poll
auth-lldap-1  |   12: <actix_web::scope::Scope<T> as actix_web::service::HttpServiceFactory>::register::{{closure}}::{{closure}}
auth-lldap-1  |   13: <actix_web::middleware::condition::ConditionMiddlewareFuture<E,D> as core::future::future::Future>::poll
auth-lldap-1  |   14: actix_http::h1::dispatcher::InnerDispatcher<T,S,B,X,U>::poll_response
auth-lldap-1  |   15: <actix_http::h1::dispatcher::Dispatcher<T,S,B,X,U> as core::future::future::Future>::poll
auth-lldap-1  |   16: tokio::runtime::task::raw::poll
auth-lldap-1  |   17: tokio::task::local::LocalSet::tick
auth-lldap-1  |   18: <tokio::task::local::RunUntil<T> as core::future::future::Future>::poll
auth-lldap-1  |   19: tokio::task::local::LocalSet::run_until::{{closure}}
auth-lldap-1  | note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
auth-lldap-1  | 2024-01-30T18:54:00.767786062+00:00  DEBUG    [GraphQL query] users [ 184ms | 1.79% / 100.00% ]
auth-lldap-1  | 2024-01-30T18:54:00.767794830+00:00  DEBUG    ┝━ 🐛 [debug]:  | filters: None
auth-lldap-1  | 2024-01-30T18:54:00.769259284+00:00  DEBUG    ┝━ 🐛 [debug]:  | summary: "BEGIN" | db.statement: "" | rows_affected: 0 | rows_returned: 0 | elapsed: 647.479µs
auth-lldap-1  | 2024-01-30T18:54:00.772258135+00:00  DEBUG    ┝━ 🐛 [debug]:  | summary: "SELECT \"user_attribute_schema\".\"user_attribute_schema_name\", \"user_attribute_sc
hema\".\"user_attribute_schema_type\", \"user_attribute_schema\".\"user_attribute_schema_is_list\", …" | db.statement: "\n\nSELECT\n  \"user_attribute_schema\".\"user_attribu
te_schema_name\",\n  \"user_attribute_schema\".\"user_attribute_schema_type\",\n  \"user_attribute_schema\".\"user_attribute_schema_is_list\",\n  \"user_attribute_schema\".\"
user_attribute_schema_is_user_visible\",\n  \"user_attribute_schema\".\"user_attribute_schema_is_user_editable\",\n  \"user_attribute_schema\".\"user_attribute_schema_is_hard
coded\"\nFROM\n  \"user_attribute_schema\"\nORDER BY\n  \"user_attribute_schema\".\"user_attribute_schema_name\" ASC\n" | rows_affected: 3 | rows_returned: 3 | elapsed: 2.268
182ms
auth-lldap-1  | 2024-01-30T18:54:00.775296545+00:00  DEBUG    ┝━ 🐛 [debug]:  | summary: "SELECT \"group_attribute_schema\".\"group_attribute_schema_name\", \"group_attribute
_schema\".\"group_attribute_schema_type\", \"group_attribute_schema\".\"group_attribute_schema_is_list\", …" | db.statement: "\n\nSELECT\n  \"group_attribute_schema\".\"group
_attribute_schema_name\",\n  \"group_attribute_schema\".\"group_attribute_schema_type\",\n  \"group_attribute_schema\".\"group_attribute_schema_is_list\",\n  \"group_attribut
e_schema\".\"group_attribute_schema_is_group_visible\",\n  \"group_attribute_schema\".\"group_attribute_schema_is_group_editable\",\n  \"group_attribute_schema\".\"group_attr
ibute_schema_is_hardcoded\"\nFROM\n  \"group_attribute_schema\"\nORDER BY\n  \"group_attribute_schema\".\"group_attribute_schema_name\" ASC\n" | rows_affected: 0 | rows_retur
ned: 0 | elapsed: 2.237188ms
auth-lldap-1  | 2024-01-30T18:54:00.776090725+00:00  DEBUG    ┝━ 🐛 [debug]:  | summary: "COMMIT" | db.statement: "" | rows_affected: 0 | rows_returned: 0 | elapsed: 742.46µs
auth-lldap-1  | 2024-01-30T18:54:00.776229233+00:00  DEBUG    ┕━ list_users [ 181ms | 98.21% ] filters: None | _get_groups: false
auth-lldap-1  | 2024-01-30T18:54:00.807388036+00:00  DEBUG       ┝━ 🐛 [debug]:  | summary: "SELECT \"users\".\"user_id\" AS \"A_user_id\", …" | db.statement: "\n\nSELECT\n
\"users\".\"user_id\" AS \"A_user_id\",\n  \"users\".\"email\" AS \"A_email\",\n  \"users\".\"lowercase_email\" AS \"A_lowercase_email\",\n  \"users\".\"display_name\" AS \"A
_display_name\",\n  \"users\".\"creation_date\" AS \"A_creation_date\",\n  \"users\".\"password_hash\" AS \"A_password_hash\",\n  \"users\".\"totp_secret\" AS \"A_totp_secret
\",\n  \"users\".\"mfa_type\" AS \"A_mfa_type\",\n  \"users\".\"uuid\" AS \"A_uuid\",\n  \"r1\".\"group_id\" AS \"B_group_id\",\n  \"r1\".\"display_name\" AS \"B_display_name
\",\n  \"r1\".\"lowercase_display_name\" AS \"B_lowercase_display_name\",\n  \"r1\".\"creation_date\" AS \"B_creation_date\",\n  \"r1\".\"uuid\" AS \"B_uuid\"\nFROM\n  \"user
s\"\n  LEFT JOIN \"memberships\" AS \"r0\" ON \"users\".\"user_id\" = \"r0\".\"user_id\"\n  LEFT JOIN \"groups\" AS \"r1\" ON \"r0\".\"group_id\" = \"r1\".\"group_id\"\nWHERE
\n  $1\nORDER BY\n  \"users\".\"user_id\" ASC,\n  \"r1\".\"display_name\" ASC\n" | rows_affected: 1246 | rows_returned: 1246 | elapsed: 29.205577ms
auth-lldap-1  | 2024-01-30T18:54:00.845373003+00:00  DEBUG       ┕━ 🐛 [debug]:  | summary: "SELECT \"user_attributes\".\"user_attribute_user_id\", \"user_attributes\".\"user
_attribute_name\", \"user_attributes\".\"user_attribute_value\" …" | db.statement: "\n\nSELECT\n  \"user_attributes\".\"user_attribute_user_id\",\n  \"user_attributes\".\"use
r_attribute_name\",\n  \"user_attributes\".\"user_attribute_value\"\nFROM\n  \"user_attributes\"\nWHERE\n  \"user_attributes\".\"user_attribute_user_id\" IN (\n    $1,\n    $
2,\n    $3,\n    $4,\n    $5,\n    $6,\n    $7,\n    $8,\n    $9,\n    $10,\n    $11,\n    $12,\n    $13,\n    $14,\n    $15,\n    $16,\n    $17,\n    $18,\n    $19,\n    $20
,\n    $21,\n    $22,\n    $23,\n    $24,\n    $25,\n    $26,\n    $27,\n    $28,\n    $29,\n    $30,\n    $31,\n    $32,\n    $33,\n    $34,\n    $35,\n    $36,\n    $37,\n
   $38,\n    $39,\n    $40,\n    $41,\n    $42,\n    $43,\n    $44,\n    $45,\n    $46,\n    $47,\n    $48,\n    $49,\n    $50,\n    $51,\n    $52,\n    $53,\n    $54,\n    $
55,\n    $56,\n    $57,\n    $58,\n    $59,\n    $60,\n    $61,\n    $62,\n    $63,\n    $64,\n    $65,\n    $66,\n    $67,\n    $68,\n    $69,\n    $70,\n    $71,\n    $72,\
n    $73,\n    $74,\n    $75,\n    $76,\n    $77,\n    $78,\n    $79,\n    $80,\n    $81,\n    $82,\n    $83,\n    $84,\n    $85,\n    $86,\n    $87,\n    $88,\n    $89,\n
 $90,\n    $91,\n    $92,\n    $93,\n    $94,\n    $95,\n    $96,\n    $97,\n    $98,\n    $99,\n    $100,\n    $101,\n    $102,\n    $103,\n    $104,\n    $105,\n    $106,\n
    $107,\n    $108,\n    $109,\n    $110,\n    $111,\n    $112,\n    $113,\n    $114,\n    $115,\n    $116,\n    $117,\n    $118,\n    $119,\n    $120,\n    $121,\n    $122,
\n    $123,\n    $124,\n    $125,\n    $126,\n    $127,\n    $128,\n    $129,\n    $130,\n    $131,\n    $132,\n    $133,\n    $134,\n    $135,\n    $136,\n    $137,\n    $13
8,\n    $139,\n    $140,\n    $141,\n    $142,\n    $143,\n    $144,\n    $145,\n    $146,\n    $147,\n    $148,\n    $149,\n    $150,\n    $151,\n    $152,\n    $153,\n    $
154,\n    $155,\n    $156,\n    $157,\n    $158,\n    $159,\n    $160,\n    $161,\n    $162,\n    $163,\n    $164,\n    $165,\n    $166,\n    $167,\n    $168,\n    $169,\n
 $170,\n    $171,\n    $172,\n    $173,\n    $174,\n    $175,\n    $176,\n    $177,\n    $178,\n    $179,\n    $180,\n    $181,\n    $182,\n    $183,\n    $184,\n    $185,\n
   $186,\n    $187,\n    $188,\n    $189,\n    $190,\n    $191,\n    $192,\n    $193,\n    $194,\n    $195,\n    $196,\n    $197,\n    $198,\n    $199,\n    $200,\n    $201,\
n    $202,\n    $203,\n    $204,\n    $205,\n    $206,\n    $207,\n    $208,\n    $209,\n    $210,\n    $211,\n    $212,\n    $213,\n    $214,\n    $215,\n    $216,\n    $217
,\n    $218,\n    $219,\n    $220,\n    $221,\n    $222,\n    $223,\n    $224,\n    $225,\n    $226,\n    $227,\n    $228,\n    $229,\n    $230,\n    $231,\n    $232,\n    $2
33,\n    $234,\n    $235,\n    $236,\n    $237,\n    $238,\n    $239,\n    $240,\n    $241,\n    $242,\n    $243,\n    $244,\n    $245,\n    $246,\n    $247,\n    $248,\n
$249,\n    $250,\n    $251,\n    $252,\n    $253,\n    $254,\n    $255,\n    $256,\n    $257,\n    $258,\n    $259,\n    $260,\n    $261,\n    $262,\n    $263,\n    $264,\n
  $265,\n    $266,\n    $267,\n    $268,\n    $269,\n    $270,\n    $271,\n    $272,\n    $273,\n    $274,\n    $275,\n    $276,\n    $277,\n    $278,\n    $279,\n    $280,\n
    $281,\n    $282,\n    $283,\n    $284,\n    $285,\n    $286,\n    $287,\n    $288,\n    $289,\n    $290,\n    $291,\n    $292,\n    $293,\n    $294,\n    $295,\n    $296,
\n    $297,\n    $298,\n    $299,\n    $300,\n    $301,\n    $302,\n    $303,\n    $304,\n    $305,\n    $306,\n    $307,\n    $308,\n    $309,\n    $310,\n    $311,\n    $31
2,\n    $313,\n    $314,\n    $315,\n    $316,\n    $317,\n    $318,\n    $319,\n    $320,\n    $321,\n    $322,\n    $323,\n    $324,\n    $325,\n    $326,\n    $327,\n    $
328,\n    $329,\n    $330,\n    $331,\n    $332,\n    $333,\n    $334,\n    $335,\n    $336,\n    $337,\n    $338,\n    $339,\n    $340,\n    $341,\n    $342,\n    $343,\n
 $344,\n    $345,\n    $346,\n    $347,\n    $348,\n    $349,\n    $350,\n    $351,\n    $352,\n    $353,\n    $354,\n    $355,\n    $356,\n    $357,\n    $358,\n    $359,\n
   $360,\n    $361,\n    $362,\n    $363,\n    $364,\n    $365,\n    $366,\n    $367,\n    $368,\n    $369,\n    $370,\n    $371,\n    $372,\n    $373,\n    $374,\n    $375,\
n    $376,\n    $377,\n    $378,\n    $379,\n    $380,\n    $381,\n    $382,\n    $383,\n    $384,\n    $385,\n    $386,\n    $387,\n    $388,\n    $389,\n    $390,\n    $391
,\n    $392,\n    $393,\n    $394,\n    $395,\n    $396,\n    $397,\n    $398,\n    $399,\n    $400,\n    $401,\n    $402,\n    $403,\n    $404,\n    $405,\n    $406,\n    $4
07,\n    $408,\n    $409,\n    $410,\n    $411,\n    $412,\n    $413,\n    $414,\n    $415,\n    $416,\n    $417,\n    $418,\n    $419,\n    $420,\n    $421,\n    $422,\n
$423,\n    $424,\n    $425,\n    $426,\n    $427,\n    $428,\n    $429,\n    $430,\n    $431,\n    $432,\n    $433,\n    $434,\n    $435,\n    $436,\n    $437,\n    $438,\n
  $439,\n    $440,\n    $441,\n    $442,\n    $443,\n    $444,\n    $445,\n    $446,\n    $447,\n    $448,\n    $449,\n    $450,\n    $451,\n    $452,\n    $453,\n    $454,\n
    $455,\n    $456,\n    $457,\n    $458,\n    $459,\n    $460,\n    $461,\n    $462,\n    $463,\n    $464,\n    $465,\n    $466,\n    $467,\n    $468,\n    $469,\n    $470,
\n    $471,\n    $472,\n    $473,\n    $474,\n    $475,\n    $476\n  )\nORDER BY\n  \"user_attributes\".\"user_attribute_user_id\" ASC,\n  \"user_attributes\".\"user_attribu........

The only quirk I see is an awful monstrous ... IN (...) clause. But I can not find the query source. Does it come from some ORM? Hmm. What if I'd have much more than 476 users?
IMO such queries should read select ... from ... where foo = any($1) passing the array to the parameter.

from lldap.

nitnelave avatar nitnelave commented on June 11, 2024

Ah, yeah, LLDAP was not built with "big" servers in mind, more for self-hosted homelabs. But still, 476 users is not that much, it should work.

One limitation that we have is that we support only the subset of SQL common to PG, MySQL and SQLite. That often leads us to write less-than-ideal queries. I'll see if it's possible to pass an array, but I didn't think that an online table would be a problem.

from lldap.

dvv avatar dvv commented on June 11, 2024

I'm struggling with this:

        let attributes = model::UserAttributes::find()
            //.filter(model::UserAttributesColumn::UserId.is_in(user_ids)) // <-- this may choke
            .filter(model::UserAttributesColumn::UserId.eq(Expr::cust_with_values("ANY(?)", [user_ids]))) <-- this does not compile
            .order_by_asc(model::UserAttributesColumn::UserId)
            .order_by_asc(model::UserAttributesColumn::AttributeName)
            .all(&self.sql_pool)
            .await?;
1.224    Compiling lldap v0.5.1-alpha (/app/server)
4.693 error[E0277]: the trait bound `sea_orm::Value: std::convert::From<std::iter::Map<std::slice::Iter<'_, UserAndGroups>, {closure@server/src/domain/sql_user_backend_handle
r.rs:138:41: 138:44}>>` is not satisfied
4.693    --> server/src/domain/sql_user_backend_handler.rs:141:60
4.693     |
4.693 141 |             .filter(model::UserAttributesColumn::UserId.eq(Expr::cust_with_values("ANY(?)", [user_ids])))
4.693     |                                                            ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::iter::Map<std::slice::Iter<'_, UserAndGroups>
, {closure@server/src/domain/sql_user_backend_handler.rs:138:41: 138:44}>>` is not implemented for `sea_orm::Value`
4.693     |
4.693     = help: the following other types implement trait `std::convert::From<T>`:
4.693               <sea_orm::Value as std::convert::From<bool>>
4.693               <sea_orm::Value as std::convert::From<char>>
4.693               <sea_orm::Value as std::convert::From<i8>>
4.693               <sea_orm::Value as std::convert::From<i16>>
4.693               <sea_orm::Value as std::convert::From<i32>>
4.693               <sea_orm::Value as std::convert::From<i64>>
4.693               <sea_orm::Value as std::convert::From<u8>>
4.693               <sea_orm::Value as std::convert::From<u16>>
4.693             and 41 others
4.693     = note: required for `std::iter::Map<std::slice::Iter<'_, UserAndGroups>, {closure@server/src/domain/sql_user_backend_handler.rs:138:41: 138:44}>` to implement `Int
o<sea_orm::Value>`
...

Can you point out what's wrong there?

from lldap.

nitnelave avatar nitnelave commented on June 11, 2024

I'm not in front of the computer, but you can try with user_ids.collect::<Vec<_>>()

from lldap.

nitnelave avatar nitnelave commented on June 11, 2024

Got it to compile with:

        let user_ids: Vec<_> = users.iter().map(|u| u.user.user_id.to_string()).collect();

        let attributes = model::UserAttributes::find()
            //.filter(model::UserAttributesColumn::UserId.eq(Func::cust(Any).arg(user_ids)))
            .filter(Expr::cust_with_exprs(
                "? = ANY(?)",
                [
                    SimpleExpr::Column(model::UserAttributesColumn::UserId.into_column_ref()),
                    user_ids.into(),
                ],
            ))
            .order_by_asc(model::UserAttributesColumn::UserId)
            .order_by_asc(model::UserAttributesColumn::AttributeName)
            .all(&self.sql_pool)
            .await?;

But then we hit Sqlite doesn't support array arguments.

Can you try https://github.com/lldap/lldap/tree/filters instead? I repeat the query above with the same filter as a filter subquery. It's a bit ugly, but it should work (and it passes the tests).

from lldap.

dvv avatar dvv commented on June 11, 2024

"filters" downs at the same assert

from lldap.

dvv avatar dvv commented on June 11, 2024

Well,

-- sqlite3
select 'test.tools' >= 'testsamba'; -- 0
-- mysql
select 'test.tools' >= 'testsamba'; -- 0
# rust
println!(">= {}", "test.tools" >= "testsamba"); // false

but

-- default postgres from docker
select 'test.tools' >= 'testsamba'; -- true

from lldap.

nitnelave avatar nitnelave commented on June 11, 2024

from lldap.

nitnelave avatar nitnelave commented on June 11, 2024

from lldap.

dvv avatar dvv commented on June 11, 2024

I fix the issue altering the collation of the database.
This one may be closed.
Will you pull filters' query so that no long IN (...) live in the main branch?

from lldap.

nitnelave avatar nitnelave commented on June 11, 2024

@dvv sure. Can you give me the SQL command you ran to update the collation? I'd like to include that in the migration scripts.

from lldap.

nitnelave avatar nitnelave commented on June 11, 2024

On second thought, it shouldn't be necessary: the order should be the same, so just removing the assert should be enough.

from lldap.

dvv avatar dvv commented on June 11, 2024

@nitnelave first I tried https://stackoverflow.com/a/61595309

but then just recreated database as follows:

  lldap-db:
    image: postgres:16.1
    environment:
      ...
      LC_COLLATE: C

from lldap.

nitnelave avatar nitnelave commented on June 11, 2024

On third thought, I think the itertools utility used for grouping uses the ordering, so we have to re-sort.

from lldap.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.