mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
argument parsing, fail on parsing
This commit is contained in:
parent
6b7bdb1e62
commit
42dfa6cddc
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.idea
|
134
scripts/ddl2cpp
134
scripts/ddl2cpp
@ -31,40 +31,28 @@ import re
|
|||||||
import os
|
import os
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
|
# error codes, we should refactor this later
|
||||||
|
ERROR_DATA_TYPE = 10
|
||||||
|
ERROR_STRANGE_PARSING = 20
|
||||||
|
|
||||||
from pyparsing import CaselessLiteral, Literal, SkipTo, restOfLine, oneOf, ZeroOrMore, Optional, Combine, Suppress, \
|
from pyparsing import CaselessLiteral, Literal, SkipTo, restOfLine, oneOf, ZeroOrMore, Optional, Combine, Suppress, \
|
||||||
WordStart, WordEnd, Word, alphas, alphanums, nums, QuotedString, nestedExpr, MatchFirst, OneOrMore, delimitedList, Or, Group
|
WordStart, WordEnd, Word, alphas, alphanums, nums, QuotedString, nestedExpr, MatchFirst, OneOrMore, delimitedList, Or, Group, ParseException
|
||||||
|
|
||||||
def usage():
|
|
||||||
print('Usage: ddl2cpp [-no-timestamp-warning] <path to ddl> <path to target (without extension, e.g. /tmp/MyTable)> <namespace>')
|
|
||||||
|
|
||||||
if len(sys.argv) not in (4,5):
|
|
||||||
usage()
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
firstPositional = 1
|
|
||||||
timestampWarning = True
|
|
||||||
if len(sys.argv) == 5:
|
|
||||||
if sys.argv[1] == '-no-timestamp-warning':
|
|
||||||
firstPositional += 1
|
|
||||||
timestampWarning = False
|
|
||||||
else:
|
|
||||||
usage()
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
pathToDdl = sys.argv[firstPositional]
|
|
||||||
pathToHeader = sys.argv[firstPositional + 1] + '.h'
|
|
||||||
namespace = sys.argv[firstPositional + 2]
|
|
||||||
|
|
||||||
INCLUDE = 'sqlpp11'
|
|
||||||
NAMESPACE = 'sqlpp'
|
|
||||||
|
|
||||||
# HELPERS
|
# HELPERS
|
||||||
|
|
||||||
def get_include_guard_name(namespace, inputfile):
|
def get_include_guard_name(namespace, inputfile):
|
||||||
val = re.sub("[^A-Za-z]+", "_", namespace + '_' + os.path.basename(inputfile))
|
val = re.sub("[^A-Za-z]+", "_", namespace + '_' + os.path.basename(inputfile))
|
||||||
return val.upper()
|
return val.upper()
|
||||||
|
|
||||||
|
|
||||||
def repl_func(m):
|
def repl_func(m):
|
||||||
if (m.group(1) == '_'):
|
if m.group(1) == '_':
|
||||||
|
return m.group(2).upper()
|
||||||
|
else:
|
||||||
|
return m.group(1) + m.group(2).upper()
|
||||||
|
|
||||||
|
def repl_func_for_args(m):
|
||||||
|
if m.group(1) == '-':
|
||||||
return m.group(2).upper()
|
return m.group(2).upper()
|
||||||
else:
|
else:
|
||||||
return m.group(1) + m.group(2).upper()
|
return m.group(1) + m.group(2).upper()
|
||||||
@ -72,10 +60,61 @@ def repl_func(m):
|
|||||||
def toClassName(s):
|
def toClassName(s):
|
||||||
return re.sub("(^|\s|[_0-9])(\S)", repl_func, s)
|
return re.sub("(^|\s|[_0-9])(\S)", repl_func, s)
|
||||||
|
|
||||||
|
|
||||||
def toMemberName(s):
|
def toMemberName(s):
|
||||||
return re.sub("(\s|_|[0-9])(\S)", repl_func, s)
|
return re.sub("(\s|_|[0-9])(\S)", repl_func, s)
|
||||||
|
|
||||||
|
|
||||||
|
def setArgumentBool(s, bool_value):
|
||||||
|
first_lower = lambda s: s[:1].lower() + s[1:] if s else '' # http://stackoverflow.com/a/3847369/5006740
|
||||||
|
var_name = first_lower(re.sub("(\s|-|[0-9])(\S)", repl_func_for_args, s))
|
||||||
|
globals()[var_name] = bool_value
|
||||||
|
|
||||||
|
|
||||||
|
def usage():
|
||||||
|
print('Usage: ddl2cpp [-no-timestamp-warning] <path to ddl> <path to target (without extension, e.g. /tmp/MyTable)> <namespace>')
|
||||||
|
|
||||||
|
# ARGUMENT PARSING
|
||||||
|
if len(sys.argv) < (4):
|
||||||
|
usage()
|
||||||
|
sys.exit(20)
|
||||||
|
|
||||||
|
firstPositional = 1
|
||||||
|
timestampWarning = True
|
||||||
|
failOnParse = True
|
||||||
|
|
||||||
|
optionalArgs = {
|
||||||
|
# if -some-key is present, it will set variable someKey to True
|
||||||
|
# if -no-some-key is present, it will set variable someKey to False
|
||||||
|
'timestamp-warning', # timeStampWarning = True
|
||||||
|
# '-no-time-stamp-warning' # timeStampWarning = False
|
||||||
|
'fail-on-parse' # failOnParse = True
|
||||||
|
# 'no-fail-on-parse' # failOnParse = False
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(sys.argv) >= 4:
|
||||||
|
|
||||||
|
for arg in sys.argv:
|
||||||
|
noArg = arg.replace('-no-', '')
|
||||||
|
|
||||||
|
if arg in optionalArgs:
|
||||||
|
setArgumentBool(arg, True)
|
||||||
|
firstPositional += 1
|
||||||
|
elif noArg in optionalArgs:
|
||||||
|
setArgumentBool(noArg, False)
|
||||||
|
firstPositional += 1
|
||||||
|
|
||||||
|
#sys.exit(0)
|
||||||
|
pathToDdl = sys.argv[firstPositional]
|
||||||
|
pathToHeader = sys.argv[firstPositional + 1] + '.h'
|
||||||
|
namespace = sys.argv[firstPositional + 2]
|
||||||
|
|
||||||
|
INCLUDE = 'sqlpp11'
|
||||||
|
NAMESPACE = 'sqlpp'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# PARSER
|
# PARSER
|
||||||
def ddlWord(string):
|
def ddlWord(string):
|
||||||
return WordStart(alphanums + "_") + CaselessLiteral(string) + WordEnd(alphanums + "_")
|
return WordStart(alphanums + "_") + CaselessLiteral(string) + WordEnd(alphanums + "_")
|
||||||
@ -87,8 +126,8 @@ ddlTerm = Word(alphas, alphanums + "_$")
|
|||||||
ddlName = Or([ddlTerm, ddlString])
|
ddlName = Or([ddlTerm, ddlString])
|
||||||
ddlArguments = "(" + delimitedList(Or([ddlString, ddlTerm, ddlNum])) + ")"
|
ddlArguments = "(" + delimitedList(Or([ddlString, ddlTerm, ddlNum])) + ")"
|
||||||
ddlNotNull = Group(ddlWord("NOT") + ddlWord("NULL")).setResultsName("notNull")
|
ddlNotNull = Group(ddlWord("NOT") + ddlWord("NULL")).setResultsName("notNull")
|
||||||
ddlDefaultValue = ddlWord("DEFAULT").setResultsName("hasDefaultValue");
|
ddlDefaultValue = ddlWord("DEFAULT").setResultsName("hasDefaultValue")
|
||||||
ddlAutoValue = ddlWord("AUTO_INCREMENT").setResultsName("hasAutoValue");
|
ddlAutoValue = ddlWord("AUTO_INCREMENT").setResultsName("hasAutoValue")
|
||||||
ddlColumnComment = Group(ddlWord("COMMENT") + ddlString).setResultsName("comment")
|
ddlColumnComment = Group(ddlWord("COMMENT") + ddlString).setResultsName("comment")
|
||||||
ddlConstraint = Or([
|
ddlConstraint = Or([
|
||||||
ddlWord("CONSTRAINT"),
|
ddlWord("CONSTRAINT"),
|
||||||
@ -98,14 +137,6 @@ ddlConstraint = Or([
|
|||||||
ddlWord("INDEX"),
|
ddlWord("INDEX"),
|
||||||
ddlWord("UNIQUE"),
|
ddlWord("UNIQUE"),
|
||||||
])
|
])
|
||||||
ddlColumn = Group(Optional(ddlConstraint).setResultsName("isConstraint") + OneOrMore(MatchFirst([ddlNotNull, ddlAutoValue, ddlDefaultValue, ddlTerm, ddlNum, ddlColumnComment, ddlString, ddlArguments])))
|
|
||||||
createTable = Group(ddlWord("CREATE") + ddlWord("TABLE") + ddlName.setResultsName("tableName") + "(" + Group(delimitedList(ddlColumn)).setResultsName("columns") + ")").setResultsName("create")
|
|
||||||
|
|
||||||
|
|
||||||
ddl = ZeroOrMore(Suppress(SkipTo(createTable, False)) + createTable)
|
|
||||||
|
|
||||||
ddlComment = oneOf(["--", "#"]) + restOfLine
|
|
||||||
ddl.ignore(ddlComment)
|
|
||||||
|
|
||||||
# MAP SQL TYPES
|
# MAP SQL TYPES
|
||||||
types = {
|
types = {
|
||||||
@ -132,9 +163,26 @@ types = {
|
|||||||
'set': 'text', # MYSQL
|
'set': 'text', # MYSQL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ddlColumn = Group(Optional(ddlConstraint).setResultsName("isConstraint") + OneOrMore(MatchFirst([ddlNotNull, ddlAutoValue, ddlDefaultValue, ddlTerm, ddlNum, ddlColumnComment, ddlString, ddlArguments])))
|
||||||
|
createTable = Group(ddlWord("CREATE") + ddlWord("TABLE") + ddlName.setResultsName("tableName") + "(" + Group(delimitedList(ddlColumn)).setResultsName("columns") + ")").setResultsName("create")
|
||||||
|
ddlComment = oneOf(["--", "#"]) + restOfLine
|
||||||
|
|
||||||
|
if failOnParse:
|
||||||
|
ddl = OneOrMore(Suppress(SkipTo(createTable, False)) + createTable)
|
||||||
|
ddl.ignore(ddlComment)
|
||||||
|
try:
|
||||||
|
tableCreations = ddl.parseFile(pathToDdl)
|
||||||
|
except ParseException as e:
|
||||||
|
print("parsing error, possible reason: can't parse default value for a field")
|
||||||
|
sys.exit()
|
||||||
|
else:
|
||||||
|
ddl = ZeroOrMore(Suppress(SkipTo(createTable, False)) + createTable)
|
||||||
|
ddl.ignore(ddlComment)
|
||||||
|
tableCreations = ddl.parseFile(pathToDdl)
|
||||||
|
|
||||||
# PROCESS DDL
|
# PROCESS DDL
|
||||||
tableCreations = ddl.parseFile(pathToDdl)
|
|
||||||
|
|
||||||
|
|
||||||
header = open(pathToHeader, 'w')
|
header = open(pathToHeader, 'w')
|
||||||
print('// generated by ' + ' '.join(sys.argv), file=header)
|
print('// generated by ' + ' '.join(sys.argv), file=header)
|
||||||
@ -147,7 +195,7 @@ print('#include <' + INCLUDE + '/char_sequence.h>', file=header)
|
|||||||
print('', file=header)
|
print('', file=header)
|
||||||
print('namespace ' + namespace, file=header)
|
print('namespace ' + namespace, file=header)
|
||||||
print('{', file=header)
|
print('{', file=header)
|
||||||
DataTypeError = False;
|
DataTypeError = False
|
||||||
for create in tableCreations:
|
for create in tableCreations:
|
||||||
sqlTableName = create.tableName
|
sqlTableName = create.tableName
|
||||||
tableClass = toClassName(sqlTableName)
|
tableClass = toClassName(sqlTableName)
|
||||||
@ -184,22 +232,22 @@ for create in tableCreations:
|
|||||||
print(' };', file=header)
|
print(' };', file=header)
|
||||||
print(' };', file=header)
|
print(' };', file=header)
|
||||||
try:
|
try:
|
||||||
traitslist = [NAMESPACE + '::' + types[sqlColumnType]];
|
traitslist = [NAMESPACE + '::' + types[sqlColumnType]]
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
print ('Error: datatype "' + sqlColumnType + '"" is not supported.')
|
print ('Error: datatype "' + sqlColumnType + '"" is not supported.')
|
||||||
DataTypeError = True
|
DataTypeError = True
|
||||||
requireInsert = True
|
requireInsert = True
|
||||||
if column.hasAutoValue:
|
if column.hasAutoValue:
|
||||||
traitslist.append(NAMESPACE + '::tag::must_not_insert');
|
traitslist.append(NAMESPACE + '::tag::must_not_insert')
|
||||||
traitslist.append(NAMESPACE + '::tag::must_not_update');
|
traitslist.append(NAMESPACE + '::tag::must_not_update')
|
||||||
requireInsert = False
|
requireInsert = False
|
||||||
if not column.notNull:
|
if not column.notNull:
|
||||||
traitslist.append(NAMESPACE + '::tag::can_be_null');
|
traitslist.append(NAMESPACE + '::tag::can_be_null')
|
||||||
requireInsert = False
|
requireInsert = False
|
||||||
if column.hasDefaultValue:
|
if column.hasDefaultValue:
|
||||||
requireInsert = False
|
requireInsert = False
|
||||||
if requireInsert:
|
if requireInsert:
|
||||||
traitslist.append(NAMESPACE + '::tag::require_insert');
|
traitslist.append(NAMESPACE + '::tag::require_insert')
|
||||||
print(' using _traits = ' + NAMESPACE + '::make_traits<' + ', '.join(traitslist) + '>;', file=header)
|
print(' using _traits = ' + NAMESPACE + '::make_traits<' + ', '.join(traitslist) + '>;', file=header)
|
||||||
print(' };', file=header)
|
print(' };', file=header)
|
||||||
print(' }', file=header)
|
print(' }', file=header)
|
||||||
|
Loading…
Reference in New Issue
Block a user