execsql2 2.15.1__py3-none-any.whl → 2.15.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. execsql/config.py +1 -1
  2. execsql/db/duckdb.py +6 -7
  3. execsql/db/sqlite.py +46 -46
  4. execsql/parser.py +3 -2
  5. execsql/types.py +28 -15
  6. {execsql2-2.15.1.dist-info → execsql2-2.15.2.dist-info}/METADATA +1 -1
  7. {execsql2-2.15.1.dist-info → execsql2-2.15.2.dist-info}/RECORD +26 -26
  8. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/README.md +0 -0
  9. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/config_settings.sqlite +0 -0
  10. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/example_config_prompt.sql +0 -0
  11. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/execsql.conf +0 -0
  12. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/make_config_db.sql +0 -0
  13. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/md_compare.sql +0 -0
  14. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/md_glossary.sql +0 -0
  15. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/md_upsert.sql +0 -0
  16. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/pg_compare.sql +0 -0
  17. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/pg_glossary.sql +0 -0
  18. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/pg_upsert.sql +0 -0
  19. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/script_template.sql +0 -0
  20. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/ss_compare.sql +0 -0
  21. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/ss_glossary.sql +0 -0
  22. {execsql2-2.15.1.data → execsql2-2.15.2.data}/data/execsql2_extras/ss_upsert.sql +0 -0
  23. {execsql2-2.15.1.dist-info → execsql2-2.15.2.dist-info}/WHEEL +0 -0
  24. {execsql2-2.15.1.dist-info → execsql2-2.15.2.dist-info}/entry_points.txt +0 -0
  25. {execsql2-2.15.1.dist-info → execsql2-2.15.2.dist-info}/licenses/LICENSE.txt +0 -0
  26. {execsql2-2.15.1.dist-info → execsql2-2.15.2.dist-info}/licenses/NOTICE +0 -0
execsql/config.py CHANGED
@@ -569,7 +569,7 @@ class WriteHooks:
569
569
 
570
570
  def write_err(self, strval: str) -> None:
571
571
  """Write an error string to the error-output hook, or to sys.stderr if unset."""
572
- if strval[-1] != "\n":
572
+ if not strval.endswith("\n"):
573
573
  strval += "\n"
574
574
  if self.err_func:
575
575
  self.err_func(strval)
execsql/db/duckdb.py CHANGED
@@ -81,11 +81,10 @@ class DuckDBDatabase(Database):
81
81
  def schema_exists(self, schema_name: str) -> bool:
82
82
  """Return True if the named schema exists in the current DuckDB catalog."""
83
83
  # In DuckDB, the 'schemata' view is not limited to the current database.
84
- curs = self.cursor()
85
- curs.execute(
86
- "SELECT schema_name FROM information_schema.schemata WHERE schema_name = ? and catalog_name = ?;",
87
- (schema_name, self.catalog_name),
88
- )
89
- rows = curs.fetchall()
90
- curs.close()
84
+ with self._cursor() as curs:
85
+ curs.execute(
86
+ "SELECT schema_name FROM information_schema.schemata WHERE schema_name = ? and catalog_name = ?;",
87
+ (schema_name, self.catalog_name),
88
+ )
89
+ rows = curs.fetchall()
91
90
  return len(rows) > 0
execsql/db/sqlite.py CHANGED
@@ -82,21 +82,21 @@ class SQLiteDatabase(Database):
82
82
 
83
83
  def table_exists(self, table_name: str, schema_name: str | None = None) -> bool:
84
84
  """Return True if the named table exists in the SQLite database."""
85
- curs = self.cursor()
86
- sql = "select name from sqlite_master where type='table' and name=?;"
87
- try:
88
- curs.execute(sql, (table_name,))
89
- except ErrInfo:
90
- raise
91
- except Exception as e:
92
- self.rollback()
93
- raise ErrInfo(
94
- type="db",
95
- command_text=sql,
96
- exception_msg=exception_desc(),
97
- other_msg=f'Failed test for existence of SQLite table "{table_name}";',
98
- ) from e
99
- rows = curs.fetchall()
85
+ with self._cursor() as curs:
86
+ sql = "select name from sqlite_master where type='table' and name=?;"
87
+ try:
88
+ curs.execute(sql, (table_name,))
89
+ except ErrInfo:
90
+ raise
91
+ except Exception as e:
92
+ self.rollback()
93
+ raise ErrInfo(
94
+ type="db",
95
+ command_text=sql,
96
+ exception_msg=exception_desc(),
97
+ other_msg=f'Failed test for existence of SQLite table "{table_name}";',
98
+ ) from e
99
+ rows = curs.fetchall()
100
100
  return len(rows) > 0
