Skip to content

Commit 243bb00

Browse files
pearsonrlfjf2002
authored andcommitted
Added paging support and pageSize option and improved data parsing and array handling.
1 parent 9154481 commit 243bb00

File tree

1 file changed

+62
-5
lines changed

1 file changed

+62
-5
lines changed

python/multicorn/ldapfdw.py

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343
``bindpwd`` (string)
4444
The credentials for the binddn.
4545
46+
``pageSize`` (integer)
47+
Paged mode size (default: 1000)
48+
49+
4650
Usage Example
4751
-------------
4852
@@ -79,6 +83,48 @@
7983
[email protected] | Some Test User |
8084
(3 rows)
8185
86+
.. code-block:: bash
87+
88+
CREATE FOREIGN TABLE ldapgroups (
89+
entryDN character varying,
90+
cn character varying,
91+
ou character varying[],
92+
gidnumber integer,
93+
memberuid character varying[],
94+
objectClass character varying[]
95+
) server ldap_srv options (
96+
uri 'ldap://localhost',
97+
path 'ou=Groups,dc=example,dc=com',
98+
scope 'sub',
99+
objectclass '*',
100+
pagesize '200'
101+
);
102+
103+
SELECT cn,gidnumber,objectClass FROM ldapgroups WHERE cn = 'Administrators';
104+
105+
.. code-block:: bash
106+
107+
cn | gidnumber | objectclass
108+
----------------+-----------+--------------------------------
109+
Administrators | 544 | {posixGroup,sambaGroupMapping}
110+
(1 row)
111+
112+
.. code-block:: bash
113+
114+
SELECT unnest(objectClass) as cls,count(entryDN) as cnt FROM ldapgroups GROUP BY cls;
115+
116+
.. code-block:: bash
117+
118+
cls | cnt
119+
---------------------+-----
120+
domainRelatedObject | 1
121+
organizationalUnit | 4
122+
groupOfUniqueNames | 1
123+
top | 10
124+
sambaGroupMapping | 10
125+
posixGroup | 16
126+
(6 rows)
127+
82128
"""
83129

84130
from . import ForeignDataWrapper
@@ -110,6 +156,7 @@ class LdapFdw(ForeignDataWrapper):
110156
scope -- the ldap scope (one, sub or base)
111157
binddn -- the ldap bind DN (ex: 'cn=Admin,dc=example,dc=com')
112158
bindpwd -- the ldap bind Password
159+
pageSize -- the max entries per page (default: 1000 per Active Directory)
113160
114161
"""
115162

@@ -123,7 +170,8 @@ def __init__(self, fdw_options, fdw_columns):
123170
ldap3.Server(self.ldapuri),
124171
user=fdw_options.get("binddn", None),
125172
password=fdw_options.get("bindpwd", None),
126-
client_strategy=ldap3.RESTARTABLE if ldap3.version.__version__ > '2.0.0' else ldap3.STRATEGY_SYNC_RESTARTABLE)
173+
client_strategy=ldap3.RESTARTABLE if ldap3.version.__version__ > '2.0.0' else ldap3.STRATEGY_SYNC_RESTARTABLE,
174+
return_empty_attributes=False)
127175
self.path = fdw_options["path"]
128176
self.scope = self.parse_scope(fdw_options.get("scope", None))
129177
self.object_class = fdw_options["objectclass"]
@@ -133,6 +181,7 @@ def __init__(self, fdw_options, fdw_columns):
133181
self.array_columns = [
134182
col.column_name for name, col in self.field_definitions.items()
135183
if col.type_name.endswith('[]')]
184+
self.page_size = int(fdw_options["pagesize"]) if "pagesize" in fdw_options else 1000
136185

137186
def execute(self, quals, columns):
138187
request = unicode_("(objectClass=%s)") % self.object_class
@@ -150,22 +199,30 @@ def execute(self, quals, columns):
150199
val = qual.value
151200
request = unicode_("(&%s(%s=%s))") % (
152201
request, qual.field_name, val)
153-
self.ldap.search(
202+
# Always use paged search mode to read data
203+
generator = self.ldap.extend.standard.paged_search(
154204
self.path, request, self.scope,
155-
attributes=list(self.field_definitions))
156-
for entry in self.ldap.response:
205+
attributes=list(self.field_definitions),
206+
paged_size=self.page_size,
207+
generator=True)
208+
for entry in generator:
157209
# Case insensitive lookup for the attributes
158210
litem = dict()
159211
for key, value in entry["attributes"].items():
160212
if key.lower() in self.field_definitions:
161213
pgcolname = self.field_definitions[key.lower()].column_name
162214
if ldap3.version.__version__ > '2.0.0':
163-
value = value
215+
if pgcolname in self.array_columns:
216+
value = value
217+
else:
218+
value = value[0] if isinstance(value, list) else value
164219
else:
165220
if pgcolname in self.array_columns:
166221
value = value
167222
else:
168223
value = value[0]
224+
if not value:
225+
value = None
169226
litem[pgcolname] = value
170227
yield litem
171228

0 commit comments

Comments
 (0)