ããŒãã£ãŒã®æ³åã«ãããšãéžæãããããžã§ã¯ããè€æ°ããå Žåã¯ãææ¡ãããŠãããããžã§ã¯ãã®ãã¡æãé£ãããã®ãåŒãåããŸãã ããã¯ãããŒã¿ããŒã¹ç®¡çã·ã¹ãã ïŒDBMSïŒã®ã³ãŒã¹ã®æåŸã®ã¿ã¹ã¯ã§çºçããŸããã
![ã«ããŒ/ dropSQL](https://habrastorage.org/webt/rc/0n/pg/rc0npgm2cp9pwpwb6hpcknftmd0.jpeg)
åé¡ã®å£°æ
äœæ¥æ瀺æžã«ãããšãVanilla Python 3.6ã§DBMSããŒãããäœæããå¿ èŠããããŸããïŒãµãŒãããŒãã£ã©ã€ãã©ãªãªãïŒã æçµè£œåã«ã¯æ¬¡ã®ããããã£ãå¿ èŠã§ãã
- ããŒã¿ããŒã¹ãåäžã®ãã¡ã€ã«ã«ãã€ããªåœ¢åŒã§ä¿åããŸã
- DDLïŒæŽæ°ãæµ®åãããã³å¯å€é·æåïŒNïŒã®3ã€ã®ããŒã¿åããµããŒãããŸãã ç°¡åã«ããããã«ããããã¯ãã¹ãŠåºå®é·ã§ãã
- DMLïŒåºæ¬çãªSQLæäœããµããŒãããŸãã
- æ¿å ¥
- æŽæ°
- åé€
- WHEREããã³JOINã䜿çšããSELECTã ã©ã®JOINã«æ£ç¢ºã«åå ãããã¯ç€ºãããŠããªããããCROSSãšINNERã®äž¡æ¹ãè¡ã£ãå Žåã«åããŠ
- 100'000ã¬ã³ãŒãã«èãã
èšèšã¢ãããŒã
DBMSããŒãããéçºããããšã¯ãéèŠãªã¿ã¹ã¯ã®ããã«æããŸããïŒå¥åŠãªããšã«ããã®ããã«ãªããŸããïŒã ãããã£ãŠãæã -ecat3ãš@ratijas-ã¯ãã®åé¡ã«ç§åŠçã«ã¢ãããŒãããŸããã ããŒã ã«ã¯2人ããããŸããïŒèªåèªèº«ãšç§ã®äººå¡ã¯èæ ®ããŠããŸããïŒãã€ãŸããã¿ã¹ã¯ãå®éã«å®è¡ããããããã¿ã¹ã¯ã調æŽããŠå®è£ ã調æŽããæ¹ãã¯ããã«ç°¡åã§ãã ã«ããã®çµããã«ã次ã®ããšãèµ·ãããŸããã
ææŠãã | è«è² æ¥è |
---|---|
ããŒãµãŒ+ AST + REPL | ratijasãããããçš®é¡ã®lex / yaccã«ã€ããŠè€æ°ã®èšç®æ©ãæžãã |
åºæ¬ãã¡ã€ã«æ§é | ãã¡ã€ã«ã·ã¹ãã ã§ecat3ãé£ã¹ãç¬ |
ãšã³ãžã³
ïŒäœã¬ãã«ã®ããŒã¿ããŒã¹æäœïŒ | ecat3 |
ã€ã³ã¿ãŒãã§ãŒã¹
ïŒé«ã¬ãã«ã®æ¥çïŒ | äžç·ã« |
åœåã¯2é±éãå²ãåœãŠãããŠãããããåã ã®ã¿ã¹ã¯ã1é±éã§å®äºããããšã«ãªã£ãŠãããæ®ãã®æéã¯å ±åã§æ¥çãšãã¹ãã«å ãŠãããŸãã
æ£åŒãªéšåãçµäºããããå®çšã«ç§»ããŸãããã DBMSã¯ææ°ãã€é©åãªãã®ã§ãªããã°ãªããŸããã çŸä»£ã®ã€ãããªã¹ã§ã¯ããã¬ã°ã©ã ã®ã¡ãã»ã³ãžã£ãŒããã£ããããããããã³ã/ã¹ã©ãã·ã¥ã¿ã°ãã䜿çšããã°ã«ãŒãéä¿¡ãé¢é£ããŠããŸãïŒããã¯ïŒããã·ã¥ã¿ã°ã®ãããªãã®ã§ã/ã¹ã©ãã·ã¥ã§å§ãŸããŸãïŒã ãããã£ãŠãSQLã«ãã䌌ãã¯ãšãªèšèªã§ã¯å€§æåãšå°æåãåºå¥ãããªãã ãã§ãªãã倧æåãšå°æåãåºå¥ãããŸããã ããã«ã倧åŠçãšåæ§ã«ãåèšèªã®ã¹ããŒãã¡ã³ãïŒã¹ããŒãã¡ã³ãïŒã¯ã/ãããããã§çµããå¿ èŠããããŸãã ïŒãã¡ãããç»é²ç°¿ã«é¢ä¿ãªãããã®ãããªç¶æ³ã§äžè¬çã«èª°ãããã®ç»é²ç°¿ãæ°ã«ããŸããïŒïŒ
å
žåçãª/æ¥äž/ãã£ãã
![/ autist_s_dr](https://habrastorage.org/webt/ss/kn/f3/ssknf3opseg5poir4yqfpqpu5ai.png)
ããã§ãååã®ã¢ã€ãã¢ãçãŸããŸããïŒ dropSQL ã å®éã«/ãããã 'thã¯ã倧åŠããã®åŠçã®è¿œæŸãšåŒã°ããŠããŸãã äœããã®çç±ã§ããã®èšèã¯ç§ãã¡ã®ã€ãããªã¹ã§åºãŸã£ãŠããŸãã ïŒå¥ã®å±æçŸè±¡ïŒèªéçããŸãã¯ããæ£ç¢ºã«ã¯ã/èªéçãããããç§ãã¡ã¯ç¹å¥ãªã±ãŒã¹ã®ããã«ãããäºçŽããŸãããïŒ
ãŸããdropSQLææ³ãBNFã«å解ããŸããïŒãããŠãç¡é§ãªããšã«ãå·Šååž°ã¯éé ããŒãµãŒã«ã¯é©ããŠããŸããïŒã
BNFææ³dropSQL
å®å
šçã¯ãã¡ã
/stmt : /create_stmt | /drop_stmt | /insert_stmt | /update_stmt | /delete_stmt | /select_stmt ; /create_stmt : "/create" "table" existence /table_name "(" /columns_def ")" "/drop" ; existence : /* empty */ | "if" "not" "exists" ; /table_name : /identifier ; /columns_def : /column_def | /columns_def "," /column_def ; /column_def : /column_name type /primary_key ; ...
補åãªã³ã©ã€ã³ãã«ãã®æå¹ãªdropSQLã³ãã³ãã®äŸ
/create table t(a integer, b float, c varchar(42)) /drop /insert into t (a, c, b) values (42, 'morty', 13.37), (?1, ?2, ?3) /drop /select *, a, 2 * b, c /as d from t Alias /where (a < 100) /and (c /= '') /drop /update t set c = 'rick', a = a + 1 /drop /delete from t where c > 'r' /drop /drop table if exists t /drop
ç§ãã¡ã¯çµæã®ããã«åããŸãïŒ äŸå€ãªãïŒ
Rustãã¡ã€ã³èšèªãšããŠæ°ã¶æéãããåŸãç§ã¯æ¬åœã«äŸå€åŠçã§åã³è¡ãè©°ãŸããããããŸããã§ããã äŸå€ã«å¯Ÿããæçœãªè°è«ã¯ãããããæããã®ã«è²»çšãããããšããããšã§ããããã£ããã¯æ±ãã«ããã§ãã Pythonã¯ãJavaèªäœãšã¯ç°ãªããType AnnotationsãåããããŒãžã§ã³3.6ã§ããã¡ãœããããé£ã³åºãå¯èœæ§ã®ããäŸå€ã®ã¿ã€ããæå®ã§ããªããšããäºå®ã«ãã£ãŠç¶æ³ãæªåããŠããŸãã ã€ãŸããã¡ãœããã®ã·ã°ããã£ãèŠããšãã¡ãœããã«äœãæåŸ ã§ããããæããã«ãªãã¯ãã§ãã ããã§ã¯ããããã®ã¿ã€ãããenum ErrorããšåŒã°ãã1ã€ã®å±æ ¹ã®äžã§çµã¿åãããŠã¿ãŸããã ãããŠãã®äžã«ãResultãšããå¥ã®ãå±æ ¹ããäœæããŸãã 以äžã§èª¬æããŸãã ãã¡ãããæšæºã©ã€ãã©ãªã«ã¯ãççºãã§ããå ŽæããããŸãã ããããã³ãŒãå ã®ãã®ãããªåŒã³åºãã¯ããã¹ãŠã®åŽããtry'iã«ãã£ãŠç¢ºå®ã«èª²ãããŸããããã«ãããäŸå€ãæžãããŠãšã©ãŒãè¿ããããå®è¡äžã®ç·æ¥äºæ ã®çºçãæå°éã«æããããŸãã
ãã®ãããçµæã®ä»£æ°åïŒhelloãRustïŒãèªè»¢è»ã«ä¹ããããšã決å®ãããŸããã 代æ°åã®pythonã§ã¯ããã¹ãŠãæªãã§ãã æšæºã®enumã©ã€ãã©ãªã®ã¢ãžã¥ãŒã«ã¯ãããããªå°è žã®ãããªãã®ã§ãã
ææªã®OOPã®äŒçµ±ã§ã¯ãç¶æ¿ã䜿çšããŠçµæã³ã³ã¹ãã©ã¯ã¿ãŒOkãšErrãå®çŸ©ããŸãã ãããŠãéçåä»ããå¿ããªãã§ãã ããïŒ ãŸããç§ã¯ãã§ã«3çªç®ã®ããŒãžã§ã³ãæã£ãŠããŸãïŒæçµçã«Pythonã§éçåä»ããããŠãããã§ããïŒ ïŒïŒ
result.py
import abc from typing import * class Result(Generic[T, E], metaclass=abc.ABCMeta): """ enum Result< T > { Ok(T), Err(E), } """ # def is_ok(self) -> bool: return False def is_err(self) -> bool: return False def ok(self) -> T: raise NotImplementedError def err(self) -> E: raise NotImplementedError ... class Ok(Generic[T, E], Result[T, E]): def __init__(self, ok: T) -> None: self._ok = ok def is_ok(self) -> bool: return True def ok(self) -> T: return self._ok ... class Err(Generic[T, E], Result[T, E]): def __init__(self, error: E) -> None: self._err = error def is_err(self) -> bool: return True def err(self) -> E: return self._err ...
ãããïŒ æ©èœçãªå€æããäœãããå°ããªãœãŒã¹ã§å³ä»ãããŸãã ãã¹ãŠãå¿ èŠãªããã§ã¯ãããŸããã®ã§ãå¿ èŠæå°éããšã£ãŠãã ããã
result.pyïŒç¶ãïŒ
class Result(Generic[T, E], metaclass=abc.ABCMeta): ... def ok_or(self, default: T) -> T: ... def err_or(self, default: E) -> E: ... def map(self, f: Callable[[T], U]) -> 'Result[U, E]': # -! ? # , Python "forward declaration". # -. PEP 484: # https://www.python.org/dev/peps/pep-0484/#forward-references ... def and_then(self, f: Callable[[T], 'Result[U, E]']) -> 'Result[U, E]': ... def __bool__(self) -> bool: # `if` return self.is_ok()
ãããŠããã«äœ¿çšäŸïŒ
çµæã®äŸ
def try_int(x: str) -> Result[int, str]: try: return Ok(int(x)) except ValueError as e: return Err(str(e)) def fn(arg: str) -> None: r = try_int(arg) # 'r' for 'Result' if not r: return print(r.err()) # one-liner, shortcut for `if r.is_err()` index = r.ok() print(index) # do something with index
ãã®ã¹ã¿ã€ã«ã§ã®èœæžãã¯ãåãââã£ã¬ã³ãžã«å¯ŸããŠ3è¡å¿ èŠã§ãã ãããããã®åŸãã©ã®ãšã©ãŒãçºçããå¯èœæ§ããããã©ã®ãããªãšã©ãŒãçºçããããæ確ã«ç解ã§ããŸãã ããã«ãã³ãŒãã¯åãã¬ãã«ã®ãã¹ãã§ç¶ç¶ãããŸãã ã¡ãœããã«åããŒã¹ã®åçš®ã®åŒã³åºããå«ãŸããå Žåãããã¯éåžžã«éèŠãªå質ã§ãã
ããŒãµãŒãIResultããšã©ãŒ:: {空ãäžå®å šãæ§æ}ãREPLã9600ããŒããã¹ãŠãã¹ãŠ
ããŒãµãŒã¯éçºæéã®ããªãã®éšåãå ããŸããã é©åã«èšèšãããããŒãµãŒã¯ã補åã®ããã³ããšã³ãã䜿çšããå©äŸ¿æ§ããŠãŒã¶ãŒã«æäŸããå¿ èŠããããŸãã ããŒãµãŒã®æãéèŠãªã¿ã¹ã¯ã¯æ¬¡ã®ãšããã§ãã
- ãšã©ãŒå ±åãã¯ãªã¢ãã
- ã€ã³ã¿ã©ã¯ãã£ããªã€ã³ã¯ãªã¡ã³ã¿ã«ã©ã€ã³å ¥åããŸãã¯ããåçŽã«REPL
ãå šäœã®ãæšæºPythonã©ã€ãã©ãªã ãã§ãªããããŒãµãŒäœæã®æ§ãããªç¥èããããããè¢ããŸããäžããŠæåã®ååž°äžéããŒãµãŒïŒEngãRecursive descent parserïŒãäœæããå¿ èŠãããããšã«æ°ä»ããŸããã ããã¯é·ãéå±ãªããžãã¹ã§ãããç¶æ³ãé«åºŠã«å¶åŸ¡ã§ããŸãã
çããããã¹ãæåã®è³ªåã®1ã€ïŒééããã©ããããïŒ ã©ããªãã-ãã§ã«äžã§èãåºããã ããããééãã¯äœã§ããïŒ ããšãã°ãã/ create tableãã®åŸã«ãif not existsããååšããå Žåãããã°ãååšããªãå ŽåããããŸã-ããã¯ééãã§ããïŒ ãããããªããã©ã®ãããªïŒ ã©ãã§åŠçããå¿ èŠããããŸããïŒ ïŒãäžæåæ¢ãããã³ã¡ã³ãã§ãªãã·ã§ã³ãææ¡ããŸããïŒ
ããŒãµãŒã®æåã®ããŒãžã§ã³ã¯ã 2ã€ã®ã¿ã€ãã®ãšã©ãŒãåºå¥ããŸããïŒäºæãããïŒ1ã€ãæåŸ ããŸãããäœãä»ã®ãã®ãåãåããŸããïŒããã³EOFïŒãã¡ã€ã«ã®çµããïŒåã®ãµãã¯ã©ã¹ãšããŠã REPLã«å°éãããŸã§ã¯ããã¹ãŠåé¡ãããŸããã ãã®ãããªããŒãµãŒã¯ãéšåçãªå ¥åïŒã³ãã³ãã®éå§ïŒãšäœãååšããªãããšïŒEOFã端æ«ããã®å¯Ÿè©±åå ¥åã«ã€ããŠèšãã°ïŒãåºå¥ããŸããã ããã1é±éåŸãè©Šè¡é¯èª€ãç¹°ãè¿ããŠããã¡ã€ã³é åãæºããã¹ããŒã ãèŠã€ããããšãã§ããŸããã
ã¹ããŒã ã¯ããã¹ãŠãã¹ããªãŒã ã§ãããããŒãµãŒã¯ã¹ããªãŒã äžã®ãããããªnextïŒïŒã¡ãœããã§ãããšãããã®ã§ãã ãŸãããšã©ãŒã¯ã©ã¹ã¯ïŒResultãªã©ã®ïŒä»£æ°ã«æžãæããå¿ èŠãããã EOFã®ä»£ããã«Emptyãªãã·ã§ã³ãšIncompleteãªãã·ã§ã³ãå°å ¥ãããŸãã
![ãã¹ãŠãã¹ããªãŒã ã§ã](https://habrastorage.org/getpro/habr/post_images/8fe/48e/b71/8fe48eb71aa5f92aa6be3d22d135aa32.jpg)
æ°ããã¿ã€ãã®ãšã©ãŒ
class Error(metaclass=abc.ABCMeta): """ enum Error { Empty, Incomplete, Syntax { expected: str, got: str }, } """ def empty_to_incomplete(self) -> 'Error': if isinstance(self, Empty): return Incomplete() else: return self class Empty(Error): ... class Incomplete(Error): ... class Syntax(Error): def __init__(self, expected: str, got: str) -> None: ... # stream-specific result type alias IResult = Result[T, Error] IOk = Ok[T, Error] IErr = Err[T, Error]
ã¹ããªãŒã ã€ã³ã¿ãŒãã§ãŒã¹
class Stream(Generic[T], metaclass=abc.ABCMeta): def current(self) -> IResult[T]: ... def next(self) -> IResult[T]: ... def collect(self) -> IResult[List[T]]: ... def peek(self) -> IResult[T]: ... def back(self, n: int = 1) -> None: ... @abc.abstractmethod def next_impl(self) -> IResult[T]: ...
ãããŒã¯æœè±¡åã§ãã ã¹ããªãŒã ã¯ãã©ã®èŠçŽ ãçæããããæ°ã«ããŸããã ã¹ããªãŒã ã¯ãã€åæ¢ããããç¥ã£ãŠããŸãã ã¹ããªãŒã ãå®è£ ããããã«å¿ èŠãªããšã¯ãæœè±¡ã¡ãœããnext_implïŒïŒ-> IResult [T]ã®ã¿ãæžãæããããšã§ãã ãã®ã¡ãœãããè¿ããã®ã¯äœã§ããïŒ ããŒã¯ã³ã¹ããªãŒã ã®äŸãèããŠã¿ãŸãããã
次ã¯äœã§ãã | äŸïŒå ¥åïŒ | çµæã¿ã€ã | äŸïŒçµæïŒ |
---|---|---|---|
ãã¹ãŠãããŸããããå¥ã®èŠçŽ | / tããåé€... | IOkïŒããŒã¯ã³ïŒ | IOkïŒåé€ïŒïŒïŒ |
ã®ã£ãããšã³ã¡ã³ãã®ã¿ãæ®ã£ãŠããŸã | \ n-ã¯ã -ã«ã -ããããïŒ | IErrïŒç©ºïŒïŒïŒ | IErrïŒç©ºïŒïŒïŒ |
ãã£ãšäœãã®å§ãŸã | 'æåå...ïŒéãåŒçšç¬ŠãªãïŒ | IErrïŒäžå®å šïŒïŒïŒ | IErrïŒäžå®å šïŒïŒïŒ |
ããªãã¯ç§ã«ããã€ãã®ã²ãŒã ãããã | ïŒ$ïŒ | IErrïŒæ§æïŒ...ïŒïŒ | IErrïŒæ§æïŒexpected = 'token'ãgot = 'ïŒ'ïŒïŒ |
ã¹ããªãŒã ã¯éå±€æ§é ã«ãªã£ãŠããŸã ã åã¬ãã«ã«ã¯ç¬èªã®ãããã¡ãŒãå«ãŸããŠãããå¿ èŠã«å¿ããŠå èªã¿ïŒ peekïŒïŒ-> IResult [T] ïŒããã³ããŒã«ããã¯ïŒ backïŒnïŒint = 1ïŒ-> None ïŒãå¯èœã§ãã
![ã¹ããªãŒã éå±€](https://habrastorage.org/webt/zz/_z/hc/zz_zhcvelzsfonpcyqwvkxaf6sa.png)
ãããŠãæè¯ã®éšåã¯ãã¹ããªãŒã ããã¹ãŠã®IOkïŒèŠçŽ ïŒã® 1ã€ã®å€§ããªãªã¹ãã«ã ã¢ã»ã³ãã« ãã§ããããšã§ããããã«ããã nextïŒïŒ -ãã¡ããæåã®IErrïŒïŒãŸã§ãåŸãããŸãã IErrã«Emptyãå«ãŸããŠããå Žåã«ã®ã¿ããªã¹ãã¯äœãè¿ããŸããã ããã§ãªãå Žåããšã©ãŒã¯ããé«ãã¹ããŒãããŸãã ãã®èšèšã«ãããREPLãç°¡åãã€ãšã¬ã¬ã³ãã«æ§ç¯ã§ããŸãã
REPL Foundation
class Repl: def reset(self): self.buffer = '' self.PS = self.PS1 def start(self): self.reset() while True: self.buffer += input(self.PS) self.buffer += '\n' stmts = Statements.from_str(self.buffer).collect() if stmts.is_ok(): ... # execute one-by-one self.reset() elif stmts.err().is_incomplete(): self.PS = self.PS2 # read more elif stmts.err().is_syntax(): print(stmts.err()) self.reset() else: pass # ignore Err(Empty())
ãã£ã©ã¯ã¿ãŒ
ãã®ã¹ããªãŒã ã¯ãæååã®æåãééããŸãã å¯äžã®ã¿ã€ãã®ãšã©ãŒïŒè¡ã®æåŸã空ã§ãã
ããŒã¯ã³
ããŒã¯ã³ãããŒã 圌ã®ããã«ããŒã ã¯ã¬ã¯ãµãŒã§ãã ãšã©ãŒãéãåŒçšç¬Šã®ãªãè¡ãããã³ãã¹ãŠããããŸã...
åããŒã¯ãŒããåå¥ã«å«ãããŒã¯ã³ã®åã¿ã€ãã¯ãæœè±¡ããŒã¯ã³ã¯ã©ã¹ã®åå¥ã®ããªã¢ã³ãã¯ã©ã¹ã§è¡šãããŸãïŒãŸãã¯ãåæåããŒã¯ã³ãšèããæ¹ãããã§ããããïŒïŒããã¯ãã¹ããŒãã¡ã³ãããŒãµãŒãããŒã¯ã³ãç¹å®ã®ã¿ã€ãã«ãã£ã¹ãããã®ã«äŸ¿å©ã§ãã
å
žåçãªåå¥è§£æéš
def next_impl(self, ...) -> IResult[Token]: ... char = self.characters.current().ok() if char == ',': self.characters.next() return IOk(Comma()) elif char == '(': self.characters.next() return IOk(LParen()) elif ...
声æ
ã¯ã©ã€ããã¯ã¹ãããŒãµãŒã æ°åã®åèªã®ä»£ããã«ãããã€ãã®ã¹ããããïŒ
ã¹ããªãŒã /statements.py
class Statements(Stream[AstStmt]): def __init__(self, tokens: Stream[Token]) -> None: super().__init__() self.tokens = tokens @classmethod def from_str(cls, source: str) -> 'Statements': return Statements(Tokens.from_str(source)) def next_impl(self) -> IResult[AstStmt]: t = self.tokens.peek() if not t: return Err(t.err()) tok = t.ok() if isinstance(tok, Create): return CreateTable.from_sql(self.tokens) if isinstance(tok, Drop): return DropTable.from_sql(self.tokens) if isinstance(tok, Insert): return InsertInto.from_sql(self.tokens) if isinstance(tok, Delete): return DeleteFrom.from_sql(self.tokens) if isinstance(tok, Update): return UpdateSet.from_sql(self.tokens) if isinstance(tok, Select): return SelectFrom.from_sql(self.tokens) return Err(Syntax('/create, /drop, /insert, /delete, /update or /select', str(tok)))
ast / delete_from.py
class DeleteFrom(AstStmt): def __init__(self, table: Identifier, where: Optional[Expression]) -> None: super().__init__() self.table = table self.where = where @classmethod def from_sql(cls, tokens: Stream[Token]) -> IResult['DeleteFrom']: """ /delete_stmt : "/delete" "from" /table_name /where_clause /drop ; """ # next item must be the "/delete" token t = tokens.next().and_then(Cast(Delete)) if not t: return IErr(t.err()) t = tokens.next().and_then(Cast(From)) if not t: return IErr(t.err().empty_to_incomplete()) t = tokens.next().and_then(Cast(Identifier)) if not t: return IErr(t.err().empty_to_incomplete()) table = t.ok() t = WhereFromSQL.from_sql(tokens) if not t: return IErr(t.err().empty_to_incomplete()) where = t.ok() t = tokens.next().and_then(Cast(Drop)) if not t: return IErr(t.err().empty_to_incomplete()) return IOk(DeleteFrom(table, where))
REPLãæ£ããæ©èœããããã«ã¯ãæåã®ããŒãµãŒãé€ããã¿ã€ããEmptyã®ãšã©ãŒã¯ãã¹ãŠããŒãµãŒãIncompleteã«å€æããå¿ èŠãããããšã«æ³šæããããšãéèŠã§ãã ããã«ã¯è£å©é¢æ°empty_to_incompleteïŒïŒ-> ErrorããããŸã ã ãã¯ãã§ã¯ãããŸããããã¯ãã¯ãããŸãããtïŒif IErrïŒt.errïŒïŒãEmpty_to_incompleteïŒïŒïŒã¯ãã³ãŒãããŒã¹ã§å°ãªããšã50åçºçããäœãå®è¡ãããŸããã çå£ã«ãããæç¹ã§ãSyshnyããªããã»ããµã䜿çšãããã£ãã®ã§ãã
ãããã€ããªåœ¢åŒ
ã°ããŒãã«ã«ãããŒã¿ããŒã¹ãã¡ã€ã«ã¯ãããã¯ã«åå²ããããã¡ã€ã«ãµã€ãºã¯ãããã¯ã®ãµã€ãºã®åæ°ã«ãªããŸãã ããã©ã«ãã®ãããã¯ãµã€ãºã¯12 KiBã§ããããªãã·ã§ã³ã§18ã24ããŸãã¯36 KiBã«å¢ããããšãã§ããŸãã ããªããéè¡ã®æªé䞻矩è ã§ãããããªããéåžžã«å€§ããªããŒã¿ãæã£ãŠãããªããããªãã¯ããã42 KiBãŸã§äžããããšããã§ããŸãã
ãããã¯ã«ã¯æåããçªå·ãä»ããããŸãã ãŒããããã¯ã«ã¯ãããŒã¿ããŒã¹å šäœã«é¢ããã¡ã¿ããŒã¿ãå«ãŸããŠããŸãã ãã®èåŸã«ã¯ãããŒãã«ã¡ã¿ããŒã¿çšã®16ãããã¯ããããŸãã ãããã¯ïŒ17ã¯ããŒã¿ãããã¯ã§å§ãŸããŸãã ãããã¯ãžã®ãã€ã³ã¿ã¯ã ãããã¯ã·ãŒã±ã³ã¹çªå·ãšåŒã°ããŸãã
![ãã¡ã€ã«](https://habrastorage.org/webt/6d/np/xp/6dnpxprn9mbznje8tcv-o3ljsbc.png)
çŸåšãããŒã¿ããŒã¹ã¡ã¿ããŒã¿ã¯ããã»ã©å€ãã¯ãããŸãããååã¯æ倧256ãã€ãã§ãããŒã¿ãããã¯ã®æ°ã§ãã
![ããŒã¿ããŒã¹ã¡ã¿](https://habrastorage.org/webt/4u/05/up/4u05upvnj-rccevgxf40lacisbm.png)
ããŒãã«ã®ã¡ã¿ãããã¯ã¯æãå°é£ã§ãã ããã«ã¯ãããŒãã«ã®ååããã¹ãŠã®åãšãã®ã¿ã€ãã®ãªã¹ããã¬ã³ãŒãæ°ãããã³ããŒã¿ãããã¯ãžã®ãã€ã³ã¿ãŒãä¿åãããŸãã
ããŒãã«ã®æ°ã¯ã³ãŒãã§åºå®ãããŠããŸãã ãã ããããŒã¿ããŒã¹ã®ã¡ã¿ãããã¯ã«ããŒãã«ã®ã¡ã¿ãããã¯ãžã®ãã€ã³ã¿ãæ ŒçŽãããšãããã¯æ¯èŒçç°¡åã«ä¿®æ£ã§ããŸãã
![ããŒãã«ã¡ã¿](https://habrastorage.org/webt/db/xt/rd/dbxtrd_bvzk0fey90paacc8lxve.png)
ãããã¯ãžã®ãã€ã³ã¿ã¯ãiããŒãå ã®ãã€ã³ã¿ã®åçã§æ©èœããŸã ã Tanenbaumãšä»ã®äœå人ãã®å°æ¬ããã人ã ã¯ããã®ããšã«ã€ããŠçŸããæžããŸããã ãããã£ãŠãããŒãã«ã¯ããŒã¿ãããã¯ããããŒãžããšèŠãªããŸãã éãã¯ãããŒãã«ã®èŠ³ç¹ããé çªã«æ¥ãããŒãžããç¥ãéã眮ãããã«ãã¡ã€ã«å ã«ç©ççã«é 眮ãããããšã§ãã OSã®ä»®æ³ã¡ã¢ãªãšã®é¡äŒŒæ§ã®æç»ãããŒãžïŒä»®æ³ããŒãžçªå·ããããã¯ïŒç©çããŒãžçªå·ã
![iããŒããã€ã³ã¿ãŒæ§é](https://habrastorage.org/getpro/habr/post_images/288/13c/9ce/28813c9cea052290bae8051669fa5536.gif)
ããŒã¿ãããã¯èªäœã«ã¯ç¹å®ã®æ§é ã¯ãããŸããã ãããããã€ã³ã¿ã«ãã£ãŠæ瀺ãããé åºã§çµåããããšãåºå®é·ã®ã¬ã³ãŒãïŒã¬ã³ãŒã/ã¿ãã«ïŒã®é£ç¶ã¹ããªãŒã ãšããŠè¡šç€ºãããŸãã ãããã£ãŠãã¬ã³ãŒãã®ã·ãªã¢ã«çªå·ãç¥ãããããæœåºãŸãã¯æžã蟌ãããšã¯ãã»ãŒäžå®æéOïŒ1 * ïŒã®æäœã§ãããå¿ èŠã«å¿ããŠæ°ãããããã¯ã®å²ãåœãŠãæžäŸ¡ããŸãã
ã¬ã³ãŒãã®æåã®ãã€ãã«ã¯ããã®ã¬ã³ãŒããçããŠãããåé€ããããã«é¢ããæ å ±ãå«ãŸããŠããŸãã ããŒã¿ã®ããã¯ãšã¢ã³ããã¯ã«é¢ããæ®ãã®äœæ¥ã¯ãæšæºã®structã¢ãžã¥ãŒã«ã«ãã£ãŠè¡ãããŸãã
/æŽæ°æäœã¯åžžã«ãã€ã³ãã¬ãŒã¹ããäžæžããã/ deleteã¯æåã®ãã€ãã®ã¿ã眮ãæããŸãã VACUUMæäœã¯ãµããŒããããŠããŸããã
![ããŒã¿ãããã¯](https://habrastorage.org/webt/em/_g/n4/em_gn4s3q2avpystlsgg3swfzfa.png)
ããŒãã«æäœãRowSetãããã³çµåã«ã€ããŠ
ããŒãã®ããã€ãã®ããã§2ã€ã®äžçã®ãã¹ãããã£ãããšåºå®ããæã§ãã
å·ŠåŽã®MC -ASTãããã¬ãã«ããŒãïŒAstStmtãµãã¯ã©ã¹ïŒã ãããã®å®è¡ã¯ãããŒã¿ããŒã¹ãžã®æ¥ç¶ã®ã³ã³ããã¹ãã§çºçããŸãã äœçœ®åŒæ°ããµããŒããããŠããŸã-ãªã¯ãšã¹ãæ¬æã®åŒã«ãããïŒNãããŒã¯ã³ãããšãã°ãã/ delete from student / where name =ïŒ1 / dropãã åŒèªäœã¯ååž°çã§ããããã®èšç®ã¯ç§åŠçãªãã¬ãŒã¯ã¹ã«ãŒãæ§æããŸããã
å³åŽã®MCã¯ãããŒãã«å ã®ã·ãŒã±ã³ã¹çªå·ãèå¥åãšããŠäœ¿çšããŠãã¬ã³ãŒãã1ã€ãã€æäœããããŒã¿ããŒã¹ãã©ã€ããŒã§ãã 圌ãç¥ã£ãŠããã®ã¯ãã©ã®ããŒãã«ãååšããã©ã®ããã«ããŒãã«ãæäœããããç¥ã£ãŠããããšã ãã§ãã
è¡ããïŒ
åµé æ§ã«é¢ãã圌ãã®æåã®å ±åã·ã³ã°ã«ã æ°ããããŒãã«ãäœæããã®ã¯ãæåã®ç©ºã®èšè¿°åã§ãã16ãèŠã€ããŠããã«ååãšåã®ãªã¹ããå ¥åããã®ãšåããããç°¡åã§ãã
次ã«ãã·ã³ããªãã¯å/ããããã®ãã©ãã¯ã ãã¢ã¬ã³ãŒãã®ããŒã ããŒãžã§ã³ã§ã¯ã次ã®ããšãèµ·ãããŸãã1ïŒååã§ããŒãã«èšè¿°åãèŠã€ããŸãã 2ïŒãŒãã«ãªã»ããããŸãã 誰ãããŒã¿ããŒãžã®æªãªãªãŒã¹ãããã¯ãæ°ã«ããŸããïŒ
æ¿å ¥ã¯åã®é åºã«éåããŠãããããæžã蟌ã¿çšã®ã¿ãã«ãéä¿¡ããåã«ãç¹å¥ãªãã£ã«ã¿ãŒtransition_vectorãééããŸãã
ããã«ãããŒãã«ãšã³ããªã®æäœã«ã€ããŠèª¬æããŸãã®ã§ãããã«å¯©å€RowSetã玹ä»ããŸãã
ç空äžã®çç¶RowSet
class RowSet(metaclass=abc.ABCMeta): @abc.abstractmethod def columns(self) -> List[Column]: """ Describe columns in this row set. """ @abc.abstractmethod def iter(self) -> Iterator['Row']: """ Return a generator which yields rows from the underlying row stream or a table. """
ãã®ç£ã®äž»ãªç¹å®ã®äºçš®-TableRowSet-ã¯ããã¹ãŠã®ã©ã€ãïŒåé€ãããŠããªãïŒã¬ã³ãŒããé çªã«éžæããŸãã dropSQLã®ä»ã®çš®é¡ã®RowSetã¯ãå¿ èŠãªæå°ã®é¢ä¿ä»£æ°ãå®è£ ããŸãã
é¢ä¿ä»£æ°æŒç®å | æå® | ã¯ã©ã¹ |
---|---|---|
æ圱 | Ï ïŒIDãNAMEïŒ expr | ProjectionRowSet |
ååãå€æŽ | Ïa / b expr | ProjectionRowSet + RenameTableRowSet |
ãµã³ããªã³ã° | Ï ïŒPRICE> 90ïŒ expr | FilteredRowSet |
ãã«ã«ãç© | 補åÃ販売è | CrossJoinRowSet |
å
éšçµå
ïŒæ¡åŒµæ©èœãšåŒã³ãŸãïŒ | Ï ïŒæ¡ä»¶ïŒ ïŒA x BïŒ | InnerJoinRowSet = FilteredRowSetïŒ CrossJoinRowSetïŒ...ïŒïŒ |
ããã«ãããã°ã©ã å¯èœãªMockRowSetããããŸãã ãã¹ãã«é©ããŠããŸãã ãŸãããã®å©ããåããŠãã / autism ããšåŒã°ãããã¹ã¿ãŒããŒãã«ã«ã¢ã¯ã»ã¹ã§ããŸãã
çŸããã¯ãããŸããŸãªRowSetsãèªç±ã«çµã¿åãããããšãã§ããããšã§ãããåŠçãããŒãã«ãéžæãããšã€ãªã¢ã¹ãSããæå®ããã/ where scholarship> '12k'ããé€å€ããå¥ã®ããŒãã«ãcoursesããéžæããã/ onïŒcourse / sid = S / idïŒ/ andïŒcourse / grade <'B'ïŒ "ãproject into" S / idãS / first_name / as / name "-ããã¯æ¬¡ã®éå±€ã§è¡šãããŸãã
ProjectionRowSet([S/id, S/first_name/as/name]) FilteredRowSet((course/sid = S/id) /and (course/grade < 'B')) CrossJoinRowSet FilteredRowSet(scholarship > '12k') RenameTableRowSet('S') TableRowSet('student') TableRowSet('courses')
ãã®ããããã®ãããªåŒ·åãªæ¥œåšãè£ åããŠã16äžçŽã®ãªã¥ãŒãé³æ¥œã«æ»ããŸã...
4çªç®ã®ãã©ãã¯/ selectã«ã€ããŠããã以äžè¿œå ãããã®ã¯ãããŸããã RowSetsã®äº€é¿æ²ã¯ãéãé äºãããããªãã®ã§ãã ããã«ãããå®è£ ã¯éåžžã«ç°¡æœã«ãªããŸããã
å®è£
/éžæ...ãã
class SelectFrom(AstStmt): ... def execute(self, db: 'fs.DBFile', args: ARGS_TYPE = ()) -> Result['RowSet', str]: r = self.table.row_set(db) if not r: return Err(r.err()) rs = r.ok() for join in self.joins: r = join.join(rs, db, args) if not r: return Err(r.err()) rs = r.ok() if self.where is not None: rs = FilteredRowSet(rs, self.where, args) rs = ProjectionRowSet(rs, self.columns, args) return Ok(rs)
æåŸã®2ã€ïŒ / updateããã³/ deleteã¯ãåä»»è ã®å®çžŸã䜿çšããŸãã ããã«ã/ updateã¯ãäžèšã®transition_vectorã«äŒŒãææ³ã䜿çšããŸãã
ãããªã³ã³ãµãŒãïŒ ãæž èŽããããšãããããŸããïŒ ã«ãŒãã³ïŒ..
ãŠã£ãã·ã¥ãªã¹ã
ãŸã å®çŸããŠããªã倢ïŒ
- ãµããŒã/ããŒãµãŒã ãã§ãªãäž»ããŒ
- åé æŒç®å
- ãã¹ããããã¯ãšãª
- åŒã®åæšè«
- Pythonçšã®äŸ¿å©ãªAPI
ããã¯ãã¬ãŒãã³ã°ãããžã§ã¯ãã§ãã£ããããç§ãã¡ã¯ããã«å¯ŸããŠãããŒãåŸãããšãã§ããŸããã§ããã ããããslocã®çµ±èšããå€æãããšã圌ãã¯ä»ã§ã¯èµ€ãã£ãã¢ãé£ã¹ãããšãã§ããŸããã
Sloccountã¬ããŒã
Have a non-directory at the top, so creating directory top_dir Creating filelist for dropSQL Creating filelist for tests Creating filelist for util Categorizing files. Finding a working MD5 command.... Found a working MD5 command. Computing results. SLOC Directory SLOC-by-Language (Sorted) 2764 dropSQL python=2764 675 tests python=675 28 util python=28 Totals grouped by language (dominant language first): python: 3467 (100.00%) Total Physical Source Lines of Code (SLOC) = 3,467 Development Effort Estimate, Person-Years (Person-Months) = 0.74 (8.85) (Basic COCOMO model, Person-Months = 2.4 * (KSLOC**1.05)) Schedule Estimate, Years (Months) = 0.48 (5.73) (Basic COCOMO model, Months = 2.5 * (person-months**0.38)) Estimated Average Number of Developers (Effort/Schedule) = 1.55 Total Estimated Cost to Develop = $ 99,677 (average salary = $56,286/year, overhead = 2.40). SLOCCount, Copyright (C) 2001-2004 David A. Wheeler SLOCCount is Open Source Software/Free Software, licensed under the GNU GPL. SLOCCount comes with ABSOLUTELY NO WARRANTY, and you are welcome to redistribute it under certain conditions as specified by the GNU GPL license; see the documentation for details. Please credit this data as "generated using David A. Wheeler's 'SLOCCount'."
è¬èŸ
- ã€ãããªã¹å€§åŠã®å± å¿å°ã®è¯ãç°å¢ãšçŽ æŽãããåºäŒã
- ã³ã³ãã€ã©å šè¬ã«é¢ããã³ãŒã¹ãç¹ã«ããŒãµãŒã«é¢ããè¬çŸ©ã«ã€ããŠã¯ãYevgeny Zuevææ
- DBMSã³ãŒã¹ã«ã€ããŠã¯ãManuel MazzaraææãšTA Ruslanææã«ã / GodBlessMazzara
ãããŠæ¬¡åã¯ããã€ãã©ã€ã³ãšãã©ã³ã¶ã¯ã·ã§ã³ãéçŽããéãªã¬ãŒã·ã§ãã«ã¢ãŒããå®è£ ããŸãã ãããŠãããåŒã³åºã-/ noDropSQLïŒ