101
101
 
102
102
  def column_exists(
@@ -111,40 +111,40 @@ class SQLiteDatabase(Database):
111
111
 
112
112
  def table_columns(self, table_name: str, schema_name: str | None = None) -> list[str]:
113
113
  """Return a list of column names for the given SQLite table."""
114
- curs = self.cursor()
115
- quoted_tbl = self.quote_identifier(table_name)
116
- sql = f"select * from {quoted_tbl} where 1=0;"
117
- try:
118
- curs.execute(sql)
119
- except ErrInfo:
120
- raise
121
- except Exception as e:
122
- self.rollback()
123
- raise ErrInfo(
124
- type="db",
125
- command_text=sql,
126
- exception_msg=exception_desc(),
127
- other_msg=f"Failed to get column names for table {table_name} of {self.name()}",
128
- ) from e
129
- return [d[0] for d in curs.description]
114
+ with self._cursor() as curs:
115
+ quoted_tbl = self.quote_identifier(table_name)
116
+ sql = f"select * from {quoted_tbl} where 1=0;"
117
+ try:
118
+ curs.execute(sql)
119
+ except ErrInfo:
120
+ raise
121
+ except Exception as e:
122
+ self.rollback()
123
+ raise ErrInfo(
124
+ type="db",
125
+ command_text=sql,
126
+ exception_msg=exception_desc(),
127
+ other_msg=f"Failed to get column names for table {table_name} of {self.name()}",
128
+ ) from e
129
+ return [d[0] for d in curs.description]
130
130
 
131
131
  def view_exists(self, view_name: str) -> bool:
132
132
  """Return True if the named view exists in the SQLite database."""
133
- curs = self.cursor()
134
- sql = "select name from sqlite_master where type='view' and name=?;"
135
- try:
136
- curs.execute(sql, (view_name,))
137
- except ErrInfo:
138
- raise
139
- except Exception as e:
140
- self.rollback()
141
- raise ErrInfo(
142
- type="db",
143
- command_text=sql,
144
- exception_msg=exception_desc(),
145
- other_msg=f'Failed test for existence of SQLite view "{view_name}";',
146
- ) from e
147
- rows = curs.fetchall()
133
+ with self._cursor() as curs:
134
+ sql = "select name from sqlite_master where type='view' and name=?;"
135
+ try:
136
+ curs.execute(sql, (view_name,))
137
+ except ErrInfo:
138
+ raise
139
+ except Exception as e:
140
+ self.rollback()
141
+ raise ErrInfo(
142
+ type="db",
143
+ command_text=sql,
144
+ exception_msg=exception_desc(),
145
+ other_msg=f'Failed test for existence of SQLite view "{view_name}";',
146
+ ) from e
147
+ rows = curs.fetchall()
148
148
  return len(rows) > 0
149
149
 
150
150
  def schema_exists(self, schema_name: str) -> bool:
execsql/parser.py CHANGED
@@ -151,8 +151,6 @@ class CondAstNode(CondTokens):
151
151
 
152
152
  def eval(self) -> bool:
153
153
  """Evaluate this subtree and return a boolean result."""
154
- # Evaluates the subtrees and/or conditional value for this node,
155
- # returning True or False.
156
154
  if self.type == self.CONDITIONAL:
157
155
  exec_fn = self.left[0].exec_fn
158
156
  cmdargs = self.left[1]
@@ -168,6 +166,7 @@ class CondAstNode(CondTokens):
168
166
  if lcond:
169
167
  return True
170
168
  return self.right.eval()
169
+ raise CondParserError(f"Unknown conditional node type: {self.type}")
171
170
 
172
171
 
173
172
  # AST for numeric expressions
@@ -200,6 +199,8 @@ class NumericAstNode(NumTokens):
200
199
  if self.type == self.MUL:
201
200
  return lnum * rnum
202
201
  elif self.type == self.DIV:
202
+ if rnum == 0:
203
+ raise NumericParserError("Division by zero.")
203
204
  return lnum / rnum
204
205
  elif self.type == self.ADD:
205
206
  return lnum + rnum
execsql/types.py CHANGED
@@ -296,14 +296,24 @@ class DT_Boolean(DataType):
296
296
  data_type_name = "boolean"
297
297
  data_type = bool
298
298
 
299
+ def __init__(self) -> None:
300
+ """Initialise with empty match caches; populated on first use."""
301
+ self.true: tuple = ()
302
+ self.false: tuple = ()
303
+ self.bool_repr: tuple = ()
304
+ self._cache_key: tuple | None = None
305
+
299
306
  def __repr__(self) -> str:
300
307
  return "DT_Boolean()"
301
308
 
302
- def set_bool_matches(self) -> None:
303
- """Populate the true/false match tuples from the current configuration."""
309
+ def _ensure_bool_matches(self) -> None:
310
+ """Rebuild true/false match tuples only when the config has changed."""
304
311
  import execsql.state as _state
305
312
 
306
313
  conf = _state.conf
314
+ key = (conf.boolean_words, conf.boolean_int)
315
+ if key == self._cache_key:
316
+ return
307
317
  self.true = ("yes", "true")
308
318
  self.false = ("no", "false")
309
319
  if not conf.boolean_words:
@@ -313,6 +323,7 @@ class DT_Boolean(DataType):
313
323
  self.true += ("1",)
314
324
  self.false += ("0",)
315
325
  self.bool_repr = self.true + self.false
326
+ self._cache_key = key
316
327
 
317
328
  def _is_match(self, data: object) -> bool:
318
329
  import execsql.state as _state
@@ -320,7 +331,7 @@ class DT_Boolean(DataType):
320
331
  conf = _state.conf
321
332
  if data is None:
322
333
  return False
323
- self.set_bool_matches()
334
+ self._ensure_bool_matches()
324
335
  return bool(
325
336
  isinstance(data, bool)
326
337
  or conf.boolean_int
@@ -336,7 +347,7 @@ class DT_Boolean(DataType):
336
347
  conf = _state.conf
337
348
  if data is None:
338
349
  raise DataTypeError(self.data_type_name, self._CONV_ERR % "NULL")
339
- self.set_bool_matches()
350
+ self._ensure_bool_matches()
340
351
  if isinstance(data, bool):
341
352
  return data
342
353
  elif conf.boolean_int and type(data) is int and data in (0, 1):
@@ -352,6 +363,7 @@ class DT_Integer(DataType):
352
363
 
353
364
  data_type_name = "integer"
354
365
  data_type = int
366
+ _INT_RX = re.compile(r"^\s*[+-]?\d+\s*$")
355
367
 
356
368
  def __repr__(self) -> str:
357
369
  return "DT_Integer()"
@@ -367,7 +379,7 @@ class DT_Integer(DataType):
367
379
  elif isinstance(data, str):
368
380
  if leading_zero_num(data):
369
381
  return False
370
- if not re.match(r"^\s*[+-]?\d+\s*$", data):
382
+ if not self._INT_RX.match(data):
371
383
  return False
372
384
  try:
373
385
  i = int(data)
@@ -387,7 +399,7 @@ class DT_Integer(DataType):
387
399
  return int(data)
388
400
  else:
389
401
  raise DataTypeError(self.data_type_name, self._CONV_ERR % data)
390
- if isinstance(data, str) and not re.match(r"^\s*[+-]?\d+\s*$", data):
402
+ if isinstance(data, str) and not self._INT_RX.match(data):
391
403
  raise DataTypeError(self.data_type_name, self._CONV_ERR % data)
392
404
  try:
393
405
  i = int(data)
@@ -439,6 +451,7 @@ class DT_Float(DataType):
439
451
 
440
452
  data_type_name = "float"
441
453
  data_type = float
454
+ _FLOAT_RX = re.compile(r"^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$")
442
455
 
443
456
  def __repr__(self) -> str:
444
457
  return "DT_Float()"
@@ -450,7 +463,7 @@ class DT_Float(DataType):
450
463
  return True
451
464
  if leading_zero_num(data):
452
465
  return False
453
- if isinstance(data, str) and not re.match(r"^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$", data):
466
+ if isinstance(data, str) and not self._FLOAT_RX.match(data):
454
467
  return False
455
468
  try:
456
469
  float(data)
@@ -465,7 +478,7 @@ class DT_Float(DataType):
465
478
  return data
466
479
  if leading_zero_num(data):
467
480
  raise DataTypeError(self.data_type_name, self._CONV_ERR % data)
468
- if isinstance(data, str) and not re.match(r"^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$", data):
481
+ if isinstance(data, str) and not self._FLOAT_RX.match(data):
469
482
  raise DataTypeError(self.data_type_name, self._CONV_ERR % data)
470
483
  try:
471
484
  i = float(data)
@@ -480,6 +493,7 @@ class DT_Decimal(DataType):
480
493
  data_type_name = "decimal"
481
494
  data_type = Decimal
482
495
  precspec = True
496
+ _DECIMAL_RX = re.compile(r"^[+-]?(\d+(\.\d*)?|\.\d+)$")
483
497
 
484
498
  def __repr__(self) -> str:
485
499
  return "DT_Decimal()"
@@ -504,7 +518,7 @@ class DT_Decimal(DataType):
504
518
  self.set_scale_prec(data)
505
519
  return data
506
520
  elif isinstance(data, str):
507
- if not re.match(r"^[+-]?(\d+(\.\d*)?|\.\d+)$", data):
521
+ if not self._DECIMAL_RX.match(data):
508
522
  raise DataTypeError(self.data_type_name, self._CONV_ERR % data)
509
523
  try:
510
524
  dec = Decimal(data)
@@ -565,21 +579,20 @@ class DT_Varchar(DataType):
565
579
  # This varchar data type is the same as the character data type.
566
580
  if data is None:
567
581
  raise DataTypeError(self.data_type_name, self._CONV_ERR % "NULL")
568
- data_type = str
569
- if isinstance(data, str):
582
+ if not isinstance(data, str):
570
583
  try:
571
- data = data_type(data)
584
+ data = str(data)
572
585
  except ValueError as e:
573
586
  raise DataTypeError(self.data_type_name, self._CONV_ERR % data) from e
574
- if len(data) > 255:
575
- raise DataTypeError(self.data_type_name, self._CONV_ERR % data)
587
+ if len(data) > 255:
588
+ raise DataTypeError(self.data_type_name, self._CONV_ERR % data)
576
589
  return data
577
590
 
578
591
 
579
592
  class DT_Text(DataType):
580
593
  """Unbounded text string data type."""
581
594
 
582
- data_type_name = "character"
595
+ data_type_name = "text"
583
596
 
584
597
  def __repr__(self) -> str:
585
598
  return "DT_Text()"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: execsql2
3
- Version: 2.15.1
3
+ Version: 2.15.2
4
4
  Summary: Runs a SQL script against a PostgreSQL, SQLite, MariaDB/MySQL, DuckDB, Firebird, MS-Access, MS-SQL-Server, or Oracle database, or an ODBC DSN. Provides metacommands to import and export data, copy data between databases, conditionally execute SQL and metacommands, and dynamically alter SQL and metacommands with substitution variables.
5
5
  Project-URL: Homepage, https://execsql2.readthedocs.io
6
6
  Project-URL: Repository, https://github.com/geocoug/execsql
@@ -1,13 +1,13 @@
1
1
  execsql/__init__.py,sha256=BIny4bL8uHuSl3gXPqEkIB2FtcexlARjR7IYPwtD9bM,486
2
2
  execsql/__main__.py,sha256=HdbK-SAhyUmfB6xINY5AzxdMSxGzWSGEG_2dv42Jn64,315
3
- execsql/config.py,sha256=eks1FldtzbTLdHFXWiAGQk-UiAeesB0fF65rWGAT3n4,28375
3
+ execsql/config.py,sha256=1cC0a_IAQzfFJ0SdLCf5fCJXztMoDajr9qlqTRdFyLY,28382
4
4
  execsql/exceptions.py,sha256=dpOjpD67nWQlKJIz4M2emDv5RbUbCo6-QuvnQ5M39p8,8477
5
5
  execsql/format.py,sha256=-6iknDddqbkapMo4NKmT5LAynDLqMW5kHgDWRg0KSws,11990
6
6
  execsql/models.py,sha256=6k5saa_tpZGhr_BjPUnLeUWYQq98ORooG_R6GDuYDdQ,13478
7
- execsql/parser.py,sha256=IyOz3UUb6pNKOoDKPm8sUgGbWOP8504lu86V4-HzuO0,15428
7
+ execsql/parser.py,sha256=P3ea8k7T_XLMrbhpFNZXwytdShrY302MKnhosqza1lo,15493
8
8
  execsql/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  execsql/state.py,sha256=29b3SwG4GirED2KVQc-cCC7Z_-FsGN3fEt9xQNN-Puo,15090
10
- execsql/types.py,sha256=RpWuBfamg8oXr0ghWbyN4qIumyDdwmrEorfHoPGlzQA,31372
10
+ execsql/types.py,sha256=5K3aTuWQZHftz5slFODwqxlcvvt6lROISUnvUtRUazs,31799
11
11
  execsql/cli/__init__.py,sha256=YXxOVF2lNkCkifXyjoC7yWrhHJFT9PzI7cnCzsLJwT8,16488
12
12
  execsql/cli/dsn.py,sha256=svaZtrUXFRL2W5G6FRRiKtR6kehOp7urrVhIx_642Z8,2820
13
13
  execsql/cli/help.py,sha256=Sn_TgSJiQeBx-xZH0fuP5OvR_wasSTumjWF9UHfIX5k,5414
@@ -17,13 +17,13 @@ execsql/db/__init__.py,sha256=jTbuafuKOqYtXFR1wvCOoKK5Lr3l1uErfaIbIr6UywI,1063
17
17
  execsql/db/access.py,sha256=L79gUnAnnM9EJ_f4k42jr7DI0qGcKtLOnJTlBC7uPm0,17879
18
18
  execsql/db/base.py,sha256=OnYjJciEAI3oFWkA6WEZs7nrs850pevU0QbTtvQWszg,31185
19
19
  execsql/db/dsn.py,sha256=TgQUedVCxnEYA3vae7JETyhb8kK23qkNbPxsMQrNUN8,5368
20
- execsql/db/duckdb.py,sha256=cKeMwiSlYPyPDn1VLaJgbUD6_IEEaNqtUToLcmq7QaE,3189
20
+ execsql/db/duckdb.py,sha256=dmTNOhDyn4LVRoC6MvxYv_Rxwio3pIG_YqCtBvrOLB4,3196
21
21
  execsql/db/factory.py,sha256=YR1m_c2Hhj_GXVGGkWoSEPZBpgNu_c4FxRnbp-xV3rs,5230
22
22
  execsql/db/firebird.py,sha256=P_5H_aWTh8fzJoH3vWwwUpAd0hehoXvwDcjggoZqhWE,8537
23
23
  execsql/db/mysql.py,sha256=BR68IeVCh3HlUuePOTtcih1m5-kEIWI_6xUiYBJnHeA,13703
24
24
  execsql/db/oracle.py,sha256=AFVHhGlCzBuU7JgrAqeUG6e8TUUkk1Y80XVJQnGOqLM,10547
25
25
  execsql/db/postgres.py,sha256=oXR7ODzQhR3yO6q-aNa9_il_rO3SpOX9yYGsfIqHwLI,20139
26
- execsql/db/sqlite.py,sha256=yU15xs5SL88VHMHbmmgtYUX0BAgen88nFlVdV2xln7E,10204
26
+ execsql/db/sqlite.py,sha256=bUHVnB5TDv45Aah-dctXUwnR2qSlyIMzHXGItnMuq9M,10400
27
27
  execsql/db/sqlserver.py,sha256=mNwmIIxTzqXU-cOjpNpeFi568HjQHsAk8Xnn-tR6F_E,7563
28
28
  execsql/debug/__init__.py,sha256=j6EGUR0dHzUhWN1mHHtf1-Lhjq3Sb1V-vmnq2Ztgj1M,178
29
29
  execsql/debug/repl.py,sha256=HeQ9emFKUjo7UTouxuTcmpGCTJIR1nOLxKkRJ5mvd2c,16669
@@ -93,24 +93,24 @@ execsql/utils/numeric.py,sha256=xh02ANSRk3nUpQ-rtm66ILoMqoi7HtzCoRMIOT9U8QI,1570
93
93
  execsql/utils/regex.py,sha256=diEzTZqU_HHwVMadPAvN1Vgzhl7I03eVaEFGCXyGGL8,3770
94
94
  execsql/utils/strings.py,sha256=5Dvzrk-9SIw2lpxXZQkiJbNyo1sy7iXXAtSULlZ0KG8,8488
95
95
  execsql/utils/timer.py,sha256=eDYf5VzCNFk7oo90InJucUm3XcBdhYMogjZMqeg9xzc,1899
96
- execsql2-2.15.1.data/data/execsql2_extras/README.md,sha256=sxwVyU0ZahCfANv56LahkyuM505kFjrMhe-1SvWE69E,4845
97
- execsql2-2.15.1.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
98
- execsql2-2.15.1.data/data/execsql2_extras/example_config_prompt.sql,sha256=SY3Jxn1qcVm4kPW9xmmTfknHfvURXmeEYTbRjYrjGSw,7487
99
- execsql2-2.15.1.data/data/execsql2_extras/execsql.conf,sha256=_45iJ-KWZnB8uMW_gEg067MM5pmGJ-dVl7VbAZMunAE,9530
100
- execsql2-2.15.1.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
101
- execsql2-2.15.1.data/data/execsql2_extras/md_compare.sql,sha256=B8Wd7LZ0vnMY2qvA139JIEBkPObgRH2i5xj6PejTQt8,24092
102
- execsql2-2.15.1.data/data/execsql2_extras/md_glossary.sql,sha256=DJRHcU5NbFpxTTX-IwH3yRlsboj1q6BBGrUAHKn4Cuo,10796
103
- execsql2-2.15.1.data/data/execsql2_extras/md_upsert.sql,sha256=v_7GbWh_N1mBTmw3gvTrkagOVp2q0KmXvM8hE-DlFxY,112524
104
- execsql2-2.15.1.data/data/execsql2_extras/pg_compare.sql,sha256=9dWa8hnfy5dVJI-z2iGpd9JzQmI4j2ziMlEdpnr66ro,24352
105
- execsql2-2.15.1.data/data/execsql2_extras/pg_glossary.sql,sha256=pKjIIDsROAgJq2H-1qNEcRMAWManivcZ_AEVHzUUlic,9908
106
- execsql2-2.15.1.data/data/execsql2_extras/pg_upsert.sql,sha256=k7AFiGTLBy3nf-qO5QIaZrEYTAKvdxxU3JDLx9jqkzs,108315
107
- execsql2-2.15.1.data/data/execsql2_extras/script_template.sql,sha256=1Estacb_vm1FgK41k_G9nuduP1yiA-fQ1Kn4Z4mv5Ao,11153
108
- execsql2-2.15.1.data/data/execsql2_extras/ss_compare.sql,sha256=TsVxWm3cEpR5-EiMYXNhtaY0arSNeKZhsJdHdLA7xeI,24833
109
- execsql2-2.15.1.data/data/execsql2_extras/ss_glossary.sql,sha256=cLM7nN8JOIu9ZVP9oY9qdSK3hrnWJiDcX6nZmQQbQWI,13065
110
- execsql2-2.15.1.data/data/execsql2_extras/ss_upsert.sql,sha256=BCqmBykXBF-BpCgOFeG1qhf2XfScKsxPD17wd1hYfHw,120647
111
- execsql2-2.15.1.dist-info/METADATA,sha256=VBTsF8PHpQOrunzJTFlSlOJbj9JtfnzjV1wLd9QDEzQ,17602
112
- execsql2-2.15.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
113
- execsql2-2.15.1.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
114
- execsql2-2.15.1.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
115
- execsql2-2.15.1.dist-info/licenses/NOTICE,sha256=sqVrM73Ys9zfvWC_P797lHfTnoPW_ETeBSrUTFaob0A,339
116
- execsql2-2.15.1.dist-info/RECORD,,
96
+ execsql2-2.15.2.data/data/execsql2_extras/README.md,sha256=sxwVyU0ZahCfANv56LahkyuM505kFjrMhe-1SvWE69E,4845
97
+ execsql2-2.15.2.data/data/execsql2_extras/config_settings.sqlite,sha256=aY5cxR7Q7J6zJ4bC9lu5mHUrhy211Cq3MNKPQVCt02E,20480
98
+ execsql2-2.15.2.data/data/execsql2_extras/example_config_prompt.sql,sha256=SY3Jxn1qcVm4kPW9xmmTfknHfvURXmeEYTbRjYrjGSw,7487
99
+ execsql2-2.15.2.data/data/execsql2_extras/execsql.conf,sha256=_45iJ-KWZnB8uMW_gEg067MM5pmGJ-dVl7VbAZMunAE,9530
100
+ execsql2-2.15.2.data/data/execsql2_extras/make_config_db.sql,sha256=WwyC6dK-Eh5CAVppiBCDHqiI1_wEI9U95Ytpr4lsZkg,8726
101
+ execsql2-2.15.2.data/data/execsql2_extras/md_compare.sql,sha256=B8Wd7LZ0vnMY2qvA139JIEBkPObgRH2i5xj6PejTQt8,24092
102
+ execsql2-2.15.2.data/data/execsql2_extras/md_glossary.sql,sha256=DJRHcU5NbFpxTTX-IwH3yRlsboj1q6BBGrUAHKn4Cuo,10796
103
+ execsql2-2.15.2.data/data/execsql2_extras/md_upsert.sql,sha256=v_7GbWh_N1mBTmw3gvTrkagOVp2q0KmXvM8hE-DlFxY,112524
104
+ execsql2-2.15.2.data/data/execsql2_extras/pg_compare.sql,sha256=9dWa8hnfy5dVJI-z2iGpd9JzQmI4j2ziMlEdpnr66ro,24352
105
+ execsql2-2.15.2.data/data/execsql2_extras/pg_glossary.sql,sha256=pKjIIDsROAgJq2H-1qNEcRMAWManivcZ_AEVHzUUlic,9908
106
+ execsql2-2.15.2.data/data/execsql2_extras/pg_upsert.sql,sha256=k7AFiGTLBy3nf-qO5QIaZrEYTAKvdxxU3JDLx9jqkzs,108315
107
+ execsql2-2.15.2.data/data/execsql2_extras/script_template.sql,sha256=1Estacb_vm1FgK41k_G9nuduP1yiA-fQ1Kn4Z4mv5Ao,11153
108
+ execsql2-2.15.2.data/data/execsql2_extras/ss_compare.sql,sha256=TsVxWm3cEpR5-EiMYXNhtaY0arSNeKZhsJdHdLA7xeI,24833
109
+ execsql2-2.15.2.data/data/execsql2_extras/ss_glossary.sql,sha256=cLM7nN8JOIu9ZVP9oY9qdSK3hrnWJiDcX6nZmQQbQWI,13065
110
+ execsql2-2.15.2.data/data/execsql2_extras/ss_upsert.sql,sha256=BCqmBykXBF-BpCgOFeG1qhf2XfScKsxPD17wd1hYfHw,120647
111
+ execsql2-2.15.2.dist-info/METADATA,sha256=PdSyFj4MRGHYDVsxeFghoKXGdBs2qWG1bkhoP3M03Ak,17602
112
+ execsql2-2.15.2.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
113
+ execsql2-2.15.2.dist-info/entry_points.txt,sha256=sUOxkM-dN1eBGGpSpDLsAaE0yNXYQKWZAfxPOlMkQyk,90
114
+ execsql2-2.15.2.dist-info/licenses/LICENSE.txt,sha256=LBdhuxejF8_bLCHZ2kWfmDXpDGUu914Gbd6_3JjCRe0,676
115
+ execsql2-2.15.2.dist-info/licenses/NOTICE,sha256=sqVrM73Ys9zfvWC_P797lHfTnoPW_ETeBSrUTFaob0A,339
116
+ execsql2-2.15.2.dist-info/RECORD,,