Python and SAP: Part 3 - Write your queries in SQL
This is the third part of my SAP and Python series (see part 1 and part 2 first!)
After you complete part 1 and part 2 - you can connect to SAP and query data. However, the RFC call parameters are clunky and the whole thing feels a bit complicated for daily use (to me at least).
To make my life easier, I wrote a little SQL parser. It's not special and it's not even all that efficient, but the it does the job.
In part 2, I wrote the following (without comments for a quicker read):
s = main()
fields = ['MATNR', 'EAN11']
table = 'MEAN'
where = ['MATNR <> 0']
maxrows = 10
fromrow = 0
results, headers = s.qry(fields, table, where, maxrows, fromrow)
print headers
print results
Hardly pretty... However, with my SQL parser, I write this instead:
s = main()
query = "select matnr, ean11 from mean where matnr <> 0"
maxrows = 10
fromrow = 0
results, headers = s.sql_query(query, maxrows, fromrow)
print headers
print results
Much cleaner. I just write SQL and suddenly, writing a little program do some mundane query is a breeze!
The two functions for this lovely toy is below. Let me know if you find a better method...
Good luck with your SQL adventures :)
def split_where(self, seg):
# This magical function splits by spaces when not enclosed in quotes..
where = seg.split(' ')
where = [x.replace('@', ' ') for x in where]
return where
def select_parse(self, statement):
statement = " ".join([x.strip('\t') for x in statement.upper().split('\n')])
if 'WHERE' not in statement:
statement = statement + ' WHERE '
regex = re.compile("SELECT(.*)FROM(.*)WHERE(.*)")
parts = regex.findall(statement)
parts = parts[0]
select = [x.strip() for x in parts[0].split(',')]
frm = parts[1].strip()
where = parts[2].strip()
# splits by spaces but ignores quoted string with ''
PATTERN = re.compile(r"""((?:[^ '"]|'[^']*'|"[^"]*")+)""")
where = PATTERN.split(where)[1::2]
cleaned = [select, frm, where]
return cleaned
*** Update *** As requested by Florian, here is the code for sql_query. I've removed the headers option (as I prefer to get the rows into a dictionary, which provides the headers).
def sql_query(self, statement, MaxRows=0, FromRow=0, to_dict=False): statement = self.select_parse(statement) results = self.qry(statement[0], statement[1], statement[2], MaxRows, FromRow) if to_dict: headers = statement[0] results2 = [] for line in results: new_line = OrderedDict() header_counter = 0 for field in line: try: new_line[headers[header_counter]] = field.strip() header_counter += 1 except Exception as e: new_line[headers[header_counter-1]] = new_line[headers[header_counter-1]]+ " " + " ".join(line[header_counter:]) break results2.append(new_line) results = results2 return results